1 /* exechelp-w32.c - Fork and exec helpers for W32.
2 * Copyright (C) 2004, 2007, 2008, 2009,
3 * 2010 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * This file is free software; you can redistribute it and/or modify
8 * it under the terms of either
10 * - the GNU Lesser General Public License as published by the Free
11 * Software Foundation; either version 3 of the License, or (at
12 * your option) any later version.
16 * - the GNU General Public License as published by the Free
17 * Software Foundation; either version 2 of the License, or (at
18 * your option) any later version.
20 * or both in parallel, as here.
22 * This file is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, see <http://www.gnu.org/licenses/>.
33 #if !defined(HAVE_W32_SYSTEM) || defined (HAVE_W32CE_SYSTEM)
34 #error This code is only used on W32.
48 #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */
58 # include <sys/stat.h>
67 /* Define to 1 do enable debugging. */
68 #define DEBUG_W32_SPAWN 1
71 /* It seems Vista doesn't grok X_OK and so fails access() tests.
72 Previous versions interpreted X_OK as F_OK anyway, so we'll just
77 /* We assume that a HANDLE can be represented by an int which should
78 be true for all i386 systems (HANDLE is defined as void *) and
79 these are the only systems for which Windows is available. Further
80 we assume that -1 denotes an invalid handle. */
81 # define fd_to_handle(a) ((HANDLE)(a))
82 # define handle_to_fd(a) ((int)(a))
83 # define pid_to_handle(a) ((HANDLE)(a))
84 # define handle_to_pid(a) ((int)(a))
87 /* Return the maximum number of currently allowed open file
88 descriptors. Only useful on POSIX systems but returns a value on
101 max_fds = 256; /* Arbitrary limit. */
107 /* Under Windows this is a dummy function. */
109 close_all_fds (int first, int *except)
116 /* Returns an array with all currently open file descriptors. The end
117 of the array is marked by -1. The caller needs to release this
118 array using the *standard free* and not with xfree. This allow the
119 use of this fucntion right at startup even before libgcrypt has
120 been initialized. Returns NULL on error and sets ERRNO
123 get_all_open_fds (void)
129 array = calloc (1, sizeof *array);
135 max_fd = get_max_fds ();
136 narray = 32; /* If you change this change also t-exechelp.c. */
137 array = calloc (narray, sizeof *array);
141 /* Note: The list we return is ordered. */
142 for (idx=0, fd=0; fd < max_fd; fd++)
143 if (!(fstat (fd, &statbuf) == -1 && errno == EBADF))
149 narray += (narray < 256)? 32:256;
150 tmp = realloc (array, narray * sizeof *array);
166 /* Helper function to build_w32_commandline. */
168 build_w32_commandline_copy (char *buffer, const char *string)
173 if (!*string) /* Empty string. */
174 p = stpcpy (p, "\"\"");
175 else if (strpbrk (string, " \t\n\v\f\""))
177 /* Need to do some kind of quoting. */
178 p = stpcpy (p, "\"");
179 for (s=string; *s; s++)
189 p = stpcpy (p, string);
194 /* Build a command line for use with W32's CreateProcess. On success
195 CMDLINE gets the address of a newly allocated string. */
197 build_w32_commandline (const char *pgmname, const char * const *argv,
207 n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */
210 n++; /* Need to double inner quotes. */
211 for (i=0; (s=argv[i]); i++)
213 n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */
216 n++; /* Need to double inner quotes. */
220 buf = p = xtrymalloc (n);
222 return gpg_error_from_syserror ();
224 p = build_w32_commandline_copy (p, pgmname);
225 for (i=0; argv[i]; i++)
228 p = build_w32_commandline_copy (p, argv[i]);
236 /* Create pipe where one end is inheritable: With an INHERIT_IDX of 0
237 the read end is inheritable, with 1 the write end is inheritable. */
239 create_inheritable_pipe (HANDLE filedes[2], int inherit_idx)
242 SECURITY_ATTRIBUTES sec_attr;
244 memset (&sec_attr, 0, sizeof sec_attr );
245 sec_attr.nLength = sizeof sec_attr;
246 sec_attr.bInheritHandle = FALSE;
248 if (!CreatePipe (&r, &w, &sec_attr, 0))
251 if (!DuplicateHandle (GetCurrentProcess(), inherit_idx? w : r,
252 GetCurrentProcess(), &h, 0,
253 TRUE, DUPLICATE_SAME_ACCESS ))
255 log_error ("DuplicateHandle failed: %s\n", w32_strerror (-1));
279 w32_open_null (int for_write)
283 hfile = CreateFileW (L"nul",
284 for_write? GENERIC_WRITE : GENERIC_READ,
285 FILE_SHARE_READ | FILE_SHARE_WRITE,
286 NULL, OPEN_EXISTING, 0, NULL);
287 if (hfile == INVALID_HANDLE_VALUE)
288 log_debug ("can't open 'nul': %s\n", w32_strerror (-1));
294 do_create_pipe (int filedes[2], int inherit_idx)
299 filedes[0] = filedes[1] = -1;
300 err = gpg_error (GPG_ERR_GENERAL);
301 if (!create_inheritable_pipe (fds, inherit_idx))
303 filedes[0] = _open_osfhandle (handle_to_fd (fds[0]), 0);
304 if (filedes[0] == -1)
306 log_error ("failed to translate osfhandle %p\n", fds[0]);
307 CloseHandle (fds[1]);
311 filedes[1] = _open_osfhandle (handle_to_fd (fds[1]), 1);
312 if (filedes[1] == -1)
314 log_error ("failed to translate osfhandle %p\n", fds[1]);
317 CloseHandle (fds[1]);
326 /* Portable function to create a pipe. Under Windows the write end is
329 gnupg_create_inbound_pipe (int filedes[2])
331 return do_create_pipe (filedes, 1);
335 /* Portable function to create a pipe. Under Windows the read end is
338 gnupg_create_outbound_pipe (int filedes[2])
340 return do_create_pipe (filedes, 0);
344 /* Fork and exec the PGMNAME, see exechelp.h for details. */
346 gnupg_spawn_process (const char *pgmname, const char *argv[],
347 gpg_err_source_t errsource,
348 void (*preexec)(void), unsigned int flags,
355 SECURITY_ATTRIBUTES sec_attr;
356 PROCESS_INFORMATION pi =
358 NULL, /* Returns process handle. */
359 0, /* Returns primary thread handle. */
360 0, /* Returns pid. */
366 HANDLE inpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
367 HANDLE outpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
368 HANDLE errpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
369 estream_t infp = NULL;
370 estream_t outfp = NULL;
371 estream_t errfp = NULL;
372 HANDLE nullhd[3] = {INVALID_HANDLE_VALUE,
373 INVALID_HANDLE_VALUE,
374 INVALID_HANDLE_VALUE};
384 *pid = (pid_t)(-1); /* Always required. */
388 if (create_inheritable_pipe (inpipe, 0))
390 err = gpg_err_make (errsource, GPG_ERR_GENERAL);
391 log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
395 syshd.type = ES_SYSHD_HANDLE;
396 syshd.u.handle = inpipe[1];
397 infp = es_sysopen (&syshd, "w");
400 err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
401 log_error (_("error creating a stream for a pipe: %s\n"),
403 CloseHandle (inpipe[0]);
404 CloseHandle (inpipe[1]);
405 inpipe[0] = inpipe[1] = INVALID_HANDLE_VALUE;
412 if (create_inheritable_pipe (outpipe, 1))
414 err = gpg_err_make (errsource, GPG_ERR_GENERAL);
415 log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
419 syshd.type = ES_SYSHD_HANDLE;
420 syshd.u.handle = outpipe[0];
421 outfp = es_sysopen (&syshd, "r");
424 err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
425 log_error (_("error creating a stream for a pipe: %s\n"),
427 CloseHandle (outpipe[0]);
428 CloseHandle (outpipe[1]);
429 outpipe[0] = outpipe[1] = INVALID_HANDLE_VALUE;
432 else if (inpipe[1] != INVALID_HANDLE_VALUE)
433 CloseHandle (outpipe[1]);
434 if (inpipe[0] != INVALID_HANDLE_VALUE)
435 CloseHandle (inpipe[0]);
442 if (create_inheritable_pipe (errpipe, 1))
444 err = gpg_err_make (errsource, GPG_ERR_GENERAL);
445 log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
449 syshd.type = ES_SYSHD_HANDLE;
450 syshd.u.handle = errpipe[0];
451 errfp = es_sysopen (&syshd, "r");
454 err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
455 log_error (_("error creating a stream for a pipe: %s\n"),
457 CloseHandle (errpipe[0]);
458 CloseHandle (errpipe[1]);
459 errpipe[0] = errpipe[1] = INVALID_HANDLE_VALUE;
462 else if (outpipe[0] != INVALID_HANDLE_VALUE)
463 CloseHandle (outpipe[0]);
464 if (outpipe[1] != INVALID_HANDLE_VALUE)
465 CloseHandle (outpipe[1]);
468 else if (inpipe[1] != INVALID_HANDLE_VALUE)
469 CloseHandle (outpipe[1]);
470 if (inpipe[0] != INVALID_HANDLE_VALUE)
471 CloseHandle (inpipe[0]);
476 /* Prepare security attributes. */
477 memset (&sec_attr, 0, sizeof sec_attr );
478 sec_attr.nLength = sizeof sec_attr;
479 sec_attr.bInheritHandle = FALSE;
481 /* Build the command line. */
482 err = build_w32_commandline (pgmname, argv, &cmdline);
486 if (inpipe[0] != INVALID_HANDLE_VALUE)
487 nullhd[0] = w32_open_null (0);
488 if (outpipe[1] != INVALID_HANDLE_VALUE)
489 nullhd[1] = w32_open_null (0);
490 if (errpipe[1] != INVALID_HANDLE_VALUE)
491 nullhd[2] = w32_open_null (0);
493 /* Start the process. Note that we can't run the PREEXEC function
494 because this might change our own environment. */
497 memset (&si, 0, sizeof si);
499 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
500 si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
501 si.hStdInput = inpipe[0] == INVALID_HANDLE_VALUE? nullhd[0] : inpipe[0];
502 si.hStdOutput = outpipe[1] == INVALID_HANDLE_VALUE? nullhd[1] : outpipe[1];
503 si.hStdError = errpipe[1] == INVALID_HANDLE_VALUE? nullhd[2] : errpipe[1];
505 cr_flags = (CREATE_DEFAULT_ERROR_MODE
506 | ((flags & GNUPG_SPAWN_DETACHED)? DETACHED_PROCESS : 0)
507 | GetPriorityClass (GetCurrentProcess ())
509 /* log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */
510 if (!CreateProcess (pgmname, /* Program to start. */
511 cmdline, /* Command line arguments. */
512 &sec_attr, /* Process security attributes. */
513 &sec_attr, /* Thread security attributes. */
514 TRUE, /* Inherit handles. */
515 cr_flags, /* Creation flags. */
516 NULL, /* Environment. */
517 NULL, /* Use current drive/directory. */
518 &si, /* Startup information. */
519 &pi /* Returns process information. */
522 log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
526 else if (inpipe[1] != INVALID_HANDLE_VALUE)
527 CloseHandle (outpipe[1]);
528 if (inpipe[0] != INVALID_HANDLE_VALUE)
529 CloseHandle (inpipe[0]);
532 else if (outpipe[0] != INVALID_HANDLE_VALUE)
533 CloseHandle (outpipe[0]);
534 if (outpipe[1] != INVALID_HANDLE_VALUE)
535 CloseHandle (outpipe[1]);
538 else if (errpipe[0] != INVALID_HANDLE_VALUE)
539 CloseHandle (errpipe[0]);
540 if (errpipe[1] != INVALID_HANDLE_VALUE)
541 CloseHandle (errpipe[1]);
542 return gpg_err_make (errsource, GPG_ERR_GENERAL);
547 /* Close the inherited handles to /dev/null. */
548 for (i=0; i < DIM (nullhd); i++)
549 if (nullhd[i] != INVALID_HANDLE_VALUE)
550 CloseHandle (nullhd[i]);
552 /* Close the inherited ends of the pipes. */
553 if (inpipe[0] != INVALID_HANDLE_VALUE)
554 CloseHandle (inpipe[0]);
555 if (outpipe[1] != INVALID_HANDLE_VALUE)
556 CloseHandle (outpipe[1]);
557 if (errpipe[1] != INVALID_HANDLE_VALUE)
558 CloseHandle (errpipe[1]);
560 /* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
561 /* " dwProcessID=%d dwThreadId=%d\n", */
562 /* pi.hProcess, pi.hThread, */
563 /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
564 /* log_debug (" outfp=%p errfp=%p\n", outfp, errfp); */
566 /* Fixme: For unknown reasons AllowSetForegroundWindow returns an
567 invalid argument error if we pass it the correct processID. As a
568 workaround we use -1 (ASFW_ANY). */
569 if ((flags & GNUPG_SPAWN_RUN_ASFW))
570 gnupg_allow_set_foregound_window ((pid_t)(-1)/*pi.dwProcessId*/);
572 /* Process has been created suspended; resume it now. */
573 ResumeThread (pi.hThread);
574 CloseHandle (pi.hThread);
583 *pid = handle_to_pid (pi.hProcess);
590 /* Simplified version of gnupg_spawn_process. This function forks and
591 then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
592 and ERRFD to stderr (any of them may be -1 to connect them to
593 /dev/null). The arguments for the process are expected in the NULL
594 terminated array ARGV. The program name itself should not be
595 included there. Calling gnupg_wait_process is required.
597 Returns 0 on success or an error code. */
599 gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
600 int infd, int outfd, int errfd, pid_t *pid)
603 SECURITY_ATTRIBUTES sec_attr;
604 PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
610 /* Setup return values. */
613 /* Prepare security attributes. */
614 memset (&sec_attr, 0, sizeof sec_attr );
615 sec_attr.nLength = sizeof sec_attr;
616 sec_attr.bInheritHandle = FALSE;
618 /* Build the command line. */
619 err = build_w32_commandline (pgmname, argv, &cmdline);
623 memset (&si, 0, sizeof si);
625 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
626 si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
627 stdhd[0] = infd == -1? w32_open_null (0) : INVALID_HANDLE_VALUE;
628 stdhd[1] = outfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
629 stdhd[2] = errfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
630 si.hStdInput = infd == -1? stdhd[0] : (void*)_get_osfhandle (infd);
631 si.hStdOutput = outfd == -1? stdhd[1] : (void*)_get_osfhandle (outfd);
632 si.hStdError = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd);
634 /* log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */
635 if (!CreateProcess (pgmname, /* Program to start. */
636 cmdline, /* Command line arguments. */
637 &sec_attr, /* Process security attributes. */
638 &sec_attr, /* Thread security attributes. */
639 TRUE, /* Inherit handles. */
640 (CREATE_DEFAULT_ERROR_MODE
641 | GetPriorityClass (GetCurrentProcess ())
642 | CREATE_SUSPENDED | DETACHED_PROCESS),
643 NULL, /* Environment. */
644 NULL, /* Use current drive/directory. */
645 &si, /* Startup information. */
646 &pi /* Returns process information. */
649 log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
650 err = gpg_error (GPG_ERR_GENERAL);
655 for (i=0; i < 3; i++)
656 if (stdhd[i] != INVALID_HANDLE_VALUE)
657 CloseHandle (stdhd[i]);
661 /* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
662 /* " dwProcessID=%d dwThreadId=%d\n", */
663 /* pi.hProcess, pi.hThread, */
664 /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
666 /* Process has been created suspended; resume it now. */
667 ResumeThread (pi.hThread);
668 CloseHandle (pi.hThread);
670 *pid = handle_to_pid (pi.hProcess);
676 /* See exechelp.h for a description. */
678 gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode)
681 HANDLE proc = fd_to_handle (pid);
688 if (pid == (pid_t)(-1))
689 return gpg_error (GPG_ERR_INV_VALUE);
691 /* FIXME: We should do a pth_waitpid here. However this has not yet
692 been implemented. A special W32 pth system call would even be
694 code = WaitForSingleObject (proc, hang? INFINITE : 0);
698 ec = GPG_ERR_TIMEOUT;
702 log_error (_("waiting for process %d to terminate failed: %s\n"),
703 (int)pid, w32_strerror (-1));
704 ec = GPG_ERR_GENERAL;
708 if (!GetExitCodeProcess (proc, &exc))
710 log_error (_("error getting exit code of process %d: %s\n"),
711 (int)pid, w32_strerror (-1) );
712 ec = GPG_ERR_GENERAL;
716 log_error (_("error running '%s': exit status %d\n"),
719 *r_exitcode = (int)exc;
720 ec = GPG_ERR_GENERAL;
731 log_error ("WaitForSingleObject returned unexpected "
732 "code %d for pid %d\n", code, (int)pid );
733 ec = GPG_ERR_GENERAL;
737 return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
743 gnupg_release_process (pid_t pid)
745 if (pid != (pid_t)INVALID_HANDLE_VALUE)
747 HANDLE process = (HANDLE)pid;
749 CloseHandle (process);
754 /* Spawn a new process and immediatley detach from it. The name of
755 the program to exec is PGMNAME and its arguments are in ARGV (the
756 programname is automatically passed as first argument).
757 Environment strings in ENVP are set. An error is returned if
758 pgmname is not executable; to make this work it is necessary to
759 provide an absolute file name. All standard file descriptors are
760 connected to /dev/null. */
762 gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
766 SECURITY_ATTRIBUTES sec_attr;
767 PROCESS_INFORMATION pi =
769 NULL, /* Returns process handle. */
770 0, /* Returns primary thread handle. */
771 0, /* Returns pid. */
779 /* We don't use ENVP. */
782 if (access (pgmname, X_OK))
783 return gpg_error_from_syserror ();
785 /* Prepare security attributes. */
786 memset (&sec_attr, 0, sizeof sec_attr );
787 sec_attr.nLength = sizeof sec_attr;
788 sec_attr.bInheritHandle = FALSE;
790 /* Build the command line. */
791 err = build_w32_commandline (pgmname, argv, &cmdline);
795 /* Start the process. */
796 memset (&si, 0, sizeof si);
798 si.dwFlags = STARTF_USESHOWWINDOW;
799 si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
801 cr_flags = (CREATE_DEFAULT_ERROR_MODE
802 | GetPriorityClass (GetCurrentProcess ())
803 | CREATE_NEW_PROCESS_GROUP
805 /* log_debug ("CreateProcess(detached), path='%s' cmdline='%s'\n", */
806 /* pgmname, cmdline); */
807 if (!CreateProcess (pgmname, /* Program to start. */
808 cmdline, /* Command line arguments. */
809 &sec_attr, /* Process security attributes. */
810 &sec_attr, /* Thread security attributes. */
811 FALSE, /* Inherit handles. */
812 cr_flags, /* Creation flags. */
813 NULL, /* Environment. */
814 NULL, /* Use current drive/directory. */
815 &si, /* Startup information. */
816 &pi /* Returns process information. */
819 log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1));
821 return gpg_error (GPG_ERR_GENERAL);
826 /* log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p" */
827 /* " dwProcessID=%d dwThreadId=%d\n", */
828 /* pi.hProcess, pi.hThread, */
829 /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
831 CloseHandle (pi.hThread);
837 /* Kill a process; that is send an appropriate signal to the process.
838 gnupg_wait_process must be called to actually remove the process
839 from the system. An invalid PID is ignored. */
841 gnupg_kill_process (pid_t pid)
843 if (pid != (pid_t) INVALID_HANDLE_VALUE)
845 HANDLE process = (HANDLE) pid;
847 /* Arbitrary error code. */
848 TerminateProcess (process, 1);