gpg: Do not bail on an invalid packet in the local keyring.
[gnupg.git] / common / exechelp-w32.c
1 /* exechelp-w32.c - Fork and exec helpers for W32.
2  * Copyright (C) 2004, 2007-2009, 2010 Free Software Foundation, Inc.
3  * Copyright (C) 2004, 2006-2012, 2014-2017 g10 Code GmbH
4  *
5  * This file is part of GnuPG.
6  *
7  * This file is free software; you can redistribute it and/or modify
8  * it under the terms of either
9  *
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.
13  *
14  * or
15  *
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.
19  *
20  * or both in parallel, as here.
21  *
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.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, see <https://www.gnu.org/licenses/>.
29  * SPDX-License-Identifier: (LGPL-3.0+ OR GPL-2.0+)
30  */
31
32 #include <config.h>
33
34 #if !defined(HAVE_W32_SYSTEM) || defined (HAVE_W32CE_SYSTEM)
35 #error This code is only used on W32.
36 #endif
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <errno.h>
42 #include <assert.h>
43 #ifdef HAVE_SIGNAL_H
44 # include <signal.h>
45 #endif
46 #include <unistd.h>
47 #include <fcntl.h>
48
49 #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth.  */
50 #undef HAVE_NPTH
51 #undef USE_NPTH
52 #endif
53
54 #ifdef HAVE_NPTH
55 #include <npth.h>
56 #endif
57
58 #ifdef HAVE_STAT
59 # include <sys/stat.h>
60 #endif
61
62
63 #include "util.h"
64 #include "i18n.h"
65 #include "sysutils.h"
66 #include "exechelp.h"
67
68 /* Define to 1 do enable debugging.  */
69 #define DEBUG_W32_SPAWN 0
70
71
72 /* It seems Vista doesn't grok X_OK and so fails access() tests.
73    Previous versions interpreted X_OK as F_OK anyway, so we'll just
74    use F_OK directly. */
75 #undef X_OK
76 #define X_OK F_OK
77
78 /* We assume that a HANDLE can be represented by an int which should
79    be true for all i386 systems (HANDLE is defined as void *) and
80    these are the only systems for which Windows is available.  Further
81    we assume that -1 denotes an invalid handle.  */
82 # define fd_to_handle(a)  ((HANDLE)(a))
83 # define handle_to_fd(a)  ((int)(a))
84 # define pid_to_handle(a) ((HANDLE)(a))
85 # define handle_to_pid(a) ((int)(a))
86
87
88 /* Helper */
89 static inline gpg_error_t
90 my_error_from_syserror (void)
91 {
92   return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
93 }
94
95 static inline gpg_error_t
96 my_error (int errcode)
97 {
98   return gpg_err_make (default_errsource, errcode);
99 }
100
101
102 /* Return the maximum number of currently allowed open file
103    descriptors.  Only useful on POSIX systems but returns a value on
104    other systems too.  */
105 int
106 get_max_fds (void)
107 {
108   int max_fds = -1;
109
110 #ifdef OPEN_MAX
111   if (max_fds == -1)
112     max_fds = OPEN_MAX;
113 #endif
114
115   if (max_fds == -1)
116     max_fds = 256;  /* Arbitrary limit.  */
117
118   return max_fds;
119 }
120
121
122 /* Under Windows this is a dummy function.  */
123 void
124 close_all_fds (int first, int *except)
125 {
126   (void)first;
127   (void)except;
128 }
129
130
131 /* Returns an array with all currently open file descriptors.  The end
132  * of the array is marked by -1.  The caller needs to release this
133  * array using the *standard free* and not with xfree.  This allow the
134  * use of this function right at startup even before libgcrypt has
135  * been initialized.  Returns NULL on error and sets ERRNO
136  * accordingly.  Note that fstat prints a warning to DebugView for all
137  * invalid fds which is a bit annoying.  We actually do not need this
138  * function in real code (close_all_fds is a dummy anyway) but we keep
139  * it for use by t-exechelp.c.  */
140 int *
141 get_all_open_fds (void)
142 {
143   int *array;
144   size_t narray;
145   int fd, max_fd, idx;
146 #ifndef HAVE_STAT
147   array = calloc (1, sizeof *array);
148   if (array)
149     array[0] = -1;
150 #else /*HAVE_STAT*/
151   struct stat statbuf;
152
153   max_fd = get_max_fds ();
154   narray = 32;  /* If you change this change also t-exechelp.c.  */
155   array = calloc (narray, sizeof *array);
156   if (!array)
157     return NULL;
158
159   /* Note:  The list we return is ordered.  */
160   for (idx=0, fd=0; fd < max_fd; fd++)
161     if (!(fstat (fd, &statbuf) == -1 && errno == EBADF))
162       {
163         if (idx+1 >= narray)
164           {
165             int *tmp;
166
167             narray += (narray < 256)? 32:256;
168             tmp = realloc (array, narray * sizeof *array);
169             if (!tmp)
170               {
171                 free (array);
172                 return NULL;
173               }
174             array = tmp;
175           }
176         array[idx++] = fd;
177       }
178   array[idx] = -1;
179 #endif /*HAVE_STAT*/
180   return array;
181 }
182
183
184 /* Helper function to build_w32_commandline. */
185 static char *
186 build_w32_commandline_copy (char *buffer, const char *string)
187 {
188   char *p = buffer;
189   const char *s;
190
191   if (!*string) /* Empty string. */
192     p = stpcpy (p, "\"\"");
193   else if (strpbrk (string, " \t\n\v\f\""))
194     {
195       /* Need to do some kind of quoting.  */
196       p = stpcpy (p, "\"");
197       for (s=string; *s; s++)
198         {
199           *p++ = *s;
200           if (*s == '\"')
201             *p++ = *s;
202         }
203       *p++ = '\"';
204       *p = 0;
205     }
206   else
207     p = stpcpy (p, string);
208
209   return p;
210 }
211
212 /* Build a command line for use with W32's CreateProcess.  On success
213    CMDLINE gets the address of a newly allocated string.  */
214 static gpg_error_t
215 build_w32_commandline (const char *pgmname, const char * const *argv,
216                        char **cmdline)
217 {
218   int i, n;
219   const char *s;
220   char *buf, *p;
221
222   *cmdline = NULL;
223   n = 0;
224   s = pgmname;
225   n += strlen (s) + 1 + 2;  /* (1 space, 2 quoting */
226   for (; *s; s++)
227     if (*s == '\"')
228       n++;  /* Need to double inner quotes.  */
229   for (i=0; (s=argv[i]); i++)
230     {
231       n += strlen (s) + 1 + 2;  /* (1 space, 2 quoting */
232       for (; *s; s++)
233         if (*s == '\"')
234           n++;  /* Need to double inner quotes.  */
235     }
236   n++;
237
238   buf = p = xtrymalloc (n);
239   if (!buf)
240     return my_error_from_syserror ();
241
242   p = build_w32_commandline_copy (p, pgmname);
243   for (i=0; argv[i]; i++)
244     {
245       *p++ = ' ';
246       p = build_w32_commandline_copy (p, argv[i]);
247     }
248
249   *cmdline= buf;
250   return 0;
251 }
252
253
254 #define INHERIT_READ    1
255 #define INHERIT_WRITE   2
256 #define INHERIT_BOTH    (INHERIT_READ|INHERIT_WRITE)
257
258 /* Create pipe.  FLAGS indicates which ends are inheritable.  */
259 static int
260 create_inheritable_pipe (HANDLE filedes[2], int flags)
261 {
262   HANDLE r, w;
263   SECURITY_ATTRIBUTES sec_attr;
264
265   memset (&sec_attr, 0, sizeof sec_attr );
266   sec_attr.nLength = sizeof sec_attr;
267   sec_attr.bInheritHandle = TRUE;
268
269   if (!CreatePipe (&r, &w, &sec_attr, 0))
270     return -1;
271
272   if ((flags & INHERIT_READ) == 0)
273     if (! SetHandleInformation (r, HANDLE_FLAG_INHERIT, 0))
274       goto fail;
275
276   if ((flags & INHERIT_WRITE) == 0)
277     if (! SetHandleInformation (w, HANDLE_FLAG_INHERIT, 0))
278       goto fail;
279
280   filedes[0] = r;
281   filedes[1] = w;
282   return 0;
283
284  fail:
285   log_error ("SetHandleInformation failed: %s\n", w32_strerror (-1));
286   CloseHandle (r);
287   CloseHandle (w);
288   return -1;
289 }
290
291
292 static HANDLE
293 w32_open_null (int for_write)
294 {
295   HANDLE hfile;
296
297   hfile = CreateFileW (L"nul",
298                        for_write? GENERIC_WRITE : GENERIC_READ,
299                        FILE_SHARE_READ | FILE_SHARE_WRITE,
300                        NULL, OPEN_EXISTING, 0, NULL);
301   if (hfile == INVALID_HANDLE_VALUE)
302     log_debug ("can't open 'nul': %s\n", w32_strerror (-1));
303   return hfile;
304 }
305
306
307 static gpg_error_t
308 create_pipe_and_estream (int filedes[2], int flags,
309                          estream_t *r_fp, int outbound, int nonblock)
310 {
311   gpg_error_t err = 0;
312   HANDLE fds[2];
313   es_syshd_t syshd;
314
315   filedes[0] = filedes[1] = -1;
316   err = my_error (GPG_ERR_GENERAL);
317   if (!create_inheritable_pipe (fds, flags))
318     {
319       filedes[0] = _open_osfhandle (handle_to_fd (fds[0]), O_RDONLY);
320       if (filedes[0] == -1)
321         {
322           log_error ("failed to translate osfhandle %p\n", fds[0]);
323           CloseHandle (fds[1]);
324         }
325       else
326         {
327           filedes[1] = _open_osfhandle (handle_to_fd (fds[1]), O_APPEND);
328           if (filedes[1] == -1)
329             {
330               log_error ("failed to translate osfhandle %p\n", fds[1]);
331               close (filedes[0]);
332               filedes[0] = -1;
333               CloseHandle (fds[1]);
334             }
335           else
336             err = 0;
337         }
338     }
339
340   if (! err && r_fp)
341     {
342       syshd.type = ES_SYSHD_HANDLE;
343       if (!outbound)
344         {
345           syshd.u.handle = fds[0];
346           *r_fp = es_sysopen (&syshd, nonblock? "r,nonblock" : "r");
347         }
348       else
349         {
350           syshd.u.handle = fds[1];
351           *r_fp = es_sysopen (&syshd, nonblock? "w,nonblock" : "w");
352         }
353       if (!*r_fp)
354         {
355           err = my_error_from_syserror ();
356           log_error (_("error creating a stream for a pipe: %s\n"),
357                      gpg_strerror (err));
358           close (filedes[0]);
359           close (filedes[1]);
360           filedes[0] = filedes[1] = -1;
361           return err;
362         }
363     }
364
365   return err;
366 }
367
368 /* Portable function to create a pipe.  Under Windows the write end is
369    inheritable.  If R_FP is not NULL, an estream is created for the
370    read end and stored at R_FP.  */
371 gpg_error_t
372 gnupg_create_inbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
373 {
374   return create_pipe_and_estream (filedes, INHERIT_WRITE,
375                                   r_fp, 0, nonblock);
376 }
377
378
379 /* Portable function to create a pipe.  Under Windows the read end is
380    inheritable.  If R_FP is not NULL, an estream is created for the
381    write end and stored at R_FP.  */
382 gpg_error_t
383 gnupg_create_outbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
384 {
385   return create_pipe_and_estream (filedes, INHERIT_READ,
386                                   r_fp, 1, nonblock);
387 }
388
389
390 /* Portable function to create a pipe.  Under Windows both ends are
391    inheritable.  */
392 gpg_error_t
393 gnupg_create_pipe (int filedes[2])
394 {
395   return create_pipe_and_estream (filedes, INHERIT_BOTH,
396                                   NULL, 0, 0);
397 }
398
399
400 /* Fork and exec the PGMNAME, see exechelp.h for details.  */
401 gpg_error_t
402 gnupg_spawn_process (const char *pgmname, const char *argv[],
403                      int *except, void (*preexec)(void), unsigned int flags,
404                      estream_t *r_infp,
405                      estream_t *r_outfp,
406                      estream_t *r_errfp,
407                      pid_t *pid)
408 {
409   gpg_error_t err;
410   SECURITY_ATTRIBUTES sec_attr;
411   PROCESS_INFORMATION pi =
412     {
413       NULL,      /* Returns process handle.  */
414       0,         /* Returns primary thread handle.  */
415       0,         /* Returns pid.  */
416       0          /* Returns tid.  */
417     };
418   STARTUPINFO si;
419   int cr_flags;
420   char *cmdline;
421   HANDLE inpipe[2]  = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
422   HANDLE outpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
423   HANDLE errpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
424   estream_t infp = NULL;
425   estream_t outfp = NULL;
426   estream_t errfp = NULL;
427   HANDLE nullhd[3] = {INVALID_HANDLE_VALUE,
428                       INVALID_HANDLE_VALUE,
429                       INVALID_HANDLE_VALUE};
430   int i;
431   es_syshd_t syshd;
432   gpg_err_source_t errsource = default_errsource;
433   int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK);
434
435   (void)except; /* Not yet used.  */
436
437   if (r_infp)
438     *r_infp = NULL;
439   if (r_outfp)
440     *r_outfp = NULL;
441   if (r_errfp)
442     *r_errfp = NULL;
443   *pid = (pid_t)(-1); /* Always required.  */
444
445   if (r_infp)
446     {
447       if (create_inheritable_pipe (inpipe, INHERIT_READ))
448         {
449           err = gpg_err_make (errsource, GPG_ERR_GENERAL);
450           log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
451           return err;
452         }
453
454       syshd.type = ES_SYSHD_HANDLE;
455       syshd.u.handle = inpipe[1];
456       infp = es_sysopen (&syshd, nonblock? "w,nonblock" : "w");
457       if (!infp)
458         {
459           err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
460           log_error (_("error creating a stream for a pipe: %s\n"),
461                      gpg_strerror (err));
462           CloseHandle (inpipe[0]);
463           CloseHandle (inpipe[1]);
464           inpipe[0] = inpipe[1] = INVALID_HANDLE_VALUE;
465           return err;
466         }
467     }
468
469   if (r_outfp)
470     {
471       if (create_inheritable_pipe (outpipe, INHERIT_WRITE))
472         {
473           err = gpg_err_make (errsource, GPG_ERR_GENERAL);
474           log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
475           return err;
476         }
477
478       syshd.type = ES_SYSHD_HANDLE;
479       syshd.u.handle = outpipe[0];
480       outfp = es_sysopen (&syshd, nonblock? "r,nonblock" : "r");
481       if (!outfp)
482         {
483           err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
484           log_error (_("error creating a stream for a pipe: %s\n"),
485                      gpg_strerror (err));
486           CloseHandle (outpipe[0]);
487           CloseHandle (outpipe[1]);
488           outpipe[0] = outpipe[1] = INVALID_HANDLE_VALUE;
489           if (infp)
490             es_fclose (infp);
491           else if (inpipe[1] != INVALID_HANDLE_VALUE)
492             CloseHandle (inpipe[1]);
493           if (inpipe[0] != INVALID_HANDLE_VALUE)
494             CloseHandle (inpipe[0]);
495           return err;
496         }
497     }
498
499   if (r_errfp)
500     {
501       if (create_inheritable_pipe (errpipe, INHERIT_WRITE))
502         {
503           err = gpg_err_make (errsource, GPG_ERR_GENERAL);
504           log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
505           return err;
506         }
507
508       syshd.type = ES_SYSHD_HANDLE;
509       syshd.u.handle = errpipe[0];
510       errfp = es_sysopen (&syshd, nonblock? "r,nonblock" : "r");
511       if (!errfp)
512         {
513           err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
514           log_error (_("error creating a stream for a pipe: %s\n"),
515                      gpg_strerror (err));
516           CloseHandle (errpipe[0]);
517           CloseHandle (errpipe[1]);
518           errpipe[0] = errpipe[1] = INVALID_HANDLE_VALUE;
519           if (outfp)
520             es_fclose (outfp);
521           else if (outpipe[0] != INVALID_HANDLE_VALUE)
522             CloseHandle (outpipe[0]);
523           if (outpipe[1] != INVALID_HANDLE_VALUE)
524             CloseHandle (outpipe[1]);
525           if (infp)
526             es_fclose (infp);
527           else if (inpipe[1] != INVALID_HANDLE_VALUE)
528             CloseHandle (inpipe[1]);
529           if (inpipe[0] != INVALID_HANDLE_VALUE)
530             CloseHandle (inpipe[0]);
531           return err;
532         }
533     }
534
535   /* Prepare security attributes.  */
536   memset (&sec_attr, 0, sizeof sec_attr );
537   sec_attr.nLength = sizeof sec_attr;
538   sec_attr.bInheritHandle = FALSE;
539
540   /* Build the command line.  */
541   err = build_w32_commandline (pgmname, argv, &cmdline);
542   if (err)
543     return err;
544
545   if (inpipe[0] == INVALID_HANDLE_VALUE)
546     nullhd[0] = w32_open_null (0);
547   if (outpipe[1] == INVALID_HANDLE_VALUE)
548     nullhd[1] = w32_open_null (1);
549   if (errpipe[1] == INVALID_HANDLE_VALUE)
550     nullhd[2] = w32_open_null (1);
551
552   /* Start the process.  Note that we can't run the PREEXEC function
553      because this might change our own environment. */
554   (void)preexec;
555
556   memset (&si, 0, sizeof si);
557   si.cb = sizeof (si);
558   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
559   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_HIDE;
560   si.hStdInput  = inpipe[0]  == INVALID_HANDLE_VALUE? nullhd[0] : inpipe[0];
561   si.hStdOutput = outpipe[1] == INVALID_HANDLE_VALUE? nullhd[1] : outpipe[1];
562   si.hStdError  = errpipe[1] == INVALID_HANDLE_VALUE? nullhd[2] : errpipe[1];
563
564   cr_flags = (CREATE_DEFAULT_ERROR_MODE
565               | ((flags & GNUPG_SPAWN_DETACHED)? DETACHED_PROCESS : 0)
566               | GetPriorityClass (GetCurrentProcess ())
567               | CREATE_SUSPENDED);
568 /*   log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */
569   if (!CreateProcess (pgmname,       /* Program to start.  */
570                       cmdline,       /* Command line arguments.  */
571                       &sec_attr,     /* Process security attributes.  */
572                       &sec_attr,     /* Thread security attributes.  */
573                       TRUE,          /* Inherit handles.  */
574                       cr_flags,      /* Creation flags.  */
575                       NULL,          /* Environment.  */
576                       NULL,          /* Use current drive/directory.  */
577                       &si,           /* Startup information. */
578                       &pi            /* Returns process information.  */
579                       ))
580     {
581       log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
582       xfree (cmdline);
583       if (infp)
584         es_fclose (infp);
585       else if (inpipe[1] != INVALID_HANDLE_VALUE)
586         CloseHandle (outpipe[1]);
587       if (inpipe[0] != INVALID_HANDLE_VALUE)
588         CloseHandle (inpipe[0]);
589       if (outfp)
590         es_fclose (outfp);
591       else if (outpipe[0] != INVALID_HANDLE_VALUE)
592         CloseHandle (outpipe[0]);
593       if (outpipe[1] != INVALID_HANDLE_VALUE)
594         CloseHandle (outpipe[1]);
595       if (errfp)
596         es_fclose (errfp);
597       else if (errpipe[0] != INVALID_HANDLE_VALUE)
598         CloseHandle (errpipe[0]);
599       if (errpipe[1] != INVALID_HANDLE_VALUE)
600         CloseHandle (errpipe[1]);
601       return gpg_err_make (errsource, GPG_ERR_GENERAL);
602     }
603   xfree (cmdline);
604   cmdline = NULL;
605
606   /* Close the inherited handles to /dev/null.  */
607   for (i=0; i < DIM (nullhd); i++)
608     if (nullhd[i] != INVALID_HANDLE_VALUE)
609       CloseHandle (nullhd[i]);
610
611   /* Close the inherited ends of the pipes.  */
612   if (inpipe[0] != INVALID_HANDLE_VALUE)
613     CloseHandle (inpipe[0]);
614   if (outpipe[1] != INVALID_HANDLE_VALUE)
615     CloseHandle (outpipe[1]);
616   if (errpipe[1] != INVALID_HANDLE_VALUE)
617     CloseHandle (errpipe[1]);
618
619   /* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
620   /*            " dwProcessID=%d dwThreadId=%d\n", */
621   /*            pi.hProcess, pi.hThread, */
622   /*            (int) pi.dwProcessId, (int) pi.dwThreadId); */
623   /* log_debug ("                     outfp=%p errfp=%p\n", outfp, errfp); */
624
625   /* Fixme: For unknown reasons AllowSetForegroundWindow returns an
626      invalid argument error if we pass it the correct processID.  As a
627      workaround we use -1 (ASFW_ANY).  */
628   if ((flags & GNUPG_SPAWN_RUN_ASFW))
629     gnupg_allow_set_foregound_window ((pid_t)(-1)/*pi.dwProcessId*/);
630
631   /* Process has been created suspended; resume it now. */
632   ResumeThread (pi.hThread);
633   CloseHandle (pi.hThread);
634
635   if (r_infp)
636     *r_infp = infp;
637   if (r_outfp)
638     *r_outfp = outfp;
639   if (r_errfp)
640     *r_errfp = errfp;
641
642   *pid = handle_to_pid (pi.hProcess);
643   return 0;
644
645 }
646
647
648
649 /* Simplified version of gnupg_spawn_process.  This function forks and
650    then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
651    and ERRFD to stderr (any of them may be -1 to connect them to
652    /dev/null).  The arguments for the process are expected in the NULL
653    terminated array ARGV.  The program name itself should not be
654    included there.  Calling gnupg_wait_process is required.
655
656    Returns 0 on success or an error code. */
657 gpg_error_t
658 gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
659                         int infd, int outfd, int errfd, pid_t *pid)
660 {
661   gpg_error_t err;
662   SECURITY_ATTRIBUTES sec_attr;
663   PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
664   STARTUPINFO si;
665   char *cmdline;
666   int i;
667   HANDLE stdhd[3];
668
669   /* Setup return values.  */
670   *pid = (pid_t)(-1);
671
672   /* Prepare security attributes.  */
673   memset (&sec_attr, 0, sizeof sec_attr );
674   sec_attr.nLength = sizeof sec_attr;
675   sec_attr.bInheritHandle = FALSE;
676
677   /* Build the command line.  */
678   err = build_w32_commandline (pgmname, argv, &cmdline);
679   if (err)
680     return err;
681
682   memset (&si, 0, sizeof si);
683   si.cb = sizeof (si);
684   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
685   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
686   stdhd[0] = infd  == -1? w32_open_null (0) : INVALID_HANDLE_VALUE;
687   stdhd[1] = outfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
688   stdhd[2] = errfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
689   si.hStdInput  = infd  == -1? stdhd[0] : (void*)_get_osfhandle (infd);
690   si.hStdOutput = outfd == -1? stdhd[1] : (void*)_get_osfhandle (outfd);
691   si.hStdError  = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd);
692
693 /*   log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */
694   if (!CreateProcess (pgmname,       /* Program to start.  */
695                       cmdline,       /* Command line arguments.  */
696                       &sec_attr,     /* Process security attributes.  */
697                       &sec_attr,     /* Thread security attributes.  */
698                       TRUE,          /* Inherit handles.  */
699                       (CREATE_DEFAULT_ERROR_MODE
700                        | GetPriorityClass (GetCurrentProcess ())
701                        | CREATE_SUSPENDED | DETACHED_PROCESS),
702                       NULL,          /* Environment.  */
703                       NULL,          /* Use current drive/directory.  */
704                       &si,           /* Startup information. */
705                       &pi            /* Returns process information.  */
706                       ))
707     {
708       log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
709       err = my_error (GPG_ERR_GENERAL);
710     }
711   else
712     err = 0;
713   xfree (cmdline);
714   for (i=0; i < 3; i++)
715     if (stdhd[i] != INVALID_HANDLE_VALUE)
716       CloseHandle (stdhd[i]);
717   if (err)
718     return err;
719
720 /*   log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
721 /*              " dwProcessID=%d dwThreadId=%d\n", */
722 /*              pi.hProcess, pi.hThread, */
723 /*              (int) pi.dwProcessId, (int) pi.dwThreadId); */
724
725   /* Process has been created suspended; resume it now. */
726   ResumeThread (pi.hThread);
727   CloseHandle (pi.hThread);
728
729   *pid = handle_to_pid (pi.hProcess);
730   return 0;
731
732 }
733
734
735 /* See exechelp.h for a description.  */
736 gpg_error_t
737 gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode)
738 {
739   return gnupg_wait_processes (&pgmname, &pid, 1, hang, r_exitcode);
740 }
741
742 /* See exechelp.h for a description.  */
743 gpg_error_t
744 gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count,
745                       int hang, int *r_exitcodes)
746 {
747   gpg_err_code_t ec = 0;
748   size_t i;
749   HANDLE *procs;
750   int code;
751
752   procs = xtrycalloc (count, sizeof *procs);
753   if (procs == NULL)
754     return my_error_from_syserror ();
755
756   for (i = 0; i < count; i++)
757     {
758       if (r_exitcodes)
759         r_exitcodes[i] = -1;
760
761       if (pids[i] == (pid_t)(-1))
762         return my_error (GPG_ERR_INV_VALUE);
763
764       procs[i] = fd_to_handle (pids[i]);
765     }
766
767   /* FIXME: We should do a pth_waitpid here.  However this has not yet
768      been implemented.  A special W32 pth system call would even be
769      better.  */
770   code = WaitForMultipleObjects (count, procs, TRUE, hang? INFINITE : 0);
771   switch (code)
772     {
773     case WAIT_TIMEOUT:
774       ec = GPG_ERR_TIMEOUT;
775       goto leave;
776
777     case WAIT_FAILED:
778       log_error (_("waiting for processes to terminate failed: %s\n"),
779                  w32_strerror (-1));
780       ec = GPG_ERR_GENERAL;
781       goto leave;
782
783     case WAIT_OBJECT_0:
784       for (i = 0; i < count; i++)
785         {
786           DWORD exc;
787
788           if (! GetExitCodeProcess (procs[i], &exc))
789             {
790               log_error (_("error getting exit code of process %d: %s\n"),
791                          (int) pids[i], w32_strerror (-1) );
792               ec = GPG_ERR_GENERAL;
793             }
794           else if (exc)
795             {
796               if (!r_exitcodes)
797                 log_error (_("error running '%s': exit status %d\n"),
798                            pgmnames[i], (int)exc);
799               else
800                 r_exitcodes[i] = (int)exc;
801               ec = GPG_ERR_GENERAL;
802             }
803           else
804             {
805               if (r_exitcodes)
806                 r_exitcodes[i] = 0;
807             }
808         }
809       break;
810
811     default:
812       log_error ("WaitForMultipleObjects returned unexpected "
813                  "code %d\n", code);
814       ec = GPG_ERR_GENERAL;
815       break;
816     }
817
818  leave:
819   return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
820 }
821
822
823
824 void
825 gnupg_release_process (pid_t pid)
826 {
827   if (pid != (pid_t)INVALID_HANDLE_VALUE)
828     {
829       HANDLE process = (HANDLE)pid;
830
831       CloseHandle (process);
832     }
833 }
834
835
836 /* Spawn a new process and immediately detach from it.  The name of
837    the program to exec is PGMNAME and its arguments are in ARGV (the
838    programname is automatically passed as first argument).
839    Environment strings in ENVP are set.  An error is returned if
840    pgmname is not executable; to make this work it is necessary to
841    provide an absolute file name.  All standard file descriptors are
842    connected to /dev/null. */
843 gpg_error_t
844 gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
845                               const char *envp[] )
846 {
847   gpg_error_t err;
848   SECURITY_ATTRIBUTES sec_attr;
849   PROCESS_INFORMATION pi =
850     {
851       NULL,      /* Returns process handle.  */
852       0,         /* Returns primary thread handle.  */
853       0,         /* Returns pid.  */
854       0          /* Returns tid.  */
855     };
856   STARTUPINFO si;
857   int cr_flags;
858   char *cmdline;
859   BOOL in_job = FALSE;
860
861
862   /* We don't use ENVP.  */
863   (void)envp;
864
865   if (access (pgmname, X_OK))
866     return my_error_from_syserror ();
867
868   /* Prepare security attributes.  */
869   memset (&sec_attr, 0, sizeof sec_attr );
870   sec_attr.nLength = sizeof sec_attr;
871   sec_attr.bInheritHandle = FALSE;
872
873   /* Build the command line.  */
874   err = build_w32_commandline (pgmname, argv, &cmdline);
875   if (err)
876     return err;
877
878   /* Start the process.  */
879   memset (&si, 0, sizeof si);
880   si.cb = sizeof (si);
881   si.dwFlags = STARTF_USESHOWWINDOW;
882   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
883
884   cr_flags = (CREATE_DEFAULT_ERROR_MODE
885               | GetPriorityClass (GetCurrentProcess ())
886               | CREATE_NEW_PROCESS_GROUP
887               | DETACHED_PROCESS);
888
889   /* Check if we were spawned as part of a Job.
890    * In a job we need to add CREATE_BREAKAWAY_FROM_JOB
891    * to the cr_flags, otherwise our child processes
892    * are killed when we terminate. */
893   if (!IsProcessInJob (GetCurrentProcess(), NULL, &in_job))
894     {
895       log_error ("IsProcessInJob() failed: %s\n", w32_strerror (-1));
896       in_job = FALSE;
897     }
898
899   if (in_job)
900     {
901       /* Only try to break away from job if it is allowed, otherwise
902        * CreateProcess() would fail with an "Access is denied" error. */
903       JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
904       if (!QueryInformationJobObject (NULL, JobObjectExtendedLimitInformation,
905                                       &info, sizeof info, NULL))
906         {
907           log_error ("QueryInformationJobObject() failed: %s\n",
908                      w32_strerror (-1));
909         }
910       else if ((info.BasicLimitInformation.LimitFlags &
911                 JOB_OBJECT_LIMIT_BREAKAWAY_OK))
912         {
913           log_debug ("Using CREATE_BREAKAWAY_FROM_JOB flag\n");
914           cr_flags |= CREATE_BREAKAWAY_FROM_JOB;
915         }
916       else if ((info.BasicLimitInformation.LimitFlags &
917                 JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK))
918         {
919           /* The child process should automatically detach from the job. */
920           log_debug ("Not using CREATE_BREAKAWAY_FROM_JOB flag; "
921                      "JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK is set\n");
922         }
923       else
924         {
925           /* It seems that the child process must remain in the job.
926            * This is not necessarily an error, although it can cause premature
927            * termination of the child process when the job is closed. */
928           log_debug ("Not using CREATE_BREAKAWAY_FROM_JOB flag\n");
929         }
930     }
931
932 /*   log_debug ("CreateProcess(detached), path='%s' cmdline='%s'\n", */
933 /*              pgmname, cmdline); */
934   if (!CreateProcess (pgmname,       /* Program to start.  */
935                       cmdline,       /* Command line arguments.  */
936                       &sec_attr,     /* Process security attributes.  */
937                       &sec_attr,     /* Thread security attributes.  */
938                       FALSE,         /* Inherit handles.  */
939                       cr_flags,      /* Creation flags.  */
940                       NULL,          /* Environment.  */
941                       NULL,          /* Use current drive/directory.  */
942                       &si,           /* Startup information. */
943                       &pi            /* Returns process information.  */
944                       ))
945     {
946       log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1));
947       xfree (cmdline);
948       return my_error (GPG_ERR_GENERAL);
949     }
950   xfree (cmdline);
951   cmdline = NULL;
952
953 /*   log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p" */
954 /*              " dwProcessID=%d dwThreadId=%d\n", */
955 /*              pi.hProcess, pi.hThread, */
956 /*              (int) pi.dwProcessId, (int) pi.dwThreadId); */
957
958   CloseHandle (pi.hThread);
959   CloseHandle (pi.hProcess);
960
961   return 0;
962 }
963
964
965 /* Kill a process; that is send an appropriate signal to the process.
966    gnupg_wait_process must be called to actually remove the process
967    from the system.  An invalid PID is ignored.  */
968 void
969 gnupg_kill_process (pid_t pid)
970 {
971   if (pid != (pid_t) INVALID_HANDLE_VALUE)
972     {
973       HANDLE process = (HANDLE) pid;
974
975       /* Arbitrary error code.  */
976       TerminateProcess (process, 1);
977     }
978 }