- Copyright (C) 1992, 1995, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1995, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005 Free Software Foundation, Inc.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
+#define RVA_TO_PTR(var,section,filedata) \
+ ((void *)((section)->PointerToRawData \
+ + ((DWORD)(var) - (section)->VirtualAddress) \
+ + (filedata).file_base))
+
/* Control whether spawnve quotes arguments as necessary to ensure
correct parsing by child process. Because not all uses of spawnve
are careful about constructing argv arrays, we make this behaviour
/* Control whether spawnve quotes arguments as necessary to ensure
correct parsing by child process. Because not all uses of spawnve
are careful about constructing argv arrays, we make this behaviour
avoids the inefficiency of frequently reading small amounts of data.
This is primarily necessary for handling DOS processes on Windows 95,
but is useful for W32 processes on both Windows 95 and NT as well. */
avoids the inefficiency of frequently reading small amounts of data.
This is primarily necessary for handling DOS processes on Windows 95,
but is useful for W32 processes on both Windows 95 and NT as well. */
/* Control conversion of upper case file names to lower case.
nil means no, t means yes. */
/* Control conversion of upper case file names to lower case.
nil means no, t means yes. */
static signal_handler sig_handlers[NSIG];
/* Fake signal implementation to record the SIGCHLD handler. */
static signal_handler sig_handlers[NSIG];
/* Fake signal implementation to record the SIGCHLD handler. */
is normally blocked until woken by select() to check for input by
reading one char. When the read completes, char_avail is signalled
to wake up the select emulator and the thread blocks itself again. */
is normally blocked until woken by select() to check for input by
reading one char. When the read completes, char_avail is signalled
to wake up the select emulator and the thread blocks itself again. */
/* We have to wait for the go-ahead before we can start */
if (cp == NULL
|| WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
/* We have to wait for the go-ahead before we can start */
if (cp == NULL
|| WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
/* If the read died, the child has died so let the thread die */
if (rc == STATUS_READ_FAILED)
break;
/* If the read died, the child has died so let the thread die */
if (rc == STATUS_READ_FAILED)
break;
/* Wait until our input is acknowledged before reading again */
if (WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
{
/* Wait until our input is acknowledged before reading again */
if (WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
{
sys_spawnve, and is not generally valid at any other time. */
static char * process_dir;
sys_spawnve, and is not generally valid at any other time. */
static char * process_dir;
create_child (char *exe, char *cmdline, char *env, int is_gui_app,
int * pPid, child_process *cp)
{
create_child (char *exe, char *cmdline, char *env, int is_gui_app,
int * pPid, child_process *cp)
{
memset (&start, 0, sizeof (start));
start.cb = sizeof (start);
memset (&start, 0, sizeof (start));
start.cb = sizeof (start);
#ifdef HAVE_NTGUI
if (NILP (Vw32_start_process_show_window) && !is_gui_app)
start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
#ifdef HAVE_NTGUI
if (NILP (Vw32_start_process_show_window) && !is_gui_app)
start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
sec_attrs.nLength = sizeof (sec_attrs);
sec_attrs.lpSecurityDescriptor = NULL /* &sec_desc */;
sec_attrs.bInheritHandle = FALSE;
sec_attrs.nLength = sizeof (sec_attrs);
sec_attrs.lpSecurityDescriptor = NULL /* &sec_desc */;
sec_attrs.bInheritHandle = FALSE;
strcpy (dir, process_dir);
unixtodos_filename (dir);
strcpy (dir, process_dir);
unixtodos_filename (dir);
to register the handle with the process
This way the select emulator knows how to match file handles with
entries in child_procs. */
to register the handle with the process
This way the select emulator knows how to match file handles with
entries in child_procs. */
cp = find_child_pid (pid);
if (cp == NULL)
{
DebPrint (("register_child unable to find pid %lu\n", pid));
return;
}
cp = find_child_pid (pid);
if (cp == NULL)
{
DebPrint (("register_child unable to find pid %lu\n", pid));
return;
}
signal failure to the select emulator.
The select emulator then calls this routine to clean up.
Since the thread signaled failure we can assume it is exiting. */
signal failure to the select emulator.
The select emulator then calls this routine to clean up.
Since the thread signaled failure we can assume it is exiting. */
When it does, close its handle
Return the pid and fill in the status if non-NULL. */
When it does, close its handle
Return the pid and fill in the status if non-NULL. */
int pid;
child_process *cp, *cps[MAX_CHILDREN];
HANDLE wait_hnd[MAX_CHILDREN];
int pid;
child_process *cp, *cps[MAX_CHILDREN];
HANDLE wait_hnd[MAX_CHILDREN];
/* We can only identify DOS .com programs from the extension. */
if (p && stricmp (p, ".com") == 0)
*is_dos_app = TRUE;
/* We can only identify DOS .com programs from the extension. */
if (p && stricmp (p, ".com") == 0)
*is_dos_app = TRUE;
else if (nt_header->Signature != IMAGE_NT_SIGNATURE
&& LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE)
{
else if (nt_header->Signature != IMAGE_NT_SIGNATURE
&& LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE)
{
/* When a new child process is created we need to register it in our list,
so intercept spawn requests. */
/* When a new child process is created we need to register it in our list,
so intercept spawn requests. */
sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
{
Lisp_Object program, full;
sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
{
Lisp_Object program, full;
full = Qnil;
GCPRO1 (program);
openp (Vexec_path, program, Vexec_suffixes, &full, make_number (X_OK));
full = Qnil;
GCPRO1 (program);
openp (Vexec_path, program, Vexec_suffixes, &full, make_number (X_OK));
/* we have to do some conjuring here to put argv and envp into the
form CreateProcess wants... argv needs to be a space separated/null
terminated list of parameters, and envp is a null
/* we have to do some conjuring here to put argv and envp into the
form CreateProcess wants... argv needs to be a space separated/null
terminated list of parameters, and envp is a null
/* Now create the process. */
if (!create_child (cmdname, cmdline, env, is_gui_app, &pid, cp))
{
/* Now create the process. */
if (!create_child (cmdname, cmdline, env, is_gui_app, &pid, cp))
{
sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
EMACS_TIME *timeout)
{
sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
EMACS_TIME *timeout)
{
child_process *cp, *cps[MAX_CHILDREN];
HANDLE wait_hnd[MAXDESC + MAX_CHILDREN];
int fdindex[MAXDESC]; /* mapping from wait handles back to descriptors */
child_process *cp, *cps[MAX_CHILDREN];
HANDLE wait_hnd[MAXDESC + MAX_CHILDREN];
int fdindex[MAXDESC]; /* mapping from wait handles back to descriptors */
timeout_ms = timeout ? (timeout->tv_sec * 1000 + timeout->tv_usec / 1000) : INFINITE;
/* If the descriptor sets are NULL but timeout isn't, then just Sleep. */
timeout_ms = timeout ? (timeout->tv_sec * 1000 + timeout->tv_usec / 1000) : INFINITE;
/* If the descriptor sets are NULL but timeout isn't, then just Sleep. */
/* Always wait on interrupt_handle, to detect C-g (quit). */
wait_hnd[0] = interrupt_handle;
fdindex[0] = -1;
/* Always wait on interrupt_handle, to detect C-g (quit). */
wait_hnd[0] = interrupt_handle;
fdindex[0] = -1;
{
DebPrint (("select.WaitForMultipleObjects (%d, %lu) failed with %lu\n",
nh + nc, timeout_ms, GetLastError ()));
{
DebPrint (("select.WaitForMultipleObjects (%d, %lu) failed with %lu\n",
nh + nc, timeout_ms, GetLastError ()));
abort; WAIT_FAILED is returned when single-stepping under
Windows 95 after switching thread focus in debugger, and
possibly at other times. */
abort; WAIT_FAILED is returned when single-stepping under
Windows 95 after switching thread focus in debugger, and
possibly at other times. */
/* Only handle signals that will result in the process dying */
if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP)
{
/* Only handle signals that will result in the process dying */
if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP)
{
/* Try to locate console window for process. */
EnumWindows (find_child_console, (LPARAM) cp);
}
/* Try to locate console window for process. */
EnumWindows (find_child_console, (LPARAM) cp);
}
if (!DuplicateHandle (parent,
(HANDLE) _get_osfhandle (out),
parent,
if (!DuplicateHandle (parent,
(HANDLE) _get_osfhandle (out),
parent,
if (!DuplicateHandle (parent,
(HANDLE) _get_osfhandle (err),
parent,
if (!DuplicateHandle (parent,
(HANDLE) _get_osfhandle (err),
parent,
/* and store them as our std handles */
if (!SetStdHandle (STD_INPUT_HANDLE, newstdin))
report_file_error ("Changing stdin handle", Qnil);
/* and store them as our std handles */
if (!SetStdHandle (STD_INPUT_HANDLE, newstdin))
report_file_error ("Changing stdin handle", Qnil);
if (!SetStdHandle (STD_OUTPUT_HANDLE, newstdout))
report_file_error ("Changing stdout handle", Qnil);
if (!SetStdHandle (STD_OUTPUT_HANDLE, newstdout))
report_file_error ("Changing stdout handle", Qnil);
DEFUN ("w32-set-current-locale", Fw32_set_current_locale, Sw32_set_current_locale, 1, 1, 0,
doc: /* Make Windows locale LCID be the current locale setting for Emacs.
If successful, the new locale id is returned, otherwise nil. */)
DEFUN ("w32-set-current-locale", Fw32_set_current_locale, Sw32_set_current_locale, 1, 1, 0,
doc: /* Make Windows locale LCID be the current locale setting for Emacs.
If successful, the new locale id is returned, otherwise nil. */)
DEFUN ("w32-set-console-codepage", Fw32_set_console_codepage,
Sw32_set_console_codepage, 1, 1, 0,
doc: /* Make Windows codepage CP be the current codepage setting for Emacs.
DEFUN ("w32-set-console-codepage", Fw32_set_console_codepage,
Sw32_set_console_codepage, 1, 1, 0,
doc: /* Make Windows codepage CP be the current codepage setting for Emacs.
DEFUN ("w32-set-console-output-codepage", Fw32_set_console_output_codepage,
Sw32_set_console_output_codepage, 1, 1, 0,
doc: /* Make Windows codepage CP be the current codepage setting for Emacs.
DEFUN ("w32-set-console-output-codepage", Fw32_set_console_output_codepage,
Sw32_set_console_output_codepage, 1, 1, 0,
doc: /* Make Windows codepage CP be the current codepage setting for Emacs.
DEFUN ("w32-set-keyboard-layout", Fw32_set_keyboard_layout,
Sw32_set_keyboard_layout, 1, 1, 0,
doc: /* Make LAYOUT be the current keyboard layout for Emacs.
DEFUN ("w32-set-keyboard-layout", Fw32_set_keyboard_layout,
Sw32_set_keyboard_layout, 1, 1, 0,
doc: /* Make LAYOUT be the current keyboard layout for Emacs.
them blocking when trying to access unmounted drives etc. */);
Vw32_start_process_inherit_error_mode = Qt;
them blocking when trying to access unmounted drives etc. */);
Vw32_start_process_inherit_error_mode = Qt;
doc: /* Forced delay before reading subprocess output.
This is done to improve the buffering of subprocess output, by
avoiding the inefficiency of frequently reading small amounts of data.
doc: /* Forced delay before reading subprocess output.
This is done to improve the buffering of subprocess output, by
avoiding the inefficiency of frequently reading small amounts of data.
reading the subprocess output. If negative, the magnitude is the number
of time slices to wait (effectively boosting the priority of the child
process temporarily). A value of zero disables waiting entirely. */);
reading the subprocess output. If negative, the magnitude is the number
of time slices to wait (effectively boosting the priority of the child
process temporarily). A value of zero disables waiting entirely. */);
DEFVAR_LISP ("w32-downcase-file-names", &Vw32_downcase_file_names,
doc: /* Non-nil means convert all-upper case file names to lower case.
This applies when performing completions and file name expansion.
Note that the value of this setting also affects remote file names,
so you probably don't want to set to non-nil if you use case-sensitive
DEFVAR_LISP ("w32-downcase-file-names", &Vw32_downcase_file_names,
doc: /* Non-nil means convert all-upper case file names to lower case.
This applies when performing completions and file name expansion.
Note that the value of this setting also affects remote file names,
so you probably don't want to set to non-nil if you use case-sensitive
Note that this option is only useful for files on NTFS volumes, where hard links
are supported. Moreover, it slows down `file-attributes' noticeably. */);
Vw32_get_true_file_attributes = Qt;
Note that this option is only useful for files on NTFS volumes, where hard links
are supported. Moreover, it slows down `file-attributes' noticeably. */);
Vw32_get_true_file_attributes = Qt;