XEmacs 21.2.34 "Molpe".
[chise/xemacs-chise.git.1] / src / process-nt.c
1 /* Asynchronous subprocess implementation for Win32
2    Copyright (C) 1985, 1986, 1987, 1988, 1992, 1993, 1994, 1995
3    Free Software Foundation, Inc.
4    Copyright (C) 1995 Sun Microsystems, Inc.
5    Copyright (C) 1995, 1996, 2000 Ben Wing.
6
7 This file is part of XEmacs.
8
9 XEmacs is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
12 later version.
13
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with XEmacs; see the file COPYING.  If not, write to
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.  */
23
24 /* Written by Kirill M. Katsnelson <kkm@kis.ru>, April 1998 */
25
26 #include <config.h>
27 #include "lisp.h"
28
29 #include "buffer.h"
30 #include "console-msw.h"
31 #include "hash.h"
32 #include "lstream.h"
33 #include "nt.h"
34 #include "process.h"
35 #include "procimpl.h"
36 #include "sysdep.h"
37
38 #include <shellapi.h>
39 #ifdef __MINGW32__
40 #include <errno.h>
41 #endif
42 #include <signal.h>
43 #ifdef HAVE_SOCKETS
44 #include <winsock.h>
45 #endif
46
47 /* Arbitrary size limit for code fragments passed to run_in_other_process */
48 #define FRAGMENT_CODE_SIZE 32
49
50 /* Implementation-specific data. Pointed to by Lisp_Process->process_data */
51 struct nt_process_data
52 {
53   HANDLE h_process;
54   DWORD dwProcessId;
55   HWND hwnd; /* console window */
56   int need_enable_child_signals;
57 };
58
59 /* Control how args are quoted to ensure correct parsing by child
60    process. */
61 Lisp_Object Vmswindows_quote_process_args;
62
63 /* Control whether create_child causes the process to inherit Emacs'
64    console window, or be given a new one of its own.  The default is
65    nil, to allow multiple DOS programs to run on Win95.  Having separate
66    consoles also allows Emacs to cleanly terminate process groups.  */
67 Lisp_Object Vmswindows_start_process_share_console;
68
69 /* Control whether create_child cause the process to inherit Emacs'
70    error mode setting.  The default is t, to minimize the possibility of
71    subprocesses blocking when accessing unmounted drives.  */
72 Lisp_Object Vmswindows_start_process_inherit_error_mode;
73
74 #define NT_DATA(p) ((struct nt_process_data*)((p)->process_data))
75 \f
76 /*-----------------------------------------------------------------------*/
77 /* Process helpers                                                       */
78 /*-----------------------------------------------------------------------*/
79
80 /* This one breaks process abstraction. Prototype is in console-msw.h,
81    used by select_process method in event-msw.c */
82 HANDLE
83 get_nt_process_handle (Lisp_Process *p)
84 {
85   return (NT_DATA (p)->h_process);
86 }
87
88 static struct Lisp_Process *
89 find_process_from_pid (DWORD pid)
90 {
91   Lisp_Object tail, proc;
92
93   for (tail = Vprocess_list; CONSP (tail); tail = XCDR (tail))
94     {
95       proc = XCAR (tail);
96       if (NT_DATA (XPROCESS (proc))->dwProcessId == pid)
97         return XPROCESS (proc);
98     }
99   return 0;
100 }
101
102 \f
103 /*-----------------------------------------------------------------------*/
104 /* Running remote threads. See Microsoft Systems Journal 1994 Number 5   */
105 /* Jeffrey Richter, Load Your 32-bit DLL into Another Process's Address..*/
106 /*-----------------------------------------------------------------------*/
107
108 typedef struct
109 {
110   HANDLE h_process;
111   HANDLE h_thread;
112   LPVOID address;
113 } process_memory;
114
115 /*
116  * Allocate SIZE bytes in H_PROCESS address space. Fill in PMC used
117  * further by other routines. Return nonzero if successful.
118  *
119  * The memory in other process is allocated by creating a suspended
120  * thread. Initial stack of that thread is used as the memory
121  * block. The thread entry point is the routine ExitThread in
122  * kernel32.dll, so the allocated memory is freed just by resuming the 
123  * thread, which immediately terminates after that.
124  */
125
126 static int 
127 alloc_process_memory (HANDLE h_process, size_t size,
128                       process_memory* pmc)
129 {
130   LPTHREAD_START_ROUTINE adr_ExitThread =
131     (LPTHREAD_START_ROUTINE)
132     GetProcAddress (GetModuleHandle ("kernel32"), "ExitThread");
133   DWORD dw_unused;
134   CONTEXT context;
135   MEMORY_BASIC_INFORMATION mbi;
136
137   pmc->h_process = h_process;
138   pmc->h_thread = CreateRemoteThread (h_process, NULL, size,
139                                      adr_ExitThread, NULL,
140                                      CREATE_SUSPENDED, &dw_unused);
141   if (pmc->h_thread == NULL)
142     return 0;
143
144   /* Get context, for thread's stack pointer */
145   context.ContextFlags = CONTEXT_CONTROL;
146   if (!GetThreadContext (pmc->h_thread, &context))
147     goto failure;
148
149   /* Determine base address of the committed range */
150   if (sizeof(mbi) != VirtualQueryEx (h_process,
151 #if defined (_X86_)
152                                      (LPDWORD)context.Esp - 1,
153 #elif defined (_ALPHA_)
154                                      (LPDWORD)context.IntSp - 1,
155 #else
156 #error Unknown processor architecture
157 #endif
158                                      &mbi, sizeof(mbi)))
159     goto failure;
160
161   /* Change the page protection of the allocated memory to executable,
162      read, and write. */
163   if (!VirtualProtectEx (h_process, mbi.BaseAddress, size,
164                          PAGE_EXECUTE_READWRITE, &dw_unused))
165     goto failure;
166
167   pmc->address = mbi.BaseAddress;
168   return 1;
169
170  failure:
171   ResumeThread (pmc->h_thread);
172   pmc->address = 0;
173   return 0;
174 }
175
176 static void
177 free_process_memory (process_memory* pmc)
178 {
179   ResumeThread (pmc->h_thread);
180 }
181
182 /*
183  * Run ROUTINE in the context of process determined by H_PROCESS. The
184  * routine is passed the address of DATA as parameter. The ROUTINE must
185  * not be longer than ROUTINE_CODE_SIZE bytes. DATA_SIZE is the size of
186  * DATA structure.
187  *
188  * Note that the code must be positionally independent, and compiled
189  * without stack checks (they cause implicit calls into CRT so will
190  * fail). DATA should not refer any data in calling process, as both
191  * routine and its data are copied into remote process. Size of data
192  * and code together should not exceed one page (4K on x86 systems).
193  *
194  * Return the value returned by ROUTINE, or (DWORD)-1 if call failed.
195  */
196 static DWORD
197 run_in_other_process (HANDLE h_process,
198                       LPTHREAD_START_ROUTINE routine,
199                       LPVOID data, size_t data_size)
200 {
201   process_memory pm;
202   const size_t code_size = FRAGMENT_CODE_SIZE;
203   /* Need at most 3 extra bytes of memory, for data alignment */
204   size_t total_size = code_size + data_size + 3;
205   LPVOID remote_data;
206   HANDLE h_thread;
207   DWORD dw_unused;
208
209   /* Allocate memory */
210   if (!alloc_process_memory (h_process, total_size, &pm))
211     return (DWORD)-1;
212
213   /* Copy code */
214   if (!WriteProcessMemory (h_process, pm.address, (LPVOID)routine,
215                            code_size, NULL))
216     goto failure;
217
218   /* Copy data */
219   if (data_size)
220     {
221       remote_data = (LPBYTE)pm.address + ((code_size + 4) & ~3);
222       if (!WriteProcessMemory (h_process, remote_data, data, data_size, NULL))
223         goto failure;
224     }
225   else
226     remote_data = NULL;
227
228   /* Execute the remote copy of code, passing it remote data */
229   h_thread = CreateRemoteThread (h_process, NULL, 0,
230                                  (LPTHREAD_START_ROUTINE) pm.address,
231                                  remote_data, 0, &dw_unused);
232   if (h_thread == NULL)
233     goto failure;
234
235   /* Wait till thread finishes */
236   WaitForSingleObject (h_thread, INFINITE);
237
238   /* Free remote memory */
239   free_process_memory (&pm);
240
241   /* Return thread's exit code */
242   {
243     DWORD exit_code;
244     GetExitCodeThread (h_thread, &exit_code);
245     CloseHandle (h_thread);
246     return exit_code;
247   }
248
249  failure:
250   free_process_memory (&pm);
251   return (DWORD)-1;
252 }
253 \f
254 /*-----------------------------------------------------------------------*/
255 /* Sending signals                                                       */
256 /*-----------------------------------------------------------------------*/
257
258 /* ---------------------------- the NT way ------------------------------- */
259
260 /*
261  * We handle the following signals:
262  *
263  * SIGKILL, SIGTERM, SIGQUIT, SIGHUP - These four translate to ExitProcess
264  *    executed by the remote process
265  * SIGINT - The remote process is sent CTRL_BREAK_EVENT
266  *
267  * The MSVC5.0 compiler feels free to re-order functions within a
268  * compilation unit, so we have no way of finding out the size of the
269  * following functions. Therefore these functions must not be larger than
270  * FRAGMENT_CODE_SIZE.
271  */
272
273 /*
274  * Sending SIGKILL
275  */
276 typedef struct
277 {
278   void (WINAPI *adr_ExitProcess) (UINT);
279 } sigkill_data;
280
281 static DWORD WINAPI
282 sigkill_proc (sigkill_data* data)
283 {
284   (*data->adr_ExitProcess)(255);
285   return 1;
286 }
287
288 /*
289  * Sending break or control c
290  */
291 typedef struct
292 {
293   BOOL (WINAPI *adr_GenerateConsoleCtrlEvent) (DWORD, DWORD);
294   DWORD event;
295 } sigint_data;
296
297 static DWORD WINAPI
298 sigint_proc (sigint_data* data)
299 {
300   return (*data->adr_GenerateConsoleCtrlEvent) (data->event, 0);
301 }
302
303 /*
304  * Enabling signals
305  */
306 typedef struct
307 {
308   BOOL (WINAPI *adr_SetConsoleCtrlHandler) (LPVOID, BOOL);
309 } sig_enable_data;
310
311 static DWORD WINAPI
312 sig_enable_proc (sig_enable_data* data)
313 {
314   (*data->adr_SetConsoleCtrlHandler) (NULL, FALSE);
315   return 1;
316 }
317
318 /*
319  * Send signal SIGNO to process H_PROCESS.
320  * Return nonzero if successful.
321  */
322
323 static int
324 send_signal_the_nt_way (struct nt_process_data *cp, int pid, int signo)
325 {
326   HANDLE h_process;
327   HMODULE h_kernel = GetModuleHandle ("kernel32");
328   int close_process = 0;
329   DWORD retval;
330   
331   assert (h_kernel != NULL);
332   
333   if (cp)
334     {
335       pid = cp->dwProcessId;
336       h_process = cp->h_process;
337     }
338   else
339     {
340       close_process = 1;
341       /* Try to open the process with required privileges */
342       h_process = OpenProcess (PROCESS_CREATE_THREAD
343                                | PROCESS_QUERY_INFORMATION 
344                                | PROCESS_VM_OPERATION
345                                | PROCESS_VM_WRITE,
346                                FALSE, pid);
347       if (!h_process)
348         return 0;
349     }
350
351   switch (signo)
352     {
353     case SIGKILL:
354     case SIGTERM:
355     case SIGQUIT:
356     case SIGHUP:
357       {
358         sigkill_data d;
359
360         d.adr_ExitProcess =
361           (void (WINAPI *) (UINT)) GetProcAddress (h_kernel, "ExitProcess");
362         assert (d.adr_ExitProcess);
363         retval = run_in_other_process (h_process, 
364                                        (LPTHREAD_START_ROUTINE)sigkill_proc,
365                                        &d, sizeof (d));
366         break;
367       }
368     case SIGINT:
369       {
370         sigint_data d;
371         d.adr_GenerateConsoleCtrlEvent =
372           (BOOL (WINAPI *) (DWORD, DWORD))
373           GetProcAddress (h_kernel, "GenerateConsoleCtrlEvent");
374         assert (d.adr_GenerateConsoleCtrlEvent);
375         d.event = CTRL_C_EVENT;
376         retval = run_in_other_process (h_process, 
377                                        (LPTHREAD_START_ROUTINE)sigint_proc,
378                                        &d, sizeof (d));
379         break;
380       }
381     default:
382       assert (0);
383     }
384
385   if (close_process)
386     CloseHandle (h_process);
387   return (int)retval > 0 ? 1 : 0;
388 }
389
390 /*
391  * Enable CTRL_C_EVENT handling in a new child process
392  */
393 static void
394 enable_child_signals (HANDLE h_process)
395 {
396   HMODULE h_kernel = GetModuleHandle ("kernel32");
397   sig_enable_data d;
398   
399   assert (h_kernel != NULL);
400   d.adr_SetConsoleCtrlHandler =
401     (BOOL (WINAPI *) (LPVOID, BOOL))
402     GetProcAddress (h_kernel, "SetConsoleCtrlHandler");
403   assert (d.adr_SetConsoleCtrlHandler);
404   run_in_other_process (h_process, (LPTHREAD_START_ROUTINE)sig_enable_proc,
405                         &d, sizeof (d));
406 }
407   
408 #pragma warning (default : 4113)
409
410 /* ---------------------------- the 95 way ------------------------------- */
411
412 static BOOL CALLBACK
413 find_child_console (HWND hwnd, struct nt_process_data *cp)
414 {
415   DWORD thread_id;
416   DWORD process_id;
417
418   thread_id = GetWindowThreadProcessId (hwnd, &process_id);
419   if (process_id == cp->dwProcessId)
420     {
421       char window_class[32];
422
423       GetClassName (hwnd, window_class, sizeof (window_class));
424       if (strcmp (window_class,
425                   msw_windows9x_p ()
426                   ? "tty"
427                   : "ConsoleWindowClass") == 0)
428         {
429           cp->hwnd = hwnd;
430           return FALSE;
431         }
432     }
433   /* keep looking */
434   return TRUE;
435 }
436
437 static int
438 send_signal_the_95_way (struct nt_process_data *cp, int pid, int signo)
439 {
440   HANDLE h_process;
441   int close_process = 0;
442   int rc = 1;
443   
444   if (cp)
445     {
446       pid = cp->dwProcessId;
447       h_process = cp->h_process;
448
449       /* Try to locate console window for process. */
450       EnumWindows (find_child_console, (LPARAM) cp);
451     }
452   else
453     {
454       close_process = 1;
455       /* Try to open the process with required privileges */
456       h_process = OpenProcess (PROCESS_TERMINATE, FALSE, pid);
457       if (!h_process)
458         return 0;
459     }
460     
461   if (signo == SIGINT)
462     {
463       if (NILP (Vmswindows_start_process_share_console) && cp && cp->hwnd)
464         {
465           BYTE control_scan_code = (BYTE) MapVirtualKey (VK_CONTROL, 0);
466           BYTE vk_break_code = VK_CANCEL;
467           BYTE break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0);
468           HWND foreground_window;
469
470           if (break_scan_code == 0)
471             {
472               /* Fake Ctrl-C if we can't manage Ctrl-Break. */
473               vk_break_code = 'C';
474               break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0);
475             }
476
477           foreground_window = GetForegroundWindow ();
478           if (foreground_window)
479             {
480               /* NT 5.0, and apparently also Windows 98, will not allow
481                  a Window to be set to foreground directly without the
482                  user's involvement. The workaround is to attach
483                  ourselves to the thread that owns the foreground
484                  window, since that is the only thread that can set the
485                  foreground window.  */
486               DWORD foreground_thread, child_thread;
487               foreground_thread =
488                 GetWindowThreadProcessId (foreground_window, NULL);
489               if (foreground_thread == GetCurrentThreadId ()
490                   || !AttachThreadInput (GetCurrentThreadId (),
491                                          foreground_thread, TRUE))
492                 foreground_thread = 0;
493
494               child_thread = GetWindowThreadProcessId (cp->hwnd, NULL);
495               if (child_thread == GetCurrentThreadId ()
496                   || !AttachThreadInput (GetCurrentThreadId (),
497                                          child_thread, TRUE))
498                 child_thread = 0;
499
500               /* Set the foreground window to the child.  */
501               if (SetForegroundWindow (cp->hwnd))
502                 {
503                   /* Generate keystrokes as if user had typed Ctrl-Break or
504                      Ctrl-C.  */
505                   keybd_event (VK_CONTROL, control_scan_code, 0, 0);
506                   keybd_event (vk_break_code, break_scan_code,
507                     (vk_break_code == 'C' ? 0 : KEYEVENTF_EXTENDEDKEY), 0);
508                   keybd_event (vk_break_code, break_scan_code,
509                     (vk_break_code == 'C' ? 0 : KEYEVENTF_EXTENDEDKEY)
510                     | KEYEVENTF_KEYUP, 0);
511                   keybd_event (VK_CONTROL, control_scan_code,
512                                KEYEVENTF_KEYUP, 0);
513
514                   /* Sleep for a bit to give time for Emacs frame to respond
515                      to focus change events (if Emacs was active app).  */
516                   Sleep (100);
517
518                   SetForegroundWindow (foreground_window);
519                 }
520               /* Detach from the foreground and child threads now that
521                  the foreground switching is over.  */
522               if (foreground_thread)
523                 AttachThreadInput (GetCurrentThreadId (),
524                                    foreground_thread, FALSE);
525               if (child_thread)
526                 AttachThreadInput (GetCurrentThreadId (),
527                                    child_thread, FALSE);
528             }
529         }
530       /* Ctrl-Break is NT equivalent of SIGINT.  */
531       else if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid))
532         {
533 #if 0 /* FSF Emacs */
534           DebPrint (("sys_kill.GenerateConsoleCtrlEvent return %d "
535                      "for pid %lu\n", GetLastError (), pid));
536           errno = EINVAL;
537 #endif
538           rc = 0;
539         }
540     }
541   else
542     {
543       if (NILP (Vmswindows_start_process_share_console) && cp && cp->hwnd)
544         {
545 #if 1
546           if (msw_windows9x_p ())
547             {
548 /*
549    Another possibility is to try terminating the VDM out-right by
550    calling the Shell VxD (id 0x17) V86 interface, function #4
551    "SHELL_Destroy_VM", ie.
552
553      mov edx,4
554      mov ebx,vm_handle
555      call shellapi
556
557    First need to determine the current VM handle, and then arrange for
558    the shellapi call to be made from the system vm (by using
559    Switch_VM_and_callback).
560
561    Could try to invoke DestroyVM through CallVxD.
562
563 */
564 #if 0
565               /* On Win95, posting WM_QUIT causes the 16-bit subsystem
566                  to hang when cmdproxy is used in conjunction with
567                  command.com for an interactive shell.  Posting
568                  WM_CLOSE pops up a dialog that, when Yes is selected,
569                  does the same thing.  TerminateProcess is also less
570                  than ideal in that subprocesses tend to stick around
571                  until the machine is shutdown, but at least it
572                  doesn't freeze the 16-bit subsystem.  */
573               PostMessage (cp->hwnd, WM_QUIT, 0xff, 0);
574 #endif
575               if (!TerminateProcess (h_process, 0xff))
576                 {
577 #if 0 /* FSF Emacs */
578                   DebPrint (("sys_kill.TerminateProcess returned %d "
579                              "for pid %lu\n", GetLastError (), pid));
580                   errno = EINVAL;
581 #endif
582                   rc = 0;
583                 }
584             }
585           else
586 #endif
587             PostMessage (cp->hwnd, WM_CLOSE, 0, 0);
588         }
589       /* Kill the process.  On W32 this doesn't kill child processes
590          so it doesn't work very well for shells which is why it's not
591          used in every case.  */
592       else if (!TerminateProcess (h_process, 0xff))
593         {
594 #if 0 /* FSF Emacs */
595           DebPrint (("sys_kill.TerminateProcess returned %d "
596                      "for pid %lu\n", GetLastError (), pid));
597           errno = EINVAL;
598 #endif
599           rc = 0;
600         }
601     }
602
603   if (close_process)
604     CloseHandle (h_process);
605
606   return rc;
607 }
608
609 /* -------------------------- all-OS functions ---------------------------- */
610
611 static int
612 send_signal (struct nt_process_data *cp, int pid, int signo)
613 {
614   return send_signal_the_nt_way (cp, pid, signo)
615     || send_signal_the_95_way (cp, pid, signo);
616 }
617
618 /*
619  * Signal error if SIGNO is not supported
620  */
621 static void
622 validate_signal_number (int signo)
623 {
624   if (signo != SIGKILL && signo != SIGTERM
625       && signo != SIGQUIT && signo != SIGINT
626       && signo != SIGHUP)
627     signal_simple_error ("Signal number not supported", make_int (signo));
628 }
629 \f  
630 /*-----------------------------------------------------------------------*/
631 /* Process methods                                                       */
632 /*-----------------------------------------------------------------------*/
633
634 /*
635  * Allocate and initialize Lisp_Process->process_data
636  */
637
638 static void
639 nt_alloc_process_data (Lisp_Process *p)
640 {
641   p->process_data = xnew_and_zero (struct nt_process_data);
642 }
643
644 static void
645 nt_finalize_process_data (Lisp_Process *p, int for_disksave)
646 {
647   assert (!for_disksave);
648   if (NT_DATA (p)->h_process)
649     CloseHandle (NT_DATA (p)->h_process);
650 }
651
652 /*
653  * Initialize XEmacs process implementation once
654  */
655 static void
656 nt_init_process (void)
657 {
658   /* Initialize winsock */
659   WSADATA wsa_data;
660   /* Request Winsock v1.1 Note the order: (minor=1, major=1) */
661   WSAStartup (MAKEWORD (1,1), &wsa_data);
662 }
663
664 /*
665  * Fork off a subprocess. P is a pointer to newly created subprocess
666  * object. If this function signals, the caller is responsible for
667  * deleting (and finalizing) the process object.
668  *
669  * The method must return PID of the new process, a (positive??? ####) number
670  * which fits into Lisp_Int. No return value indicates an error, the method
671  * must signal an error instead.
672  */
673
674 static void
675 signal_cannot_launch (Lisp_Object image_file, DWORD err)
676 {
677   mswindows_set_errno (err);
678   signal_simple_error_2 ("Error starting", image_file, lisp_strerror (errno));
679 }
680
681 static void
682 ensure_console_window_exists (void)
683 {
684   if (msw_windows9x_p ())
685     msw_hide_console ();
686 }
687
688 int
689 compare_env (const void *strp1, const void *strp2)
690 {
691   const char *str1 = *(const char**)strp1, *str2 = *(const char**)strp2;
692
693   while (*str1 && *str2 && *str1 != '=' && *str2 != '=')
694     {
695       if ((*str1) > (*str2))
696         return 1;
697       else if ((*str1) < (*str2))
698         return -1;
699       str1++, str2++;
700     }
701
702   if (*str1 == '=' && *str2 == '=')
703     return 0;
704   else if (*str1 == '=')
705     return -1;
706   else
707     return 1;
708 }
709
710 static int
711 nt_create_process (Lisp_Process *p,
712                    Lisp_Object *argv, int nargv,
713                    Lisp_Object program, Lisp_Object cur_dir)
714 {
715   /* Synched up with sys_spawnve in FSF 20.6.  Significantly different
716      but still synchable. */
717   HANDLE hmyshove, hmyslurp, hprocin, hprocout, hprocerr;
718   Extbyte *command_line;
719   BOOL do_io, windowed;
720   char *proc_env;
721
722   /* No need to DOS-ize the filename; expand-file-name (called prior)
723      already does this. */
724
725   /* Find out whether the application is windowed or not */
726   {
727     /* SHGetFileInfo tends to return ERROR_FILE_NOT_FOUND on most
728        errors. This leads to bogus error message. */
729     DWORD image_type;
730     char *p = strrchr ((char *)XSTRING_DATA (program), '.');
731     if (p != NULL &&
732         (stricmp (p, ".exe") == 0 ||
733          stricmp (p, ".com") == 0 ||
734          stricmp (p, ".bat") == 0 ||
735          stricmp (p, ".cmd") == 0))
736       {
737         image_type = SHGetFileInfo ((char *)XSTRING_DATA (program), 0,NULL,
738                                     0, SHGFI_EXETYPE);
739       }
740     else
741       {
742         char progname[MAX_PATH];
743         sprintf (progname, "%s.exe", (char *)XSTRING_DATA (program));
744         image_type = SHGetFileInfo (progname, 0, NULL, 0, SHGFI_EXETYPE);
745       }
746     if (image_type == 0)
747       signal_cannot_launch (program, (GetLastError () == ERROR_FILE_NOT_FOUND
748                                       ? ERROR_BAD_FORMAT : GetLastError ()));
749     windowed = HIWORD (image_type) != 0;
750   }
751
752   /* Decide whether to do I/O on process handles, or just mark the
753      process exited immediately upon successful launching. We do I/O if the
754      process is a console one, or if it is windowed but windowed_process_io
755      is non-zero */
756   do_io = !windowed || windowed_process_io ;
757   
758   if (do_io)
759     {
760       /* Create two unidirectional named pipes */
761       HANDLE htmp;
762       SECURITY_ATTRIBUTES sa;
763
764       sa.nLength = sizeof(sa);
765       sa.bInheritHandle = TRUE;
766       sa.lpSecurityDescriptor = NULL;
767
768       CreatePipe (&hprocin, &hmyshove, &sa, 0);
769       CreatePipe (&hmyslurp, &hprocout, &sa, 0);
770
771       /* Duplicate the stdout handle for use as stderr */
772       DuplicateHandle(GetCurrentProcess(), hprocout, GetCurrentProcess(),
773                       &hprocerr, 0, TRUE, DUPLICATE_SAME_ACCESS);
774
775       /* Stupid Win32 allows to create a pipe with *both* ends either
776          inheritable or not. We need process ends inheritable, and local
777          ends not inheritable. */
778       DuplicateHandle (GetCurrentProcess(), hmyshove, GetCurrentProcess(),
779                        &htmp, 0, FALSE,
780                        DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS);
781       hmyshove = htmp;
782       DuplicateHandle (GetCurrentProcess(), hmyslurp, GetCurrentProcess(),
783                        &htmp, 0, FALSE,
784                        DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS);
785       hmyslurp = htmp;
786     }
787
788   /* Convert an argv vector into Win32 style command line. */
789   {
790     int i;
791     Bufbyte **quoted_args;
792     int is_dos_app, is_cygnus_app;
793     int do_quoting = 0;
794     char escape_char = 0;
795
796     nargv++; /* include program; we access argv offset by 1 below */
797     quoted_args = alloca_array (Bufbyte *, nargv);
798
799     /* Determine whether program is a 16-bit DOS executable, or a Win32
800        executable that is implicitly linked to the Cygnus dll (implying it
801        was compiled with the Cygnus GNU toolchain and hence relies on
802        cygwin.dll to parse the command line - we use this to decide how to
803        escape quote chars in command line args that must be quoted). */
804     mswindows_executable_type (XSTRING_DATA (program),
805                                &is_dos_app, &is_cygnus_app);
806
807 #if 0
808     /* #### we need to port this. */
809     /* On Windows 95, if cmdname is a DOS app, we invoke a helper
810        application to start it by specifying the helper app as cmdname,
811        while leaving the real app name as argv[0].  */
812     if (is_dos_app)
813       {
814         cmdname = (char*) alloca (MAXPATHLEN);
815         if (egetenv ("CMDPROXY"))
816           strcpy ((char*)cmdname, egetenv ("CMDPROXY"));
817         else
818           {
819             strcpy ((char*)cmdname, XSTRING_DATA (Vinvocation_directory));
820             strcat ((char*)cmdname, "cmdproxy.exe");
821           }
822       }
823 #endif
824   
825     /* we have to do some conjuring here to put argv and envp into the
826        form CreateProcess wants...  argv needs to be a space separated/null
827        terminated list of parameters, and envp is a null
828        separated/double-null terminated list of parameters.
829
830        Additionally, zero-length args and args containing whitespace or
831        quote chars need to be wrapped in double quotes - for this to work,
832        embedded quotes need to be escaped as well.  The aim is to ensure
833        the child process reconstructs the argv array we start with
834        exactly, so we treat quotes at the beginning and end of arguments
835        as embedded quotes.
836
837        The Win32 GNU-based library from Cygnus doubles quotes to escape
838        them, while MSVC uses backslash for escaping.  (Actually the MSVC
839        startup code does attempt to recognize doubled quotes and accept
840        them, but gets it wrong and ends up requiring three quotes to get a
841        single embedded quote!)  So by default we decide whether to use
842        quote or backslash as the escape character based on whether the
843        binary is apparently a Cygnus compiled app.
844
845        Note that using backslash to escape embedded quotes requires
846        additional special handling if an embedded quote is already
847        preceded by backslash, or if an arg requiring quoting ends with
848        backslash.  In such cases, the run of escape characters needs to be
849        doubled.  For consistency, we apply this special handling as long
850        as the escape character is not quote.
851    
852        Since we have no idea how large argv and envp are likely to be we
853        figure out list lengths on the fly and allocate them.  */
854   
855     if (!NILP (Vmswindows_quote_process_args))
856       {
857         do_quoting = 1;
858         /* Override escape char by binding mswindows-quote-process-args to
859            desired character, or use t for auto-selection.  */
860         if (INTP (Vmswindows_quote_process_args))
861           escape_char = (char) XINT (Vmswindows_quote_process_args);
862         else
863           escape_char = is_cygnus_app ? '"' : '\\';
864       }
865   
866     /* do argv...  */
867     for (i = 0; i < nargv; ++i)
868       {
869         Bufbyte *targ = XSTRING_DATA (i == 0 ? program : argv[i - 1]);
870         Bufbyte *p = targ;
871         int need_quotes = 0;
872         int escape_char_run = 0;
873         int arglen = 0;
874
875         if (*p == 0)
876           need_quotes = 1;
877         for ( ; *p; p++)
878           {
879             if (*p == '"')
880               {
881                 /* allow for embedded quotes to be escaped */
882                 arglen++;
883                 need_quotes = 1;
884                 /* handle the case where the embedded quote is already escaped */
885                 if (escape_char_run > 0)
886                   {
887                     /* To preserve the arg exactly, we need to double the
888                        preceding escape characters (plus adding one to
889                        escape the quote character itself).  */
890                     arglen += escape_char_run;
891                   }
892               }
893             else if (*p == ' ' || *p == '\t')
894               {
895                 need_quotes = 1;
896               }
897
898             if (*p == escape_char && escape_char != '"')
899               escape_char_run++;
900             else
901               escape_char_run = 0;
902           }
903         if (need_quotes)
904           {
905             arglen += 2;
906             /* handle the case where the arg ends with an escape char - we
907                must not let the enclosing quote be escaped.  */
908             if (escape_char_run > 0)
909               arglen += escape_char_run;
910           }
911         arglen += strlen (targ) + 1;
912
913         quoted_args[i] = alloca_array (Bufbyte, arglen); 
914       }
915
916     for (i = 0; i < nargv; ++i)
917       {
918         Bufbyte *targ = XSTRING_DATA (i == 0 ? program : argv[i - 1]);
919         Bufbyte *p = targ;
920         int need_quotes = 0;
921         Bufbyte *parg = quoted_args[i];
922
923         if (*p == 0)
924           need_quotes = 1;
925
926         if (do_quoting)
927           {
928             for ( ; *p; p++)
929               if (*p == ' ' || *p == '\t' || *p == '"')
930                 need_quotes = 1;
931           }
932         if (need_quotes)
933           {
934             int escape_char_run = 0;
935             Bufbyte * first;
936             Bufbyte * last;
937
938             p = targ;
939             first = p;
940             last = p + strlen (p) - 1;
941             *parg++ = '"';
942 #if 0
943             /* This version does not escape quotes if they occur at the
944                beginning or end of the arg - this could lead to incorrect
945                behavior when the arg itself represents a command line
946                containing quoted args.  I believe this was originally done
947                as a hack to make some things work, before
948                `mswindows-quote-process-args' was added.  */
949             while (*p)
950               {
951                 if (*p == '"' && p > first && p < last)
952                   *parg++ = escape_char;        /* escape embedded quotes */
953                 *parg++ = *p++;
954               }
955 #else
956             for ( ; *p; p++)
957               {
958                 if (*p == '"')
959                   {
960                     /* double preceding escape chars if any */
961                     while (escape_char_run > 0)
962                       {
963                         *parg++ = escape_char;
964                         escape_char_run--;
965                       }
966                     /* escape all quote chars, even at beginning or end */
967                     *parg++ = escape_char;
968                   }
969                 *parg++ = *p;
970
971                 if (*p == escape_char && escape_char != '"')
972                   escape_char_run++;
973                 else
974                   escape_char_run = 0;
975               }
976             /* double escape chars before enclosing quote */
977             while (escape_char_run > 0)
978               {
979                 *parg++ = escape_char;
980                 escape_char_run--;
981               }
982 #endif
983             *parg++ = '"';
984           }
985         else
986           {
987             strcpy (parg, targ);
988             parg += strlen (targ);
989           }
990         *parg = '\0';
991       }
992
993     {
994       int total_cmdline_len = 0;
995       Extcount *extargcount = (Extcount *) alloca_array (Extcount, nargv);
996       Extbyte **extarg = (Extbyte **) alloca_array (Extbyte *, nargv);
997       Extbyte *command_ptr;
998
999       for (i = 0; i < nargv; ++i)
1000         {
1001           TO_EXTERNAL_FORMAT (C_STRING, quoted_args[i], ALLOCA,
1002                               (extarg[i], extargcount[i]), Qmswindows_tstr);
1003           /* account for space and terminating null */
1004           total_cmdline_len += extargcount[i] + EITCHAR_SIZE;
1005         }
1006
1007       command_line = alloca_array (char, total_cmdline_len);
1008       command_ptr = command_line;
1009       for (i = 0; i < nargv; ++i)
1010         {
1011           memcpy (command_ptr, extarg[i], extargcount[i]);
1012           command_ptr += extargcount[i];
1013           EICOPY_TCHAR (command_ptr, ' ');
1014           command_ptr += EITCHAR_SIZE;
1015         }
1016       EICOPY_TCHAR (command_ptr, '\0');
1017       command_ptr += EITCHAR_SIZE;
1018     }
1019   }
1020   /* Set `proc_env' to a nul-separated array of the strings in
1021      Vprocess_environment terminated by 2 nuls.  */
1022  
1023   {
1024     char **env;
1025     REGISTER Lisp_Object tem;
1026     REGISTER char **new_env;
1027     REGISTER int new_length = 0, i, new_space;
1028     char *penv;
1029     
1030     for (tem = Vprocess_environment;
1031          (CONSP (tem)
1032           && STRINGP (XCAR (tem)));
1033          tem = XCDR (tem))
1034       new_length++;
1035
1036     /* FSF adds an extra env var to hold the current process ID of the
1037        Emacs process.  Apparently this is used only by emacsserver.c,
1038        which we have superseded to gnuserv.c. (#### Does it work under
1039        MS Windows?)
1040
1041        sprintf (ppid_env_var_buffer, "EM_PARENT_PROCESS_ID=%d", 
1042          GetCurrentProcessId ());
1043        arglen += strlen (ppid_env_var_buffer) + 1;
1044        numenv++;
1045     */
1046     
1047     /* new_length + 1 to include terminating 0.  */
1048     env = new_env = alloca_array (char *, new_length + 1);
1049  
1050     /* Copy the Vprocess_environment strings into new_env.  */
1051     for (tem = Vprocess_environment;
1052          (CONSP (tem)
1053           && STRINGP (XCAR (tem)));
1054          tem = XCDR (tem))
1055       {
1056         char **ep = env;
1057         char *string = (char *) XSTRING_DATA (XCAR (tem));
1058         /* See if this string duplicates any string already in the env.
1059            If so, don't put it in.
1060            When an env var has multiple definitions,
1061            we keep the definition that comes first in process-environment.  */
1062         for (; ep != new_env; ep++)
1063           {
1064             char *p = *ep, *q = string;
1065             while (1)
1066               {
1067                 if (*q == 0)
1068                   /* The string is malformed; might as well drop it.  */
1069                   goto duplicate;
1070                 if (*q != *p)
1071                   break;
1072                 if (*q == '=')
1073                   goto duplicate;
1074                 p++, q++;
1075               }
1076           }
1077         *new_env++ = string;
1078       duplicate: ;
1079       }
1080     *new_env = 0;
1081     
1082     /* Sort the environment variables */
1083     new_length = new_env - env;
1084     qsort (env, new_length, sizeof (char *), compare_env);
1085     
1086     /* Work out how much space to allocate */
1087     new_space = 0;
1088     for (i = 0; i < new_length; i++)
1089       {
1090         new_space += strlen(env[i]) + 1;
1091       }
1092     new_space++;
1093     
1094     /* Allocate space and copy variables into it */
1095     penv = proc_env = (char*) alloca(new_space);
1096     for (i = 0; i < new_length; i++)
1097       {
1098         strcpy(penv, env[i]);
1099         penv += strlen(env[i]) + 1;
1100       }
1101     *penv = 0;
1102   }
1103   
1104   /* Create process */
1105   {
1106     STARTUPINFO si;
1107     PROCESS_INFORMATION pi;
1108     DWORD err;
1109     DWORD flags;
1110
1111     xzero (si);
1112     si.dwFlags = STARTF_USESHOWWINDOW;
1113     si.wShowWindow = windowed ? SW_SHOWNORMAL : SW_HIDE;
1114     if (do_io)
1115       {
1116         si.hStdInput = hprocin;
1117         si.hStdOutput = hprocout;
1118         si.hStdError = hprocerr;
1119         si.dwFlags |= STARTF_USESTDHANDLES;
1120       }
1121
1122     flags = CREATE_SUSPENDED;
1123     if (msw_windows9x_p ())
1124       flags |= (!NILP (Vmswindows_start_process_share_console)
1125                 ? CREATE_NEW_PROCESS_GROUP
1126                 : CREATE_NEW_CONSOLE);
1127     else
1128       flags |= CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP;
1129     if (NILP (Vmswindows_start_process_inherit_error_mode))
1130       flags |= CREATE_DEFAULT_ERROR_MODE;
1131
1132     ensure_console_window_exists ();
1133
1134     err = (CreateProcess (NULL, command_line, NULL, NULL, TRUE, flags,
1135                           proc_env, (char *) XSTRING_DATA (cur_dir), &si, &pi)
1136            ? 0 : GetLastError ());
1137
1138     if (do_io)
1139       {
1140         /* These just have been inherited; we do not need a copy */
1141         CloseHandle (hprocin);
1142         CloseHandle (hprocout);
1143         CloseHandle (hprocerr);
1144       }
1145     
1146     /* Handle process creation failure */
1147     if (err)
1148       {
1149         if (do_io)
1150           {
1151             CloseHandle (hmyshove);
1152             CloseHandle (hmyslurp);
1153           }
1154         signal_cannot_launch (program, GetLastError ());
1155       }
1156
1157     /* The process started successfully */
1158     if (do_io)
1159       {
1160         NT_DATA(p)->h_process = pi.hProcess;
1161         NT_DATA(p)->dwProcessId = pi.dwProcessId;
1162         init_process_io_handles (p, (void*)hmyslurp, (void*)hmyshove, 0);
1163       }
1164     else
1165       {
1166         /* Indicate as if the process has exited immediately. */
1167         p->status_symbol = Qexit;
1168         CloseHandle (pi.hProcess);
1169       }
1170
1171     ResumeThread (pi.hThread);
1172     CloseHandle (pi.hThread);
1173
1174     /* Remember to enable child signals later if this is not a windowed
1175        app.  Can't do it right now because that screws up the MKS Toolkit
1176        shell. */
1177     if (!windowed)
1178       {
1179         NT_DATA(p)->need_enable_child_signals = 10;
1180         kick_status_notify ();
1181       }
1182
1183     return ((int)pi.dwProcessId);
1184   }
1185 }
1186
1187 /* 
1188  * This method is called to update status fields of the process
1189  * structure. If the process has not existed, this method is expected
1190  * to do nothing.
1191  *
1192  * The method is called only for real child processes.  
1193  */
1194
1195 static void
1196 nt_update_status_if_terminated (Lisp_Process* p)
1197 {
1198   DWORD exit_code;
1199
1200   if (NT_DATA(p)->need_enable_child_signals > 1)
1201     {
1202       NT_DATA(p)->need_enable_child_signals -= 1;
1203       kick_status_notify ();
1204     }
1205   else if (NT_DATA(p)->need_enable_child_signals == 1)
1206     {
1207       enable_child_signals(NT_DATA(p)->h_process);
1208       NT_DATA(p)->need_enable_child_signals = 0;
1209     }
1210
1211   if (GetExitCodeProcess (NT_DATA(p)->h_process, &exit_code)
1212       && exit_code != STILL_ACTIVE)
1213     {
1214       p->tick++;
1215       p->core_dumped = 0;
1216       /* The exit code can be a code returned by process, or an
1217          NTSTATUS value. We cannot accurately handle the latter since
1218          it is a full 32 bit integer */
1219       if (exit_code & 0xC0000000)
1220         {
1221           p->status_symbol = Qsignal;
1222           p->exit_code = exit_code & 0x1FFFFFFF;
1223         }
1224       else
1225         {
1226           p->status_symbol = Qexit;
1227           p->exit_code = exit_code;
1228         }
1229     }
1230 }
1231
1232 /*
1233  * Stuff the entire contents of LSTREAM to the process output pipe
1234  */
1235
1236 /* #### If only this function could be somehow merged with
1237    unix_send_process... */
1238
1239 static void
1240 nt_send_process (Lisp_Object proc, struct lstream* lstream)
1241 {
1242   volatile Lisp_Object vol_proc = proc;
1243   Lisp_Process *volatile p = XPROCESS (proc);
1244
1245   /* use a reasonable-sized buffer (somewhere around the size of the
1246      stream buffer) so as to avoid inundating the stream with blocked
1247      data. */
1248   Bufbyte chunkbuf[512];
1249   Bytecount chunklen;
1250
1251   while (1)
1252     {
1253       ssize_t writeret;
1254
1255       chunklen = Lstream_read (lstream, chunkbuf, 512);
1256       if (chunklen <= 0)
1257         break; /* perhaps should abort() if < 0?
1258                   This should never happen. */
1259
1260       /* Lstream_write() will never successfully write less than the
1261          amount sent in.  In the worst case, it just buffers the
1262          unwritten data. */
1263       writeret = Lstream_write (XLSTREAM (DATA_OUTSTREAM(p)), chunkbuf,
1264                                 chunklen);
1265       Lstream_flush (XLSTREAM (DATA_OUTSTREAM(p)));
1266       if (writeret < 0)
1267         {
1268           p->status_symbol = Qexit;
1269           p->exit_code = ERROR_BROKEN_PIPE;
1270           p->core_dumped = 0;
1271           p->tick++;
1272           process_tick++;
1273           deactivate_process (*((Lisp_Object *) (&vol_proc)));
1274           error ("Broken pipe error sending to process %s; closed it",
1275                  XSTRING_DATA (p->name));
1276         }
1277
1278       {
1279         int wait_ms = 25;
1280         while (Lstream_was_blocked_p (XLSTREAM (p->pipe_outstream)))
1281           {
1282             /* Buffer is full.  Wait, accepting input; that may allow
1283                the program to finish doing output and read more.  */
1284             Faccept_process_output (Qnil, Qzero, make_int (wait_ms));
1285             Lstream_flush (XLSTREAM (p->pipe_outstream));
1286             wait_ms = min (1000, 2 * wait_ms);
1287           }
1288       }
1289     }
1290 }
1291
1292 /*
1293  * Send a signal number SIGNO to PROCESS.
1294  * CURRENT_GROUP means send to the process group that currently owns
1295  * the terminal being used to communicate with PROCESS.
1296  * This is used for various commands in shell mode.
1297  * If NOMSG is zero, insert signal-announcements into process's buffers
1298  * right away.
1299  *
1300  * If we can, we try to signal PROCESS by sending control characters
1301  * down the pty.  This allows us to signal inferiors who have changed
1302  * their uid, for which killpg would return an EPERM error.
1303  *
1304  * The method signals an error if the given SIGNO is not valid
1305  */
1306
1307 static void
1308 nt_kill_child_process (Lisp_Object proc, int signo,
1309                        int current_group, int nomsg)
1310 {
1311   Lisp_Process *p = XPROCESS (proc);
1312
1313   /* Enable child signals if necessary.  This may lose the first
1314      but it's better than nothing. */
1315   if (NT_DATA (p)->need_enable_child_signals > 0)
1316     {
1317       enable_child_signals (NT_DATA(p)->h_process);
1318       NT_DATA (p)->need_enable_child_signals = 0;
1319     }
1320
1321   /* Signal error if SIGNO cannot be sent */
1322   validate_signal_number (signo);
1323
1324   /* Send signal */
1325   if (!send_signal (NT_DATA (p), 0, signo))
1326     signal_simple_error ("Cannot send signal to process", proc);
1327 }
1328
1329 /*
1330  * Kill any process in the system given its PID
1331  *
1332  * Returns zero if a signal successfully sent, or
1333  * negative number upon failure
1334  */
1335 static int
1336 nt_kill_process_by_pid (int pid, int signo)
1337 {
1338   struct Lisp_Process *p;
1339
1340   /* Signal error if SIGNO cannot be sent */
1341   validate_signal_number (signo);
1342
1343   p = find_process_from_pid (pid);
1344   return send_signal (p ? NT_DATA (p) : 0, pid, signo) ? 0 : -1;
1345 }
1346 \f
1347 /*-----------------------------------------------------------------------*/
1348 /* Sockets connections                                                   */
1349 /*-----------------------------------------------------------------------*/
1350 #ifdef HAVE_SOCKETS
1351
1352 /* #### Hey MS, how long Winsock 2 for '95 will be in beta? */
1353
1354 #define SOCK_TIMER_ID 666
1355 #define XM_SOCKREPLY (WM_USER + 666)
1356
1357 static int
1358 get_internet_address (Lisp_Object host, struct sockaddr_in *address,
1359                       Error_behavior errb)
1360 {
1361   char buf [MAXGETHOSTSTRUCT];
1362   HWND hwnd;
1363   HANDLE hasync;
1364   int success = 0;
1365
1366   address->sin_family = AF_INET;
1367
1368   /* First check if HOST is already a numeric address */
1369   {
1370     unsigned long inaddr = inet_addr (XSTRING_DATA (host));
1371     if (inaddr != INADDR_NONE)
1372       {
1373         address->sin_addr.s_addr = inaddr;
1374         return 1;
1375       }
1376   }
1377
1378   /* Create a window which will receive completion messages */
1379   hwnd = CreateWindow ("STATIC", NULL, WS_OVERLAPPED, 0, 0, 1, 1,
1380                        NULL, NULL, NULL, NULL);
1381   assert (hwnd);
1382
1383   /* Post name resolution request */
1384   hasync = WSAAsyncGetHostByName (hwnd, XM_SOCKREPLY, XSTRING_DATA (host),
1385                                   buf, sizeof (buf));
1386   if (hasync == NULL)
1387     goto done;
1388
1389   /* Set a timer to poll for quit every 250 ms */
1390   SetTimer (hwnd, SOCK_TIMER_ID, 250, NULL);
1391
1392   while (1)
1393     {
1394       MSG msg;
1395       GetMessage (&msg, hwnd, 0, 0);
1396       if (msg.message == XM_SOCKREPLY)
1397         {
1398           /* Ok, got an answer */
1399           if (WSAGETASYNCERROR(msg.lParam) == NO_ERROR)
1400             success = 1;
1401           else
1402             {
1403               warn_when_safe(Qstream, Qwarning,
1404                              "cannot get IP address for host \"%s\"",
1405                              XSTRING_DATA (host));
1406             }
1407           goto done;
1408         }
1409       else if (msg.message == WM_TIMER && msg.wParam == SOCK_TIMER_ID)
1410         {
1411           if (QUITP)
1412             {
1413               WSACancelAsyncRequest (hasync);
1414               KillTimer (hwnd, SOCK_TIMER_ID);
1415               DestroyWindow (hwnd);
1416               REALLY_QUIT;
1417             }
1418         }
1419       DispatchMessage (&msg);
1420     }
1421
1422  done:
1423   KillTimer (hwnd, SOCK_TIMER_ID);
1424   DestroyWindow (hwnd);
1425   if (success)
1426     {
1427       /* BUF starts with struct hostent */
1428       struct hostent* he = (struct hostent*) buf;
1429       address->sin_addr.s_addr = *(unsigned long*)he->h_addr_list[0];
1430     }
1431   return success;
1432 }
1433
1434 static Lisp_Object
1435 nt_canonicalize_host_name (Lisp_Object host)
1436 {
1437   struct sockaddr_in address;
1438
1439   if (!get_internet_address (host, &address, ERROR_ME_NOT))
1440     return host;
1441
1442   if (address.sin_family == AF_INET)
1443     return build_string (inet_ntoa (address.sin_addr));
1444   else
1445     return host;
1446 }
1447
1448 /* open a TCP network connection to a given HOST/SERVICE.  Treated
1449    exactly like a normal process when reading and writing.  Only
1450    differences are in status display and process deletion.  A network
1451    connection has no PID; you cannot signal it.  All you can do is
1452    deactivate and close it via delete-process */
1453
1454 static void
1455 nt_open_network_stream (Lisp_Object name, Lisp_Object host,
1456                         Lisp_Object service,
1457                         Lisp_Object protocol, void** vinfd, void** voutfd)
1458 {
1459   /* !!#### not Mule-ized */
1460   struct sockaddr_in address;
1461   SOCKET s;
1462   int port;
1463   int retval;
1464
1465   CHECK_STRING (host);
1466
1467   if (!EQ (protocol, Qtcp))
1468     signal_simple_error ("Unsupported protocol", protocol);
1469
1470   if (INTP (service))
1471     port = htons ((unsigned short) XINT (service));
1472   else
1473     {
1474       struct servent *svc_info;
1475       CHECK_STRING (service);
1476       svc_info = getservbyname ((char *) XSTRING_DATA (service), "tcp");
1477       if (svc_info == 0)
1478         signal_simple_error ("Unknown service", service);
1479       port = svc_info->s_port;
1480     }
1481
1482   get_internet_address (host, &address, ERROR_ME);
1483   address.sin_port = port;
1484
1485   s = socket (address.sin_family, SOCK_STREAM, 0);
1486   if (s < 0)
1487     report_file_error ("error creating socket", list1 (name));
1488
1489   /* We don't want to be blocked on connect */
1490   {
1491     unsigned long nonblock = 1;
1492     ioctlsocket (s, FIONBIO, &nonblock);
1493   }
1494   
1495   retval = connect (s, (struct sockaddr *) &address, sizeof (address));
1496   if (retval != NO_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
1497     goto connect_failed;
1498   /* Wait while connection is established */
1499   while (1)
1500     {
1501       fd_set fdset;
1502       struct timeval tv;
1503       int nsel;
1504
1505       if (QUITP)
1506         {
1507           closesocket (s);
1508           REALLY_QUIT;
1509         }
1510
1511       /* Poll for quit every 250 ms */
1512       tv.tv_sec = 0;
1513       tv.tv_usec = 250 * 1000;
1514
1515       FD_ZERO (&fdset);
1516       FD_SET (s, &fdset);
1517       nsel = select (0, NULL, &fdset, &fdset, &tv);
1518
1519       if (nsel > 0)
1520         {
1521           /* Check: was connection successful or not? */
1522           tv.tv_usec = 0;
1523           nsel = select (0, NULL, NULL, &fdset, &tv);
1524           if (nsel > 0)
1525             goto connect_failed;
1526           else
1527             break;
1528         }
1529     }
1530
1531   /* We are connected at this point */
1532   *vinfd = (void*)s;
1533   DuplicateHandle (GetCurrentProcess(), (HANDLE)s,
1534                    GetCurrentProcess(), (LPHANDLE)voutfd,
1535                    0, FALSE, DUPLICATE_SAME_ACCESS);
1536   return;
1537
1538  connect_failed:  
1539   closesocket (s);
1540   if (INTP (service))
1541     {
1542       warn_when_safe (Qstream, Qwarning,
1543                       "failure to open network stream to host \"%s\" for service \"%d\"",
1544                       XSTRING_DATA (host),
1545                       (unsigned short) XINT (service));
1546     }
1547   else
1548     {
1549       warn_when_safe (Qstream, Qwarning,
1550                       "failure to open network stream to host \"%s\" for service \"%s\"",
1551                       XSTRING_DATA (host),
1552                       XSTRING_DATA (service));
1553     }
1554   report_file_error ("connection failed", list2 (host, name));
1555 }
1556
1557 #endif
1558 \f
1559 /*-----------------------------------------------------------------------*/
1560 /* Initialization                                                        */
1561 /*-----------------------------------------------------------------------*/
1562
1563 void
1564 process_type_create_nt (void)
1565 {
1566   PROCESS_HAS_METHOD (nt, alloc_process_data);
1567   PROCESS_HAS_METHOD (nt, finalize_process_data);
1568   PROCESS_HAS_METHOD (nt, init_process);
1569   PROCESS_HAS_METHOD (nt, create_process);
1570   PROCESS_HAS_METHOD (nt, update_status_if_terminated);
1571   PROCESS_HAS_METHOD (nt, send_process);
1572   PROCESS_HAS_METHOD (nt, kill_child_process);
1573   PROCESS_HAS_METHOD (nt, kill_process_by_pid);
1574 #ifdef HAVE_SOCKETS
1575   PROCESS_HAS_METHOD (nt, canonicalize_host_name);
1576   PROCESS_HAS_METHOD (nt, open_network_stream);
1577 #ifdef HAVE_MULTICAST
1578 #error I won't do this until '95 has winsock2
1579   PROCESS_HAS_METHOD (nt, open_multicast_group);
1580 #endif
1581 #endif
1582 }
1583
1584 void
1585 syms_of_process_nt (void)
1586 {
1587 }
1588
1589 void
1590 vars_of_process_nt (void)
1591 {
1592   DEFVAR_LISP ("mswindows-quote-process-args",
1593                &Vmswindows_quote_process_args /*
1594 Non-nil enables quoting of process arguments to ensure correct parsing.
1595 Because Windows does not directly pass argv arrays to child processes,
1596 programs have to reconstruct the argv array by parsing the command
1597 line string.  For an argument to contain a space, it must be enclosed
1598 in double quotes or it will be parsed as multiple arguments.
1599
1600 If the value is a character, that character will be used to escape any
1601 quote characters that appear, otherwise a suitable escape character
1602 will be chosen based on the type of the program (normal or Cygwin).
1603 */ );                                                             
1604   Vmswindows_quote_process_args = Qt;
1605
1606   DEFVAR_LISP ("mswindows-start-process-share-console",
1607                &Vmswindows_start_process_share_console /*
1608 When nil, new child processes are given a new console.
1609 When non-nil, they share the Emacs console; this has the limitation of
1610 allowing only only DOS subprocess to run at a time (whether started directly
1611 or indirectly by Emacs), and preventing Emacs from cleanly terminating the
1612 subprocess group, but may allow Emacs to interrupt a subprocess that doesn't
1613 otherwise respond to interrupts from Emacs.
1614 */ );
1615   Vmswindows_start_process_share_console = Qnil;
1616
1617   DEFVAR_LISP ("mswindows-start-process-inherit-error-mode",
1618                &Vmswindows_start_process_inherit_error_mode /*
1619     "When nil, new child processes revert to the default error mode.
1620 When non-nil, they inherit their error mode setting from Emacs, which stops
1621 them blocking when trying to access unmounted drives etc.
1622 */ );
1623   Vmswindows_start_process_inherit_error_mode = Qt;
1624 }