common: Add feature to ease using argparse's usage().
[gnupg.git] / common / exechelp-w32.c
index 4616bec..05e9e10 100644 (file)
@@ -4,12 +4,22 @@
  *
  * This file is part of GnuPG.
  *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either
  *
- * GnuPG is distributed in the hope that it will be useful,
+ *   - the GNU Lesser General Public License as published by the Free
+ *     Software Foundation; either version 3 of the License, or (at
+ *     your option) any later version.
+ *
+ * or
+ *
+ *   - the GNU General Public License as published by the Free
+ *     Software Foundation; either version 2 of the License, or (at
+ *     your option) any later version.
+ *
+ * or both in parallel, as here.
+ *
+ * This file is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
 #ifdef HAVE_SIGNAL_H
 # include <signal.h>
 #endif
-#include <unistd.h> 
+#include <unistd.h>
 #include <fcntl.h>
 
-#ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth.  */
-#undef HAVE_PTH
-#undef USE_GNU_PTH
+#ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth.  */
+#undef HAVE_NPTH
+#undef USE_NPTH
 #endif
 
-#ifdef USE_GNU_PTH      
-#include <pth.h>
+#ifdef HAVE_NPTH
+#include <npth.h>
 #endif
 
 #ifdef HAVE_STAT
@@ -94,43 +104,12 @@ get_max_fds (void)
 }
 
 
-/* Close all file descriptors starting with descriptor FIRST.  If
-   EXCEPT is not NULL, it is expected to be a list of file descriptors
-   which shall not be closed.  This list shall be sorted in ascending
-   order with the end marked by -1.  */
+/* Under Windows this is a dummy function.  */
 void
 close_all_fds (int first, int *except)
 {
-  int max_fd = get_max_fds ();
-  int fd, i, except_start;
-
-  if (except)
-    {
-      except_start = 0;
-      for (fd=first; fd < max_fd; fd++)
-        {
-          for (i=except_start; except[i] != -1; i++)
-            {
-              if (except[i] == fd)
-                {
-                  /* If we found the descriptor in the exception list
-                     we can start the next compare run at the next
-                     index because the exception list is ordered.  */
-                except_start = i + 1;
-                break;
-                }
-            }
-          if (except[i] == -1)
-            close (fd);
-        }
-    }
-  else
-    {
-      for (fd=first; fd < max_fd; fd++)
-        close (fd);
-    }
-
-  gpg_err_set_errno (0);
+  (void)first;
+  (void)except;
 }
 
 
@@ -158,7 +137,7 @@ get_all_open_fds (void)
   array = calloc (narray, sizeof *array);
   if (!array)
     return NULL;
-  
+
   /* Note:  The list we return is ordered.  */
   for (idx=0, fd=0; fd < max_fd; fd++)
     if (!(fstat (fd, &statbuf) == -1 && errno == EBADF))
@@ -215,7 +194,7 @@ build_w32_commandline_copy (char *buffer, const char *string)
 /* Build a command line for use with W32's CreateProcess.  On success
    CMDLINE gets the address of a newly allocated string.  */
 static gpg_error_t
-build_w32_commandline (const char *pgmname, const char * const *argv, 
+build_w32_commandline (const char *pgmname, const char * const *argv,
                        char **cmdline)
 {
   int i, n;
@@ -243,7 +222,7 @@ build_w32_commandline (const char *pgmname, const char * const *argv,
     return gpg_error_from_syserror ();
 
   p = build_w32_commandline_copy (p, pgmname);
-  for (i=0; argv[i]; i++) 
+  for (i=0; argv[i]; i++)
     {
       *p++ = ' ';
       p = build_w32_commandline_copy (p, argv[i]);
@@ -257,7 +236,7 @@ build_w32_commandline (const char *pgmname, const char * const *argv,
 /* Create pipe where one end is inheritable: With an INHERIT_IDX of 0
    the read end is inheritable, with 1 the write end is inheritable.  */
 static int
-create_inheritable_pipe (int filedes[2], int inherit_idx)
+create_inheritable_pipe (HANDLE filedes[2], int inherit_idx)
 {
   HANDLE r, w, h;
   SECURITY_ATTRIBUTES sec_attr;
@@ -265,7 +244,7 @@ create_inheritable_pipe (int filedes[2], int inherit_idx)
   memset (&sec_attr, 0, sizeof sec_attr );
   sec_attr.nLength = sizeof sec_attr;
   sec_attr.bInheritHandle = FALSE;
-    
+
   if (!CreatePipe (&r, &w, &sec_attr, 0))
     return -1;
 
@@ -290,8 +269,8 @@ create_inheritable_pipe (int filedes[2], int inherit_idx)
       r = h;
     }
 
-  filedes[0] = handle_to_fd (r);
-  filedes[1] = handle_to_fd (w);
+  filedes[0] = r;
+  filedes[1] = w;
   return 0;
 }
 
@@ -306,7 +285,7 @@ w32_open_null (int for_write)
                        FILE_SHARE_READ | FILE_SHARE_WRITE,
                        NULL, OPEN_EXISTING, 0, NULL);
   if (hfile == INVALID_HANDLE_VALUE)
-    log_debug ("can't open `nul': %s\n", w32_strerror (-1));
+    log_debug ("can't open 'nul': %s\n", w32_strerror (-1));
   return hfile;
 }
 
@@ -315,27 +294,27 @@ static gpg_error_t
 do_create_pipe (int filedes[2], int inherit_idx)
 {
   gpg_error_t err = 0;
-  int fds[2];
+  HANDLE fds[2];
 
   filedes[0] = filedes[1] = -1;
   err = gpg_error (GPG_ERR_GENERAL);
   if (!create_inheritable_pipe (fds, inherit_idx))
     {
-      filedes[0] = _open_osfhandle (fds[0], 0);
+      filedes[0] = _open_osfhandle (handle_to_fd (fds[0]), 0);
       if (filedes[0] == -1)
         {
-          log_error ("failed to translate osfhandle %p\n", (void*)fds[0]);
-          CloseHandle (fd_to_handle (fds[1]));
+          log_error ("failed to translate osfhandle %p\n", fds[0]);
+          CloseHandle (fds[1]);
         }
-      else 
+      else
         {
-          filedes[1] = _open_osfhandle (fds[1], 1);
+          filedes[1] = _open_osfhandle (handle_to_fd (fds[1]), 1);
           if (filedes[1] == -1)
             {
-              log_error ("failed to translate osfhandle %p\n", (void*)fds[1]);
+              log_error ("failed to translate osfhandle %p\n", fds[1]);
               close (filedes[0]);
               filedes[0] = -1;
-              CloseHandle (fd_to_handle (fds[1]));
+              CloseHandle (fds[1]);
             }
           else
             err = 0;
@@ -365,13 +344,16 @@ gnupg_create_outbound_pipe (int filedes[2])
 /* Fork and exec the PGMNAME, see exechelp.h for details.  */
 gpg_error_t
 gnupg_spawn_process (const char *pgmname, const char *argv[],
-                     estream_t infile, estream_t outfile,
+                     gpg_err_source_t errsource,
                      void (*preexec)(void), unsigned int flags,
-                     estream_t *statusfile, pid_t *pid)
+                     estream_t infp,
+                     estream_t *r_outfp,
+                     estream_t *r_errfp,
+                     pid_t *pid)
 {
   gpg_error_t err;
   SECURITY_ATTRIBUTES sec_attr;
-  PROCESS_INFORMATION pi = 
+  PROCESS_INFORMATION pi =
     {
       NULL,      /* Returns process handle.  */
       0,         /* Returns primary thread handle.  */
@@ -381,70 +363,138 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
   STARTUPINFO si;
   int cr_flags;
   char *cmdline;
-  int fd, fdout, rp[2];
-  HANDLE nullhd[];
+  HANDLE inhandle = INVALID_HANDLE_VALUE;
+  HANDLE outpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
+  HANDLE errpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
+  estream_t outfp = NULL;
+  estream_t errfp = NULL;
+  HANDLE nullhd[3] = {INVALID_HANDLE_VALUE,
+                      INVALID_HANDLE_VALUE,
+                      INVALID_HANDLE_VALUE};
   int i;
+  es_syshd_t syshd;
 
-  (void)preexec;
+  if (r_outfp)
+    *r_outfp = NULL;
+  if (r_errfp)
+    *r_errfp = NULL;
+  *pid = (pid_t)(-1); /* Always required.  */
 
-  /* Setup return values.  */
-  *statusfile = NULL;
-  *pid = (pid_t)(-1);
-  
-  if (infile)
+  if (infp)
+    {
+      es_fflush (infp);
+      es_rewind (infp);
+      es_syshd (infp, &syshd);
+      switch (syshd.type)
+        {
+        case ES_SYSHD_FD:
+          inhandle = (HANDLE)_get_osfhandle (syshd.u.fd);
+          break;
+        case ES_SYSHD_SOCK:
+          inhandle = (HANDLE)_get_osfhandle (syshd.u.sock);
+          break;
+        case ES_SYSHD_HANDLE:
+          inhandle = syshd.u.handle;
+          break;
+        default:
+          inhandle = INVALID_HANDLE_VALUE;
+          break;
+        }
+      if (inhandle == INVALID_HANDLE_VALUE)
+        return gpg_err_make (errsource, GPG_ERR_INV_VALUE);
+      /* FIXME: In case we can't get a system handle (e.g. due to
+         es_fopencookie we should create a piper and a feeder
+         thread.  */
+    }
+
+  if (r_outfp)
     {
-      es_fflush (infile);
-      es_rewind (infile);
-      fd = _get_osfhandle (es_fileno (infile));
+      if (create_inheritable_pipe (outpipe, 1))
+        {
+          err = gpg_err_make (errsource, GPG_ERR_GENERAL);
+          log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
+          return err;
+        }
+
+      syshd.type = ES_SYSHD_HANDLE;
+      syshd.u.handle = outpipe[0];
+      outfp = es_sysopen (&syshd, "r");
+      if (!outfp)
+        {
+          err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
+          log_error (_("error creating a stream for a pipe: %s\n"),
+                     gpg_strerror (err));
+          CloseHandle (outpipe[0]);
+          CloseHandle (outpipe[1]);
+          outpipe[0] = outpipe[1] = INVALID_HANDLE_VALUE;
+          return err;
+        }
     }
-  else
-    fd = -1;
 
-  if (outfile)
-    fdout = _get_osfhandle (es_fileno (outfile));
-  else
-    fdout = -1;
+  if (r_errfp)
+    {
+      if (create_inheritable_pipe (errpipe, 1))
+        {
+          err = gpg_err_make (errsource, GPG_ERR_GENERAL);
+          log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
+          return err;
+        }
 
-  if ( (infile && fd == -1) || (outfile && fdout == -1))
-    log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
+      syshd.type = ES_SYSHD_HANDLE;
+      syshd.u.handle = errpipe[0];
+      errfp = es_sysopen (&syshd, "r");
+      if (!errfp)
+        {
+          err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
+          log_error (_("error creating a stream for a pipe: %s\n"),
+                     gpg_strerror (err));
+          CloseHandle (errpipe[0]);
+          CloseHandle (errpipe[1]);
+          errpipe[0] = errpipe[1] = INVALID_HANDLE_VALUE;
+          if (outfp)
+            es_fclose (outfp);
+          else if (outpipe[0] != INVALID_HANDLE_VALUE)
+            CloseHandle (outpipe[0]);
+          if (outpipe[1] != INVALID_HANDLE_VALUE)
+            CloseHandle (outpipe[1]);
+          return err;
+        }
+    }
 
   /* Prepare security attributes.  */
   memset (&sec_attr, 0, sizeof sec_attr );
   sec_attr.nLength = sizeof sec_attr;
   sec_attr.bInheritHandle = FALSE;
-  
+
   /* Build the command line.  */
   err = build_w32_commandline (pgmname, argv, &cmdline);
   if (err)
-    return err; 
+    return err;
 
-  /* Create a pipe.  */
-  if (create_inheritable_pipe (rp, 1))
-    {
-      err = gpg_error (GPG_ERR_GENERAL);
-      log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
-      xfree (cmdline);
-      return err;
-    }
-  
-  nullhd[0] =    fd == -1? w32_open_null (0) : INVALID_HANDLE_VALUE;
-  nullhd[1] = outfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
+  if (inhandle != INVALID_HANDLE_VALUE)
+    nullhd[0] = w32_open_null (0);
+  if (outpipe[1] != INVALID_HANDLE_VALUE)
+    nullhd[1] = w32_open_null (0);
+  if (errpipe[1] != INVALID_HANDLE_VALUE)
+    nullhd[2] = w32_open_null (0);
 
   /* Start the process.  Note that we can't run the PREEXEC function
-     because this would change our own environment. */
+     because this might change our own environment. */
+  (void)preexec;
+
   memset (&si, 0, sizeof si);
   si.cb = sizeof (si);
   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
-  si.hStdInput  =    fd == -1? nullhd[0] : fd_to_handle (fd);
-  si.hStdOutput = outfd == -1? nullhd[1] : fd_to_handle (fdout);
-  si.hStdError  = fd_to_handle (rp[1]);
+  si.hStdInput  =   inhandle == INVALID_HANDLE_VALUE? nullhd[0] : inhandle;
+  si.hStdOutput = outpipe[1] == INVALID_HANDLE_VALUE? nullhd[1] : outpipe[1];
+  si.hStdError  = errpipe[1] == INVALID_HANDLE_VALUE? nullhd[2] : errpipe[1];
 
   cr_flags = (CREATE_DEFAULT_ERROR_MODE
               | ((flags & 128)? DETACHED_PROCESS : 0)
               | GetPriorityClass (GetCurrentProcess ())
-              | CREATE_SUSPENDED); 
-/*   log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */
+              | CREATE_SUSPENDED);
+/*   log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */
   if (!CreateProcess (pgmname,       /* Program to start.  */
                       cmdline,       /* Command line arguments.  */
                       &sec_attr,     /* Process security attributes.  */
@@ -459,9 +509,19 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
     {
       log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
       xfree (cmdline);
-      CloseHandle (fd_to_handle (rp[0]));
-      CloseHandle (fd_to_handle (rp[1]));
-      return gpg_error (GPG_ERR_GENERAL);
+      if (outfp)
+        es_fclose (outfp);
+      else if (outpipe[0] != INVALID_HANDLE_VALUE)
+        CloseHandle (outpipe[0]);
+      if (outpipe[1] != INVALID_HANDLE_VALUE)
+        CloseHandle (outpipe[1]);
+      if (errfp)
+        es_fclose (errfp);
+      else if (errpipe[0] != INVALID_HANDLE_VALUE)
+        CloseHandle (errpipe[0]);
+      if (errpipe[1] != INVALID_HANDLE_VALUE)
+        CloseHandle (errpipe[1]);
+      return gpg_err_make (errsource, GPG_ERR_GENERAL);
     }
   xfree (cmdline);
   cmdline = NULL;
@@ -471,40 +531,32 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
     if (nullhd[i] != INVALID_HANDLE_VALUE)
       CloseHandle (nullhd[i]);
 
-  /* Close the other end of the pipe.  */
-  CloseHandle (fd_to_handle (rp[1]));
-  
-/*   log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
-/*              " dwProcessID=%d dwThreadId=%d\n", */
-/*              pi.hProcess, pi.hThread, */
-/*              (int) pi.dwProcessId, (int) pi.dwThreadId); */
-  
+  /* Close the inherited ends of the pipes.  */
+  if (outpipe[1] != INVALID_HANDLE_VALUE)
+    CloseHandle (outpipe[1]);
+  if (errpipe[1] != INVALID_HANDLE_VALUE)
+    CloseHandle (errpipe[1]);
+
+  /* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
+  /*            " dwProcessID=%d dwThreadId=%d\n", */
+  /*            pi.hProcess, pi.hThread, */
+  /*            (int) pi.dwProcessId, (int) pi.dwThreadId); */
+  /* log_debug ("                     outfp=%p errfp=%p\n", outfp, errfp); */
+
   /* Fixme: For unknown reasons AllowSetForegroundWindow returns an
-     invalid argument error if we pass the correct processID to
-     it.  As a workaround we use -1 (ASFW_ANY).  */
+     invalid argument error if we pass it the correct processID.  As a
+     workaround we use -1 (ASFW_ANY).  */
   if ( (flags & 64) )
     gnupg_allow_set_foregound_window ((pid_t)(-1)/*pi.dwProcessId*/);
 
   /* Process has been created suspended; resume it now. */
   ResumeThread (pi.hThread);
-  CloseHandle (pi.hThread); 
-
-  {
-    int x;
-
-    x = _open_osfhandle (rp[0], 0);
-    if (x == -1)
-      log_error ("failed to translate osfhandle %p\n", (void*)rp[0] );
-    else 
-      *statusfile = es_fdopen (x, "r");
-  }
-  if (!*statusfile)
-    {
-      err = gpg_error_from_syserror ();
-      log_error (_("can't fdopen pipe for reading: %s\n"), gpg_strerror (err));
-      CloseHandle (pi.hProcess);
-      return err;
-    }
+  CloseHandle (pi.hThread);
+
+  if (r_outfp)
+    *r_outfp = outfp;
+  if (r_errfp)
+    *r_errfp = errfp;
 
   *pid = handle_to_pid (pi.hProcess);
   return 0;
@@ -540,11 +592,11 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
   memset (&sec_attr, 0, sizeof sec_attr );
   sec_attr.nLength = sizeof sec_attr;
   sec_attr.bInheritHandle = FALSE;
-  
+
   /* Build the command line.  */
   err = build_w32_commandline (pgmname, argv, &cmdline);
   if (err)
-    return err; 
+    return err;
 
   memset (&si, 0, sizeof si);
   si.cb = sizeof (si);
@@ -557,7 +609,7 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
   si.hStdOutput = outfd == -1? stdhd[1] : (void*)_get_osfhandle (outfd);
   si.hStdError  = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd);
 
-/*   log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */
+/*   log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */
   if (!CreateProcess (pgmname,       /* Program to start.  */
                       cmdline,       /* Command line arguments.  */
                       &sec_attr,     /* Process security attributes.  */
@@ -591,7 +643,7 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
 
   /* Process has been created suspended; resume it now. */
   ResumeThread (pi.hThread);
-  CloseHandle (pi.hThread); 
+  CloseHandle (pi.hThread);
 
   *pid = handle_to_pid (pi.hProcess);
   return 0;
@@ -599,22 +651,17 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
 }
 
 
-/* Wait for the process identified by PID to terminate. PGMNAME should
-   be the same as supplied to the spawn function and is only used for
-   diagnostics. Returns 0 if the process succeeded, GPG_ERR_GENERAL
-   for any failures of the spawned program or other error codes.  If
-   EXITCODE is not NULL the exit code of the process is stored at this
-   address or -1 if it could not be retrieved. */
+/* See exechelp.h for a description.  */
 gpg_error_t
-gnupg_wait_process (const char *pgmname, pid_t pid, int *exitcode)
+gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode)
 {
   gpg_err_code_t ec;
   HANDLE proc = fd_to_handle (pid);
   int code;
   DWORD exc;
 
-  if (exitcode)
-    *exitcode = -1;
+  if (r_exitcode)
+    *r_exitcode = -1;
 
   if (pid == (pid_t)(-1))
     return gpg_error (GPG_ERR_INV_VALUE);
@@ -622,50 +669,66 @@ gnupg_wait_process (const char *pgmname, pid_t pid, int *exitcode)
   /* FIXME: We should do a pth_waitpid here.  However this has not yet
      been implemented.  A special W32 pth system call would even be
      better.  */
-  code = WaitForSingleObject (proc, INFINITE);
-  switch (code) 
+  code = WaitForSingleObject (proc, hang? INFINITE : 0);
+  switch (code)
     {
-      case WAIT_FAILED:
-        log_error (_("waiting for process %d to terminate failed: %s\n"),
-                   (int)pid, w32_strerror (-1));
-        ec = GPG_ERR_GENERAL;
-        break;
-
-      case WAIT_OBJECT_0:
-        if (!GetExitCodeProcess (proc, &exc))
-          {
-            log_error (_("error getting exit code of process %d: %s\n"),
-                         (int)pid, w32_strerror (-1) );
-            ec = GPG_ERR_GENERAL;
-          }
-        else if (exc)
-          {
-            log_error (_("error running `%s': exit status %d\n"),
-                       pgmname, (int)exc );
-            if (exitcode)
-              *exitcode = (int)exc;
-            ec = GPG_ERR_GENERAL;
-          }
-        else
-          {
-            if (exitcode)
-              *exitcode = 0;
-            ec = 0;
-          }
-        CloseHandle (proc);
-        break;
-
-      default:
-        log_error ("WaitForSingleObject returned unexpected "
-                   "code %d for pid %d\n", code, (int)pid );
-        ec = GPG_ERR_GENERAL;
-        break;
+    case WAIT_TIMEOUT:
+      ec = GPG_ERR_TIMEOUT;
+      break;
+
+    case WAIT_FAILED:
+      log_error (_("waiting for process %d to terminate failed: %s\n"),
+                 (int)pid, w32_strerror (-1));
+      ec = GPG_ERR_GENERAL;
+      break;
+
+    case WAIT_OBJECT_0:
+      if (!GetExitCodeProcess (proc, &exc))
+        {
+          log_error (_("error getting exit code of process %d: %s\n"),
+                     (int)pid, w32_strerror (-1) );
+          ec = GPG_ERR_GENERAL;
+        }
+      else if (exc)
+        {
+          log_error (_("error running '%s': exit status %d\n"),
+                     pgmname, (int)exc );
+          if (r_exitcode)
+            *r_exitcode = (int)exc;
+          ec = GPG_ERR_GENERAL;
+        }
+      else
+        {
+          if (r_exitcode)
+            *r_exitcode = 0;
+          ec = 0;
+        }
+      break;
+
+    default:
+      log_error ("WaitForSingleObject returned unexpected "
+                 "code %d for pid %d\n", code, (int)pid );
+      ec = GPG_ERR_GENERAL;
+      break;
     }
 
   return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
 }
 
 
+
+void
+gnupg_release_process (pid_t pid)
+{
+  if (pid != (pid_t)INVALID_HANDLE_VALUE)
+    {
+      HANDLE process = (HANDLE)pid;
+
+      CloseHandle (process);
+    }
+}
+
+
 /* Spawn a new process and immediatley detach from it.  The name of
    the program to exec is PGMNAME and its arguments are in ARGV (the
    programname is automatically passed as first argument).
@@ -679,7 +742,7 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
 {
   gpg_error_t err;
   SECURITY_ATTRIBUTES sec_attr;
-  PROCESS_INFORMATION pi = 
+  PROCESS_INFORMATION pi =
     {
       NULL,      /* Returns process handle.  */
       0,         /* Returns primary thread handle.  */
@@ -691,10 +754,7 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
   char *cmdline;
 
 
-  /* FIXME: We don't make use of ENVP yet.  It is currently only used
-     to pass the GPG_AGENT_INFO variable to gpg-agent.  As the default
-     on windows is to use a standard socket, this does not really
-     matter.  */
+  /* We don't use ENVP.  */
   (void)envp;
 
   if (access (pgmname, X_OK))
@@ -704,11 +764,11 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
   memset (&sec_attr, 0, sizeof sec_attr );
   sec_attr.nLength = sizeof sec_attr;
   sec_attr.bInheritHandle = FALSE;
-  
+
   /* Build the command line.  */
   err = build_w32_commandline (pgmname, argv, &cmdline);
   if (err)
-    return err; 
+    return err;
 
   /* Start the process.  */
   memset (&si, 0, sizeof si);
@@ -719,8 +779,8 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
   cr_flags = (CREATE_DEFAULT_ERROR_MODE
               | GetPriorityClass (GetCurrentProcess ())
               | CREATE_NEW_PROCESS_GROUP
-              | DETACHED_PROCESS); 
-/*   log_debug ("CreateProcess(detached), path=`%s' cmdline=`%s'\n", */
+              | DETACHED_PROCESS);
+/*   log_debug ("CreateProcess(detached), path='%s' cmdline='%s'\n", */
 /*              pgmname, cmdline); */
   if (!CreateProcess (pgmname,       /* Program to start.  */
                       cmdline,       /* Command line arguments.  */
@@ -746,7 +806,7 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
 /*              pi.hProcess, pi.hThread, */
 /*              (int) pi.dwProcessId, (int) pi.dwThreadId); */
 
-  CloseHandle (pi.hThread); 
+  CloseHandle (pi.hThread);
 
   return 0;
 }
@@ -761,7 +821,7 @@ gnupg_kill_process (pid_t pid)
   if (pid != (pid_t) INVALID_HANDLE_VALUE)
     {
       HANDLE process = (HANDLE) pid;
-      
+
       /* Arbitrary error code.  */
       TerminateProcess (process, 1);
     }