This commit was generated by cvs2svn to compensate for changes in r1383,
[chise/xemacs-chise.git.1] / src / ntproc.c
1 /* Process support for Windows NT port of XEMACS.
2    Copyright (C) 1992, 1995 Free Software Foundation, Inc.
3
4 This file is part of XEmacs.
5
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
9 later version.
10
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
14 for more details.
15
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.
20
21    Drew Bliss                   Oct 14, 1993
22      Adapted from alarm.c by Tim Fleehart */
23
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> */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <io.h>
31 #include <fcntl.h>
32 #include <signal.h>
33
34 /* must include CRT headers *before* config.h */
35 /* #### I don't believe it - martin */
36 #include <config.h>
37 #undef signal
38 #undef wait
39 #undef spawnve
40 #undef select
41 #undef kill
42
43 #include <windows.h>
44 #include <sys/socket.h>
45 #ifdef HAVE_A_OUT_H
46 #include <a.out.h>
47 #endif
48 #include "lisp.h"
49 #include "sysproc.h"
50 #include "nt.h"
51 #include "ntheap.h" /* From 19.34.6 */
52 #include "systime.h"
53 #include "syssignal.h"
54 #include "sysfile.h"
55 #include "syswait.h"
56 #include "buffer.h"
57 #include "process.h"
58 /*#include "w32term.h"*/ /* From 19.34.6: sync in ? --marcpa */
59
60 /* #### I'm not going to play with shit. */
61 #pragma warning (disable:4013 4024 4090)
62
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;
68
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;
72
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;
78
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;
84
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;
90
91 Lisp_Object Qhigh, Qlow;
92
93 extern Lisp_Object Vlisp_EXEC_SUFFIXES;
94
95 #ifndef DEBUG_XEMACS
96 __inline
97 #endif
98 void _DebPrint (const char *fmt, ...)
99 {
100 #ifdef DEBUG_XEMACS
101   char buf[1024];
102   va_list args;
103
104   va_start (args, fmt);
105   vsprintf (buf, fmt, args);
106   va_end (args);
107   OutputDebugString (buf);
108 #endif
109 }
110
111 /* sys_signal moved to nt.c. It's now called msw_signal... */
112
113 /* Defined in <process.h> which conflicts with the local copy */
114 #define _P_NOWAIT 1
115
116 /* Child process management list.  */
117 int child_proc_count = 0;
118 child_process child_procs[ MAX_CHILDREN ];
119 child_process *dead_child = NULL;
120
121 DWORD WINAPI reader_thread (void *arg);
122
123 /* Determine if running on Windows 9x and not NT */
124 static int
125 windows9x_p (void)
126 {
127   return GetVersion () & 0x80000000;
128 }
129
130 /* Find an unused process slot.  */
131 child_process *
132 new_child (void)
133 {
134   child_process *cp;
135   DWORD id;
136   
137   for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
138     if (!CHILD_ACTIVE (cp))
139       goto Initialize;
140   if (child_proc_count == MAX_CHILDREN)
141     return NULL;
142   cp = &child_procs[child_proc_count++];
143
144  Initialize:
145   xzero (*cp);
146   cp->fd = -1;
147   cp->pid = -1;
148   if (cp->procinfo.hProcess)
149     CloseHandle(cp->procinfo.hProcess);
150   cp->procinfo.hProcess = NULL;
151   cp->status = STATUS_READ_ERROR;
152
153   /* use manual reset event so that select() will function properly */
154   cp->char_avail = CreateEvent (NULL, TRUE, FALSE, NULL);
155   if (cp->char_avail)
156     {
157       cp->char_consumed = CreateEvent (NULL, FALSE, FALSE, NULL);
158       if (cp->char_consumed)
159         {
160           cp->thrd = CreateThread (NULL, 1024, reader_thread, cp, 0, &id);
161           if (cp->thrd)
162             return cp;
163         }
164     }
165   delete_child (cp);
166   return NULL;
167 }
168
169 void 
170 delete_child (child_process *cp)
171 {
172   int i;
173
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)
177       abort ();
178
179   if (!CHILD_ACTIVE (cp))
180     return;
181
182   /* reap thread if necessary */
183   if (cp->thrd)
184     {
185       DWORD rc;
186
187       if (GetExitCodeThread (cp->thrd, &rc) && rc == STILL_ACTIVE)
188         {
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)
193             {
194               DebPrint (("delete_child.WaitForSingleObject (thread) failed "
195                          "with %lu for fd %ld\n", GetLastError (), cp->fd));
196               TerminateThread (cp->thrd, 0);
197             }
198         }
199       CloseHandle (cp->thrd);
200       cp->thrd = NULL;
201     }
202   if (cp->char_avail)
203     {
204       CloseHandle (cp->char_avail);
205       cp->char_avail = NULL;
206     }
207   if (cp->char_consumed)
208     {
209       CloseHandle (cp->char_consumed);
210       cp->char_consumed = NULL;
211     }
212
213   /* update child_proc_count (highest numbered slot in use plus one) */
214   if (cp == child_procs + child_proc_count - 1)
215     {
216       for (i = child_proc_count-1; i >= 0; i--)
217         if (CHILD_ACTIVE (&child_procs[i]))
218           {
219             child_proc_count = i + 1;
220             break;
221           }
222     }
223   if (i < 0)
224     child_proc_count = 0;
225 }
226
227 /* Find a child by pid.  */
228 static child_process *
229 find_child_pid (DWORD pid)
230 {
231   child_process *cp;
232
233   for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
234     if (CHILD_ACTIVE (cp) && pid == cp->pid)
235       return cp;
236   return NULL;
237 }
238
239 /* Function to do blocking read of one byte, needed to implement
240    select.  It is only allowed on sockets and pipes. */
241 static int
242 _sys_read_ahead (int fd)
243 {
244   child_process * cp;
245   int rc = 0;
246
247   if (fd < 0 || fd >= MAXDESC)
248     return STATUS_READ_ERROR;
249
250   cp = fd_info[fd].cp;
251
252   if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
253     return STATUS_READ_ERROR;
254
255   if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
256       || (fd_info[fd].flags & FILE_READ) == 0)
257     {
258       /* fd is not a pipe or socket */
259       abort ();
260     }
261   
262   cp->status = STATUS_READ_IN_PROGRESS;
263   
264   if (fd_info[fd].flags & FILE_PIPE)
265     {
266       rc = _read (fd, &cp->chr, sizeof (char));
267
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. */
275       if (rc > 0)
276         {
277           int wait = XINT (Vwin32_pipe_read_delay);
278
279           if (wait > 0)
280             Sleep (wait);
281           else if (wait < 0)
282             while (++wait <= 0)
283               /* Yield remainder of our time slice, effectively giving a
284                  temporary priority boost to the child process. */
285               Sleep (0);
286         }
287     }
288
289   if (rc == sizeof (char))
290     cp->status = STATUS_READ_SUCCEEDED;
291   else
292     cp->status = STATUS_READ_FAILED;
293
294   return cp->status;
295 }
296
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. */
301 DWORD WINAPI 
302 reader_thread (void *arg)
303 {
304   child_process *cp;
305   
306   /* Our identity */
307   cp = (child_process *)arg;
308   
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! */
312
313   /*
314   if (cp == NULL ||
315       WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
316   */
317
318   if (cp == NULL)
319   {
320       return 1;
321   }
322
323   for (;;)
324     {
325       int rc;
326
327       rc = _sys_read_ahead (cp->fd);
328
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))
332         {
333           DebPrint (("reader_thread.SetEvent failed with %lu for fd %ld\n",
334                      GetLastError (), cp->fd));
335           return 1;
336         }
337
338       if (rc == STATUS_READ_ERROR)
339       {
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;
345         }
346         if (cp->thrd) {
347           CloseHandle (cp->thrd);
348           cp->thrd = NULL;
349         }
350         if (cp->char_consumed) {
351           CloseHandle(cp->char_consumed);
352           cp->char_consumed = NULL;
353         }
354         if (cp->procinfo.hProcess)
355         {
356           CloseHandle (cp->procinfo.hProcess);
357           cp->procinfo.hProcess=NULL;
358         }
359         return 1;
360       }
361         
362       /* If the read died, the child has died so let the thread die */
363       if (rc == STATUS_READ_FAILED)
364         break;
365         
366       /* Wait until our input is acknowledged before reading again */
367       if (WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
368         {
369           DebPrint (("reader_thread.WaitForSingleObject failed with "
370                      "%lu for fd %ld\n", GetLastError (), cp->fd));
371           break;
372         }
373     }
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;
379   }
380   if (cp->thrd) {
381     CloseHandle (cp->thrd);
382     cp->thrd = NULL;
383   }
384   if (cp->char_consumed) {
385     CloseHandle(cp->char_consumed);
386     cp->char_consumed = NULL;
387   }
388   if (cp->procinfo.hProcess)
389   {
390     CloseHandle (cp->procinfo.hProcess);
391     cp->procinfo.hProcess=NULL;
392   }
393   
394   return 0;
395 }
396
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;
401
402 static BOOL 
403 create_child (const char *exe, char *cmdline, char *env,
404               int * pPid, child_process *cp)
405 {
406   STARTUPINFO start;
407   SECURITY_ATTRIBUTES sec_attrs;
408   SECURITY_DESCRIPTOR sec_desc;
409   char dir[ MAXPATHLEN ];
410   
411   if (cp == NULL) abort ();
412   
413   xzero (start);
414   start.cb = sizeof (start);
415   
416 #ifdef HAVE_NTGUI
417   if (NILP (Vwin32_start_process_show_window))
418   start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
419   else
420     start.dwFlags = STARTF_USESTDHANDLES;
421   start.wShowWindow = SW_HIDE;
422
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 */
427
428   /* Explicitly specify no security */
429   if (!InitializeSecurityDescriptor (&sec_desc, SECURITY_DESCRIPTOR_REVISION))
430     goto EH_Fail;
431   if (!SetSecurityDescriptorDacl (&sec_desc, TRUE, NULL, FALSE))
432     goto EH_Fail;
433   sec_attrs.nLength = sizeof (sec_attrs);
434   sec_attrs.lpSecurityDescriptor = &sec_desc;
435   sec_attrs.bInheritHandle = FALSE;
436   
437   strcpy (dir, process_dir);
438   unixtodos_filename (dir);
439   
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),
444                       env, dir,
445                       &start, &cp->procinfo))
446     goto EH_Fail;
447
448   cp->pid = (int) cp->procinfo.dwProcessId;
449
450   CloseHandle (cp->procinfo.hThread);
451   CloseHandle (cp->procinfo.hProcess);
452   cp->procinfo.hThread=NULL;
453   cp->procinfo.hProcess=NULL;
454
455   /* pid must fit in a Lisp_Int */
456
457
458   *pPid = cp->pid;
459   
460   return TRUE;
461   
462  EH_Fail:
463   DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError()););
464   return FALSE;
465 }
466
467 #ifndef __MINGW32__
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)
472 {
473   PIMAGE_SECTION_HEADER section;
474   int i;
475
476   section = IMAGE_FIRST_SECTION (nt_header);
477
478   for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
479     {
480       if (rva >= section->VirtualAddress
481           && rva < section->VirtualAddress + section->SizeOfRawData)
482         return section;
483       section++;
484     }
485   return NULL;
486 }
487 #endif
488
489 void
490 win32_executable_type (const char * filename, int * is_dos_app, int * is_cygnus_app)
491 {
492   file_data executable;
493   char * p;
494
495   /* Default values in case we can't tell for sure.  */
496   *is_dos_app = FALSE;
497   *is_cygnus_app = FALSE;
498
499   if (!open_input_file (&executable, filename))
500     return;
501
502   p = strrchr (filename, '.');
503
504       /* We can only identify DOS .com programs from the extension. */
505       if (p && stricmp (p, ".com") == 0)
506     *is_dos_app = TRUE;
507   else if (p && (stricmp (p, ".bat") == 0 ||
508                  stricmp (p, ".cmd") == 0))
509     {
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");
517       if (p)
518         win32_executable_type (p, is_dos_app, is_cygnus_app);
519     }
520       else
521         {
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. */
526
527 #ifdef __MINGW32__
528           /* mingw32 doesn't have enough headers to detect cygwin
529              apps, just do what we can. */
530           FILHDR * exe_header;
531
532           exe_header = (FILHDR*) executable.file_base;
533           if (exe_header->e_magic != DOSMAGIC)
534             goto unwind;
535
536           if ((char*) exe_header->e_lfanew > (char*) executable.size)
537             {
538               /* Some dos headers (pkunzip) have bogus e_lfanew fields.  */
539               *is_dos_app = TRUE;
540             } 
541           else if (exe_header->nt_signature != NT_SIGNATURE)
542             {
543               *is_dos_app = TRUE;
544             }
545 #else
546           IMAGE_DOS_HEADER * dos_header;
547           IMAGE_NT_HEADERS * nt_header;
548
549           dos_header = (PIMAGE_DOS_HEADER) executable.file_base;
550           if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
551             goto unwind;
552           
553           nt_header = (PIMAGE_NT_HEADERS) ((char*) dos_header + dos_header->e_lfanew);
554           
555           if ((char*) nt_header > (char*) dos_header + executable.size) 
556             {
557               /* Some dos headers (pkunzip) have bogus e_lfanew fields.  */
558               *is_dos_app = TRUE;
559             } 
560           else if (nt_header->Signature != IMAGE_NT_SIGNATURE &&
561                    LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE)
562             {
563               *is_dos_app = TRUE;
564             }
565           else if (nt_header->Signature == IMAGE_NT_SIGNATURE)
566             {
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;
572
573               section = rva_to_section (import_dir.VirtualAddress, nt_header);
574               imports = (IMAGE_IMPORT_DESCRIPTOR *) RVA_TO_PTR (import_dir.VirtualAddress,
575                                                                 section, executable);
576               
577               for ( ; imports->Name; imports++)
578                 {
579                   char *dllname = (char*) RVA_TO_PTR (imports->Name, section, executable);
580
581                   if (strcmp (dllname, "cygwin.dll") == 0)
582                     {
583                       *is_cygnus_app = TRUE;
584                       break;
585                     }
586                 }
587             }
588 #endif
589         }
590
591  unwind:
592       close_file_data (&executable);
593 }
594
595 int
596 compare_env (const void *strp1, const void *strp2)
597 {
598   const char *str1 = *(const char**)strp1, *str2 = *(const char**)strp2;
599
600   while (*str1 && *str2 && *str1 != '=' && *str2 != '=')
601     {
602       if ((*str1) > (*str2))
603         return 1;
604       else if ((*str1) < (*str2))
605         return -1;
606       str1++, str2++;
607     }
608
609   if (*str1 == '=' && *str2 == '=')
610     return 0;
611   else if (*str1 == '=')
612     return -1;
613   else
614     return 1;
615 }
616
617 void
618 merge_and_sort_env (char **envp1, char **envp2, char **new_envp)
619 {
620   char **optr, **nptr;
621   int num;
622
623   nptr = new_envp;
624   optr = envp1;
625   while (*optr)
626     *nptr++ = *optr++;
627   num = optr - envp1;
628
629   optr = envp2;
630   while (*optr)
631     *nptr++ = *optr++;
632   num += optr - envp2;
633
634   qsort (new_envp, num, sizeof (char*), compare_env);
635
636   *nptr = NULL;
637 }
638
639 /* When a new child process is created we need to register it in our list,
640    so intercept spawn requests.  */
641 int 
642 sys_spawnve (int mode, const char *cmdname,
643              const char * const *argv, const char *const *envp)
644 {
645   Lisp_Object program, full;
646   char *cmdline, *env, *parg, **targ;
647   int arglen, numenv;
648   int pid;
649   child_process *cp;
650   int is_dos_app, is_cygnus_app;
651   int do_quoting = 0;
652   char escape_char = 0;
653   /* We pass our process ID to our children by setting up an environment
654      variable in their environment.  */
655   char ppid_env_var_buffer[64];
656   char *extra_env[] = {ppid_env_var_buffer, NULL};
657   struct gcpro gcpro1;
658     
659   /* We don't care about the other modes */
660   if (mode != _P_NOWAIT)
661     {
662       errno = EINVAL;
663       return -1;
664     }
665
666   /* Handle executable names without an executable suffix.  */
667   program = make_string (cmdname, strlen (cmdname));
668   GCPRO1 (program);
669   if (NILP (Ffile_executable_p (program)))
670     {
671       full = Qnil;
672       locate_file (Vexec_path, program, Vlisp_EXEC_SUFFIXES, &full, 1);
673       if (NILP (full))
674         {
675           UNGCPRO;
676           errno = EINVAL;
677           return -1;
678         }
679       TO_EXTERNAL_FORMAT (LISP_STRING, full,
680                           C_STRING_ALLOCA, cmdname,
681                           Qfile_name);
682     }
683   else
684     {
685       cmdname = (char*)alloca (strlen (argv[0]) + 1);
686       strcpy ((char*)cmdname, argv[0]);
687     }
688   UNGCPRO;
689
690   /* make sure argv[0] and cmdname are both in DOS format */
691   unixtodos_filename ((char*)cmdname);
692   /* #### KLUDGE */
693   ((const char**)argv)[0] = cmdname;
694
695   /* Determine whether program is a 16-bit DOS executable, or a Win32
696      executable that is implicitly linked to the Cygnus dll (implying it
697      was compiled with the Cygnus GNU toolchain and hence relies on
698      cygwin.dll to parse the command line - we use this to decide how to
699      escape quote chars in command line args that must be quoted). */
700   win32_executable_type (cmdname, &is_dos_app, &is_cygnus_app);
701
702   /* On Windows 95, if cmdname is a DOS app, we invoke a helper
703      application to start it by specifying the helper app as cmdname,
704      while leaving the real app name as argv[0].  */
705   if (is_dos_app)
706     {
707       cmdname = (char*) alloca (MAXPATHLEN);
708       if (egetenv ("CMDPROXY"))
709         strcpy ((char*)cmdname, egetenv ("CMDPROXY"));
710       else
711     {
712           strcpy ((char*)cmdname, XSTRING_DATA (Vinvocation_directory));
713           strcat ((char*)cmdname, "cmdproxy.exe");
714         }
715       unixtodos_filename ((char*)cmdname);
716     }
717   
718   /* we have to do some conjuring here to put argv and envp into the
719      form CreateProcess wants...  argv needs to be a space separated/null
720      terminated list of parameters, and envp is a null
721      separated/double-null terminated list of parameters.
722
723      Additionally, zero-length args and args containing whitespace or
724      quote chars need to be wrapped in double quotes - for this to work,
725      embedded quotes need to be escaped as well.  The aim is to ensure
726      the child process reconstructs the argv array we start with
727      exactly, so we treat quotes at the beginning and end of arguments
728      as embedded quotes.
729
730      The Win32 GNU-based library from Cygnus doubles quotes to escape
731      them, while MSVC uses backslash for escaping.  (Actually the MSVC
732      startup code does attempt to recognize doubled quotes and accept
733      them, but gets it wrong and ends up requiring three quotes to get a
734      single embedded quote!)  So by default we decide whether to use
735      quote or backslash as the escape character based on whether the
736      binary is apparently a Cygnus compiled app.
737
738      Note that using backslash to escape embedded quotes requires
739      additional special handling if an embedded quote is already
740      preceded by backslash, or if an arg requiring quoting ends with
741      backslash.  In such cases, the run of escape characters needs to be
742      doubled.  For consistency, we apply this special handling as long
743      as the escape character is not quote.
744    
745      Since we have no idea how large argv and envp are likely to be we
746      figure out list lengths on the fly and allocate them.  */
747   
748   if (!NILP (Vwin32_quote_process_args))
749     {
750       do_quoting = 1;
751       /* Override escape char by binding win32-quote-process-args to
752          desired character, or use t for auto-selection.  */
753       if (INTP (Vwin32_quote_process_args))
754         escape_char = XINT (Vwin32_quote_process_args);
755       else
756         escape_char = is_cygnus_app ? '"' : '\\';
757     }
758   
759   /* do argv...  */
760   arglen = 0;
761   targ = (char**)argv;
762   while (*targ)
763     {
764       char * p = *targ;
765       int need_quotes = 0;
766       int escape_char_run = 0;
767
768       if (*p == 0)
769         need_quotes = 1;
770       for ( ; *p; p++)
771         {
772           if (*p == '"')
773           {
774               /* allow for embedded quotes to be escaped */
775             arglen++;
776               need_quotes = 1;
777               /* handle the case where the embedded quote is already escaped */
778               if (escape_char_run > 0)
779                 {
780                   /* To preserve the arg exactly, we need to double the
781                      preceding escape characters (plus adding one to
782                      escape the quote character itself).  */
783                   arglen += escape_char_run;
784           }
785             }
786       else if (*p == ' ' || *p == '\t')
787             {
788               need_quotes = 1;
789             }
790
791           if (*p == escape_char && escape_char != '"')
792             escape_char_run++;
793           else
794             escape_char_run = 0;
795         }
796       if (need_quotes)
797         {
798         arglen += 2;
799           /* handle the case where the arg ends with an escape char - we
800              must not let the enclosing quote be escaped.  */
801           if (escape_char_run > 0)
802             arglen += escape_char_run;
803         }
804       arglen += strlen (*targ++) + 1;
805     }
806   cmdline = (char*) alloca (arglen);
807   targ = (char**)argv;
808   parg = cmdline;
809   while (*targ)
810     {
811       char * p = *targ;
812       int need_quotes = 0;
813
814       if (*p == 0)
815         need_quotes = 1;
816
817       if (do_quoting)
818         {
819           for ( ; *p; p++)
820             if (*p == ' ' || *p == '\t' || *p == '"')
821               need_quotes = 1;
822         }
823       if (need_quotes)
824         {
825           int escape_char_run = 0;
826           char * first;
827           char * last;
828
829           p = *targ;
830           first = p;
831           last = p + strlen (p) - 1;
832           *parg++ = '"';
833 #if 0
834           /* This version does not escape quotes if they occur at the
835              beginning or end of the arg - this could lead to incorrect
836              behavior when the arg itself represents a command line
837              containing quoted args.  I believe this was originally done
838              as a hack to make some things work, before
839              `win32-quote-process-args' was added.  */
840           while (*p)
841             {
842               if (*p == '"' && p > first && p < last)
843                 *parg++ = escape_char;  /* escape embedded quotes */
844               *parg++ = *p++;
845             }
846 #else
847           for ( ; *p; p++)
848             {
849               if (*p == '"')
850                 {
851                   /* double preceding escape chars if any */
852                   while (escape_char_run > 0)
853                     {
854                       *parg++ = escape_char;
855                       escape_char_run--;
856                     }
857                   /* escape all quote chars, even at beginning or end */
858                   *parg++ = escape_char;
859                 }
860               *parg++ = *p;
861
862               if (*p == escape_char && escape_char != '"')
863                 escape_char_run++;
864               else
865                 escape_char_run = 0;
866             }
867           /* double escape chars before enclosing quote */
868           while (escape_char_run > 0)
869             {
870               *parg++ = escape_char;
871               escape_char_run--;
872             }
873 #endif
874           *parg++ = '"';
875         }
876       else
877         {
878           strcpy (parg, *targ);
879           parg += strlen (*targ);
880         }
881       *parg++ = ' ';
882       targ++;
883     }
884   *--parg = '\0';
885   
886   /* and envp...  */
887   arglen = 1;
888   targ = (char**) envp;
889   numenv = 1; /* for end null */
890   while (*targ)
891     {
892       arglen += strlen (*targ++) + 1;
893       numenv++;
894     }
895   /* extra env vars... */
896   sprintf (ppid_env_var_buffer, "__PARENT_PROCESS_ID=%d", 
897            GetCurrentProcessId ());
898   arglen += strlen (ppid_env_var_buffer) + 1;
899   numenv++;
900
901   /* merge env passed in and extra env into one, and sort it.  */
902   targ = (char **) alloca (numenv * sizeof (char*));
903   merge_and_sort_env ((char**) envp, extra_env, targ);
904
905   /* concatenate env entries.  */
906   env = (char*) alloca (arglen);
907   parg = env;
908   while (*targ)
909     {
910       strcpy (parg, *targ);
911       parg += strlen (*targ++);
912       *parg++ = '\0';
913     }
914   *parg++ = '\0';
915   *parg = '\0';
916
917   cp = new_child ();
918   if (cp == NULL)
919     {
920       errno = EAGAIN;
921       return -1;
922     }
923   
924   /* Now create the process.  */
925   if (!create_child (cmdname, cmdline, env, &pid, cp))
926     {
927       delete_child (cp);
928       errno = ENOEXEC;
929       return -1;
930     }
931
932   return pid;
933 }
934
935 /* Substitute for certain kill () operations */
936
937 static BOOL CALLBACK
938 find_child_console (HWND hwnd, child_process * cp)
939 {
940   DWORD thread_id;
941   DWORD process_id;
942
943   thread_id = GetWindowThreadProcessId (hwnd, &process_id);
944   if (process_id == cp->procinfo.dwProcessId)
945     {
946       char window_class[32];
947
948       GetClassName (hwnd, window_class, sizeof (window_class));
949       if (strcmp (window_class,
950                   windows9x_p()
951                   ? "tty"
952                   : "ConsoleWindowClass") == 0)
953         {
954           cp->hwnd = hwnd;
955           return FALSE;
956         }
957     }
958   /* keep looking */
959   return TRUE;
960 }
961
962 int 
963 sys_kill (int pid, int sig)
964 {
965   child_process *cp;
966   HANDLE proc_hand;
967   int need_to_free = 0;
968   int rc = 0;
969   
970   /* Only handle signals that will result in the process dying */
971   if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP)
972     {
973       errno = EINVAL;
974       return -1;
975     }
976
977   cp = find_child_pid (pid);
978   if (cp == NULL)
979     {
980       proc_hand = OpenProcess (PROCESS_TERMINATE, 0, pid);
981       if (proc_hand == NULL)
982         {
983           errno = EPERM;
984           return -1;
985         }
986       need_to_free = 1;
987     }
988   else
989     {
990       proc_hand = cp->procinfo.hProcess;
991       pid = cp->procinfo.dwProcessId;
992
993       /* Try to locate console window for process. */
994       EnumWindows ((WNDENUMPROC)find_child_console, (LPARAM) cp);
995     }
996   
997   if (sig == SIGINT)
998     {
999       if (NILP (Vwin32_start_process_share_console) && cp && cp->hwnd)
1000         {
1001           BYTE control_scan_code = (BYTE) MapVirtualKey (VK_CONTROL, 0);
1002           BYTE vk_break_code = VK_CANCEL;
1003           BYTE break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0);
1004           HWND foreground_window;
1005
1006           if (break_scan_code == 0)
1007             {
1008               /* Fake Ctrl-C if we can't manage Ctrl-Break. */
1009               vk_break_code = 'C';
1010               break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0);
1011             }
1012
1013           foreground_window = GetForegroundWindow ();
1014           if (foreground_window && SetForegroundWindow (cp->hwnd))
1015             {
1016               /* Generate keystrokes as if user had typed Ctrl-Break or Ctrl-C.  */
1017               keybd_event (VK_CONTROL, control_scan_code, 0, 0);
1018               keybd_event (vk_break_code, break_scan_code, 0, 0);
1019               keybd_event (vk_break_code, break_scan_code, KEYEVENTF_KEYUP, 0);
1020               keybd_event (VK_CONTROL, control_scan_code, KEYEVENTF_KEYUP, 0);
1021
1022               /* Sleep for a bit to give time for Emacs frame to respond
1023                  to focus change events (if Emacs was active app).  */
1024               Sleep (10);
1025
1026               SetForegroundWindow (foreground_window);
1027             }
1028         }
1029       /* Ctrl-Break is NT equivalent of SIGINT.  */
1030       else if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid))
1031         {
1032           DebPrint (("sys_kill.GenerateConsoleCtrlEvent return %d "
1033                      "for pid %lu\n", GetLastError (), pid));
1034           errno = EINVAL;
1035           rc = -1;
1036         }
1037     }
1038   else
1039     {
1040       if (NILP (Vwin32_start_process_share_console) && cp && cp->hwnd)
1041         {
1042 #if 1
1043           if (windows9x_p())
1044             {
1045 /*
1046    Another possibility is to try terminating the VDM out-right by
1047    calling the Shell VxD (id 0x17) V86 interface, function #4
1048    "SHELL_Destroy_VM", ie.
1049
1050      mov edx,4
1051      mov ebx,vm_handle
1052      call shellapi
1053
1054    First need to determine the current VM handle, and then arrange for
1055    the shellapi call to be made from the system vm (by using
1056    Switch_VM_and_callback).
1057
1058    Could try to invoke DestroyVM through CallVxD.
1059
1060 */
1061 #if 0
1062               /* On Win95, posting WM_QUIT causes the 16-bit subsystem
1063                  to hang when cmdproxy is used in conjunction with
1064                  command.com for an interactive shell.  Posting
1065                  WM_CLOSE pops up a dialog that, when Yes is selected,
1066                  does the same thing.  TerminateProcess is also less
1067                  than ideal in that subprocesses tend to stick around
1068                  until the machine is shutdown, but at least it
1069                  doesn't freeze the 16-bit subsystem.  */
1070               PostMessage (cp->hwnd, WM_QUIT, 0xff, 0);
1071 #endif
1072               if (!TerminateProcess (proc_hand, 0xff))
1073                 {
1074                   DebPrint (("sys_kill.TerminateProcess returned %d "
1075                              "for pid %lu\n", GetLastError (), pid));
1076                   errno = EINVAL;
1077                   rc = -1;
1078                 }
1079             }
1080           else
1081 #endif
1082             PostMessage (cp->hwnd, WM_CLOSE, 0, 0);
1083         }
1084       /* Kill the process.  On Win32 this doesn't kill child processes
1085          so it doesn't work very well for shells which is why it's not
1086          used in every case.  */
1087       else if (!TerminateProcess (proc_hand, 0xff))
1088         {
1089           DebPrint (("sys_kill.TerminateProcess returned %d "
1090                      "for pid %lu\n", GetLastError (), pid));
1091           errno = EINVAL;
1092           rc = -1;
1093         }
1094     }
1095
1096   if (need_to_free)
1097     CloseHandle (proc_hand);
1098
1099   return rc;
1100 }
1101
1102 #if 0
1103 /* Sync with FSF Emacs 19.34.6 note: ifdef'ed out in XEmacs */
1104 extern int report_file_error (const char *, Lisp_Object);
1105 #endif
1106 /* The following two routines are used to manipulate stdin, stdout, and
1107    stderr of our child processes.
1108
1109    Assuming that in, out, and err are *not* inheritable, we make them
1110    stdin, stdout, and stderr of the child as follows:
1111
1112    - Save the parent's current standard handles.
1113    - Set the std handles to inheritable duplicates of the ones being passed in.
1114      (Note that _get_osfhandle() is an io.h procedure that retrieves the
1115      NT file handle for a crt file descriptor.)
1116    - Spawn the child, which inherits in, out, and err as stdin,
1117      stdout, and stderr. (see Spawnve)
1118    - Close the std handles passed to the child.
1119    - Reset the parent's standard handles to the saved handles.
1120      (see reset_standard_handles)
1121    We assume that the caller closes in, out, and err after calling us.  */
1122
1123 void
1124 prepare_standard_handles (int in, int out, int err, HANDLE handles[3])
1125 {
1126   HANDLE parent;
1127   HANDLE newstdin, newstdout, newstderr;
1128
1129   parent = GetCurrentProcess ();
1130
1131   handles[0] = GetStdHandle (STD_INPUT_HANDLE);
1132   handles[1] = GetStdHandle (STD_OUTPUT_HANDLE);
1133   handles[2] = GetStdHandle (STD_ERROR_HANDLE);
1134
1135   /* make inheritable copies of the new handles */
1136   if (!DuplicateHandle (parent, 
1137                        (HANDLE) _get_osfhandle (in),
1138                        parent,
1139                        &newstdin, 
1140                        0, 
1141                        TRUE, 
1142                        DUPLICATE_SAME_ACCESS))
1143     report_file_error ("Duplicating input handle for child", Qnil);
1144   
1145   if (!DuplicateHandle (parent,
1146                        (HANDLE) _get_osfhandle (out),
1147                        parent,
1148                        &newstdout,
1149                        0,
1150                        TRUE,
1151                        DUPLICATE_SAME_ACCESS))
1152     report_file_error ("Duplicating output handle for child", Qnil);
1153   
1154   if (!DuplicateHandle (parent,
1155                        (HANDLE) _get_osfhandle (err),
1156                        parent,
1157                        &newstderr,
1158                        0,
1159                        TRUE,
1160                        DUPLICATE_SAME_ACCESS))
1161     report_file_error ("Duplicating error handle for child", Qnil);
1162
1163   /* and store them as our std handles */
1164   if (!SetStdHandle (STD_INPUT_HANDLE, newstdin))
1165     report_file_error ("Changing stdin handle", Qnil);
1166   
1167   if (!SetStdHandle (STD_OUTPUT_HANDLE, newstdout))
1168     report_file_error ("Changing stdout handle", Qnil);
1169
1170   if (!SetStdHandle (STD_ERROR_HANDLE, newstderr))
1171     report_file_error ("Changing stderr handle", Qnil);
1172 }
1173
1174 void
1175 reset_standard_handles (int in, int out, int err, HANDLE handles[3])
1176 {
1177   /* close the duplicated handles passed to the child */
1178   CloseHandle (GetStdHandle (STD_INPUT_HANDLE));
1179   CloseHandle (GetStdHandle (STD_OUTPUT_HANDLE));
1180   CloseHandle (GetStdHandle (STD_ERROR_HANDLE));
1181
1182   /* now restore parent's saved std handles */
1183   SetStdHandle (STD_INPUT_HANDLE, handles[0]);
1184   SetStdHandle (STD_OUTPUT_HANDLE, handles[1]);
1185   SetStdHandle (STD_ERROR_HANDLE, handles[2]);
1186 }
1187
1188 void
1189 set_process_dir (const char * dir)
1190 {
1191   process_dir = dir;
1192 }
1193 \f
1194 /* Some miscellaneous functions that are Windows specific, but not GUI
1195    specific (ie. are applicable in terminal or batch mode as well).  */
1196
1197 /* lifted from fileio.c  */
1198 #define CORRECT_DIR_SEPS(s) \
1199   do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \
1200        else unixtodos_filename (s); \
1201   } while (0)
1202
1203 DEFUN ("win32-short-file-name", Fwin32_short_file_name, 1, 1, "", /*
1204   Return the short file name version (8.3) of the full path of FILENAME.
1205 If FILENAME does not exist, return nil.
1206 All path elements in FILENAME are converted to their short names.
1207 */
1208        (filename))
1209 {
1210   char shortname[MAX_PATH];
1211
1212   CHECK_STRING (filename);
1213
1214   /* first expand it.  */
1215   filename = Fexpand_file_name (filename, Qnil);
1216
1217   /* luckily, this returns the short version of each element in the path.  */
1218   if (GetShortPathName (XSTRING_DATA (filename), shortname, MAX_PATH) == 0)
1219     return Qnil;
1220
1221   CORRECT_DIR_SEPS (shortname);
1222
1223   return build_string (shortname);
1224 }
1225
1226
1227 DEFUN ("win32-long-file-name", Fwin32_long_file_name, 1, 1, "", /*
1228   Return the long file name version of the full path of FILENAME.
1229 If FILENAME does not exist, return nil.
1230 All path elements in FILENAME are converted to their long names.
1231 */
1232        (filename))
1233 {
1234   char longname[ MAX_PATH ];
1235
1236   CHECK_STRING (filename);
1237
1238   /* first expand it.  */
1239   filename = Fexpand_file_name (filename, Qnil);
1240
1241   if (!win32_get_long_filename (XSTRING_DATA (filename), longname, MAX_PATH))
1242     return Qnil;
1243
1244   CORRECT_DIR_SEPS (longname);
1245
1246   return build_string (longname);
1247 }
1248
1249 DEFUN ("win32-set-process-priority", Fwin32_set_process_priority, 2, 2, "", /*
1250   Set the priority of PROCESS to PRIORITY.
1251 If PROCESS is nil, the priority of Emacs is changed, otherwise the
1252 priority of the process whose pid is PROCESS is changed.
1253 PRIORITY should be one of the symbols high, normal, or low;
1254 any other symbol will be interpreted as normal.
1255
1256 If successful, the return value is t, otherwise nil.
1257 */
1258        (process, priority))
1259 {
1260   HANDLE proc_handle = GetCurrentProcess ();
1261   DWORD  priority_class = NORMAL_PRIORITY_CLASS;
1262   Lisp_Object result = Qnil;
1263
1264   CHECK_SYMBOL (priority);
1265
1266   if (!NILP (process))
1267     {
1268       DWORD pid;
1269       child_process *cp;
1270
1271       CHECK_INT (process);
1272
1273       /* Allow pid to be an internally generated one, or one obtained
1274          externally.  This is necessary because real pids on Win95 are
1275          negative.  */
1276
1277       pid = XINT (process);
1278       cp = find_child_pid (pid);
1279       if (cp != NULL)
1280         pid = cp->procinfo.dwProcessId;
1281
1282       proc_handle = OpenProcess (PROCESS_SET_INFORMATION, FALSE, pid);
1283     }
1284
1285   if (EQ (priority, Qhigh))
1286     priority_class = HIGH_PRIORITY_CLASS;
1287   else if (EQ (priority, Qlow))
1288     priority_class = IDLE_PRIORITY_CLASS;
1289
1290   if (proc_handle != NULL)
1291     {
1292       if (SetPriorityClass (proc_handle, priority_class))
1293         result = Qt;
1294       if (!NILP (process))
1295         CloseHandle (proc_handle);
1296     }
1297
1298   return result;
1299 }
1300
1301
1302 DEFUN ("win32-get-locale-info", Fwin32_get_locale_info, 1, 2, "", /*
1303   "Return information about the Windows locale LCID.
1304 By default, return a three letter locale code which encodes the default
1305 language as the first two characters, and the country or regional variant
1306 as the third letter.  For example, ENU refers to `English (United States)',
1307 while ENC means `English (Canadian)'.
1308
1309 If the optional argument LONGFORM is non-nil, the long form of the locale
1310 name is returned, e.g. `English (United States)' instead.
1311
1312 If LCID (a 16-bit number) is not a valid locale, the result is nil.
1313 */
1314      (lcid, longform))
1315 {
1316   int got_abbrev;
1317   int got_full;
1318   char abbrev_name[32] = { 0 };
1319   char full_name[256] = { 0 };
1320
1321   CHECK_INT (lcid);
1322
1323   if (!IsValidLocale (XINT (lcid), LCID_SUPPORTED))
1324     return Qnil;
1325
1326   if (NILP (longform))
1327     {
1328       got_abbrev = GetLocaleInfo (XINT (lcid),
1329                                   LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
1330                                   abbrev_name, sizeof (abbrev_name));
1331       if (got_abbrev)
1332         return build_string (abbrev_name);
1333     }
1334   else
1335     {
1336       got_full = GetLocaleInfo (XINT (lcid),
1337                                 LOCALE_SLANGUAGE | LOCALE_USE_CP_ACP,
1338                                 full_name, sizeof (full_name));
1339       if (got_full)
1340         return build_string (full_name);
1341     }
1342
1343   return Qnil;
1344 }
1345
1346
1347 DEFUN ("win32-get-current-locale-id", Fwin32_get_current_locale_id, 0, 0, "", /*
1348   "Return Windows locale id for current locale setting.
1349 This is a numerical value; use `win32-get-locale-info' to convert to a
1350 human-readable form.
1351 */
1352        ())
1353 {
1354   return make_int (GetThreadLocale ());
1355 }
1356
1357
1358 DEFUN ("win32-get-default-locale-id", Fwin32_get_default_locale_id, 0, 1, "", /*
1359   "Return Windows locale id for default locale setting.
1360 By default, the system default locale setting is returned; if the optional
1361 parameter USERP is non-nil, the user default locale setting is returned.
1362 This is a numerical value; use `win32-get-locale-info' to convert to a
1363 human-readable form.
1364 */
1365        (userp))
1366 {
1367   if (NILP (userp))
1368     return make_int (GetSystemDefaultLCID ());
1369   return make_int (GetUserDefaultLCID ());
1370 }
1371
1372 DWORD int_from_hex (char * s)
1373 {
1374   DWORD val = 0;
1375   static char hex[] = "0123456789abcdefABCDEF";
1376   char * p;
1377
1378   while (*s && (p = strchr(hex, *s)) != NULL)
1379     {
1380       unsigned digit = p - hex;
1381       if (digit > 15)
1382         digit -= 6;
1383       val = val * 16 + digit;
1384       s++;
1385     }
1386   return val;
1387 }
1388
1389 /* We need to build a global list, since the EnumSystemLocale callback
1390    function isn't given a context pointer.  */
1391 Lisp_Object Vwin32_valid_locale_ids;
1392
1393 BOOL CALLBACK enum_locale_fn (LPTSTR localeNum)
1394 {
1395   DWORD id = int_from_hex (localeNum);
1396   Vwin32_valid_locale_ids = Fcons (make_int (id), Vwin32_valid_locale_ids);
1397   return TRUE;
1398 }
1399
1400 DEFUN ("win32-get-valid-locale-ids", Fwin32_get_valid_locale_ids, 0, 0, "", /*
1401   Return list of all valid Windows locale ids.
1402 Each id is a numerical value; use `win32-get-locale-info' to convert to a
1403 human-readable form.
1404 */
1405        ())
1406 {
1407   Vwin32_valid_locale_ids = Qnil;
1408
1409   EnumSystemLocales (enum_locale_fn, LCID_SUPPORTED);
1410
1411   Vwin32_valid_locale_ids = Fnreverse (Vwin32_valid_locale_ids);
1412   return Vwin32_valid_locale_ids;
1413 }
1414
1415
1416 DEFUN ("win32-set-current-locale", Fwin32_set_current_locale, 1, 1, "", /*
1417   Make Windows locale LCID be the current locale setting for Emacs.
1418 If successful, the new locale id is returned, otherwise nil.
1419 */
1420      (lcid))
1421 {
1422   CHECK_INT (lcid);
1423
1424   if (!IsValidLocale (XINT (lcid), LCID_SUPPORTED))
1425     return Qnil;
1426
1427   if (!SetThreadLocale (XINT (lcid)))
1428     return Qnil;
1429
1430 /* Sync with FSF Emacs 19.34.6 note: dwWinThreadId declared in
1431    w32term.h and defined in w32fns.c, both of which are not in current
1432    XEmacs.  #### Check what we lose by ifdef'ing out these. --marcpa */
1433 #if 0
1434   /* Need to set input thread locale if present.  */
1435   if (dwWinThreadId)
1436     /* Reply is not needed.  */
1437     PostThreadMessage (dwWinThreadId, WM_EMACS_SETLOCALE, XINT (lcid), 0);
1438 #endif
1439
1440   return make_int (GetThreadLocale ());
1441 }
1442
1443 \f
1444 void
1445 syms_of_ntproc ()
1446 {
1447   DEFSUBR (Fwin32_short_file_name);
1448   DEFSUBR (Fwin32_long_file_name);
1449   DEFSUBR (Fwin32_set_process_priority);
1450   DEFSUBR (Fwin32_get_locale_info);
1451   DEFSUBR (Fwin32_get_current_locale_id);
1452   DEFSUBR (Fwin32_get_default_locale_id);
1453   DEFSUBR (Fwin32_get_valid_locale_ids);
1454   DEFSUBR (Fwin32_set_current_locale);
1455 }
1456
1457
1458 void
1459 vars_of_ntproc (void)
1460 {
1461   defsymbol (&Qhigh, "high");
1462   defsymbol (&Qlow, "low");
1463
1464   DEFVAR_LISP ("win32-quote-process-args", &Vwin32_quote_process_args /*
1465     Non-nil enables quoting of process arguments to ensure correct parsing.
1466 Because Windows does not directly pass argv arrays to child processes,
1467 programs have to reconstruct the argv array by parsing the command
1468 line string.  For an argument to contain a space, it must be enclosed
1469 in double quotes or it will be parsed as multiple arguments.
1470
1471 If the value is a character, that character will be used to escape any
1472 quote characters that appear, otherwise a suitable escape character
1473 will be chosen based on the type of the program.
1474 */ );
1475   Vwin32_quote_process_args = Qt;
1476
1477   DEFVAR_LISP ("win32-start-process-show-window",
1478                &Vwin32_start_process_show_window /*
1479     When nil, processes started via start-process hide their windows.
1480 When non-nil, they show their window in the method of their choice.
1481 */ );
1482   Vwin32_start_process_show_window = Qnil;
1483
1484   DEFVAR_LISP ("win32-start-process-share-console",
1485                &Vwin32_start_process_share_console /*
1486     When nil, processes started via start-process are given a new console.
1487 When non-nil, they share the Emacs console; this has the limitation of
1488 allowing only only DOS subprocess to run at a time (whether started directly
1489 or indirectly by Emacs), and preventing Emacs from cleanly terminating the
1490 subprocess group, but may allow Emacs to interrupt a subprocess that doesn't
1491 otherwise respond to interrupts from Emacs.
1492 */ );
1493   Vwin32_start_process_share_console = Qt;
1494
1495   DEFVAR_LISP ("win32-pipe-read-delay", &Vwin32_pipe_read_delay /*
1496     Forced delay before reading subprocess output.
1497 This is done to improve the buffering of subprocess output, by
1498 avoiding the inefficiency of frequently reading small amounts of data.
1499
1500 If positive, the value is the number of milliseconds to sleep before
1501 reading the subprocess output.  If negative, the magnitude is the number
1502 of time slices to wait (effectively boosting the priority of the child
1503 process temporarily).  A value of zero disables waiting entirely.
1504 */ );
1505   Vwin32_pipe_read_delay = make_int (50);
1506
1507 #if 0
1508   DEFVAR_LISP ("win32-generate-fake-inodes", &Vwin32_generate_fake_inodes /*
1509     "Non-nil means attempt to fake realistic inode values.
1510 This works by hashing the truename of files, and should detect 
1511 aliasing between long and short (8.3 DOS) names, but can have
1512 false positives because of hash collisions.  Note that determining
1513 the truename of a file can be slow.
1514 */ );
1515   Vwin32_generate_fake_inodes = Qnil;
1516 #endif
1517 }
1518
1519 /* end of ntproc.c */