1 /* Process support for Windows NT port of XEMACS.
2 Copyright (C) 1992, 1995 Free Software Foundation, Inc.
4 This file is part of XEmacs.
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
21 Drew Bliss Oct 14, 1993
22 Adapted from alarm.c by Tim Fleehart */
24 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */
25 /* Synced with FSF Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */
34 /* must include CRT headers *before* config.h */
35 /* #### I don't believe it - martin */
44 #include <sys/socket.h>
51 #include "ntheap.h" /* From 19.34.6 */
53 #include "syssignal.h"
58 /*#include "w32term.h"*/ /* From 19.34.6: sync in ? --marcpa */
60 /* #### I'm not going to play with shit. */
61 #pragma warning (disable:4013 4024 4090)
63 /* Control whether spawnve quotes arguments as necessary to ensure
64 correct parsing by child process. Because not all uses of spawnve
65 are careful about constructing argv arrays, we make this behavior
66 conditional (off by default). */
67 Lisp_Object Vwin32_quote_process_args;
69 /* Control whether create_child causes the process' window to be
70 hidden. The default is nil. */
71 Lisp_Object Vwin32_start_process_show_window;
73 /* Control whether create_child causes the process to inherit Emacs'
74 console window, or be given a new one of its own. The default is
75 nil, to allow multiple DOS programs to run on Win95. Having separate
76 consoles also allows Emacs to cleanly terminate process groups. */
77 Lisp_Object Vwin32_start_process_share_console;
79 /* Time to sleep before reading from a subprocess output pipe - this
80 avoids the inefficiency of frequently reading small amounts of data.
81 This is primarily necessary for handling DOS processes on Windows 95,
82 but is useful for Win32 processes on both Win95 and NT as well. */
83 Lisp_Object Vwin32_pipe_read_delay;
85 /* Control whether stat() attempts to generate fake but hopefully
86 "accurate" inode values, by hashing the absolute truenames of files.
87 This should detect aliasing between long and short names, but still
88 allows the possibility of hash collisions. */
89 Lisp_Object Vwin32_generate_fake_inodes;
91 Lisp_Object Qhigh, Qlow;
93 extern Lisp_Object Vlisp_EXEC_SUFFIXES;
98 void _DebPrint (const char *fmt, ...)
104 va_start (args, fmt);
105 vsprintf (buf, fmt, args);
107 OutputDebugString (buf);
111 /* sys_signal moved to nt.c. It's now called msw_signal... */
113 /* Defined in <process.h> which conflicts with the local copy */
116 /* Child process management list. */
117 int child_proc_count = 0;
118 child_process child_procs[ MAX_CHILDREN ];
119 child_process *dead_child = NULL;
121 DWORD WINAPI reader_thread (void *arg);
123 /* Determine if running on Windows 9x and not NT */
127 return GetVersion () & 0x80000000;
130 /* Find an unused process slot. */
137 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
138 if (!CHILD_ACTIVE (cp))
140 if (child_proc_count == MAX_CHILDREN)
142 cp = &child_procs[child_proc_count++];
148 if (cp->procinfo.hProcess)
149 CloseHandle(cp->procinfo.hProcess);
150 cp->procinfo.hProcess = NULL;
151 cp->status = STATUS_READ_ERROR;
153 /* use manual reset event so that select() will function properly */
154 cp->char_avail = CreateEvent (NULL, TRUE, FALSE, NULL);
157 cp->char_consumed = CreateEvent (NULL, FALSE, FALSE, NULL);
158 if (cp->char_consumed)
160 cp->thrd = CreateThread (NULL, 1024, reader_thread, cp, 0, &id);
170 delete_child (child_process *cp)
174 /* Should not be deleting a child that is still needed. */
175 for (i = 0; i < MAXDESC; i++)
176 if (fd_info[i].cp == cp)
179 if (!CHILD_ACTIVE (cp))
182 /* reap thread if necessary */
187 if (GetExitCodeThread (cp->thrd, &rc) && rc == STILL_ACTIVE)
189 /* let the thread exit cleanly if possible */
190 cp->status = STATUS_READ_ERROR;
191 SetEvent (cp->char_consumed);
192 if (WaitForSingleObject (cp->thrd, 1000) != WAIT_OBJECT_0)
194 DebPrint (("delete_child.WaitForSingleObject (thread) failed "
195 "with %lu for fd %ld\n", GetLastError (), cp->fd));
196 TerminateThread (cp->thrd, 0);
199 CloseHandle (cp->thrd);
204 CloseHandle (cp->char_avail);
205 cp->char_avail = NULL;
207 if (cp->char_consumed)
209 CloseHandle (cp->char_consumed);
210 cp->char_consumed = NULL;
213 /* update child_proc_count (highest numbered slot in use plus one) */
214 if (cp == child_procs + child_proc_count - 1)
216 for (i = child_proc_count-1; i >= 0; i--)
217 if (CHILD_ACTIVE (&child_procs[i]))
219 child_proc_count = i + 1;
224 child_proc_count = 0;
227 /* Find a child by pid. */
228 static child_process *
229 find_child_pid (DWORD pid)
233 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
234 if (CHILD_ACTIVE (cp) && pid == cp->pid)
239 /* Function to do blocking read of one byte, needed to implement
240 select. It is only allowed on sockets and pipes. */
242 _sys_read_ahead (int fd)
247 if (fd < 0 || fd >= MAXDESC)
248 return STATUS_READ_ERROR;
252 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
253 return STATUS_READ_ERROR;
255 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
256 || (fd_info[fd].flags & FILE_READ) == 0)
258 /* fd is not a pipe or socket */
262 cp->status = STATUS_READ_IN_PROGRESS;
264 if (fd_info[fd].flags & FILE_PIPE)
266 rc = _read (fd, &cp->chr, sizeof (char));
268 /* Give subprocess time to buffer some more output for us before
269 reporting that input is available; we need this because Win95
270 connects DOS programs to pipes by making the pipe appear to be
271 the normal console stdout - as a result most DOS programs will
272 write to stdout without buffering, ie. one character at a
273 time. Even some Win32 programs do this - "dir" in a command
274 shell on NT is very slow if we don't do this. */
277 int wait = XINT (Vwin32_pipe_read_delay);
283 /* Yield remainder of our time slice, effectively giving a
284 temporary priority boost to the child process. */
289 if (rc == sizeof (char))
290 cp->status = STATUS_READ_SUCCEEDED;
292 cp->status = STATUS_READ_FAILED;
297 /* Thread proc for child process and socket reader threads. Each thread
298 is normally blocked until woken by select() to check for input by
299 reading one char. When the read completes, char_avail is signalled
300 to wake up the select emulator and the thread blocks itself again. */
302 reader_thread (void *arg)
307 cp = (child_process *)arg;
309 /* <matts@tibco.com> - I think the test below is wrong - we don't
310 want to wait for someone to signal char_consumed, as we haven't
311 read anything for them to consume yet! */
315 WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
327 rc = _sys_read_ahead (cp->fd);
329 /* The name char_avail is a misnomer - it really just means the
330 read-ahead has completed, whether successfully or not. */
331 if (!SetEvent (cp->char_avail))
333 DebPrint (("reader_thread.SetEvent failed with %lu for fd %ld\n",
334 GetLastError (), cp->fd));
338 if (rc == STATUS_READ_ERROR)
340 /* We are finished, so clean up handles and set to NULL so
341 that CHILD_ACTIVE will see what is going on */
342 if (cp->char_avail) {
343 CloseHandle (cp->char_avail);
344 cp->char_avail = NULL;
347 CloseHandle (cp->thrd);
350 if (cp->char_consumed) {
351 CloseHandle(cp->char_consumed);
352 cp->char_consumed = NULL;
354 if (cp->procinfo.hProcess)
356 CloseHandle (cp->procinfo.hProcess);
357 cp->procinfo.hProcess=NULL;
362 /* If the read died, the child has died so let the thread die */
363 if (rc == STATUS_READ_FAILED)
366 /* Wait until our input is acknowledged before reading again */
367 if (WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
369 DebPrint (("reader_thread.WaitForSingleObject failed with "
370 "%lu for fd %ld\n", GetLastError (), cp->fd));
374 /* We are finished, so clean up handles and set to NULL so that
375 CHILD_ACTIVE will see what is going on */
376 if (cp->char_avail) {
377 CloseHandle (cp->char_avail);
378 cp->char_avail = NULL;
381 CloseHandle (cp->thrd);
384 if (cp->char_consumed) {
385 CloseHandle(cp->char_consumed);
386 cp->char_consumed = NULL;
388 if (cp->procinfo.hProcess)
390 CloseHandle (cp->procinfo.hProcess);
391 cp->procinfo.hProcess=NULL;
397 /* To avoid Emacs changing directory, we just record here the directory
398 the new process should start in. This is set just before calling
399 sys_spawnve, and is not generally valid at any other time. */
400 static const char * process_dir;
403 create_child (CONST char *exe, char *cmdline, char *env,
404 int * pPid, child_process *cp)
407 SECURITY_ATTRIBUTES sec_attrs;
408 SECURITY_DESCRIPTOR sec_desc;
409 char dir[ MAXPATHLEN ];
411 if (cp == NULL) abort ();
414 start.cb = sizeof (start);
417 if (NILP (Vwin32_start_process_show_window))
418 start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
420 start.dwFlags = STARTF_USESTDHANDLES;
421 start.wShowWindow = SW_HIDE;
423 start.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
424 start.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
425 start.hStdError = GetStdHandle (STD_ERROR_HANDLE);
426 #endif /* HAVE_NTGUI */
428 /* Explicitly specify no security */
429 if (!InitializeSecurityDescriptor (&sec_desc, SECURITY_DESCRIPTOR_REVISION))
431 if (!SetSecurityDescriptorDacl (&sec_desc, TRUE, NULL, FALSE))
433 sec_attrs.nLength = sizeof (sec_attrs);
434 sec_attrs.lpSecurityDescriptor = &sec_desc;
435 sec_attrs.bInheritHandle = FALSE;
437 strcpy (dir, process_dir);
438 unixtodos_filename (dir);
440 if (!CreateProcess (exe, cmdline, &sec_attrs, NULL, TRUE,
441 (!NILP (Vwin32_start_process_share_console)
442 ? CREATE_NEW_PROCESS_GROUP
443 : CREATE_NEW_CONSOLE),
445 &start, &cp->procinfo))
448 cp->pid = (int) cp->procinfo.dwProcessId;
450 CloseHandle (cp->procinfo.hThread);
451 CloseHandle (cp->procinfo.hProcess);
452 cp->procinfo.hThread=NULL;
453 cp->procinfo.hProcess=NULL;
455 /* pid must fit in a Lisp_Int */
463 DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError()););
468 /* Return pointer to section header for section containing the given
469 relative virtual address. */
470 static IMAGE_SECTION_HEADER *
471 rva_to_section (DWORD rva, IMAGE_NT_HEADERS * nt_header)
473 PIMAGE_SECTION_HEADER section;
476 section = IMAGE_FIRST_SECTION (nt_header);
478 for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
480 if (rva >= section->VirtualAddress
481 && rva < section->VirtualAddress + section->SizeOfRawData)
490 win32_executable_type (CONST char * filename, int * is_dos_app, int * is_cygnus_app)
492 file_data executable;
495 /* Default values in case we can't tell for sure. */
497 *is_cygnus_app = FALSE;
499 if (!open_input_file (&executable, filename))
502 p = strrchr (filename, '.');
504 /* We can only identify DOS .com programs from the extension. */
505 if (p && stricmp (p, ".com") == 0)
507 else if (p && (stricmp (p, ".bat") == 0 ||
508 stricmp (p, ".cmd") == 0))
510 /* A DOS shell script - it appears that CreateProcess is happy to
511 accept this (somewhat surprisingly); presumably it looks at
512 COMSPEC to determine what executable to actually invoke.
513 Therefore, we have to do the same here as well. */
514 /* Actually, I think it uses the program association for that
515 extension, which is defined in the registry. */
516 p = egetenv ("COMSPEC");
518 win32_executable_type (p, is_dos_app, is_cygnus_app);
522 /* Look for DOS .exe signature - if found, we must also check that
523 it isn't really a 16- or 32-bit Windows exe, since both formats
524 start with a DOS program stub. Note that 16-bit Windows
525 executables use the OS/2 1.x format. */
528 /* mingw32 doesn't have enough headers to detect cygwin
529 apps, just do what we can. */
532 exe_header = (FILHDR*) executable.file_base;
533 if (exe_header->e_magic != DOSMAGIC)
536 if ((char *) exe_header->e_lfanew > (char *) executable.size)
538 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */
541 else if (exe_header->nt_signature != NT_SIGNATURE)
546 IMAGE_DOS_HEADER * dos_header;
547 IMAGE_NT_HEADERS * nt_header;
549 dos_header = (PIMAGE_DOS_HEADER) executable.file_base;
550 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
553 nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew);
555 if ((char *) nt_header > (char *) dos_header + executable.size)
557 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */
560 else if (nt_header->Signature != IMAGE_NT_SIGNATURE &&
561 LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE)
565 else if (nt_header->Signature == IMAGE_NT_SIGNATURE)
567 /* Look for cygwin.dll in DLL import list. */
568 IMAGE_DATA_DIRECTORY import_dir =
569 nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
570 IMAGE_IMPORT_DESCRIPTOR * imports;
571 IMAGE_SECTION_HEADER * section;
573 section = rva_to_section (import_dir.VirtualAddress, nt_header);
574 imports = RVA_TO_PTR (import_dir.VirtualAddress, section, executable);
576 for ( ; imports->Name; imports++)
578 char * dllname = RVA_TO_PTR (imports->Name, section, executable);
580 if (strcmp (dllname, "cygwin.dll") == 0)
582 *is_cygnus_app = TRUE;
591 close_file_data (&executable);
595 compare_env (const void *strp1, const void *strp2)
597 const char *str1 = *(const char**)strp1, *str2 = *(const char**)strp2;
599 while (*str1 && *str2 && *str1 != '=' && *str2 != '=')
601 if ((*str1) > (*str2))
603 else if ((*str1) < (*str2))
608 if (*str1 == '=' && *str2 == '=')
610 else if (*str1 == '=')
617 merge_and_sort_env (char **envp1, char **envp2, char **new_envp)
633 qsort (new_envp, num, sizeof (char *), compare_env);
638 /* When a new child process is created we need to register it in our list,
639 so intercept spawn requests. */
641 sys_spawnve (int mode, CONST char *cmdname,
642 CONST char * CONST *argv, CONST char *CONST *envp)
644 Lisp_Object program, full;
645 char *cmdline, *env, *parg, **targ;
649 int is_dos_app, is_cygnus_app;
651 char escape_char = 0;
652 /* We pass our process ID to our children by setting up an environment
653 variable in their environment. */
654 char ppid_env_var_buffer[64];
655 char *extra_env[] = {ppid_env_var_buffer, NULL};
658 /* We don't care about the other modes */
659 if (mode != _P_NOWAIT)
665 /* Handle executable names without an executable suffix. */
666 program = make_string (cmdname, strlen (cmdname));
668 if (NILP (Ffile_executable_p (program)))
671 locate_file (Vexec_path, program, Vlisp_EXEC_SUFFIXES, &full, 1);
678 TO_EXTERNAL_FORMAT (LISP_STRING, full,
679 C_STRING_ALLOCA, cmdname,
684 (char*)cmdname = alloca (strlen (argv[0]) + 1);
685 strcpy ((char*)cmdname, argv[0]);
689 /* make sure argv[0] and cmdname are both in DOS format */
690 unixtodos_filename ((char*)cmdname);
692 ((CONST char**)argv)[0] = cmdname;
694 /* Determine whether program is a 16-bit DOS executable, or a Win32
695 executable that is implicitly linked to the Cygnus dll (implying it
696 was compiled with the Cygnus GNU toolchain and hence relies on
697 cygwin.dll to parse the command line - we use this to decide how to
698 escape quote chars in command line args that must be quoted). */
699 win32_executable_type (cmdname, &is_dos_app, &is_cygnus_app);
701 /* On Windows 95, if cmdname is a DOS app, we invoke a helper
702 application to start it by specifying the helper app as cmdname,
703 while leaving the real app name as argv[0]. */
706 cmdname = alloca (MAXPATHLEN);
707 if (egetenv ("CMDPROXY"))
708 strcpy ((char*)cmdname, egetenv ("CMDPROXY"));
711 strcpy ((char*)cmdname, XSTRING_DATA (Vinvocation_directory));
712 strcat ((char*)cmdname, "cmdproxy.exe");
714 unixtodos_filename ((char*)cmdname);
717 /* we have to do some conjuring here to put argv and envp into the
718 form CreateProcess wants... argv needs to be a space separated/null
719 terminated list of parameters, and envp is a null
720 separated/double-null terminated list of parameters.
722 Additionally, zero-length args and args containing whitespace or
723 quote chars need to be wrapped in double quotes - for this to work,
724 embedded quotes need to be escaped as well. The aim is to ensure
725 the child process reconstructs the argv array we start with
726 exactly, so we treat quotes at the beginning and end of arguments
729 The Win32 GNU-based library from Cygnus doubles quotes to escape
730 them, while MSVC uses backslash for escaping. (Actually the MSVC
731 startup code does attempt to recognize doubled quotes and accept
732 them, but gets it wrong and ends up requiring three quotes to get a
733 single embedded quote!) So by default we decide whether to use
734 quote or backslash as the escape character based on whether the
735 binary is apparently a Cygnus compiled app.
737 Note that using backslash to escape embedded quotes requires
738 additional special handling if an embedded quote is already
739 preceded by backslash, or if an arg requiring quoting ends with
740 backslash. In such cases, the run of escape characters needs to be
741 doubled. For consistency, we apply this special handling as long
742 as the escape character is not quote.
744 Since we have no idea how large argv and envp are likely to be we
745 figure out list lengths on the fly and allocate them. */
747 if (!NILP (Vwin32_quote_process_args))
750 /* Override escape char by binding win32-quote-process-args to
751 desired character, or use t for auto-selection. */
752 if (INTP (Vwin32_quote_process_args))
753 escape_char = XINT (Vwin32_quote_process_args);
755 escape_char = is_cygnus_app ? '"' : '\\';
765 int escape_char_run = 0;
773 /* allow for embedded quotes to be escaped */
776 /* handle the case where the embedded quote is already escaped */
777 if (escape_char_run > 0)
779 /* To preserve the arg exactly, we need to double the
780 preceding escape characters (plus adding one to
781 escape the quote character itself). */
782 arglen += escape_char_run;
785 else if (*p == ' ' || *p == '\t')
790 if (*p == escape_char && escape_char != '"')
798 /* handle the case where the arg ends with an escape char - we
799 must not let the enclosing quote be escaped. */
800 if (escape_char_run > 0)
801 arglen += escape_char_run;
803 arglen += strlen (*targ++) + 1;
805 cmdline = alloca (arglen);
819 if (*p == ' ' || *p == '\t' || *p == '"')
824 int escape_char_run = 0;
830 last = p + strlen (p) - 1;
833 /* This version does not escape quotes if they occur at the
834 beginning or end of the arg - this could lead to incorrect
835 behavior when the arg itself represents a command line
836 containing quoted args. I believe this was originally done
837 as a hack to make some things work, before
838 `win32-quote-process-args' was added. */
841 if (*p == '"' && p > first && p < last)
842 *parg++ = escape_char; /* escape embedded quotes */
850 /* double preceding escape chars if any */
851 while (escape_char_run > 0)
853 *parg++ = escape_char;
856 /* escape all quote chars, even at beginning or end */
857 *parg++ = escape_char;
861 if (*p == escape_char && escape_char != '"')
866 /* double escape chars before enclosing quote */
867 while (escape_char_run > 0)
869 *parg++ = escape_char;
877 strcpy (parg, *targ);
878 parg += strlen (*targ);
888 numenv = 1; /* for end null */
891 arglen += strlen (*targ++) + 1;
894 /* extra env vars... */
895 sprintf (ppid_env_var_buffer, "__PARENT_PROCESS_ID=%d",
896 GetCurrentProcessId ());
897 arglen += strlen (ppid_env_var_buffer) + 1;
900 /* merge env passed in and extra env into one, and sort it. */
901 targ = (char **) alloca (numenv * sizeof (char *));
902 merge_and_sort_env ((char**)envp, extra_env, targ);
904 /* concatenate env entries. */
905 env = alloca (arglen);
909 strcpy (parg, *targ);
910 parg += strlen (*targ++);
923 /* Now create the process. */
924 if (!create_child (cmdname, cmdline, env, &pid, cp))
934 /* Substitute for certain kill () operations */
937 find_child_console (HWND hwnd, child_process * cp)
942 thread_id = GetWindowThreadProcessId (hwnd, &process_id);
943 if (process_id == cp->procinfo.dwProcessId)
945 char window_class[32];
947 GetClassName (hwnd, window_class, sizeof (window_class));
948 if (strcmp (window_class,
951 : "ConsoleWindowClass") == 0)
962 sys_kill (int pid, int sig)
966 int need_to_free = 0;
969 /* Only handle signals that will result in the process dying */
970 if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP)
976 cp = find_child_pid (pid);
979 proc_hand = OpenProcess (PROCESS_TERMINATE, 0, pid);
980 if (proc_hand == NULL)
989 proc_hand = cp->procinfo.hProcess;
990 pid = cp->procinfo.dwProcessId;
992 /* Try to locate console window for process. */
993 EnumWindows ((WNDENUMPROC)find_child_console, (LPARAM) cp);
998 if (NILP (Vwin32_start_process_share_console) && cp && cp->hwnd)
1000 BYTE control_scan_code = (BYTE) MapVirtualKey (VK_CONTROL, 0);
1001 BYTE vk_break_code = VK_CANCEL;
1002 BYTE break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0);
1003 HWND foreground_window;
1005 if (break_scan_code == 0)
1007 /* Fake Ctrl-C if we can't manage Ctrl-Break. */
1008 vk_break_code = 'C';
1009 break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0);
1012 foreground_window = GetForegroundWindow ();
1013 if (foreground_window && SetForegroundWindow (cp->hwnd))
1015 /* Generate keystrokes as if user had typed Ctrl-Break or Ctrl-C. */
1016 keybd_event (VK_CONTROL, control_scan_code, 0, 0);
1017 keybd_event (vk_break_code, break_scan_code, 0, 0);
1018 keybd_event (vk_break_code, break_scan_code, KEYEVENTF_KEYUP, 0);
1019 keybd_event (VK_CONTROL, control_scan_code, KEYEVENTF_KEYUP, 0);
1021 /* Sleep for a bit to give time for Emacs frame to respond
1022 to focus change events (if Emacs was active app). */
1025 SetForegroundWindow (foreground_window);
1028 /* Ctrl-Break is NT equivalent of SIGINT. */
1029 else if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid))
1031 DebPrint (("sys_kill.GenerateConsoleCtrlEvent return %d "
1032 "for pid %lu\n", GetLastError (), pid));
1039 if (NILP (Vwin32_start_process_share_console) && cp && cp->hwnd)
1045 Another possibility is to try terminating the VDM out-right by
1046 calling the Shell VxD (id 0x17) V86 interface, function #4
1047 "SHELL_Destroy_VM", ie.
1053 First need to determine the current VM handle, and then arrange for
1054 the shellapi call to be made from the system vm (by using
1055 Switch_VM_and_callback).
1057 Could try to invoke DestroyVM through CallVxD.
1061 /* On Win95, posting WM_QUIT causes the 16-bit subsystem
1062 to hang when cmdproxy is used in conjunction with
1063 command.com for an interactive shell. Posting
1064 WM_CLOSE pops up a dialog that, when Yes is selected,
1065 does the same thing. TerminateProcess is also less
1066 than ideal in that subprocesses tend to stick around
1067 until the machine is shutdown, but at least it
1068 doesn't freeze the 16-bit subsystem. */
1069 PostMessage (cp->hwnd, WM_QUIT, 0xff, 0);
1071 if (!TerminateProcess (proc_hand, 0xff))
1073 DebPrint (("sys_kill.TerminateProcess returned %d "
1074 "for pid %lu\n", GetLastError (), pid));
1081 PostMessage (cp->hwnd, WM_CLOSE, 0, 0);
1083 /* Kill the process. On Win32 this doesn't kill child processes
1084 so it doesn't work very well for shells which is why it's not
1085 used in every case. */
1086 else if (!TerminateProcess (proc_hand, 0xff))
1088 DebPrint (("sys_kill.TerminateProcess returned %d "
1089 "for pid %lu\n", GetLastError (), pid));
1096 CloseHandle (proc_hand);
1102 /* Sync with FSF Emacs 19.34.6 note: ifdef'ed out in XEmacs */
1103 extern int report_file_error (CONST char *, Lisp_Object);
1105 /* The following two routines are used to manipulate stdin, stdout, and
1106 stderr of our child processes.
1108 Assuming that in, out, and err are *not* inheritable, we make them
1109 stdin, stdout, and stderr of the child as follows:
1111 - Save the parent's current standard handles.
1112 - Set the std handles to inheritable duplicates of the ones being passed in.
1113 (Note that _get_osfhandle() is an io.h procedure that retrieves the
1114 NT file handle for a crt file descriptor.)
1115 - Spawn the child, which inherits in, out, and err as stdin,
1116 stdout, and stderr. (see Spawnve)
1117 - Close the std handles passed to the child.
1118 - Reset the parent's standard handles to the saved handles.
1119 (see reset_standard_handles)
1120 We assume that the caller closes in, out, and err after calling us. */
1123 prepare_standard_handles (int in, int out, int err, HANDLE handles[3])
1126 HANDLE newstdin, newstdout, newstderr;
1128 parent = GetCurrentProcess ();
1130 handles[0] = GetStdHandle (STD_INPUT_HANDLE);
1131 handles[1] = GetStdHandle (STD_OUTPUT_HANDLE);
1132 handles[2] = GetStdHandle (STD_ERROR_HANDLE);
1134 /* make inheritable copies of the new handles */
1135 if (!DuplicateHandle (parent,
1136 (HANDLE) _get_osfhandle (in),
1141 DUPLICATE_SAME_ACCESS))
1142 report_file_error ("Duplicating input handle for child", Qnil);
1144 if (!DuplicateHandle (parent,
1145 (HANDLE) _get_osfhandle (out),
1150 DUPLICATE_SAME_ACCESS))
1151 report_file_error ("Duplicating output handle for child", Qnil);
1153 if (!DuplicateHandle (parent,
1154 (HANDLE) _get_osfhandle (err),
1159 DUPLICATE_SAME_ACCESS))
1160 report_file_error ("Duplicating error handle for child", Qnil);
1162 /* and store them as our std handles */
1163 if (!SetStdHandle (STD_INPUT_HANDLE, newstdin))
1164 report_file_error ("Changing stdin handle", Qnil);
1166 if (!SetStdHandle (STD_OUTPUT_HANDLE, newstdout))
1167 report_file_error ("Changing stdout handle", Qnil);
1169 if (!SetStdHandle (STD_ERROR_HANDLE, newstderr))
1170 report_file_error ("Changing stderr handle", Qnil);
1174 reset_standard_handles (int in, int out, int err, HANDLE handles[3])
1176 /* close the duplicated handles passed to the child */
1177 CloseHandle (GetStdHandle (STD_INPUT_HANDLE));
1178 CloseHandle (GetStdHandle (STD_OUTPUT_HANDLE));
1179 CloseHandle (GetStdHandle (STD_ERROR_HANDLE));
1181 /* now restore parent's saved std handles */
1182 SetStdHandle (STD_INPUT_HANDLE, handles[0]);
1183 SetStdHandle (STD_OUTPUT_HANDLE, handles[1]);
1184 SetStdHandle (STD_ERROR_HANDLE, handles[2]);
1188 set_process_dir (const char * dir)
1193 /* Some miscellaneous functions that are Windows specific, but not GUI
1194 specific (ie. are applicable in terminal or batch mode as well). */
1196 /* lifted from fileio.c */
1197 #define CORRECT_DIR_SEPS(s) \
1198 do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \
1199 else unixtodos_filename (s); \
1202 DEFUN ("win32-short-file-name", Fwin32_short_file_name, 1, 1, "", /*
1203 Return the short file name version (8.3) of the full path of FILENAME.
1204 If FILENAME does not exist, return nil.
1205 All path elements in FILENAME are converted to their short names.
1209 char shortname[MAX_PATH];
1211 CHECK_STRING (filename);
1213 /* first expand it. */
1214 filename = Fexpand_file_name (filename, Qnil);
1216 /* luckily, this returns the short version of each element in the path. */
1217 if (GetShortPathName (XSTRING_DATA (filename), shortname, MAX_PATH) == 0)
1220 CORRECT_DIR_SEPS (shortname);
1222 return build_string (shortname);
1226 DEFUN ("win32-long-file-name", Fwin32_long_file_name, 1, 1, "", /*
1227 Return the long file name version of the full path of FILENAME.
1228 If FILENAME does not exist, return nil.
1229 All path elements in FILENAME are converted to their long names.
1233 char longname[ MAX_PATH ];
1235 CHECK_STRING (filename);
1237 /* first expand it. */
1238 filename = Fexpand_file_name (filename, Qnil);
1240 if (!win32_get_long_filename (XSTRING_DATA (filename), longname, MAX_PATH))
1243 CORRECT_DIR_SEPS (longname);
1245 return build_string (longname);
1248 DEFUN ("win32-set-process-priority", Fwin32_set_process_priority, 2, 2, "", /*
1249 Set the priority of PROCESS to PRIORITY.
1250 If PROCESS is nil, the priority of Emacs is changed, otherwise the
1251 priority of the process whose pid is PROCESS is changed.
1252 PRIORITY should be one of the symbols high, normal, or low;
1253 any other symbol will be interpreted as normal.
1255 If successful, the return value is t, otherwise nil.
1257 (process, priority))
1259 HANDLE proc_handle = GetCurrentProcess ();
1260 DWORD priority_class = NORMAL_PRIORITY_CLASS;
1261 Lisp_Object result = Qnil;
1263 CHECK_SYMBOL (priority);
1265 if (!NILP (process))
1270 CHECK_INT (process);
1272 /* Allow pid to be an internally generated one, or one obtained
1273 externally. This is necessary because real pids on Win95 are
1276 pid = XINT (process);
1277 cp = find_child_pid (pid);
1279 pid = cp->procinfo.dwProcessId;
1281 proc_handle = OpenProcess (PROCESS_SET_INFORMATION, FALSE, pid);
1284 if (EQ (priority, Qhigh))
1285 priority_class = HIGH_PRIORITY_CLASS;
1286 else if (EQ (priority, Qlow))
1287 priority_class = IDLE_PRIORITY_CLASS;
1289 if (proc_handle != NULL)
1291 if (SetPriorityClass (proc_handle, priority_class))
1293 if (!NILP (process))
1294 CloseHandle (proc_handle);
1301 DEFUN ("win32-get-locale-info", Fwin32_get_locale_info, 1, 2, "", /*
1302 "Return information about the Windows locale LCID.
1303 By default, return a three letter locale code which encodes the default
1304 language as the first two characters, and the country or regional variant
1305 as the third letter. For example, ENU refers to `English (United States)',
1306 while ENC means `English (Canadian)'.
1308 If the optional argument LONGFORM is non-nil, the long form of the locale
1309 name is returned, e.g. `English (United States)' instead.
1311 If LCID (a 16-bit number) is not a valid locale, the result is nil.
1317 char abbrev_name[32] = { 0 };
1318 char full_name[256] = { 0 };
1322 if (!IsValidLocale (XINT (lcid), LCID_SUPPORTED))
1325 if (NILP (longform))
1327 got_abbrev = GetLocaleInfo (XINT (lcid),
1328 LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
1329 abbrev_name, sizeof (abbrev_name));
1331 return build_string (abbrev_name);
1335 got_full = GetLocaleInfo (XINT (lcid),
1336 LOCALE_SLANGUAGE | LOCALE_USE_CP_ACP,
1337 full_name, sizeof (full_name));
1339 return build_string (full_name);
1346 DEFUN ("win32-get-current-locale-id", Fwin32_get_current_locale_id, 0, 0, "", /*
1347 "Return Windows locale id for current locale setting.
1348 This is a numerical value; use `win32-get-locale-info' to convert to a
1349 human-readable form.
1353 return make_int (GetThreadLocale ());
1357 DEFUN ("win32-get-default-locale-id", Fwin32_get_default_locale_id, 0, 1, "", /*
1358 "Return Windows locale id for default locale setting.
1359 By default, the system default locale setting is returned; if the optional
1360 parameter USERP is non-nil, the user default locale setting is returned.
1361 This is a numerical value; use `win32-get-locale-info' to convert to a
1362 human-readable form.
1367 return make_int (GetSystemDefaultLCID ());
1368 return make_int (GetUserDefaultLCID ());
1371 DWORD int_from_hex (char * s)
1374 static char hex[] = "0123456789abcdefABCDEF";
1377 while (*s && (p = strchr(hex, *s)) != NULL)
1379 unsigned digit = p - hex;
1382 val = val * 16 + digit;
1388 /* We need to build a global list, since the EnumSystemLocale callback
1389 function isn't given a context pointer. */
1390 Lisp_Object Vwin32_valid_locale_ids;
1392 BOOL CALLBACK enum_locale_fn (LPTSTR localeNum)
1394 DWORD id = int_from_hex (localeNum);
1395 Vwin32_valid_locale_ids = Fcons (make_int (id), Vwin32_valid_locale_ids);
1399 DEFUN ("win32-get-valid-locale-ids", Fwin32_get_valid_locale_ids, 0, 0, "", /*
1400 Return list of all valid Windows locale ids.
1401 Each id is a numerical value; use `win32-get-locale-info' to convert to a
1402 human-readable form.
1406 Vwin32_valid_locale_ids = Qnil;
1408 EnumSystemLocales (enum_locale_fn, LCID_SUPPORTED);
1410 Vwin32_valid_locale_ids = Fnreverse (Vwin32_valid_locale_ids);
1411 return Vwin32_valid_locale_ids;
1415 DEFUN ("win32-set-current-locale", Fwin32_set_current_locale, 1, 1, "", /*
1416 Make Windows locale LCID be the current locale setting for Emacs.
1417 If successful, the new locale id is returned, otherwise nil.
1423 if (!IsValidLocale (XINT (lcid), LCID_SUPPORTED))
1426 if (!SetThreadLocale (XINT (lcid)))
1429 /* Sync with FSF Emacs 19.34.6 note: dwWinThreadId declared in
1430 w32term.h and defined in w32fns.c, both of which are not in current
1431 XEmacs. #### Check what we lose by ifdef'ing out these. --marcpa */
1433 /* Need to set input thread locale if present. */
1435 /* Reply is not needed. */
1436 PostThreadMessage (dwWinThreadId, WM_EMACS_SETLOCALE, XINT (lcid), 0);
1439 return make_int (GetThreadLocale ());
1446 DEFSUBR (Fwin32_short_file_name);
1447 DEFSUBR (Fwin32_long_file_name);
1448 DEFSUBR (Fwin32_set_process_priority);
1449 DEFSUBR (Fwin32_get_locale_info);
1450 DEFSUBR (Fwin32_get_current_locale_id);
1451 DEFSUBR (Fwin32_get_default_locale_id);
1452 DEFSUBR (Fwin32_get_valid_locale_ids);
1453 DEFSUBR (Fwin32_set_current_locale);
1458 vars_of_ntproc (void)
1460 defsymbol (&Qhigh, "high");
1461 defsymbol (&Qlow, "low");
1463 DEFVAR_LISP ("win32-quote-process-args", &Vwin32_quote_process_args /*
1464 Non-nil enables quoting of process arguments to ensure correct parsing.
1465 Because Windows does not directly pass argv arrays to child processes,
1466 programs have to reconstruct the argv array by parsing the command
1467 line string. For an argument to contain a space, it must be enclosed
1468 in double quotes or it will be parsed as multiple arguments.
1470 If the value is a character, that character will be used to escape any
1471 quote characters that appear, otherwise a suitable escape character
1472 will be chosen based on the type of the program.
1474 Vwin32_quote_process_args = Qt;
1476 DEFVAR_LISP ("win32-start-process-show-window",
1477 &Vwin32_start_process_show_window /*
1478 When nil, processes started via start-process hide their windows.
1479 When non-nil, they show their window in the method of their choice.
1481 Vwin32_start_process_show_window = Qnil;
1483 DEFVAR_LISP ("win32-start-process-share-console",
1484 &Vwin32_start_process_share_console /*
1485 When nil, processes started via start-process are given a new console.
1486 When non-nil, they share the Emacs console; this has the limitation of
1487 allowing only only DOS subprocess to run at a time (whether started directly
1488 or indirectly by Emacs), and preventing Emacs from cleanly terminating the
1489 subprocess group, but may allow Emacs to interrupt a subprocess that doesn't
1490 otherwise respond to interrupts from Emacs.
1492 Vwin32_start_process_share_console = Qt;
1494 DEFVAR_LISP ("win32-pipe-read-delay", &Vwin32_pipe_read_delay /*
1495 Forced delay before reading subprocess output.
1496 This is done to improve the buffering of subprocess output, by
1497 avoiding the inefficiency of frequently reading small amounts of data.
1499 If positive, the value is the number of milliseconds to sleep before
1500 reading the subprocess output. If negative, the magnitude is the number
1501 of time slices to wait (effectively boosting the priority of the child
1502 process temporarily). A value of zero disables waiting entirely.
1504 Vwin32_pipe_read_delay = make_int (50);
1507 DEFVAR_LISP ("win32-generate-fake-inodes", &Vwin32_generate_fake_inodes /*
1508 "Non-nil means attempt to fake realistic inode values.
1509 This works by hashing the truename of files, and should detect
1510 aliasing between long and short (8.3 DOS) names, but can have
1511 false positives because of hash collisions. Note that determining
1512 the truename of a file can be slow.
1514 Vwin32_generate_fake_inodes = Qnil;
1518 /* end of ntproc.c */