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 Ben Wing.
7 This file is part of XEmacs.
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
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
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. */
24 /* Written by Kirill M. Katsnelson <kkm@kis.ru>, April 1998 */
46 /* Arbitrary size limit for code fragments passed to run_in_other_process */
47 #define FRAGMENT_CODE_SIZE 32
49 /* Bound by winnt.el */
50 Lisp_Object Qnt_quote_process_args;
52 /* Implementation-specific data. Pointed to by Lisp_Process->process_data */
53 struct nt_process_data
56 int need_enable_child_signals;
59 #define NT_DATA(p) ((struct nt_process_data*)((p)->process_data))
61 /*-----------------------------------------------------------------------*/
63 /*-----------------------------------------------------------------------*/
65 /* This one breaks process abstraction. Prototype is in console-msw.h,
66 used by select_process method in event-msw.c */
68 get_nt_process_handle (struct Lisp_Process *p)
70 return (NT_DATA (p)->h_process);
73 /*-----------------------------------------------------------------------*/
74 /* Running remote threads. See Microsoft Systems Journal 1994 Number 5 */
75 /* Jeffrey Richter, Load Your 32-bit DLL into Another Process's Address..*/
76 /*-----------------------------------------------------------------------*/
86 * Allocate SIZE bytes in H_PROCESS address space. Fill in PMC used
87 * further by other routines. Return nonzero if successful.
89 * The memory in other process is allocated by creating a suspended
90 * thread. Initial stack of that thread is used as the memory
91 * block. The thread entry point is the routine ExitThread in
92 * kernel32.dll, so the allocated memory is freed just by resuming the
93 * thread, which immediately terminates after that.
97 alloc_process_memory (HANDLE h_process, size_t size,
100 LPTHREAD_START_ROUTINE adr_ExitThread =
101 (LPTHREAD_START_ROUTINE)
102 GetProcAddress (GetModuleHandle ("kernel32"), "ExitThread");
105 MEMORY_BASIC_INFORMATION mbi;
107 pmc->h_process = h_process;
108 pmc->h_thread = CreateRemoteThread (h_process, NULL, size,
109 adr_ExitThread, NULL,
110 CREATE_SUSPENDED, &dw_unused);
111 if (pmc->h_thread == NULL)
114 /* Get context, for thread's stack pointer */
115 context.ContextFlags = CONTEXT_CONTROL;
116 if (!GetThreadContext (pmc->h_thread, &context))
119 /* Determine base address of the committed range */
120 if (sizeof(mbi) != VirtualQueryEx (h_process,
122 (LPDWORD)context.Esp - 1,
123 #elif defined (_ALPHA_)
124 (LPDWORD)context.IntSp - 1,
126 #error Unknown processor architecture
131 /* Change the page protection of the allocated memory to executable,
133 if (!VirtualProtectEx (h_process, mbi.BaseAddress, size,
134 PAGE_EXECUTE_READWRITE, &dw_unused))
137 pmc->address = mbi.BaseAddress;
141 ResumeThread (pmc->h_thread);
147 free_process_memory (process_memory* pmc)
149 ResumeThread (pmc->h_thread);
153 * Run ROUTINE in the context of process determined by H_PROCESS. The
154 * routine is passed the address of DATA as parameter. The ROUTINE must
155 * not be longer than ROUTINE_CODE_SIZE bytes. DATA_SIZE is the size of
158 * Note that the code must be positionally independent, and compiled
159 * without stack checks (they cause implicit calls into CRT so will
160 * fail). DATA should not refer any data in calling process, as both
161 * routine and its data are copied into remote process. Size of data
162 * and code together should not exceed one page (4K on x86 systems).
164 * Return the value returned by ROUTINE, or (DWORD)-1 if call failed.
167 run_in_other_process (HANDLE h_process,
168 LPTHREAD_START_ROUTINE routine,
169 LPVOID data, size_t data_size)
172 CONST size_t code_size = FRAGMENT_CODE_SIZE;
173 /* Need at most 3 extra bytes of memory, for data alignment */
174 size_t total_size = code_size + data_size + 3;
179 /* Allocate memory */
180 if (!alloc_process_memory (h_process, total_size, &pm))
184 if (!WriteProcessMemory (h_process, pm.address, (LPVOID)routine,
191 remote_data = (LPBYTE)pm.address + ((code_size + 4) & ~3);
192 if (!WriteProcessMemory (h_process, remote_data, data, data_size, NULL))
198 /* Execute the remote copy of code, passing it remote data */
199 h_thread = CreateRemoteThread (h_process, NULL, 0,
200 (LPTHREAD_START_ROUTINE) pm.address,
201 remote_data, 0, &dw_unused);
202 if (h_thread == NULL)
205 /* Wait till thread finishes */
206 WaitForSingleObject (h_thread, INFINITE);
208 /* Free remote memory */
209 free_process_memory (&pm);
211 /* Return thread's exit code */
214 GetExitCodeThread (h_thread, &exit_code);
215 CloseHandle (h_thread);
220 free_process_memory (&pm);
224 /*-----------------------------------------------------------------------*/
225 /* Sending signals */
226 /*-----------------------------------------------------------------------*/
229 * We handle the following signals:
231 * SIGKILL, SIGTERM, SIGQUIT, SIGHUP - These four translate to ExitProcess
232 * executed by the remote process
233 * SIGINT - The remote process is sent CTRL_BREAK_EVENT
235 * The MSVC5.0 compiler feels free to re-order functions within a
236 * compilation unit, so we have no way of finding out the size of the
237 * following functions. Therefore these functions must not be larger than
238 * FRAGMENT_CODE_SIZE.
246 void (WINAPI *adr_ExitProcess) (UINT);
250 sigkill_proc (sigkill_data* data)
252 (*data->adr_ExitProcess)(255);
257 * Sending break or control c
261 BOOL (WINAPI *adr_GenerateConsoleCtrlEvent) (DWORD, DWORD);
266 sigint_proc (sigint_data* data)
268 return (*data->adr_GenerateConsoleCtrlEvent) (data->event, 0);
276 BOOL (WINAPI *adr_SetConsoleCtrlHandler) (LPVOID, BOOL);
280 sig_enable_proc (sig_enable_data* data)
282 (*data->adr_SetConsoleCtrlHandler) (NULL, FALSE);
287 * Send signal SIGNO to process H_PROCESS.
288 * Return nonzero if successful.
291 /* This code assigns a return value of GetProcAddress to function pointers
292 of many different types. Instead of heavy obscure casts, we just disable
293 warnings about assignments to different function pointer types. */
294 #pragma warning (disable : 4113)
297 send_signal (HANDLE h_process, int signo)
299 HMODULE h_kernel = GetModuleHandle ("kernel32");
302 assert (h_kernel != NULL);
312 d.adr_ExitProcess = GetProcAddress (h_kernel, "ExitProcess");
313 assert (d.adr_ExitProcess);
314 retval = run_in_other_process (h_process,
315 (LPTHREAD_START_ROUTINE)sigkill_proc,
322 d.adr_GenerateConsoleCtrlEvent =
323 GetProcAddress (h_kernel, "GenerateConsoleCtrlEvent");
324 assert (d.adr_GenerateConsoleCtrlEvent);
325 d.event = CTRL_C_EVENT;
326 retval = run_in_other_process (h_process,
327 (LPTHREAD_START_ROUTINE)sigint_proc,
335 return (int)retval > 0 ? 1 : 0;
339 * Enable CTRL_C_EVENT handling in a new child process
342 enable_child_signals (HANDLE h_process)
344 HMODULE h_kernel = GetModuleHandle ("kernel32");
347 assert (h_kernel != NULL);
348 d.adr_SetConsoleCtrlHandler =
349 GetProcAddress (h_kernel, "SetConsoleCtrlHandler");
350 assert (d.adr_SetConsoleCtrlHandler);
351 run_in_other_process (h_process, (LPTHREAD_START_ROUTINE)sig_enable_proc,
355 #pragma warning (default : 4113)
358 * Signal error if SIGNO is not supported
361 validate_signal_number (int signo)
363 if (signo != SIGKILL && signo != SIGTERM
364 && signo != SIGQUIT && signo != SIGINT
366 signal_simple_error ("Signal number not supported", make_int (signo));
369 /*-----------------------------------------------------------------------*/
370 /* Process methods */
371 /*-----------------------------------------------------------------------*/
374 * Allocate and initialize Lisp_Process->process_data
378 nt_alloc_process_data (struct Lisp_Process *p)
380 p->process_data = xnew_and_zero (struct nt_process_data);
384 nt_finalize_process_data (struct Lisp_Process *p, int for_disksave)
386 assert (!for_disksave);
387 if (NT_DATA(p)->h_process)
388 CloseHandle (NT_DATA(p)->h_process);
392 * Initialize XEmacs process implementation once
395 nt_init_process (void)
397 /* Initialize winsock */
399 /* Request Winsock v1.1 Note the order: (minor=1, major=1) */
400 WSAStartup (MAKEWORD (1,1), &wsa_data);
404 * Fork off a subprocess. P is a pointer to newly created subprocess
405 * object. If this function signals, the caller is responsible for
406 * deleting (and finalizing) the process object.
408 * The method must return PID of the new process, a (positive??? ####) number
409 * which fits into Lisp_Int. No return value indicates an error, the method
410 * must signal an error instead.
414 signal_cannot_launch (Lisp_Object image_file, DWORD err)
416 mswindows_set_errno (err);
417 signal_simple_error_2 ("Error starting", image_file, lisp_strerror (errno));
421 nt_create_process (struct Lisp_Process *p,
422 Lisp_Object *argv, int nargv,
423 Lisp_Object program, Lisp_Object cur_dir)
425 HANDLE hmyshove, hmyslurp, hprocin, hprocout, hprocerr;
427 BOOL do_io, windowed;
430 /* Find out whether the application is windowed or not */
432 /* SHGetFileInfo tends to return ERROR_FILE_NOT_FOUND on most
433 errors. This leads to bogus error message. */
435 char *p = strrchr ((char *)XSTRING_DATA (program), '.');
437 (stricmp (p, ".exe") == 0 ||
438 stricmp (p, ".com") == 0 ||
439 stricmp (p, ".bat") == 0 ||
440 stricmp (p, ".cmd") == 0))
442 image_type = SHGetFileInfo ((char *)XSTRING_DATA (program), 0,NULL,
447 char progname[MAX_PATH];
448 sprintf (progname, "%s.exe", (char *)XSTRING_DATA (program));
449 image_type = SHGetFileInfo (progname, 0, NULL, 0, SHGFI_EXETYPE);
452 signal_cannot_launch (program, (GetLastError () == ERROR_FILE_NOT_FOUND
453 ? ERROR_BAD_FORMAT : GetLastError ()));
454 windowed = HIWORD (image_type) != 0;
457 /* Decide whether to do I/O on process handles, or just mark the
458 process exited immediately upon successful launching. We do I/O if the
459 process is a console one, or if it is windowed but windowed_process_io
461 do_io = !windowed || windowed_process_io ;
465 /* Create two unidirectional named pipes */
467 SECURITY_ATTRIBUTES sa;
469 sa.nLength = sizeof(sa);
470 sa.bInheritHandle = TRUE;
471 sa.lpSecurityDescriptor = NULL;
473 CreatePipe (&hprocin, &hmyshove, &sa, 0);
474 CreatePipe (&hmyslurp, &hprocout, &sa, 0);
476 /* Duplicate the stdout handle for use as stderr */
477 DuplicateHandle(GetCurrentProcess(), hprocout, GetCurrentProcess(), &hprocerr,
478 0, TRUE, DUPLICATE_SAME_ACCESS);
480 /* Stupid Win32 allows to create a pipe with *both* ends either
481 inheritable or not. We need process ends inheritable, and local
482 ends not inheritable. */
483 DuplicateHandle (GetCurrentProcess(), hmyshove, GetCurrentProcess(), &htmp,
484 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS);
486 DuplicateHandle (GetCurrentProcess(), hmyslurp, GetCurrentProcess(), &htmp,
487 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS);
491 /* Convert an argv vector into Win32 style command line by a call to
492 lisp function `nt-quote-process-args' which see (in winnt.el)*/
495 Lisp_Object args_or_ret = Qnil;
498 GCPRO1 (args_or_ret);
500 for (i = 0; i < nargv; ++i)
501 args_or_ret = Fcons (*argv++, args_or_ret);
502 args_or_ret = Fnreverse (args_or_ret);
503 args_or_ret = Fcons (program, args_or_ret);
505 args_or_ret = call1 (Qnt_quote_process_args, args_or_ret);
507 if (!STRINGP (args_or_ret))
508 /* Luser wrote his/her own clever version */
509 error ("Bogus return value from `nt-quote-process-args'");
511 command_line = alloca_array (char, (XSTRING_LENGTH (program)
512 + XSTRING_LENGTH (args_or_ret) + 2));
513 strcpy (command_line, XSTRING_DATA (program));
514 strcat (command_line, " ");
515 strcat (command_line, XSTRING_DATA (args_or_ret));
517 UNGCPRO; /* args_or_ret */
520 /* Set `proc_env' to a nul-separated array of the strings in
521 Vprocess_environment terminated by 2 nuls. */
524 extern int compare_env (const char **strp1, const char **strp2);
526 REGISTER Lisp_Object tem;
527 REGISTER char **new_env;
528 REGISTER int new_length = 0, i, new_space;
531 for (tem = Vprocess_environment;
533 && STRINGP (XCAR (tem)));
537 /* new_length + 1 to include terminating 0. */
538 env = new_env = alloca_array (char *, new_length + 1);
540 /* Copy the Vprocess_environment strings into new_env. */
541 for (tem = Vprocess_environment;
543 && STRINGP (XCAR (tem)));
547 char *string = (char *) XSTRING_DATA (XCAR (tem));
548 /* See if this string duplicates any string already in the env.
549 If so, don't put it in.
550 When an env var has multiple definitions,
551 we keep the definition that comes first in process-environment. */
552 for (; ep != new_env; ep++)
554 char *p = *ep, *q = string;
558 /* The string is malformed; might as well drop it. */
572 /* Sort the environment variables */
573 new_length = new_env - env;
574 qsort (env, new_length, sizeof (char *), compare_env);
576 /* Work out how much space to allocate */
578 for (i = 0; i < new_length; i++)
580 new_space += strlen(env[i]) + 1;
584 /* Allocate space and copy variables into it */
585 penv = proc_env = alloca(new_space);
586 for (i = 0; i < new_length; i++)
588 strcpy(penv, env[i]);
589 penv += strlen(env[i]) + 1;
597 PROCESS_INFORMATION pi;
601 si.dwFlags = STARTF_USESHOWWINDOW;
602 si.wShowWindow = windowed ? SW_SHOWNORMAL : SW_HIDE;
605 si.hStdInput = hprocin;
606 si.hStdOutput = hprocout;
607 si.hStdError = hprocerr;
608 si.dwFlags |= STARTF_USESTDHANDLES;
611 err = (CreateProcess (NULL, command_line, NULL, NULL, TRUE,
612 CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP
614 proc_env, (char *) XSTRING_DATA (cur_dir), &si, &pi)
615 ? 0 : GetLastError ());
619 /* These just have been inherited; we do not need a copy */
620 CloseHandle (hprocin);
621 CloseHandle (hprocout);
622 CloseHandle (hprocerr);
625 /* Handle process creation failure */
630 CloseHandle (hmyshove);
631 CloseHandle (hmyslurp);
633 signal_cannot_launch (program, GetLastError ());
636 /* The process started successfully */
639 NT_DATA(p)->h_process = pi.hProcess;
640 init_process_io_handles (p, (void*)hmyslurp, (void*)hmyshove, 0);
644 /* Indicate as if the process has exited immediately. */
645 p->status_symbol = Qexit;
646 CloseHandle (pi.hProcess);
649 ResumeThread (pi.hThread);
650 CloseHandle (pi.hThread);
652 /* Remember to enable child signals later if this is not a windowed
653 app. Can't do it right now because that screws up the MKS Toolkit
657 NT_DATA(p)->need_enable_child_signals = 10;
658 kick_status_notify ();
661 return ((int)pi.dwProcessId);
666 * This method is called to update status fields of the process
667 * structure. If the process has not existed, this method is expected
670 * The method is called only for real child processes.
674 nt_update_status_if_terminated (struct Lisp_Process* p)
678 if (NT_DATA(p)->need_enable_child_signals > 1)
680 NT_DATA(p)->need_enable_child_signals -= 1;
681 kick_status_notify ();
683 else if (NT_DATA(p)->need_enable_child_signals == 1)
685 enable_child_signals(NT_DATA(p)->h_process);
686 NT_DATA(p)->need_enable_child_signals = 0;
689 if (GetExitCodeProcess (NT_DATA(p)->h_process, &exit_code)
690 && exit_code != STILL_ACTIVE)
694 /* The exit code can be a code returned by process, or an
695 NTSTATUS value. We cannot accurately handle the latter since
696 it is a full 32 bit integer */
697 if (exit_code & 0xC0000000)
699 p->status_symbol = Qsignal;
700 p->exit_code = exit_code & 0x1FFFFFFF;
704 p->status_symbol = Qexit;
705 p->exit_code = exit_code;
711 * Stuff the entire contents of LSTREAM to the process output pipe
714 /* #### If only this function could be somehow merged with
715 unix_send_process... */
718 nt_send_process (Lisp_Object proc, struct lstream* lstream)
720 volatile Lisp_Object vol_proc = proc;
721 struct Lisp_Process *volatile p = XPROCESS (proc);
723 /* use a reasonable-sized buffer (somewhere around the size of the
724 stream buffer) so as to avoid inundating the stream with blocked
726 Bufbyte chunkbuf[128];
733 chunklen = Lstream_read (lstream, chunkbuf, 128);
735 break; /* perhaps should abort() if < 0?
736 This should never happen. */
738 /* Lstream_write() will never successfully write less than the
739 amount sent in. In the worst case, it just buffers the
741 writeret = Lstream_write (XLSTREAM (DATA_OUTSTREAM(p)), chunkbuf,
743 Lstream_flush (XLSTREAM (DATA_OUTSTREAM(p)));
746 p->status_symbol = Qexit;
747 p->exit_code = ERROR_BROKEN_PIPE;
751 deactivate_process (*((Lisp_Object *) (&vol_proc)));
752 error ("Broken pipe error sending to process %s; closed it",
753 XSTRING_DATA (p->name));
758 while (Lstream_was_blocked_p (XLSTREAM (p->pipe_outstream)))
760 /* Buffer is full. Wait, accepting input; that may allow
761 the program to finish doing output and read more. */
762 Faccept_process_output (Qnil, Qzero, make_int (wait_ms));
763 Lstream_flush (XLSTREAM (p->pipe_outstream));
764 wait_ms = min (1000, 2 * wait_ms);
771 * Send a signal number SIGNO to PROCESS.
772 * CURRENT_GROUP means send to the process group that currently owns
773 * the terminal being used to communicate with PROCESS.
774 * This is used for various commands in shell mode.
775 * If NOMSG is zero, insert signal-announcements into process's buffers
778 * If we can, we try to signal PROCESS by sending control characters
779 * down the pty. This allows us to signal inferiors who have changed
780 * their uid, for which killpg would return an EPERM error.
782 * The method signals an error if the given SIGNO is not valid
786 nt_kill_child_process (Lisp_Object proc, int signo,
787 int current_group, int nomsg)
789 struct Lisp_Process *p = XPROCESS (proc);
791 /* Enable child signals if necessary. This may lose the first
792 but it's better than nothing. */
793 if (NT_DATA(p)->need_enable_child_signals > 0)
795 enable_child_signals(NT_DATA(p)->h_process);
796 NT_DATA(p)->need_enable_child_signals = 0;
799 /* Signal error if SIGNO cannot be sent */
800 validate_signal_number (signo);
803 if (!send_signal (NT_DATA(p)->h_process, signo))
804 error ("Cannot send signal to process");
808 * Kill any process in the system given its PID.
810 * Returns zero if a signal successfully sent, or
811 * negative number upon failure
814 nt_kill_process_by_pid (int pid, int signo)
819 /* Signal error if SIGNO cannot be sent */
820 validate_signal_number (signo);
822 /* Try to open the process with required privileges */
823 h_process = OpenProcess (PROCESS_CREATE_THREAD
824 | PROCESS_QUERY_INFORMATION
825 | PROCESS_VM_OPERATION
828 if (h_process == NULL)
831 send_result = send_signal (h_process, signo);
833 CloseHandle (h_process);
835 return send_result ? 0 : -1;
838 /*-----------------------------------------------------------------------*/
839 /* Sockets connections */
840 /*-----------------------------------------------------------------------*/
843 /* #### Hey MS, how long Winsock 2 for '95 will be in beta? */
845 #define SOCK_TIMER_ID 666
846 #define XM_SOCKREPLY (WM_USER + 666)
849 get_internet_address (Lisp_Object host, struct sockaddr_in *address,
852 char buf [MAXGETHOSTSTRUCT];
857 address->sin_family = AF_INET;
859 /* First check if HOST is already a numeric address */
861 unsigned long inaddr = inet_addr (XSTRING_DATA (host));
862 if (inaddr != INADDR_NONE)
864 address->sin_addr.s_addr = inaddr;
869 /* Create a window which will receive completion messages */
870 hwnd = CreateWindow ("STATIC", NULL, WS_OVERLAPPED, 0, 0, 1, 1,
871 NULL, NULL, NULL, NULL);
874 /* Post name resolution request */
875 hasync = WSAAsyncGetHostByName (hwnd, XM_SOCKREPLY, XSTRING_DATA (host),
880 /* Set a timer to poll for quit every 250 ms */
881 SetTimer (hwnd, SOCK_TIMER_ID, 250, NULL);
886 GetMessage (&msg, hwnd, 0, 0);
887 if (msg.message == XM_SOCKREPLY)
889 /* Ok, got an answer */
890 if (WSAGETASYNCERROR(msg.lParam) == NO_ERROR)
894 warn_when_safe(Qstream, Qwarning,
895 "cannot get IP address for host \"%s\"",
896 XSTRING_DATA (host));
900 else if (msg.message == WM_TIMER && msg.wParam == SOCK_TIMER_ID)
904 WSACancelAsyncRequest (hasync);
905 KillTimer (hwnd, SOCK_TIMER_ID);
906 DestroyWindow (hwnd);
910 DispatchMessage (&msg);
914 KillTimer (hwnd, SOCK_TIMER_ID);
915 DestroyWindow (hwnd);
918 /* BUF starts with struct hostent */
919 struct hostent* he = (struct hostent*) buf;
920 address->sin_addr.s_addr = *(unsigned long*)he->h_addr_list[0];
926 nt_canonicalize_host_name (Lisp_Object host)
928 struct sockaddr_in address;
930 if (!get_internet_address (host, &address, ERROR_ME_NOT))
933 if (address.sin_family == AF_INET)
934 return build_string (inet_ntoa (address.sin_addr));
939 /* open a TCP network connection to a given HOST/SERVICE. Treated
940 exactly like a normal process when reading and writing. Only
941 differences are in status display and process deletion. A network
942 connection has no PID; you cannot signal it. All you can do is
943 deactivate and close it via delete-process */
946 nt_open_network_stream (Lisp_Object name, Lisp_Object host, Lisp_Object service,
947 Lisp_Object protocol, void** vinfd, void** voutfd)
949 struct sockaddr_in address;
956 if (!EQ (protocol, Qtcp))
957 error ("Unsupported protocol \"%s\"",
958 string_data (symbol_name (XSYMBOL (protocol))));
961 port = htons ((unsigned short) XINT (service));
964 struct servent *svc_info;
965 CHECK_STRING (service);
966 svc_info = getservbyname ((char *) XSTRING_DATA (service), "tcp");
968 error ("Unknown service \"%s\"", XSTRING_DATA (service));
969 port = svc_info->s_port;
972 get_internet_address (host, &address, ERROR_ME);
973 address.sin_port = port;
975 s = socket (address.sin_family, SOCK_STREAM, 0);
977 report_file_error ("error creating socket", list1 (name));
979 /* We don't want to be blocked on connect */
981 unsigned long nonblock = 1;
982 ioctlsocket (s, FIONBIO, &nonblock);
985 retval = connect (s, (struct sockaddr *) &address, sizeof (address));
986 if (retval != NO_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
988 /* Wait while connection is established */
1001 /* Poll for quit every 250 ms */
1003 tv.tv_usec = 250 * 1000;
1007 nsel = select (0, NULL, &fdset, &fdset, &tv);
1011 /* Check: was connection successful or not? */
1013 nsel = select (0, NULL, NULL, &fdset, &tv);
1015 goto connect_failed;
1021 /* We are connected at this point */
1023 DuplicateHandle (GetCurrentProcess(), (HANDLE)s,
1024 GetCurrentProcess(), (LPHANDLE)voutfd,
1025 0, FALSE, DUPLICATE_SAME_ACCESS);
1030 if (INTP (service)) {
1031 warn_when_safe(Qstream, Qwarning,
1032 "failure to open network stream to host \"%s\" for service \"%d\"",
1033 XSTRING_DATA (host),
1034 (unsigned short) XINT (service));
1037 warn_when_safe(Qstream, Qwarning,
1038 "failure to open network stream to host \"%s\" for service \"%s\"",
1039 XSTRING_DATA (host),
1040 XSTRING_DATA (service));
1042 report_file_error ("connection failed", list2 (host, name));
1047 /*-----------------------------------------------------------------------*/
1048 /* Initialization */
1049 /*-----------------------------------------------------------------------*/
1052 process_type_create_nt (void)
1054 PROCESS_HAS_METHOD (nt, alloc_process_data);
1055 PROCESS_HAS_METHOD (nt, finalize_process_data);
1056 PROCESS_HAS_METHOD (nt, init_process);
1057 PROCESS_HAS_METHOD (nt, create_process);
1058 PROCESS_HAS_METHOD (nt, update_status_if_terminated);
1059 PROCESS_HAS_METHOD (nt, send_process);
1060 PROCESS_HAS_METHOD (nt, kill_child_process);
1061 PROCESS_HAS_METHOD (nt, kill_process_by_pid);
1063 PROCESS_HAS_METHOD (nt, canonicalize_host_name);
1064 PROCESS_HAS_METHOD (nt, open_network_stream);
1065 #ifdef HAVE_MULTICAST
1066 #error I won't do this until '95 has winsock2
1067 PROCESS_HAS_METHOD (nt, open_multicast_group);
1073 syms_of_process_nt (void)
1075 defsymbol (&Qnt_quote_process_args, "nt-quote-process-args");
1079 vars_of_process_nt (void)