comparison src/process-nt.c @ 854:1d8fb2eee1bb

[xemacs-hg @ 2002-05-28 16:06:58 by didierv] Fix header inclusion order
author didierv
date Tue, 28 May 2002 16:07:03 +0000
parents 2b6fa2618f76
children 84762348c6f9
comparison
equal deleted inserted replaced
853:2b6fa2618f76 854:1d8fb2eee1bb
32 #include "hash.h" 32 #include "hash.h"
33 #include "lstream.h" 33 #include "lstream.h"
34 #include "process.h" 34 #include "process.h"
35 #include "procimpl.h" 35 #include "procimpl.h"
36 36
37 #include "syssignal.h" 37 #include "syssignal.h" /* Always include before sysproc.h -- didier */
38 #include "sysfile.h" 38 #include "sysfile.h"
39 #include "sysproc.h" 39 #include "sysproc.h"
40 40
41 /* Bound by win32-native.el */ 41 /* Bound by win32-native.el */
42 Lisp_Object Qmswindows_construct_process_command_line; 42 Lisp_Object Qmswindows_construct_process_command_line;
125 * further by other routines. Return nonzero if successful. 125 * further by other routines. Return nonzero if successful.
126 * 126 *
127 * The memory in other process is allocated by creating a suspended 127 * The memory in other process is allocated by creating a suspended
128 * thread. Initial stack of that thread is used as the memory 128 * thread. Initial stack of that thread is used as the memory
129 * block. The thread entry point is the routine ExitThread in 129 * block. The thread entry point is the routine ExitThread in
130 * kernel32.dll, so the allocated memory is freed just by resuming the 130 * kernel32.dll, so the allocated memory is freed just by resuming the
131 * thread, which immediately terminates after that. 131 * thread, which immediately terminates after that.
132 */ 132 */
133 133
134 static int 134 static int
135 alloc_process_memory (HANDLE h_process, Bytecount size, 135 alloc_process_memory (HANDLE h_process, Bytecount size,
136 process_memory *pmc) 136 process_memory *pmc)
137 { 137 {
138 LPTHREAD_START_ROUTINE adr_ExitThread = 138 LPTHREAD_START_ROUTINE adr_ExitThread =
139 (LPTHREAD_START_ROUTINE) 139 (LPTHREAD_START_ROUTINE)
333 { 333 {
334 HANDLE h_process; 334 HANDLE h_process;
335 HMODULE h_kernel = qxeGetModuleHandle (XETEXT ("kernel32")); 335 HMODULE h_kernel = qxeGetModuleHandle (XETEXT ("kernel32"));
336 int close_process = 0; 336 int close_process = 0;
337 DWORD retval; 337 DWORD retval;
338 338
339 assert (h_kernel != NULL); 339 assert (h_kernel != NULL);
340 340
341 if (cp) 341 if (cp)
342 { 342 {
343 pid = cp->dwProcessId; 343 pid = cp->dwProcessId;
344 h_process = cp->h_process; 344 h_process = cp->h_process;
345 } 345 }
346 else 346 else
347 { 347 {
348 close_process = 1; 348 close_process = 1;
349 /* Try to open the process with required privileges */ 349 /* Try to open the process with required privileges */
350 h_process = OpenProcess (PROCESS_CREATE_THREAD 350 h_process = OpenProcess (PROCESS_CREATE_THREAD
351 | PROCESS_QUERY_INFORMATION 351 | PROCESS_QUERY_INFORMATION
352 | PROCESS_VM_OPERATION 352 | PROCESS_VM_OPERATION
353 | PROCESS_VM_WRITE, 353 | PROCESS_VM_WRITE,
354 FALSE, pid); 354 FALSE, pid);
355 if (!h_process) 355 if (!h_process)
356 return 0; 356 return 0;
366 sigkill_data d; 366 sigkill_data d;
367 367
368 d.adr_ExitProcess = 368 d.adr_ExitProcess =
369 (void (WINAPI *) (UINT)) GetProcAddress (h_kernel, "ExitProcess"); 369 (void (WINAPI *) (UINT)) GetProcAddress (h_kernel, "ExitProcess");
370 assert (d.adr_ExitProcess); 370 assert (d.adr_ExitProcess);
371 retval = run_in_other_process (h_process, 371 retval = run_in_other_process (h_process,
372 (LPTHREAD_START_ROUTINE) sigkill_proc, 372 (LPTHREAD_START_ROUTINE) sigkill_proc,
373 &d, sizeof (d)); 373 &d, sizeof (d));
374 break; 374 break;
375 } 375 }
376 case SIGINT: 376 case SIGINT:
379 d.adr_GenerateConsoleCtrlEvent = 379 d.adr_GenerateConsoleCtrlEvent =
380 (BOOL (WINAPI *) (DWORD, DWORD)) 380 (BOOL (WINAPI *) (DWORD, DWORD))
381 GetProcAddress (h_kernel, "GenerateConsoleCtrlEvent"); 381 GetProcAddress (h_kernel, "GenerateConsoleCtrlEvent");
382 assert (d.adr_GenerateConsoleCtrlEvent); 382 assert (d.adr_GenerateConsoleCtrlEvent);
383 d.event = CTRL_C_EVENT; 383 d.event = CTRL_C_EVENT;
384 retval = run_in_other_process (h_process, 384 retval = run_in_other_process (h_process,
385 (LPTHREAD_START_ROUTINE) sigint_proc, 385 (LPTHREAD_START_ROUTINE) sigint_proc,
386 &d, sizeof (d)); 386 &d, sizeof (d));
387 break; 387 break;
388 } 388 }
389 default: 389 default:
401 static void 401 static void
402 enable_child_signals (HANDLE h_process) 402 enable_child_signals (HANDLE h_process)
403 { 403 {
404 HMODULE h_kernel = qxeGetModuleHandle (XETEXT ("kernel32")); 404 HMODULE h_kernel = qxeGetModuleHandle (XETEXT ("kernel32"));
405 sig_enable_data d; 405 sig_enable_data d;
406 406
407 assert (h_kernel != NULL); 407 assert (h_kernel != NULL);
408 d.adr_SetConsoleCtrlHandler = 408 d.adr_SetConsoleCtrlHandler =
409 (BOOL (WINAPI *) (LPVOID, BOOL)) 409 (BOOL (WINAPI *) (LPVOID, BOOL))
410 GetProcAddress (h_kernel, "SetConsoleCtrlHandler"); 410 GetProcAddress (h_kernel, "SetConsoleCtrlHandler");
411 assert (d.adr_SetConsoleCtrlHandler); 411 assert (d.adr_SetConsoleCtrlHandler);
412 run_in_other_process (h_process, (LPTHREAD_START_ROUTINE)sig_enable_proc, 412 run_in_other_process (h_process, (LPTHREAD_START_ROUTINE)sig_enable_proc,
413 &d, sizeof (d)); 413 &d, sizeof (d));
414 } 414 }
415 415
416 /* ---------------------------- the 95 way ------------------------------- */ 416 /* ---------------------------- the 95 way ------------------------------- */
417 417
418 static BOOL CALLBACK 418 static BOOL CALLBACK
419 find_child_console (HWND hwnd, long putada) 419 find_child_console (HWND hwnd, long putada)
420 { 420 {
446 send_signal_the_95_way (struct nt_process_data *cp, int pid, int signo) 446 send_signal_the_95_way (struct nt_process_data *cp, int pid, int signo)
447 { 447 {
448 HANDLE h_process; 448 HANDLE h_process;
449 int close_process = 0; 449 int close_process = 0;
450 int rc = 1; 450 int rc = 1;
451 451
452 if (cp) 452 if (cp)
453 { 453 {
454 pid = cp->dwProcessId; 454 pid = cp->dwProcessId;
455 h_process = cp->h_process; 455 h_process = cp->h_process;
456 456
463 /* Try to open the process with required privileges */ 463 /* Try to open the process with required privileges */
464 h_process = OpenProcess (PROCESS_TERMINATE, FALSE, pid); 464 h_process = OpenProcess (PROCESS_TERMINATE, FALSE, pid);
465 if (!h_process) 465 if (!h_process)
466 return 0; 466 return 0;
467 } 467 }
468 468
469 if (signo == SIGINT) 469 if (signo == SIGINT)
470 { 470 {
471 if (NILP (Vmswindows_start_process_share_console) && cp && cp->hwnd) 471 if (NILP (Vmswindows_start_process_share_console) && cp && cp->hwnd)
472 { 472 {
473 BYTE control_scan_code = (BYTE) MapVirtualKeyA (VK_CONTROL, 0); 473 BYTE control_scan_code = (BYTE) MapVirtualKeyA (VK_CONTROL, 0);
632 if (signo != SIGKILL && signo != SIGTERM 632 if (signo != SIGKILL && signo != SIGTERM
633 && signo != SIGQUIT && signo != SIGINT 633 && signo != SIGQUIT && signo != SIGINT
634 && signo != SIGHUP) 634 && signo != SIGHUP)
635 invalid_constant ("Signal number not supported", make_int (signo)); 635 invalid_constant ("Signal number not supported", make_int (signo));
636 } 636 }
637 637
638 /*-----------------------------------------------------------------------*/ 638 /*-----------------------------------------------------------------------*/
639 /* Process methods */ 639 /* Process methods */
640 /*-----------------------------------------------------------------------*/ 640 /*-----------------------------------------------------------------------*/
641 641
642 /* 642 /*
784 /* Decide whether to do I/O on process handles, or just mark the 784 /* Decide whether to do I/O on process handles, or just mark the
785 process exited immediately upon successful launching. We do I/O if the 785 process exited immediately upon successful launching. We do I/O if the
786 process is a console one, or if it is windowed but windowed_process_io 786 process is a console one, or if it is windowed but windowed_process_io
787 is non-zero */ 787 is non-zero */
788 do_io = !windowed || windowed_process_io ; 788 do_io = !windowed || windowed_process_io ;
789 789
790 if (do_io) 790 if (do_io)
791 { 791 {
792 /* Create two unidirectional named pipes */ 792 /* Create two unidirectional named pipes */
793 HANDLE htmp; 793 HANDLE htmp;
794 SECURITY_ATTRIBUTES sa; 794 SECURITY_ATTRIBUTES sa;
862 { 862 {
863 Intbyte **env; 863 Intbyte **env;
864 REGISTER Lisp_Object tem; 864 REGISTER Lisp_Object tem;
865 REGISTER Intbyte **new_env; 865 REGISTER Intbyte **new_env;
866 REGISTER int new_length = 0, i; 866 REGISTER int new_length = 0, i;
867 867
868 for (tem = Vprocess_environment; 868 for (tem = Vprocess_environment;
869 (CONSP (tem) 869 (CONSP (tem)
870 && STRINGP (XCAR (tem))); 870 && STRINGP (XCAR (tem)));
871 tem = XCDR (tem)) 871 tem = XCDR (tem))
872 new_length++; 872 new_length++;
874 /* FSF adds an extra env var to hold the current process ID of the 874 /* FSF adds an extra env var to hold the current process ID of the
875 Emacs process. Apparently this is used only by emacsserver.c, 875 Emacs process. Apparently this is used only by emacsserver.c,
876 which we have superseded by gnuserv.c. (#### Does it work under 876 which we have superseded by gnuserv.c. (#### Does it work under
877 MS Windows?) 877 MS Windows?)
878 878
879 sprintf (ppid_env_var_buffer, "EM_PARENT_PROCESS_ID=%d", 879 sprintf (ppid_env_var_buffer, "EM_PARENT_PROCESS_ID=%d",
880 GetCurrentProcessId ()); 880 GetCurrentProcessId ());
881 arglen += strlen (ppid_env_var_buffer) + 1; 881 arglen += strlen (ppid_env_var_buffer) + 1;
882 numenv++; 882 numenv++;
883 */ 883 */
884 884
885 /* new_length + 1 to include terminating 0. */ 885 /* new_length + 1 to include terminating 0. */
886 env = new_env = alloca_array (Intbyte *, new_length + 1); 886 env = new_env = alloca_array (Intbyte *, new_length + 1);
887 887
888 /* Copy the Vprocess_environment strings into new_env. */ 888 /* Copy the Vprocess_environment strings into new_env. */
889 for (tem = Vprocess_environment; 889 for (tem = Vprocess_environment;
890 (CONSP (tem) 890 (CONSP (tem)
891 && STRINGP (XCAR (tem))); 891 && STRINGP (XCAR (tem)));
892 tem = XCDR (tem)) 892 tem = XCDR (tem))
914 } 914 }
915 *new_env++ = string; 915 *new_env++ = string;
916 duplicate: ; 916 duplicate: ;
917 } 917 }
918 *new_env = 0; 918 *new_env = 0;
919 919
920 /* Sort the environment variables */ 920 /* Sort the environment variables */
921 new_length = new_env - env; 921 new_length = new_env - env;
922 qsort (env, new_length, sizeof (Intbyte *), mswindows_compare_env); 922 qsort (env, new_length, sizeof (Intbyte *), mswindows_compare_env);
923 923
924 { 924 {
951 qxestrcpy (cmdname, XSTRING_DATA (Vinvocation_directory)); 951 qxestrcpy (cmdname, XSTRING_DATA (Vinvocation_directory));
952 qxestrcat (cmdname, (Intbyte *) "cmdproxy.exe"); 952 qxestrcat (cmdname, (Intbyte *) "cmdproxy.exe");
953 } 953 }
954 } 954 }
955 #endif 955 #endif
956 956
957 /* Create process */ 957 /* Create process */
958 { 958 {
959 STARTUPINFOW si; 959 STARTUPINFOW si;
960 PROCESS_INFORMATION pi; 960 PROCESS_INFORMATION pi;
961 DWORD err; 961 DWORD err;
1002 /* These just have been inherited; we do not need a copy */ 1002 /* These just have been inherited; we do not need a copy */
1003 CloseHandle (hprocin); 1003 CloseHandle (hprocin);
1004 CloseHandle (hprocout); 1004 CloseHandle (hprocout);
1005 CloseHandle (hprocerr); 1005 CloseHandle (hprocerr);
1006 } 1006 }
1007 1007
1008 /* Handle process creation failure */ 1008 /* Handle process creation failure */
1009 if (err) 1009 if (err)
1010 { 1010 {
1011 if (do_io) 1011 if (do_io)
1012 { 1012 {
1044 1044
1045 return ((int)pi.dwProcessId); 1045 return ((int)pi.dwProcessId);
1046 } 1046 }
1047 } 1047 }
1048 1048
1049 /* 1049 /*
1050 * This method is called to update status fields of the process 1050 * This method is called to update status fields of the process
1051 * structure. If the process has not existed, this method is expected 1051 * structure. If the process has not existed, this method is expected
1052 * to do nothing. 1052 * to do nothing.
1053 * 1053 *
1054 * The method is called only for real child processes. 1054 * The method is called only for real child processes.
1055 */ 1055 */
1056 1056
1057 static void 1057 static void
1058 nt_update_status_if_terminated (Lisp_Process *p) 1058 nt_update_status_if_terminated (Lisp_Process *p)
1059 { 1059 {
1343 /* We don't want to be blocked on connect */ 1343 /* We don't want to be blocked on connect */
1344 { 1344 {
1345 unsigned long nonblock = 1; 1345 unsigned long nonblock = 1;
1346 ioctlsocket (s, FIONBIO, &nonblock); 1346 ioctlsocket (s, FIONBIO, &nonblock);
1347 } 1347 }
1348 1348
1349 retval = connect (s, (struct sockaddr *) &address, sizeof (address)); 1349 retval = connect (s, (struct sockaddr *) &address, sizeof (address));
1350 if (retval != NO_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) 1350 if (retval != NO_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
1351 { 1351 {
1352 errnum = WSAGetLastError (); 1352 errnum = WSAGetLastError ();
1353 goto connect_failed; 1353 goto connect_failed;