Do handle G_SPAWN_DO_NOT_REAP_CHILD after all, similarily as on Unix. If
[platform/upstream/glib.git] / glib / gspawn-win32.c
1 /* gspawn-win32.c - Process launching on Win32
2  *
3  *  Copyright 2000 Red Hat, Inc.
4  *
5  * GLib is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * GLib is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with GLib; see the file COPYING.LIB.  If not, write
17  * to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Implementation details on Win32.
23  *
24  * - There is no way to set the no-inherit flag for
25  *   a "file descriptor" in the MS C runtime. The flag is there,
26  *   and the dospawn() function uses it, but unfortunately
27  *   this flag can only be set when opening the file.
28  * - As there is no fork(), we cannot reliably change directory
29  *   before starting the child process. (There might be several threads
30  *   running, and the current directory is common for all threads.)
31  *
32  * Thus, we must in most cases use a helper program to handle closing
33  * of (inherited) file descriptors and changing of directory. In fact,
34  * we do it all the time.
35  */
36
37 /* Define this to get some logging all the time */
38 /* #define G_SPAWN_WIN32_DEBUG */
39
40 #include <config.h>
41
42 #include "glib.h"
43
44 #include <string.h>
45 #include <stdlib.h>
46 #include <stdio.h>
47
48 #include <windows.h>
49 #include <errno.h>
50 #include <fcntl.h>
51 #include <io.h>
52 #include <process.h>
53 #include <direct.h>
54
55 #include "glibintl.h"
56
57 #ifdef G_SPAWN_WIN32_DEBUG
58   static int debug = 1;
59   #define SETUP_DEBUG() /* empty */
60
61 #else
62   static int debug = -1;
63   #define SETUP_DEBUG()                                 \
64     G_STMT_START                                        \
65       {                                                 \
66         if (debug == -1)                                \
67           {                                             \
68             if (getenv ("G_SPAWN_WIN32_DEBUG") != NULL) \
69               debug = 1;                                \
70             else                                        \
71               debug = 0;                                \
72           }                                             \
73       }                                                 \
74     G_STMT_END
75 #endif
76
77 enum
78 {
79   CHILD_NO_ERROR,
80   CHILD_CHDIR_FAILED,
81   CHILD_SPAWN_FAILED,
82 };
83
84 enum {
85   ARG_CHILD_ERR_REPORT = 1,
86   ARG_STDIN,
87   ARG_STDOUT,
88   ARG_STDERR,
89   ARG_WORKING_DIRECTORY,
90   ARG_CLOSE_DESCRIPTORS,
91   ARG_USE_PATH,
92   ARG_WAIT,
93   ARG_PROGRAM,
94   ARG_COUNT = ARG_PROGRAM
95 };
96
97 #ifndef GSPAWN_HELPER
98
99 static gboolean make_pipe            (gint                  p[2],
100                                       GError              **error);
101 static gboolean do_spawn_with_pipes  (gboolean              dont_wait,
102                                       gboolean              dont_return_handle,
103                                       const gchar          *working_directory,
104                                       gchar               **argv,
105                                       gchar               **envp,
106                                       gboolean              close_descriptors,
107                                       gboolean              search_path,
108                                       gboolean              stdout_to_null,
109                                       gboolean              stderr_to_null,
110                                       gboolean              child_inherits_stdin,
111                                       GSpawnChildSetupFunc  child_setup,
112                                       gpointer              user_data,
113                                       gint                 *child_pid,
114                                       gint                 *standard_input,
115                                       gint                 *standard_output,
116                                       gint                 *standard_error,
117                                       gint                 *exit_status,
118                                       GError              **error);
119
120 GQuark
121 g_spawn_error_quark (void)
122 {
123   static GQuark quark = 0;
124   if (quark == 0)
125     quark = g_quark_from_static_string ("g-exec-error-quark");
126   return quark;
127 }
128
129 gboolean
130 g_spawn_async (const gchar          *working_directory,
131                gchar               **argv,
132                gchar               **envp,
133                GSpawnFlags           flags,
134                GSpawnChildSetupFunc  child_setup,
135                gpointer              user_data,
136                gint                 *child_pid,
137                GError              **error)
138 {
139   g_return_val_if_fail (argv != NULL, FALSE);
140   
141   return g_spawn_async_with_pipes (working_directory,
142                                    argv, envp,
143                                    flags,
144                                    child_setup,
145                                    user_data,
146                                    child_pid,
147                                    NULL, NULL, NULL,
148                                    error);
149 }
150
151 /* Avoids a danger in threaded situations (calling close()
152  * on a file descriptor twice, and another thread has
153  * re-opened it since the first close)
154  */
155 static gint
156 close_and_invalidate (gint *fd)
157 {
158   gint ret;
159
160   if (*fd < 0)
161     return -1;
162   else
163     {
164       ret = close (*fd);
165       *fd = -1;
166     }
167
168   return ret;
169 }
170
171 typedef enum
172 {
173   READ_FAILED = 0, /* FALSE */
174   READ_OK,
175   READ_EOF
176 } ReadResult;
177
178 static ReadResult
179 read_data (GString     *str,
180            GIOChannel  *iochannel,
181            GError     **error)
182 {
183   GIOStatus giostatus;
184   gssize bytes;
185   gchar buf[4096];
186
187  again:
188   
189   giostatus = g_io_channel_read_chars (iochannel, buf, sizeof (buf), &bytes, NULL);
190
191   if (bytes == 0)
192     return READ_EOF;
193   else if (bytes > 0)
194     {
195       g_string_append_len (str, buf, bytes);
196       return READ_OK;
197     }
198   else if (giostatus == G_IO_STATUS_AGAIN)
199     goto again;
200   else if (giostatus == G_IO_STATUS_ERROR)
201     {
202       g_set_error (error,
203                    G_SPAWN_ERROR,
204                    G_SPAWN_ERROR_READ,
205                    _("Failed to read data from child process"));
206       
207       return READ_FAILED;
208     }
209   else
210     return READ_OK;
211 }
212
213 gboolean
214 g_spawn_sync (const gchar          *working_directory,
215               gchar               **argv,
216               gchar               **envp,
217               GSpawnFlags           flags,
218               GSpawnChildSetupFunc  child_setup,
219               gpointer              user_data,
220               gchar               **standard_output,
221               gchar               **standard_error,
222               gint                 *exit_status,
223               GError              **error)     
224 {
225   gint outpipe = -1;
226   gint errpipe = -1;
227   gint pid;
228   GIOChannel *outchannel = NULL;
229   GIOChannel *errchannel = NULL;
230   GPollFD outfd, errfd;
231   GPollFD fds[2];
232   gint nfds;
233   gint outindex = -1;
234   gint errindex = -1;
235   gint ret;
236   GString *outstr = NULL;
237   GString *errstr = NULL;
238   gboolean failed;
239   gint status;
240   
241   g_return_val_if_fail (argv != NULL, FALSE);
242   g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
243   g_return_val_if_fail (standard_output == NULL ||
244                         !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
245   g_return_val_if_fail (standard_error == NULL ||
246                         !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
247   
248   /* Just to ensure segfaults if callers try to use
249    * these when an error is reported.
250    */
251   if (standard_output)
252     *standard_output = NULL;
253
254   if (standard_error)
255     *standard_error = NULL;
256   
257   if (!do_spawn_with_pipes (FALSE,
258                             TRUE,
259                             working_directory,
260                             argv,
261                             envp,
262                             !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
263                             (flags & G_SPAWN_SEARCH_PATH) != 0,
264                             (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
265                             (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
266                             (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
267                             child_setup,
268                             user_data,
269                             &pid,
270                             NULL,
271                             standard_output ? &outpipe : NULL,
272                             standard_error ? &errpipe : NULL,
273                             &status,
274                             error))
275     return FALSE;
276
277   /* Read data from child. */
278   
279   failed = FALSE;
280
281   if (outpipe >= 0)
282     {
283       outstr = g_string_new ("");
284       outchannel = g_io_channel_win32_new_fd (outpipe);
285       g_io_channel_set_encoding (outchannel, NULL, NULL);
286       g_io_channel_win32_make_pollfd (outchannel,
287                                       G_IO_IN | G_IO_ERR | G_IO_HUP,
288                                       &outfd);
289     }
290       
291   if (errpipe >= 0)
292     {
293       errstr = g_string_new ("");
294       errchannel = g_io_channel_win32_new_fd (errpipe);
295       g_io_channel_set_encoding (errchannel, NULL, NULL);
296       g_io_channel_win32_make_pollfd (errchannel,
297                                       G_IO_IN | G_IO_ERR | G_IO_HUP,
298                                       &errfd);
299     }
300
301   /* Read data until we get EOF on both pipes. */
302   while (!failed &&
303          (outpipe >= 0 ||
304           errpipe >= 0))
305     {
306       nfds = 0;
307       if (outpipe >= 0)
308         {
309           fds[nfds] = outfd;
310           outindex = nfds;
311           nfds++;
312         }
313       if (errpipe >= 0)
314         {
315           fds[nfds] = errfd;
316           errindex = nfds;
317           nfds++;
318         }
319
320       if (debug)
321         g_print ("%s:g_spawn_sync: calling g_io_channel_win32_poll, nfds=%d\n",
322                  __FILE__, nfds);
323
324       ret = g_io_channel_win32_poll (fds, nfds, -1);
325
326       if (ret < 0)
327         {
328           failed = TRUE;
329
330           g_set_error (error,
331                        G_SPAWN_ERROR,
332                        G_SPAWN_ERROR_READ,
333                        _("Unexpected error in g_io_channel_win32_poll() reading data from a child process"));
334               
335           break;
336         }
337
338       if (outpipe >= 0 && (fds[outindex].revents & G_IO_IN))
339         {
340           switch (read_data (outstr, outchannel, error))
341             {
342             case READ_FAILED:
343               if (debug)
344                 g_print ("g_spawn_sync: outchannel: READ_FAILED\n");
345               failed = TRUE;
346               break;
347             case READ_EOF:
348               if (debug)
349                 g_print ("g_spawn_sync: outchannel: READ_EOF\n");
350               g_io_channel_unref (outchannel);
351               outchannel = NULL;
352               close_and_invalidate (&outpipe);
353               break;
354             default:
355               if (debug)
356                 g_print ("g_spawn_sync: outchannel: OK\n");
357               break;
358             }
359
360           if (failed)
361             break;
362         }
363
364       if (errpipe >= 0 && (fds[errindex].revents & G_IO_IN))
365         {
366           switch (read_data (errstr, errchannel, error))
367             {
368             case READ_FAILED:
369               if (debug)
370                 g_print ("g_spawn_sync: errchannel: READ_FAILED\n");
371               failed = TRUE;
372               break;
373             case READ_EOF:
374               if (debug)
375                 g_print ("g_spawn_sync: errchannel: READ_EOF\n");
376               g_io_channel_unref (errchannel);
377               errchannel = NULL;
378               close_and_invalidate (&errpipe);
379               break;
380             default:
381               if (debug)
382                 g_print ("g_spawn_sync: errchannel: OK\n");
383               break;
384             }
385
386           if (failed)
387             break;
388         }
389     }
390
391   /* These should only be open still if we had an error.  */
392   
393   if (outchannel != NULL)
394     g_io_channel_unref (outchannel);
395   if (errchannel != NULL)
396     g_io_channel_unref (errchannel);
397   if (outpipe >= 0)
398     close_and_invalidate (&outpipe);
399   if (errpipe >= 0)
400     close_and_invalidate (&errpipe);
401   
402   if (failed)
403     {
404       if (outstr)
405         g_string_free (outstr, TRUE);
406       if (errstr)
407         g_string_free (errstr, TRUE);
408
409       return FALSE;
410     }
411   else
412     {
413       if (exit_status)
414         *exit_status = status;
415       
416       if (standard_output)        
417         *standard_output = g_string_free (outstr, FALSE);
418
419       if (standard_error)
420         *standard_error = g_string_free (errstr, FALSE);
421
422       return TRUE;
423     }
424 }
425
426 gboolean
427 g_spawn_async_with_pipes (const gchar          *working_directory,
428                           gchar               **argv,
429                           gchar               **envp,
430                           GSpawnFlags           flags,
431                           GSpawnChildSetupFunc  child_setup,
432                           gpointer              user_data,
433                           gint                 *child_pid,
434                           gint                 *standard_input,
435                           gint                 *standard_output,
436                           gint                 *standard_error,
437                           GError              **error)
438 {
439   g_return_val_if_fail (argv != NULL, FALSE);
440   g_return_val_if_fail (standard_output == NULL ||
441                         !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
442   g_return_val_if_fail (standard_error == NULL ||
443                         !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
444   /* can't inherit stdin if we have an input pipe. */
445   g_return_val_if_fail (standard_input == NULL ||
446                         !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
447   
448   return do_spawn_with_pipes (TRUE,
449                               !(flags & G_SPAWN_DO_NOT_REAP_CHILD),
450                               working_directory,
451                               argv,
452                               envp,
453                               !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
454                               (flags & G_SPAWN_SEARCH_PATH) != 0,
455                               (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
456                               (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
457                               (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
458                               child_setup,
459                               user_data,
460                               child_pid,
461                               standard_input,
462                               standard_output,
463                               standard_error,
464                               NULL,
465                               error);
466 }
467
468 gboolean
469 g_spawn_command_line_sync (const gchar  *command_line,
470                            gchar       **standard_output,
471                            gchar       **standard_error,
472                            gint         *exit_status,
473                            GError      **error)
474 {
475   gboolean retval;
476   gchar **argv = 0;
477
478   g_return_val_if_fail (command_line != NULL, FALSE);
479   
480   if (!g_shell_parse_argv (command_line,
481                            NULL, &argv,
482                            error))
483     return FALSE;
484   
485   retval = g_spawn_sync (NULL,
486                          argv,
487                          NULL,
488                          G_SPAWN_SEARCH_PATH,
489                          NULL,
490                          NULL,
491                          standard_output,
492                          standard_error,
493                          exit_status,
494                          error);
495   g_strfreev (argv);
496
497   return retval;
498 }
499
500 gboolean
501 g_spawn_command_line_async (const gchar *command_line,
502                             GError     **error)
503 {
504   gboolean retval;
505   gchar **argv = 0;
506
507   g_return_val_if_fail (command_line != NULL, FALSE);
508
509   if (!g_shell_parse_argv (command_line,
510                            NULL, &argv,
511                            error))
512     return FALSE;
513   
514   retval = g_spawn_async (NULL,
515                           argv,
516                           NULL,
517                           G_SPAWN_SEARCH_PATH,
518                           NULL,
519                           NULL,
520                           NULL,
521                           error);
522   g_strfreev (argv);
523
524   return retval;
525 }
526
527 static gint
528 do_spawn (gboolean              dont_wait,
529           gint                  child_err_report_fd,
530           gint                  stdin_fd,
531           gint                  stdout_fd,
532           gint                  stderr_fd,
533           const gchar          *working_directory,
534           gchar               **argv,
535           gchar               **envp,
536           gboolean              close_descriptors,
537           gboolean              search_path,
538           gboolean              stdout_to_null,
539           gboolean              stderr_to_null,
540           gboolean              child_inherits_stdin,
541           GSpawnChildSetupFunc  child_setup,
542           gpointer              user_data)
543 {
544   gchar **new_argv;
545   gchar args[ARG_COUNT][10];
546   gint i;
547   int rc;
548   int argc = 0;
549
550   SETUP_DEBUG();
551
552   while (argv[argc])
553     ++argc;
554
555   new_argv = g_new (gchar *, argc + 1 + ARG_COUNT);
556
557   new_argv[0] = "gspawn-win32-helper";
558   sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_fd);
559   new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
560
561   if (stdin_fd >= 0)
562     {
563       sprintf (args[ARG_STDIN], "%d", stdin_fd);
564       new_argv[ARG_STDIN] = args[ARG_STDIN];
565     }
566   else if (child_inherits_stdin)
567     {
568       /* Let stdin be alone */
569       new_argv[ARG_STDIN] = "-";
570     }
571   else
572     {
573       /* Keep process from blocking on a read of stdin */
574       new_argv[ARG_STDIN] = "z";
575     }
576
577   if (stdout_fd >= 0)
578     {
579       sprintf (args[ARG_STDOUT], "%d", stdout_fd);
580       new_argv[ARG_STDOUT] = args[ARG_STDOUT];
581     }
582   else if (stdout_to_null)
583     {
584       new_argv[ARG_STDOUT] = "z";
585     }
586   else
587     {
588       new_argv[ARG_STDOUT] = "-";
589     }
590
591   if (stderr_fd >= 0)
592     {
593       sprintf (args[ARG_STDERR], "%d", stderr_fd);
594       new_argv[ARG_STDERR] = args[ARG_STDERR];
595     }
596   else if (stderr_to_null)
597     {
598       new_argv[ARG_STDERR] = "z";
599     }
600   else
601     {
602       new_argv[ARG_STDERR] = "-";
603     }
604
605   if (working_directory && *working_directory)
606     new_argv[ARG_WORKING_DIRECTORY] = g_strdup (working_directory);
607   else
608     new_argv[ARG_WORKING_DIRECTORY] = "-";
609
610   if (close_descriptors)
611     new_argv[ARG_CLOSE_DESCRIPTORS] = "y";
612   else
613     new_argv[ARG_CLOSE_DESCRIPTORS] = "-";
614
615   if (search_path)
616     new_argv[ARG_USE_PATH] = "y";
617   else
618     new_argv[ARG_USE_PATH] = "-";
619
620   if (dont_wait)
621     new_argv[ARG_WAIT] = "-";
622   else
623     new_argv[ARG_WAIT] = "w";
624
625   for (i = 0; i <= argc; i++)
626     new_argv[ARG_PROGRAM + i] = argv[i];
627
628   /* Call user function just before we execute the helper program,
629    * which executes the program. Dunno what's the usefulness of this.
630    * A child setup function used on Unix probably isn't of much use
631    * as such on Win32, anyhow
632    */
633   if (child_setup)
634     {
635       (* child_setup) (user_data);
636     }
637
638   if (debug)
639     {
640       g_print ("calling gspawn-win32-helper with argv:\n");
641       for (i = 0; i < argc + 1 + ARG_COUNT; i++)
642         g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL"));
643     }
644   
645   if (envp != NULL)
646     /* Let's hope envp hasn't mucked with PATH so that
647      * gspawn-win32-helper.exe isn't found.
648      */
649     rc = spawnvpe (P_NOWAIT, "gspawn-win32-helper", new_argv, envp);
650   else
651     rc = spawnvp (P_NOWAIT, "gspawn-win32-helper", new_argv);
652
653   /* Close the child_err_report_fd and the other process's ends of the
654    * pipes in this process, otherwise the reader will never get
655    * EOF.
656    */
657   close (child_err_report_fd);
658   if (stdin_fd >= 0)
659     close (stdin_fd);
660   if (stdout_fd >= 0)
661     close (stdout_fd);
662   if (stderr_fd >= 0)
663     close (stderr_fd);
664
665   g_free (new_argv[ARG_WORKING_DIRECTORY]);
666   g_free (new_argv);
667
668   return rc;
669 }
670
671 static gboolean
672 read_ints (int      fd,
673            gint*    buf,
674            gint     n_ints_in_buf,
675            gint    *n_ints_read,
676            GError **error)
677 {
678   gint bytes = 0;
679   
680   while (bytes < sizeof(gint)*n_ints_in_buf)
681     {
682       gint chunk;
683
684       if (debug)
685         g_print ("%s:read_ints: trying to read %d bytes from pipe...\n",
686                  __FILE__,
687                  sizeof(gint)*n_ints_in_buf - bytes);
688
689       chunk = read (fd, ((gchar*)buf) + bytes,
690                     sizeof(gint)*n_ints_in_buf - bytes);
691
692       if (debug)
693         g_print ("... got %d bytes\n", chunk);
694           
695       if (chunk < 0)
696         {
697           /* Some weird shit happened, bail out */
698               
699           g_set_error (error,
700                        G_SPAWN_ERROR,
701                        G_SPAWN_ERROR_FAILED,
702                        _("Failed to read from child pipe (%s)"),
703                        g_strerror (errno));
704
705           return FALSE;
706         }
707       else if (chunk == 0)
708         break; /* EOF */
709       else
710         bytes += chunk;
711     }
712
713   *n_ints_read = bytes/sizeof(gint);
714
715   return TRUE;
716 }
717
718 static gboolean
719 do_spawn_with_pipes (gboolean              dont_wait,
720                      gboolean              dont_return_handle,
721                      const gchar          *working_directory,
722                      gchar               **argv,
723                      gchar               **envp,
724                      gboolean              close_descriptors,
725                      gboolean              search_path,
726                      gboolean              stdout_to_null,
727                      gboolean              stderr_to_null,
728                      gboolean              child_inherits_stdin,
729                      GSpawnChildSetupFunc  child_setup,
730                      gpointer              user_data,
731                      gint                 *child_pid,
732                      gint                 *standard_input,
733                      gint                 *standard_output,
734                      gint                 *standard_error,
735                      gint                 *exit_status,
736                      GError              **error)     
737 {
738   gint stdin_pipe[2] = { -1, -1 };
739   gint stdout_pipe[2] = { -1, -1 };
740   gint stderr_pipe[2] = { -1, -1 };
741   gint child_err_report_pipe[2] = { -1, -1 };
742   gint helper = -1;
743   gint buf[2];
744   gint n_ints = 0;
745   
746   if (!make_pipe (child_err_report_pipe, error))
747     return FALSE;
748
749   if (standard_input && !make_pipe (stdin_pipe, error))
750     goto cleanup_and_fail;
751   
752   if (standard_output && !make_pipe (stdout_pipe, error))
753     goto cleanup_and_fail;
754
755   if (standard_error && !make_pipe (stderr_pipe, error))
756     goto cleanup_and_fail;
757
758   helper = do_spawn (dont_wait,
759                      child_err_report_pipe[1],
760                      stdin_pipe[0],
761                      stdout_pipe[1],
762                      stderr_pipe[1],
763                      working_directory,
764                      argv,
765                      envp,
766                      close_descriptors,
767                      search_path,
768                      stdout_to_null,
769                      stderr_to_null,
770                      child_inherits_stdin,
771                      child_setup,
772                      user_data);
773       
774   /* do_spawn() returns -1 if gspawn-win32-helper couldn't be run */
775   if (helper == -1)
776     {
777       g_set_error (error,
778                    G_SPAWN_ERROR,
779                    G_SPAWN_ERROR_FAILED,
780                    _("Failed to execute helper program"));
781       goto cleanup_and_fail;
782     }
783
784   if (!read_ints (child_err_report_pipe[0],
785                   buf, 2, &n_ints,
786                   error) ||
787       n_ints != 2)
788     goto cleanup_and_fail;
789         
790   /* Error code from gspawn-win32-helper. */
791   switch (buf[0])
792     {
793     case CHILD_NO_ERROR:
794       if (child_pid && dont_wait && !dont_return_handle)
795         {
796           /* helper is our HANDLE for gspawn-win32-helper. It has
797            * told us the HANDLE of its child. Duplicate that into
798            * a HANDLE valid in this process.
799            */
800           if (!DuplicateHandle ((HANDLE) helper, (HANDLE) buf[1],
801                                 GetCurrentProcess (), (LPHANDLE) child_pid,
802                                 0, TRUE, DUPLICATE_SAME_ACCESS))
803             *child_pid = 0;
804         }
805       else if (child_pid)
806         *child_pid = 0;
807       break;
808       
809     case CHILD_CHDIR_FAILED:
810       g_set_error (error,
811                    G_SPAWN_ERROR,
812                    G_SPAWN_ERROR_CHDIR,
813                    _("Failed to change to directory '%s' (%s)"),
814                    working_directory,
815                    g_strerror (buf[1]));
816       goto cleanup_and_fail;
817       
818     case CHILD_SPAWN_FAILED:
819       g_set_error (error,
820                    G_SPAWN_ERROR,
821                    G_SPAWN_ERROR_FAILED,
822                    _("Failed to execute child process (%s)"),
823                    g_strerror (buf[1]));
824       goto cleanup_and_fail;
825     }
826
827   /* Success against all odds! return the information */
828       
829   if (standard_input)
830     *standard_input = stdin_pipe[1];
831   if (standard_output)
832     *standard_output = stdout_pipe[0];
833   if (standard_error)
834     *standard_error = stderr_pipe[0];
835   if (exit_status)
836     *exit_status = buf[1];
837   CloseHandle ((HANDLE) helper);
838   
839   return TRUE;
840
841  cleanup_and_fail:
842   if (helper != -1)
843     CloseHandle ((HANDLE) helper);
844   close_and_invalidate (&child_err_report_pipe[0]);
845   close_and_invalidate (&child_err_report_pipe[1]);
846   close_and_invalidate (&stdin_pipe[0]);
847   close_and_invalidate (&stdin_pipe[1]);
848   close_and_invalidate (&stdout_pipe[0]);
849   close_and_invalidate (&stdout_pipe[1]);
850   close_and_invalidate (&stderr_pipe[0]);
851   close_and_invalidate (&stderr_pipe[1]);
852
853   return FALSE;
854 }
855
856 static gboolean
857 make_pipe (gint     p[2],
858            GError **error)
859 {
860   if (pipe (p) < 0)
861     {
862       g_set_error (error,
863                    G_SPAWN_ERROR,
864                    G_SPAWN_ERROR_FAILED,
865                    _("Failed to create pipe for communicating with child process (%s)"),
866                    g_strerror (errno));
867       return FALSE;
868     }
869   else
870     return TRUE;
871 }
872
873 #endif /* !GSPAWN_HELPER */