core,w32: Show w32-spawn warning only once
[gpgme.git] / src / w32-io.c
1 /* w32-io.c - W32 API I/O functions.
2  * Copyright (C) 2000 Werner Koch (dd9jn)
3  * Copyright (C) 2001-2004, 2007, 2010, 2018 g10 Code GmbH
4  *
5  * This file is part of GPGME.
6  *
7  * GPGME is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * GPGME is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, see <https://gnu.org/licenses/>.
19  * SPDX-License-Identifier: LGPL-2.1+
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #ifdef HAVE_SYS_TIME_H
32 # include <sys/time.h>
33 #endif
34 #ifdef HAVE_SYS_TYPES_H
35 # include <sys/types.h>
36 #endif
37 #include <io.h>
38
39 #include "util.h"
40 #include "sema.h"
41 #include "priv-io.h"
42 #include "debug.h"
43 #include "sys-util.h"
44
45
46 /* The number of entries in our file table.  We may eventually use a
47  * lower value and dynamically resize the table.  */
48 #define MAX_SLAFD 512
49
50 #define handle_to_fd(a)  ((int)(a))
51
52 #define READBUF_SIZE 4096
53 #define WRITEBUF_SIZE 4096
54 #define PIPEBUF_SIZE  4096
55
56
57 /* An object to store handles or sockets.  */
58 struct hddesc_s
59 {
60   HANDLE hd;
61   SOCKET sock;
62   int refcount;
63 };
64 typedef struct hddesc_s *hddesc_t;
65
66
67
68 /* The context used by a reader thread.  */
69 struct reader_context_s
70 {
71   hddesc_t hdd;
72   HANDLE thread_hd;
73   int refcount;   /* Bumped if the FD has been duped and thus we have
74                    * another FD referencing this context.  */
75
76   DECLARE_LOCK (mutex);
77
78   int stop_me;
79   int eof;
80   int eof_shortcut;
81   int error;
82   int error_code;
83
84   /* This is manually reset.  */
85   HANDLE have_data_ev;
86   /* This is automatically reset.  */
87   HANDLE have_space_ev;
88   /* This is manually reset but actually only triggered once.  */
89   HANDLE close_ev;
90
91   size_t readpos, writepos;
92   char buffer[READBUF_SIZE];
93 };
94
95
96 /* The context used by a writer thread.  */
97 struct writer_context_s
98 {
99   hddesc_t hdd;
100   HANDLE thread_hd;
101   int refcount;
102
103   DECLARE_LOCK (mutex);
104
105   int stop_me;
106   int error;
107   int error_code;
108
109   /* This is manually reset.  */
110   HANDLE have_data;
111   HANDLE is_empty;
112   HANDLE close_ev;
113   size_t nbytes;
114   char buffer[WRITEBUF_SIZE];
115 };
116
117
118 /* An object to keep track of HANDLEs and sockets and map them to an
119  * integer similar to what we use in Unix.  Note that despite this
120  * integer is often named "fd", it is not a file descriptor but really
121  * only an index into this table.  Never ever pass such an fd to any
122  * other function except for those implemented here.  */
123 static struct
124 {
125   int used;
126
127   /* The handle descriptor.  */
128   hddesc_t hdd;
129
130   /* DUP_FROM is just a debug helper to show from which fd this fd was
131    * dup-ed. */
132   int dup_from;
133
134   /* Two flags to indicate whether a reader or writer (or both) are
135    * needed.  This is so that we can delay the actual thread creation
136    * until they are needed.  */
137   unsigned int want_reader:1;
138   unsigned int want_writer:1;
139
140   /* The context of an associated reader object or NULL.  */
141   struct reader_context_s *reader;
142
143   /* The context of an associated writer object or NULL.  */
144   struct writer_context_s *writer;
145
146   /* A notification handler.  Noet that we current support only one
147    * callback per fd.  */
148   struct {
149     _gpgme_close_notify_handler_t handler;
150     void *value;
151   } notify;
152
153 } fd_table[MAX_SLAFD];
154 static size_t fd_table_size = MAX_SLAFD;
155
156 DEFINE_STATIC_LOCK (fd_table_lock);
157
158
159 /* We use a single global lock for all hddesc_t objects.  */
160 DEFINE_STATIC_LOCK (hddesc_lock);
161
162
163 \f
164 /* Wrapper around CloseHandle to print an error.  */
165 #define close_handle(hd) _close_handle ((hd), __LINE__);
166 static void
167 _close_handle (HANDLE hd, int line)
168 {
169   if (!CloseHandle (hd))
170     {
171       TRACE (DEBUG_INIT, "w32-io", hd, "CloseHandle failed at line %d: ec=%d",
172               line, (int) GetLastError ());
173     }
174 }
175
176 /* Wrapper around WaitForSingleObject to print an error.  */
177 #define wait_for_single_object(hd,msec) \
178         _wait_for_single_object ((hd), (msec), __LINE__)
179 static DWORD
180 _wait_for_single_object (HANDLE hd, DWORD msec, int line)
181 {
182   DWORD res;
183
184   res = WaitForSingleObject (hd, msec);
185   if (res == WAIT_FAILED)
186     {
187       TRACE (DEBUG_INIT, "w32-io", hd,
188               "WFSO failed at line %d: ec=%d", line, (int) GetLastError ());
189     }
190   return res;
191 }
192
193
194 /* Create a new handle descriptor object.  */
195 static hddesc_t
196 new_hddesc (void)
197 {
198   hddesc_t hdd;
199
200   hdd = malloc (sizeof *hdd);
201   if (!hdd)
202     return NULL;
203   hdd->hd = INVALID_HANDLE_VALUE;
204   hdd->sock = INVALID_SOCKET;
205   hdd->refcount = 0;
206
207   return hdd;
208 }
209
210
211 static hddesc_t
212 ref_hddesc (hddesc_t hdd)
213 {
214   LOCK (hddesc_lock);
215   hdd->refcount++;
216   UNLOCK (hddesc_lock);
217   return hdd;
218 }
219
220
221 /* Release a handle descriptor object and close its handle or socket
222  * if needed.  */
223 static void
224 release_hddesc (hddesc_t hdd)
225 {
226   if (!hdd)
227     return;
228
229   LOCK (hddesc_lock);
230   hdd->refcount--;
231   if (hdd->refcount < 1)
232     {
233       /* Holds a valid handle or was never initialized (in which case
234        * REFCOUNT would be -1 here).  */
235       TRACE_BEG  (DEBUG_SYSIO, "gpgme:release_hddesc", hdd,
236                   "hd=%p, sock=%d, refcount=%d",
237                   hdd->hd, hdd->sock, hdd->refcount);
238
239       if (hdd->hd != INVALID_HANDLE_VALUE)
240         close_handle (hdd->hd);
241
242       if (hdd->sock != INVALID_SOCKET)
243         {
244           TRACE_LOG  ("closing socket %d", hdd->sock);
245           if (closesocket (hdd->sock))
246             {
247               TRACE_LOG  ("closesocket failed: ec=%d", (int)WSAGetLastError ());
248             }
249         }
250
251       free (hdd);
252       TRACE_SUC ("");
253     }
254   UNLOCK (hddesc_lock);
255 }
256
257
258
259 /* Returns our FD or -1 on resource limit.  The returned integer
260  * references a new object which has not been initialized but can be
261  * release with release_fd.  */
262 static int
263 new_fd (void)
264 {
265   int idx;
266
267   LOCK (fd_table_lock);
268
269   for (idx = 0; idx < fd_table_size; idx++)
270     if (! fd_table[idx].used)
271       break;
272
273   if (idx == fd_table_size)
274     {
275       gpg_err_set_errno (EIO);
276       idx = -1;
277     }
278   else
279     {
280       fd_table[idx].used = 1;
281       fd_table[idx].hdd = NULL;
282       fd_table[idx].dup_from = -1;
283       fd_table[idx].want_reader = 0;
284       fd_table[idx].want_writer = 0;
285       fd_table[idx].reader = NULL;
286       fd_table[idx].writer = NULL;
287       fd_table[idx].notify.handler = NULL;
288       fd_table[idx].notify.value = NULL;
289     }
290
291   UNLOCK (fd_table_lock);
292
293   return idx;
294 }
295
296
297 /* Releases our FD but it this is just this entry.  No close operation
298  * is involved here; it must be done prior to calling this
299  * function.  */
300 static void
301 release_fd (int fd)
302 {
303   if (fd < 0 || fd >= fd_table_size)
304     return;
305
306   LOCK (fd_table_lock);
307
308   if (fd_table[fd].used)
309     {
310       release_hddesc (fd_table[fd].hdd);
311       fd_table[fd].used = 0;
312       fd_table[fd].hdd = NULL;
313       fd_table[fd].dup_from = -1;
314       fd_table[fd].want_reader = 0;
315       fd_table[fd].want_writer = 0;
316       fd_table[fd].reader = NULL;
317       fd_table[fd].writer = NULL;
318       fd_table[fd].notify.handler = NULL;
319       fd_table[fd].notify.value = NULL;
320     }
321
322   UNLOCK (fd_table_lock);
323 }
324
325
326 static int
327 get_desired_thread_priority (void)
328 {
329   int value;
330
331   if (!_gpgme_get_conf_int ("IOThreadPriority", &value))
332     {
333       value = THREAD_PRIORITY_HIGHEST;
334       TRACE (DEBUG_SYSIO, "gpgme:get_desired_thread_priority", 0,
335               "%d (default)", value);
336     }
337   else
338     {
339       TRACE (DEBUG_SYSIO, "gpgme:get_desired_thread_priority", 0,
340               "%d (configured)", value);
341     }
342   return value;
343 }
344
345
346 /* The reader thread.  Created on the fly by gpgme_io_read and
347  * destroyed by destroy_reader.  Note that this functions works with a
348  * copy of the value of the HANDLE variable frm the FS_TABLE.  */
349 static DWORD CALLBACK
350 reader (void *arg)
351 {
352   struct reader_context_s *ctx = arg;
353   int nbytes;
354   DWORD nread;
355   int sock;
356
357   TRACE_BEG  (DEBUG_SYSIO, "gpgme:reader", ctx->hdd,
358               "hd=%p, sock=%d, thread=%p, refcount=%d",
359               ctx->hdd->hd, ctx->hdd->sock, ctx->thread_hd, ctx->refcount);
360
361   if (ctx->hdd->hd != INVALID_HANDLE_VALUE)
362     sock = 0;
363   else
364     sock = 1;
365
366   for (;;)
367     {
368       LOCK (ctx->mutex);
369       /* Leave a 1 byte gap so that we can see whether it is empty or
370          full.  */
371       if ((ctx->writepos + 1) % READBUF_SIZE == ctx->readpos)
372         {
373           /* Wait for space.  */
374           if (!ResetEvent (ctx->have_space_ev))
375             {
376               TRACE_LOG  ("ResetEvent failed: ec=%d", (int) GetLastError ());
377             }
378           UNLOCK (ctx->mutex);
379           TRACE_LOG  ("waiting for space (refcnt=%d)", ctx->refcount);
380           wait_for_single_object (ctx->have_space_ev, INFINITE);
381           TRACE_LOG ("got space");
382           LOCK (ctx->mutex);
383         }
384       if (ctx->stop_me)
385         {
386           UNLOCK (ctx->mutex);
387           break;
388         }
389       nbytes = (ctx->readpos + READBUF_SIZE
390                 - ctx->writepos - 1) % READBUF_SIZE;
391       if (nbytes > READBUF_SIZE - ctx->writepos)
392         nbytes = READBUF_SIZE - ctx->writepos;
393       UNLOCK (ctx->mutex);
394
395       TRACE_LOG  ("%s %d bytes", sock? "receiving":"reading", nbytes);
396
397       if (sock)
398         {
399           int n;
400
401           n = recv (ctx->hdd->sock, ctx->buffer + ctx->writepos, nbytes, 0);
402           if (n < 0)
403             {
404               ctx->error_code = (int) WSAGetLastError ();
405               if (ctx->error_code == ERROR_BROKEN_PIPE)
406                 {
407                   ctx->eof = 1;
408                   TRACE_LOG ("got EOF (broken connection)");
409                 }
410               else
411                 {
412                   /* Check whether the shutdown triggered the error -
413                      no need to to print a warning in this case.  */
414                   if ( ctx->error_code == WSAECONNABORTED
415                        || ctx->error_code == WSAECONNRESET)
416                     {
417                       LOCK (ctx->mutex);
418                       if (ctx->stop_me)
419                         {
420                           UNLOCK (ctx->mutex);
421                           TRACE_LOG ("got shutdown");
422                           break;
423                         }
424                       UNLOCK (ctx->mutex);
425                     }
426
427                   ctx->error = 1;
428                   TRACE_LOG  ("recv error: ec=%d", ctx->error_code);
429                 }
430               break;
431             }
432           nread = n;
433         }
434       else
435         {
436           if (!ReadFile (ctx->hdd->hd,
437                          ctx->buffer + ctx->writepos, nbytes, &nread, NULL))
438             {
439               ctx->error_code = (int) GetLastError ();
440               if (ctx->error_code == ERROR_BROKEN_PIPE)
441                 {
442                   ctx->eof = 1;
443                   TRACE_LOG ("got EOF (broken pipe)");
444                 }
445               else if (ctx->error_code == ERROR_OPERATION_ABORTED)
446                 {
447                   ctx->eof = 1;
448                   TRACE_LOG ("got EOF (closed by us)");
449                 }
450               else
451                 {
452                   ctx->error = 1;
453                   TRACE_LOG  ("read error: ec=%d", ctx->error_code);
454                 }
455               break;
456             }
457         }
458       LOCK (ctx->mutex);
459       if (ctx->stop_me)
460         {
461           UNLOCK (ctx->mutex);
462           break;
463         }
464       if (!nread)
465         {
466           ctx->eof = 1;
467           TRACE_LOG ("got eof");
468           UNLOCK (ctx->mutex);
469           break;
470         }
471
472       TRACE_LOG  ("got %lu bytes (refcnt=%d)", nread, ctx->refcount);
473
474       ctx->writepos = (ctx->writepos + nread) % READBUF_SIZE;
475       if (!SetEvent (ctx->have_data_ev))
476         {
477           TRACE_LOG  ("SetEvent (%p) failed: ec=%d", ctx->have_data_ev,
478                       (int) GetLastError ());
479         }
480       UNLOCK (ctx->mutex);
481     }
482   /* Indicate that we have an error or EOF.  */
483   if (!SetEvent (ctx->have_data_ev))
484     {
485       TRACE_LOG ("SetEvent (%p) failed: ec=%d", ctx->have_data_ev,
486                 (int) GetLastError ());
487     }
488
489   TRACE_LOG ("waiting for close");
490   wait_for_single_object (ctx->close_ev, INFINITE);
491
492   release_hddesc (ctx->hdd);
493   close_handle (ctx->close_ev);
494   close_handle (ctx->have_data_ev);
495   close_handle (ctx->have_space_ev);
496   close_handle (ctx->thread_hd);
497   DESTROY_LOCK (ctx->mutex);
498   free (ctx);
499
500   TRACE_SUC ("");
501   return 0;
502 }
503
504
505 /* Create a new reader thread and return its context object.  The
506  * input is the handle descriptor HDD.  This function may not call any
507  * fd based functions because the caller already holds a lock on the
508  * fd_table.  */
509 static struct reader_context_s *
510 create_reader (hddesc_t hdd)
511 {
512   struct reader_context_s *ctx;
513   SECURITY_ATTRIBUTES sec_attr;
514   DWORD tid;
515
516   TRACE_BEG  (DEBUG_SYSIO, "gpgme:create_reader", hdd,
517               "handle=%p sock=%d refhdd=%d",
518               hdd->hd, hdd->sock, hdd->refcount);
519
520   memset (&sec_attr, 0, sizeof sec_attr);
521   sec_attr.nLength = sizeof sec_attr;
522   sec_attr.bInheritHandle = FALSE;
523
524   ctx = calloc (1, sizeof *ctx);
525   if (!ctx)
526     {
527       TRACE_SYSERR (errno);
528       return NULL;
529     }
530
531   ctx->hdd = ref_hddesc (hdd);
532
533   ctx->refcount = 1;
534   ctx->have_data_ev = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
535   if (ctx->have_data_ev)
536     ctx->have_space_ev = CreateEvent (&sec_attr, FALSE, TRUE, NULL);
537   if (ctx->have_space_ev)
538     ctx->close_ev = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
539   if (!ctx->have_data_ev || !ctx->have_space_ev || !ctx->close_ev)
540     {
541       TRACE_LOG  ("CreateEvent failed: ec=%d", (int) GetLastError ());
542       if (ctx->have_data_ev)
543         close_handle (ctx->have_data_ev);
544       if (ctx->have_space_ev)
545         close_handle (ctx->have_space_ev);
546       if (ctx->close_ev)
547         close_handle (ctx->close_ev);
548       release_hddesc (ctx->hdd);
549       free (ctx);
550       TRACE_SYSERR (EIO);
551       return NULL;
552     }
553
554   INIT_LOCK (ctx->mutex);
555
556   ctx->thread_hd = CreateThread (&sec_attr, 0, reader, ctx, 0, &tid);
557
558   if (!ctx->thread_hd)
559     {
560       TRACE_LOG  ("CreateThread failed: ec=%d", (int) GetLastError ());
561       DESTROY_LOCK (ctx->mutex);
562       if (ctx->have_data_ev)
563         close_handle (ctx->have_data_ev);
564       if (ctx->have_space_ev)
565         close_handle (ctx->have_space_ev);
566       if (ctx->close_ev)
567         close_handle (ctx->close_ev);
568       release_hddesc (ctx->hdd);
569       free (ctx);
570       TRACE_SYSERR (EIO);
571       return NULL;
572     }
573   else
574     {
575       /* We set the priority of the thread higher because we know that
576          it only runs for a short time.  This greatly helps to
577          increase the performance of the I/O.  */
578       SetThreadPriority (ctx->thread_hd, get_desired_thread_priority ());
579     }
580
581   TRACE_SUC ("");
582   return ctx;
583 }
584
585
586 /* Prepare destruction of the reader thread for CTX.  Returns 0 if a
587    call to this function is sufficient and destroy_reader_finish shall
588    not be called.  */
589 static void
590 destroy_reader (struct reader_context_s *ctx)
591 {
592   LOCK (ctx->mutex);
593   ctx->refcount--;
594   if (ctx->refcount != 0)
595     {
596       TRACE (DEBUG_SYSIO, "gpgme:destroy_reader", ctx,
597               "hdd=%p refcount now %d", ctx->hdd, ctx->refcount);
598       UNLOCK (ctx->mutex);
599       return;
600     }
601   ctx->stop_me = 1;
602   if (ctx->have_space_ev)
603     SetEvent (ctx->have_space_ev);
604   TRACE (DEBUG_SYSIO, "gpgme:destroy_reader", ctx,
605           "hdd=%p close triggered", ctx->hdd);
606   UNLOCK (ctx->mutex);
607
608   /* The reader thread is usually blocking in recv or ReadFile.  If
609      the peer does not send an EOF or breaks the pipe the WFSO might
610      get stuck waiting for the termination of the reader thread.  This
611      happens quite often with sockets, thus we definitely need to get
612      out of the recv.  A shutdown does this nicely.  For handles
613      (i.e. pipes) it would also be nice to cancel the operation, but
614      such a feature is only available since Vista.  Thus we need to
615      dlopen that syscall.  */
616   assert (ctx->hdd);
617   if (ctx->hdd && ctx->hdd->hd != INVALID_HANDLE_VALUE)
618     {
619       _gpgme_w32_cancel_synchronous_io (ctx->thread_hd);
620     }
621   else if (ctx->hdd && ctx->hdd->sock != INVALID_SOCKET)
622     {
623       if (shutdown (ctx->hdd->sock, 2))
624         TRACE (DEBUG_SYSIO, "gpgme:destroy_reader", ctx,
625                 "shutdown socket %d failed: ec=%d",
626                 ctx->hdd->sock, (int) WSAGetLastError ());
627     }
628
629   /* After setting this event CTX is void. */
630   SetEvent (ctx->close_ev);
631 }
632
633
634
635 /* Find a reader context or create a new one.  Note that the reader
636  * context will last until a _gpgme_io_close.  NULL is returned for a
637  * bad FD or for other errors.  */
638 static struct reader_context_s *
639 find_reader (int fd)
640 {
641   struct reader_context_s *rd = NULL;
642
643   TRACE_BEG (DEBUG_SYSIO, "gpgme:find_reader", fd, "");
644
645   LOCK (fd_table_lock);
646   if (fd < 0 || fd >= fd_table_size || !fd_table[fd].used)
647     {
648       UNLOCK (fd_table_lock);
649       gpg_err_set_errno (EBADF);
650       TRACE_SUC ("EBADF");
651       return NULL;
652     }
653
654   rd = fd_table[fd].reader;
655   if (rd)
656     {
657       UNLOCK (fd_table_lock);
658       TRACE_SUC ("rd=%p", rd);
659       return rd;  /* Return already initialized reader thread object.  */
660     }
661
662   /* Create a new reader thread.  */
663   TRACE_LOG  ("fd=%d -> hdd=%p dupfrom=%d creating reader",
664               fd, fd_table[fd].hdd, fd_table[fd].dup_from);
665   rd = create_reader (fd_table[fd].hdd);
666   if (!rd)
667     gpg_err_set_errno (EIO);
668   else
669     fd_table[fd].reader = rd;
670
671   UNLOCK (fd_table_lock);
672   TRACE_SUC ("rd=%p (new)", rd);
673   return rd;
674 }
675
676
677 int
678 _gpgme_io_read (int fd, void *buffer, size_t count)
679 {
680   int nread;
681   struct reader_context_s *ctx;
682   TRACE_BEG  (DEBUG_SYSIO, "_gpgme_io_read", fd,
683               "buffer=%p, count=%u", buffer, count);
684
685   ctx = find_reader (fd);
686   if (!ctx)
687     return TRACE_SYSRES (-1);
688   if (ctx->eof_shortcut)
689     return TRACE_SYSRES (0);
690
691   LOCK (ctx->mutex);
692   if (ctx->readpos == ctx->writepos && !ctx->error)
693     {
694       /* No data available.  */
695       UNLOCK (ctx->mutex);
696       TRACE_LOG  ("waiting for data from thread %p", ctx->thread_hd);
697       wait_for_single_object (ctx->have_data_ev, INFINITE);
698       TRACE_LOG  ("data from thread %p available", ctx->thread_hd);
699       LOCK (ctx->mutex);
700     }
701
702   if (ctx->readpos == ctx->writepos || ctx->error)
703     {
704       UNLOCK (ctx->mutex);
705       ctx->eof_shortcut = 1;
706       if (ctx->eof)
707         return TRACE_SYSRES (0);
708       if (!ctx->error)
709         {
710           TRACE_LOG ("EOF but ctx->eof flag not set");
711           return 0;
712         }
713       gpg_err_set_errno (ctx->error_code);
714       return TRACE_SYSRES (-1);
715     }
716
717   nread = ctx->readpos < ctx->writepos
718     ? ctx->writepos - ctx->readpos
719     : READBUF_SIZE - ctx->readpos;
720   if (nread > count)
721     nread = count;
722   memcpy (buffer, ctx->buffer + ctx->readpos, nread);
723   ctx->readpos = (ctx->readpos + nread) % READBUF_SIZE;
724   if (ctx->readpos == ctx->writepos && !ctx->eof)
725     {
726       if (!ResetEvent (ctx->have_data_ev))
727         {
728           TRACE_LOG  ("ResetEvent failed: ec=%d", (int) GetLastError ());
729           UNLOCK (ctx->mutex);
730           /* FIXME: Should translate the error code.  */
731           gpg_err_set_errno (EIO);
732           return TRACE_SYSRES (-1);
733         }
734     }
735   if (!SetEvent (ctx->have_space_ev))
736     {
737       TRACE_LOG  ("SetEvent (%p) failed: ec=%d",
738                   ctx->have_space_ev, (int) GetLastError ());
739       UNLOCK (ctx->mutex);
740       /* FIXME: Should translate the error code.  */
741       gpg_err_set_errno (EIO);
742       return TRACE_SYSRES (-1);
743     }
744   UNLOCK (ctx->mutex);
745
746   TRACE_LOGBUFX (buffer, nread);
747   return TRACE_SYSRES (nread);
748 }
749
750
751 /* The writer does use a simple buffering strategy so that we are
752    informed about write errors as soon as possible (i. e. with the the
753    next call to the write function.  */
754 static DWORD CALLBACK
755 writer (void *arg)
756 {
757   struct writer_context_s *ctx = arg;
758   DWORD nwritten;
759   int sock;
760   TRACE_BEG  (DEBUG_SYSIO, "gpgme:writer", ctx->hdd,
761               "hd=%p, sock=%d, thread=%p, refcount=%d",
762               ctx->hdd->hd, ctx->hdd->sock, ctx->thread_hd, ctx->refcount);
763
764   if (ctx->hdd->hd != INVALID_HANDLE_VALUE)
765     sock = 0;
766   else
767     sock = 1;
768
769   for (;;)
770     {
771       LOCK (ctx->mutex);
772       if (ctx->stop_me && !ctx->nbytes)
773         {
774           UNLOCK (ctx->mutex);
775           break;
776         }
777       if (!ctx->nbytes)
778         {
779           if (!SetEvent (ctx->is_empty))
780             TRACE_LOG  ("SetEvent failed: ec=%d", (int) GetLastError ());
781           if (!ResetEvent (ctx->have_data))
782             TRACE_LOG  ("ResetEvent failed: ec=%d", (int) GetLastError ());
783           UNLOCK (ctx->mutex);
784           TRACE_LOG ("idle");
785           wait_for_single_object (ctx->have_data, INFINITE);
786           TRACE_LOG ("got data to send");
787           LOCK (ctx->mutex);
788         }
789       if (ctx->stop_me && !ctx->nbytes)
790         {
791           UNLOCK (ctx->mutex);
792           break;
793         }
794       UNLOCK (ctx->mutex);
795
796       TRACE_LOG  ("%s %d bytes", sock?"sending":"writing", ctx->nbytes);
797
798       /* Note that CTX->nbytes is not zero at this point, because
799          _gpgme_io_write always writes at least 1 byte before waking
800          us up, unless CTX->stop_me is true, which we catch above.  */
801       if (sock)
802         {
803           /* We need to try send first because a socket handle can't
804              be used with WriteFile.  */
805           int n;
806
807           n = send (ctx->hdd->sock, ctx->buffer, ctx->nbytes, 0);
808           if (n < 0)
809             {
810               ctx->error_code = (int) WSAGetLastError ();
811               ctx->error = 1;
812               TRACE_LOG  ("send error: ec=%d", ctx->error_code);
813               break;
814             }
815           nwritten = n;
816         }
817       else
818         {
819           if (!WriteFile (ctx->hdd->hd, ctx->buffer,
820                           ctx->nbytes, &nwritten, NULL))
821             {
822               if (GetLastError () == ERROR_BUSY)
823                 {
824                   /* Probably stop_me is set now.  */
825                   TRACE_LOG ("pipe busy (unblocked?)");
826                   continue;
827                 }
828
829               ctx->error_code = (int) GetLastError ();
830               ctx->error = 1;
831               TRACE_LOG  ("write error: ec=%d", ctx->error_code);
832               break;
833             }
834         }
835       TRACE_LOG  ("wrote %d bytes", (int) nwritten);
836
837       LOCK (ctx->mutex);
838       ctx->nbytes -= nwritten;
839       UNLOCK (ctx->mutex);
840     }
841   /* Indicate that we have an error.  */
842   if (!SetEvent (ctx->is_empty))
843     TRACE_LOG  ("SetEvent failed: ec=%d", (int) GetLastError ());
844
845   TRACE_LOG ("waiting for close");
846   wait_for_single_object (ctx->close_ev, INFINITE);
847
848   if (ctx->nbytes)
849     TRACE_LOG  ("still %d bytes in buffer at close time", ctx->nbytes);
850
851   release_hddesc (ctx->hdd);
852   close_handle (ctx->close_ev);
853   close_handle (ctx->have_data);
854   close_handle (ctx->is_empty);
855   close_handle (ctx->thread_hd);
856   DESTROY_LOCK (ctx->mutex);
857   free (ctx);
858
859   TRACE_SUC ("");
860   return 0;
861 }
862
863
864 static struct writer_context_s *
865 create_writer (hddesc_t hdd)
866 {
867   struct writer_context_s *ctx;
868   SECURITY_ATTRIBUTES sec_attr;
869   DWORD tid;
870
871
872 TRACE_BEG  (DEBUG_SYSIO, "gpgme:create_writer", hdd,
873              "handle=%p sock=%d refhdd=%d",
874              hdd->hd, hdd->sock, hdd->refcount);
875
876   memset (&sec_attr, 0, sizeof sec_attr);
877   sec_attr.nLength = sizeof sec_attr;
878   sec_attr.bInheritHandle = FALSE;
879
880   ctx = calloc (1, sizeof *ctx);
881   if (!ctx)
882     {
883       TRACE_SYSERR (errno);
884       return NULL;
885     }
886
887   ctx->hdd = ref_hddesc (hdd);
888
889   ctx->refcount = 1;
890   ctx->have_data = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
891   if (ctx->have_data)
892     ctx->is_empty  = CreateEvent (&sec_attr, TRUE, TRUE, NULL);
893   if (ctx->is_empty)
894     ctx->close_ev = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
895   if (!ctx->have_data || !ctx->is_empty || !ctx->close_ev)
896     {
897       TRACE_LOG  ("CreateEvent failed: ec=%d", (int) GetLastError ());
898       if (ctx->have_data)
899         close_handle (ctx->have_data);
900       if (ctx->is_empty)
901         close_handle (ctx->is_empty);
902       if (ctx->close_ev)
903         close_handle (ctx->close_ev);
904       release_hddesc (ctx->hdd);
905       free (ctx);
906       TRACE_SYSERR (EIO);
907       return NULL;
908     }
909
910   INIT_LOCK (ctx->mutex);
911
912   ctx->thread_hd = CreateThread (&sec_attr, 0, writer, ctx, 0, &tid );
913   if (!ctx->thread_hd)
914     {
915       TRACE_LOG  ("CreateThread failed: ec=%d", (int) GetLastError ());
916       DESTROY_LOCK (ctx->mutex);
917       if (ctx->have_data)
918         close_handle (ctx->have_data);
919       if (ctx->is_empty)
920         close_handle (ctx->is_empty);
921       if (ctx->close_ev)
922         close_handle (ctx->close_ev);
923       release_hddesc (ctx->hdd);
924       free (ctx);
925       TRACE_SYSERR (EIO);
926       return NULL;
927     }
928   else
929     {
930       /* We set the priority of the thread higher because we know
931          that it only runs for a short time.  This greatly helps to
932          increase the performance of the I/O.  */
933       SetThreadPriority (ctx->thread_hd, get_desired_thread_priority ());
934     }
935
936   TRACE_SUC ("");
937   return ctx;
938 }
939
940
941 static void
942 destroy_writer (struct writer_context_s *ctx)
943 {
944   LOCK (ctx->mutex);
945   ctx->refcount--;
946   if (ctx->refcount != 0)
947     {
948       TRACE (DEBUG_SYSIO, "gpgme:destroy_writer", ctx,
949               "hdd=%p refcount now %d", ctx->hdd, ctx->refcount);
950       UNLOCK (ctx->mutex);
951       return;
952     }
953   ctx->stop_me = 1;
954   if (ctx->have_data)
955     SetEvent (ctx->have_data);
956   TRACE (DEBUG_SYSIO, "gpgme:destroy_writer", ctx,
957           "hdd=%p close triggered", ctx->hdd);
958   UNLOCK (ctx->mutex);
959
960   /* Give the writer a chance to flush the buffer.  */
961   wait_for_single_object (ctx->is_empty, INFINITE);
962
963   /* After setting this event CTX is void.  */
964   SetEvent (ctx->close_ev);
965 }
966
967
968 /* Find a writer context or create a new one.  Note that the writer
969  * context will last until a _gpgme_io_close.  NULL is returned for a
970  * bad FD or for other errors.  */
971 static struct writer_context_s *
972 find_writer (int fd)
973 {
974   struct writer_context_s *wt = NULL;
975
976   TRACE_BEG (DEBUG_SYSIO, "gpgme:find_writer", fd, "");
977
978   LOCK (fd_table_lock);
979   if (fd < 0 || fd >= fd_table_size || !fd_table[fd].used)
980     {
981       UNLOCK (fd_table_lock);
982       gpg_err_set_errno (EBADF);
983       TRACE_SUC ("EBADF");
984       return NULL;
985     }
986
987   wt = fd_table[fd].writer;
988   if (wt)
989     {
990       UNLOCK (fd_table_lock);
991       TRACE_SUC ("wt=%p", wt);
992       return wt;  /* Return already initialized writer thread object.  */
993     }
994
995   /* Create a new writer thread.  */
996   TRACE_LOG  ("fd=%d -> handle=%p socket=%d dupfrom=%d creating writer",
997               fd, fd_table[fd].hdd->hd, fd_table[fd].hdd->sock,
998               fd_table[fd].dup_from);
999   wt = create_writer (fd_table[fd].hdd);
1000   if (!wt)
1001     gpg_err_set_errno (EIO);
1002   else
1003     fd_table[fd].writer = wt;
1004
1005   UNLOCK (fd_table_lock);
1006   TRACE_SUC ("wt=%p (new)", wt);
1007   return wt;
1008 }
1009
1010
1011 int
1012 _gpgme_io_write (int fd, const void *buffer, size_t count)
1013 {
1014   struct writer_context_s *ctx;
1015   TRACE_BEG  (DEBUG_SYSIO, "_gpgme_io_write", fd,
1016               "buffer=%p, count=%u", buffer, count);
1017   TRACE_LOGBUFX (buffer, count);
1018
1019   if (count == 0)
1020     return TRACE_SYSRES (0);
1021
1022   ctx = find_writer (fd);
1023   if (!ctx)
1024     return TRACE_SYSRES (-1);
1025
1026   LOCK (ctx->mutex);
1027   if (!ctx->error && ctx->nbytes)
1028     {
1029       /* Bytes are pending for send.  */
1030
1031       /* Reset the is_empty event.  Better safe than sorry.  */
1032       if (!ResetEvent (ctx->is_empty))
1033         {
1034           TRACE_LOG  ("ResetEvent failed: ec=%d", (int) GetLastError ());
1035           UNLOCK (ctx->mutex);
1036           /* FIXME: Should translate the error code.  */
1037           gpg_err_set_errno (EIO);
1038           return TRACE_SYSRES (-1);
1039         }
1040       UNLOCK (ctx->mutex);
1041       TRACE_LOG  ("waiting for empty buffer in thread %p", ctx->thread_hd);
1042       wait_for_single_object (ctx->is_empty, INFINITE);
1043       TRACE_LOG  ("thread %p buffer is empty", ctx->thread_hd);
1044       LOCK (ctx->mutex);
1045     }
1046
1047   if (ctx->error)
1048     {
1049       UNLOCK (ctx->mutex);
1050       if (ctx->error_code == ERROR_NO_DATA)
1051         gpg_err_set_errno (EPIPE);
1052       else
1053         gpg_err_set_errno (EIO);
1054       return TRACE_SYSRES (-1);
1055     }
1056
1057   /* If no error occurred, the number of bytes in the buffer must be
1058      zero.  */
1059   assert (!ctx->nbytes);
1060
1061   if (count > WRITEBUF_SIZE)
1062     count = WRITEBUF_SIZE;
1063   memcpy (ctx->buffer, buffer, count);
1064   ctx->nbytes = count;
1065
1066   /* We have to reset the is_empty event early, because it is also
1067    * used by the select() implementation to probe the channel.  */
1068   if (!ResetEvent (ctx->is_empty))
1069     {
1070       TRACE_LOG  ("ResetEvent failed: ec=%d", (int) GetLastError ());
1071       UNLOCK (ctx->mutex);
1072       /* FIXME: Should translate the error code.  */
1073       gpg_err_set_errno (EIO);
1074       return TRACE_SYSRES (-1);
1075     }
1076   if (!SetEvent (ctx->have_data))
1077     {
1078       TRACE_LOG  ("SetEvent failed: ec=%d", (int) GetLastError ());
1079       UNLOCK (ctx->mutex);
1080       /* FIXME: Should translate the error code.  */
1081       gpg_err_set_errno (EIO);
1082       return TRACE_SYSRES (-1);
1083     }
1084   UNLOCK (ctx->mutex);
1085
1086   return TRACE_SYSRES ((int) count);
1087 }
1088
1089
1090 int
1091 _gpgme_io_pipe (int filedes[2], int inherit_idx)
1092 {
1093   int rfd;
1094   int wfd;
1095   HANDLE rh;
1096   HANDLE wh;
1097   hddesc_t rhdesc;
1098   hddesc_t whdesc;
1099   SECURITY_ATTRIBUTES sec_attr;
1100
1101   TRACE_BEG  (DEBUG_SYSIO, "_gpgme_io_pipe", filedes,
1102               "inherit_idx=%i (GPGME uses it for %s)",
1103               inherit_idx, inherit_idx ? "reading" : "writing");
1104
1105   /* Get a new empty file descriptor.  */
1106   rfd = new_fd ();
1107   if (rfd == -1)
1108     return TRACE_SYSRES (-1);
1109   wfd = new_fd ();
1110   if (wfd == -1)
1111     {
1112       release_fd (rfd);
1113       return TRACE_SYSRES (-1);
1114     }
1115   rhdesc = new_hddesc ();
1116   if (!rhdesc)
1117     {
1118       release_fd (rfd);
1119       release_fd (wfd);
1120       return TRACE_SYSRES (-1);
1121     }
1122   whdesc = new_hddesc ();
1123   if (!whdesc)
1124     {
1125       release_fd (rfd);
1126       release_fd (wfd);
1127       release_hddesc (rhdesc);
1128       return TRACE_SYSRES (-1);
1129     }
1130
1131   /* Create a pipe.  */
1132   memset (&sec_attr, 0, sizeof (sec_attr));
1133   sec_attr.nLength = sizeof (sec_attr);
1134   sec_attr.bInheritHandle = FALSE;
1135
1136   if (!CreatePipe (&rh, &wh, &sec_attr, PIPEBUF_SIZE))
1137     {
1138       TRACE_LOG  ("CreatePipe failed: ec=%d", (int) GetLastError ());
1139       release_fd (rfd);
1140       release_fd (wfd);
1141       release_hddesc (rhdesc);
1142       release_hddesc (whdesc);
1143       gpg_err_set_errno (EIO);
1144       return TRACE_SYSRES (-1);
1145     }
1146
1147   /* Make one end inheritable.  */
1148   if (inherit_idx == 0)
1149     {
1150       HANDLE hd;
1151       if (!DuplicateHandle (GetCurrentProcess(), rh,
1152                             GetCurrentProcess(), &hd, 0,
1153                             TRUE, DUPLICATE_SAME_ACCESS))
1154         {
1155           TRACE_LOG  ("DuplicateHandle failed: ec=%d",
1156                       (int) GetLastError ());
1157           release_fd (rfd);
1158           release_fd (wfd);
1159           close_handle (rh);
1160           close_handle (wh);
1161           release_hddesc (rhdesc);
1162           release_hddesc (whdesc);
1163           gpg_err_set_errno (EIO);
1164           return TRACE_SYSRES (-1);
1165         }
1166       close_handle (rh);
1167       rh = hd;
1168     }
1169   else if (inherit_idx == 1)
1170     {
1171       HANDLE hd;
1172       if (!DuplicateHandle( GetCurrentProcess(), wh,
1173                             GetCurrentProcess(), &hd, 0,
1174                             TRUE, DUPLICATE_SAME_ACCESS))
1175         {
1176           TRACE_LOG  ("DuplicateHandle failed: ec=%d",
1177                       (int) GetLastError ());
1178           release_fd (rfd);
1179           release_fd (wfd);
1180           close_handle (rh);
1181           close_handle (wh);
1182           release_hddesc (rhdesc);
1183           release_hddesc (whdesc);
1184           gpg_err_set_errno (EIO);
1185           return TRACE_SYSRES (-1);
1186         }
1187       close_handle (wh);
1188       wh = hd;
1189     }
1190
1191   /* Put the HANDLEs of the new pipe into the file descriptor table.
1192    * Note that we don't need to lock the table because we have just
1193    * acquired these two fresh fds and they are not known by any other
1194    * thread.  */
1195   fd_table[rfd].want_reader = 1;
1196   ref_hddesc (rhdesc)->hd = rh;
1197   fd_table[rfd].hdd = rhdesc;
1198
1199   fd_table[wfd].want_writer = 1;
1200   ref_hddesc (whdesc)->hd = wh;
1201   fd_table[wfd].hdd = whdesc;
1202
1203   filedes[0] = rfd;
1204   filedes[1] = wfd;
1205   TRACE_SUC ("read=0x%x (hdd=%p,hd=%p), write=0x%x (hdd=%p,hd=%p)",
1206              rfd, fd_table[rfd].hdd, fd_table[rfd].hdd->hd,
1207              wfd, fd_table[wfd].hdd, fd_table[wfd].hdd->hd);
1208   return 0;
1209 }
1210
1211
1212 /* Close out File descriptor FD.  */
1213 int
1214 _gpgme_io_close (int fd)
1215 {
1216   _gpgme_close_notify_handler_t handler = NULL;
1217   void *value = NULL;
1218
1219   TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd, "");
1220
1221   if (fd < 0)
1222     {
1223       gpg_err_set_errno (EBADF);
1224       return TRACE_SYSRES (-1);
1225     }
1226
1227   LOCK (fd_table_lock);
1228   /* Check the size in the locked state because we may eventually add
1229    * code to change that size.  */
1230   if (fd >= fd_table_size || !fd_table[fd].used)
1231     {
1232       UNLOCK (fd_table_lock);
1233       gpg_err_set_errno (EBADF);
1234       return TRACE_SYSRES (-1);
1235     }
1236
1237   TRACE_LOG  ("hdd=%p dupfrom=%d", fd_table[fd].hdd, fd_table[fd].dup_from);
1238
1239   if (fd_table[fd].reader)
1240     {
1241       TRACE_LOG  ("destroying reader %p", fd_table[fd].reader);
1242       destroy_reader (fd_table[fd].reader);
1243       fd_table[fd].reader = NULL;
1244     }
1245
1246   if (fd_table[fd].writer)
1247     {
1248       TRACE_LOG  ("destroying writer %p", fd_table[fd].writer);
1249       destroy_writer (fd_table[fd].writer);
1250       fd_table[fd].writer = NULL;
1251     }
1252
1253   /* The handler may not use any fd function because the table is
1254    * locked.  Can we avoid this?  */
1255   handler = fd_table[fd].notify.handler;
1256   value   = fd_table[fd].notify.value;
1257
1258   /* Release our reference to the handle descriptor.  Note that if no
1259    * reader or writer threads were used this release will also take
1260    * care that the handle descriptor is closed
1261    * (i.e. CloseHandle(hdd->hd) is called).  */
1262   release_hddesc (fd_table[fd].hdd);
1263   fd_table[fd].hdd = NULL;
1264
1265   UNLOCK (fd_table_lock);
1266
1267   /* Run the notification callback.  */
1268   if (handler)
1269     handler (fd, value);
1270
1271   release_fd (fd);  /* FIXME: We should have a release_fd_locked () */
1272
1273   return TRACE_SYSRES (0);
1274 }
1275
1276
1277 /* Set a close notification callback which is called right after FD
1278  * has been closed but before its slot (ie. the FD number) is being
1279  * released.  The HANDLER may thus use the provided value of the FD
1280  * but it may not pass it to any I/O functions.  Note: Only the last
1281  * handler set for an FD is used.  */
1282 int
1283 _gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler,
1284                             void *value)
1285 {
1286   TRACE_BEG  (DEBUG_SYSIO, "_gpgme_io_set_close_notify", fd,
1287               "close_handler=%p/%p", handler, value);
1288
1289   LOCK (fd_table_lock);
1290   if (fd < 0 || fd >= fd_table_size || !fd_table[fd].used)
1291     {
1292       UNLOCK (fd_table_lock);
1293       gpg_err_set_errno (EBADF);
1294       return TRACE_SYSRES (-1);;
1295     }
1296
1297   fd_table[fd].notify.handler = handler;
1298   fd_table[fd].notify.value = value;
1299   UNLOCK (fd_table_lock);
1300   return TRACE_SYSRES (0);
1301 }
1302
1303
1304 int
1305 _gpgme_io_set_nonblocking (int fd)
1306 {
1307   TRACE (DEBUG_SYSIO, "_gpgme_io_set_nonblocking", fd, "");
1308   return 0;
1309 }
1310
1311
1312 static char *
1313 build_commandline (char **argv)
1314 {
1315   int i;
1316   int n = 0;
1317   char *buf;
1318   char *p;
1319
1320   /* We have to quote some things because under Windows the program
1321      parses the commandline and does some unquoting.  We enclose the
1322      whole argument in double-quotes, and escape literal double-quotes
1323      as well as backslashes with a backslash.  We end up with a
1324      trailing space at the end of the line, but that is harmless.  */
1325   for (i = 0; argv[i]; i++)
1326     {
1327       p = argv[i];
1328       /* The leading double-quote.  */
1329       n++;
1330       while (*p)
1331         {
1332           /* An extra one for each literal that must be escaped.  */
1333           if (*p == '\\' || *p == '"')
1334             n++;
1335           n++;
1336           p++;
1337         }
1338       /* The trailing double-quote and the delimiter.  */
1339       n += 2;
1340     }
1341   /* And a trailing zero.  */
1342   n++;
1343
1344   buf = p = malloc (n);
1345   if (!buf)
1346     return NULL;
1347   for (i = 0; argv[i]; i++)
1348     {
1349       char *argvp = argv[i];
1350
1351       *(p++) = '"';
1352       while (*argvp)
1353         {
1354           if (*argvp == '\\' || *argvp == '"')
1355             *(p++) = '\\';
1356           *(p++) = *(argvp++);
1357         }
1358       *(p++) = '"';
1359       *(p++) = ' ';
1360     }
1361   *(p++) = 0;
1362
1363   return buf;
1364 }
1365
1366
1367 int
1368 _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
1369                  struct spawn_fd_item_s *fd_list,
1370                  void (*atfork) (void *opaque, int reserved),
1371                  void *atforkvalue, pid_t *r_pid)
1372 {
1373   PROCESS_INFORMATION pi =
1374     {
1375       NULL,      /* returns process handle */
1376       0,         /* returns primary thread handle */
1377       0,         /* returns pid */
1378       0          /* returns tid */
1379     };
1380   int i;
1381
1382   SECURITY_ATTRIBUTES sec_attr;
1383   STARTUPINFOA si;
1384   int cr_flags = CREATE_DEFAULT_ERROR_MODE;
1385   char **args;
1386   char *arg_string;
1387   /* FIXME.  */
1388   int debug_me = 0;
1389   int tmp_fd;
1390   char *tmp_name;
1391   const char *spawnhelper;
1392   static int spawn_warning_shown = 0;
1393
1394   TRACE_BEG  (DEBUG_SYSIO, "_gpgme_io_spawn", path,
1395               "path=%s", path);
1396
1397   (void)atfork;
1398   (void)atforkvalue;
1399
1400   i = 0;
1401   while (argv[i])
1402     {
1403       TRACE_LOG  ("argv[%2i] = %s", i, argv[i]);
1404       i++;
1405     }
1406
1407   /* We do not inherit any handles by default, and just insert those
1408      handles we want the child to have afterwards.  But some handle
1409      values occur on the command line, and we need to move
1410      stdin/out/err to the right location.  So we use a wrapper program
1411      which gets the information from a temporary file.  */
1412   if (_gpgme_mkstemp (&tmp_fd, &tmp_name) < 0)
1413     {
1414       TRACE_LOG  ("_gpgme_mkstemp failed: %s", strerror (errno));
1415       return TRACE_SYSRES (-1);
1416     }
1417   TRACE_LOG  ("tmp_name = %s", tmp_name);
1418
1419   args = calloc (2 + i + 1, sizeof (*args));
1420   args[0] = (char *) _gpgme_get_w32spawn_path ();
1421   args[1] = tmp_name;
1422   args[2] = (char *)path;
1423   memcpy (&args[3], &argv[1], i * sizeof (*args));
1424
1425   memset (&sec_attr, 0, sizeof sec_attr);
1426   sec_attr.nLength = sizeof sec_attr;
1427   sec_attr.bInheritHandle = FALSE;
1428
1429   arg_string = build_commandline (args);
1430   free (args);
1431   if (!arg_string)
1432     {
1433       close (tmp_fd);
1434       DeleteFileA (tmp_name);
1435       free (tmp_name);
1436       return TRACE_SYSRES (-1);
1437     }
1438
1439   memset (&si, 0, sizeof si);
1440   si.cb = sizeof (si);
1441   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
1442   si.wShowWindow = debug_me ? SW_SHOW : SW_HIDE;
1443   si.hStdInput = INVALID_HANDLE_VALUE;
1444   si.hStdOutput = INVALID_HANDLE_VALUE;
1445   si.hStdError = INVALID_HANDLE_VALUE;
1446
1447   cr_flags |= CREATE_SUSPENDED;
1448   if ((flags & IOSPAWN_FLAG_DETACHED))
1449     cr_flags |= DETACHED_PROCESS;
1450   cr_flags |= GetPriorityClass (GetCurrentProcess ());
1451   spawnhelper = _gpgme_get_w32spawn_path ();
1452   if (!spawnhelper)
1453     {
1454       /* This is a common mistake for new users of gpgme not to include
1455          gpgme-w32spawn.exe with their binary. So we want to make
1456          this transparent to developers. If users have somehow messed
1457          up their installation this should also be properly communicated
1458          as otherwise calls to gnupg will result in unsupported protocol
1459          errors that do not explain a lot. */
1460       if (!spawn_warning_shown)
1461         {
1462           char *msg;
1463           gpgrt_asprintf (&msg, "gpgme-w32spawn.exe was not found in the "
1464                                 "detected installation directory of GpgME"
1465                                 "\n\t\"%s\"\n\n"
1466                                 "Crypto operations will not work.\n\n"
1467                                 "If you see this it indicates a problem "
1468                                 "with your installation.\n"
1469                                 "Please report the problem to your "
1470                                 "distributor of GpgME.\n\n"
1471                                 "Developer's Note: The install dir can be "
1472                                 "manually set with: gpgme_set_global_flag",
1473                                 _gpgme_get_inst_dir ());
1474           MessageBoxA (NULL, msg, "GpgME not installed correctly", MB_OK);
1475           gpgrt_free (msg);
1476           spawn_warning_shown = 1;
1477         }
1478       gpg_err_set_errno (EIO);
1479       close (tmp_fd);
1480       DeleteFileA (tmp_name);
1481       free (tmp_name);
1482       return TRACE_SYSRES (-1);
1483     }
1484   if (!CreateProcessA (spawnhelper,
1485                        arg_string,
1486                        &sec_attr,     /* process security attributes */
1487                        &sec_attr,     /* thread security attributes */
1488                        FALSE,         /* inherit handles */
1489                        cr_flags,      /* creation flags */
1490                        NULL,          /* environment */
1491                        NULL,          /* use current drive/directory */
1492                        &si,           /* startup information */
1493                        &pi))          /* returns process information */
1494     {
1495       int lasterr = (int)GetLastError ();
1496       TRACE_LOG  ("CreateProcess failed: ec=%d", lasterr);
1497       free (arg_string);
1498       close (tmp_fd);
1499       DeleteFileA (tmp_name);
1500       free (tmp_name);
1501
1502       /* FIXME: Should translate the error code.  */
1503       gpg_err_set_errno (EIO);
1504       return TRACE_SYSRES (-1);
1505     }
1506
1507   if (flags & IOSPAWN_FLAG_ALLOW_SET_FG)
1508     _gpgme_allow_set_foreground_window ((pid_t)pi.dwProcessId);
1509
1510   /* Insert the inherited handles.  */
1511   LOCK (fd_table_lock);
1512   for (i = 0; fd_list[i].fd != -1; i++)
1513     {
1514       int fd = fd_list[i].fd;
1515       HANDLE ohd = INVALID_HANDLE_VALUE;
1516       HANDLE hd = INVALID_HANDLE_VALUE;
1517
1518       /* Make it inheritable for the wrapper process.  */
1519       if (fd >= 0 && fd < fd_table_size && fd_table[fd].used
1520           && fd_table[fd].hdd)
1521         ohd = fd_table[fd].hdd->hd;
1522
1523       if (!DuplicateHandle (GetCurrentProcess(), ohd,
1524                             pi.hProcess, &hd, 0, TRUE, DUPLICATE_SAME_ACCESS))
1525         {
1526           TRACE_LOG  ("DuplicateHandle failed: ec=%d", (int) GetLastError ());
1527           TerminateProcess (pi.hProcess, 0);
1528           /* Just in case TerminateProcess didn't work, let the
1529              process fail on its own.  */
1530           ResumeThread (pi.hThread);
1531           close_handle (pi.hThread);
1532           close_handle (pi.hProcess);
1533
1534           close (tmp_fd);
1535           DeleteFileA (tmp_name);
1536           free (tmp_name);
1537
1538           /* FIXME: Should translate the error code.  */
1539           gpg_err_set_errno (EIO);
1540           UNLOCK (fd_table_lock);
1541           return TRACE_SYSRES (-1);
1542         }
1543       /* Return the child name of this handle.  */
1544       fd_list[i].peer_name = handle_to_fd (hd);
1545     }
1546
1547   /* Write the handle translation information to the temporary
1548      file.  */
1549   {
1550     /* Hold roughly MAX_TRANS quadruplets of 64 bit numbers in hex
1551        notation: "0xFEDCBA9876543210" with an extra white space after
1552        every quadruplet.  10*(19*4 + 1) - 1 = 769.  This plans ahead
1553        for a time when a HANDLE is 64 bit.  */
1554 #define BUFFER_MAX 810
1555     char line[BUFFER_MAX + 1];
1556     int res;
1557     int written;
1558     size_t len;
1559
1560     if (flags)
1561       snprintf (line, BUFFER_MAX, "~%i \n", flags);
1562     else
1563       strcpy (line, "\n");
1564     for (i = 0; fd_list[i].fd != -1; i++)
1565       {
1566         /* Strip the newline.  */
1567         len = strlen (line) - 1;
1568
1569         /* Format is: Local name, stdin/stdout/stderr, peer name, argv idx.  */
1570         snprintf (&line[len], BUFFER_MAX - len, "0x%x %d 0x%x %d  \n",
1571                   fd_list[i].fd, fd_list[i].dup_to,
1572                   fd_list[i].peer_name, fd_list[i].arg_loc);
1573         /* Rather safe than sorry.  */
1574         line[BUFFER_MAX - 1] = '\n';
1575         line[BUFFER_MAX] = '\0';
1576       }
1577     len = strlen (line);
1578     written = 0;
1579     do
1580       {
1581         res = write (tmp_fd, &line[written], len - written);
1582         if (res > 0)
1583           written += res;
1584       }
1585     while (res > 0 || (res < 0 && errno == EAGAIN));
1586   }
1587   close (tmp_fd);
1588   /* The temporary file is deleted by the gpgme-w32spawn process
1589      (hopefully).  */
1590
1591   free (tmp_name);
1592   free (arg_string);
1593
1594   UNLOCK (fd_table_lock);
1595
1596   TRACE_LOG  ("CreateProcess ready: hProcess=%p, hThread=%p, "
1597               "dwProcessID=%d, dwThreadId=%d",
1598               pi.hProcess, pi.hThread,
1599               (int) pi.dwProcessId, (int) pi.dwThreadId);
1600
1601   if (r_pid)
1602     *r_pid = (pid_t)pi.dwProcessId;
1603
1604
1605   if (ResumeThread (pi.hThread) == (DWORD)(-1))
1606     TRACE_LOG  ("ResumeThread failed: ec=%d", (int) GetLastError ());
1607
1608   close_handle (pi.hThread);
1609
1610   TRACE_LOG  ("process=%p", pi.hProcess);
1611
1612   /* We don't need to wait for the process.  */
1613   close_handle (pi.hProcess);
1614
1615   if (! (flags & IOSPAWN_FLAG_NOCLOSE))
1616     {
1617       for (i = 0; fd_list[i].fd != -1; i++)
1618         _gpgme_io_close (fd_list[i].fd);
1619     }
1620
1621   for (i = 0; fd_list[i].fd != -1; i++)
1622     if (fd_list[i].dup_to == -1)
1623       TRACE_LOG  ("fd[%i] = 0x%x -> 0x%x", i, fd_list[i].fd,
1624                   fd_list[i].peer_name);
1625     else
1626       TRACE_LOG  ("fd[%i] = 0x%x -> 0x%x (std%s)", i, fd_list[i].fd,
1627                   fd_list[i].peer_name, (fd_list[i].dup_to == 0) ? "in" :
1628                   ((fd_list[i].dup_to == 1) ? "out" : "err"));
1629
1630   return TRACE_SYSRES (0);
1631 }
1632
1633
1634 /* Select on the list of fds.  Returns: -1 = error, 0 = timeout or
1635    nothing to select, > 0 = number of signaled fds.  */
1636 int
1637 _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
1638 {
1639   HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS];
1640   int waitidx[MAXIMUM_WAIT_OBJECTS];
1641   int code;
1642   int nwait;
1643   int i;
1644   int any;
1645   int count;
1646   void *dbg_help;
1647   TRACE_BEG  (DEBUG_SYSIO, "_gpgme_io_select", fds,
1648               "nfds=%u, nonblock=%u", nfds, nonblock);
1649
1650 #if 0
1651  restart:
1652 #endif
1653   TRACE_SEQ (dbg_help, "select on [ ");
1654   any = 0;
1655   nwait = 0;
1656   count = 0;
1657   for (i=0; i < nfds; i++)
1658     {
1659       if (fds[i].fd == -1)
1660         continue;
1661       fds[i].signaled = 0;
1662       if (fds[i].for_read || fds[i].for_write)
1663         {
1664           if (fds[i].for_read)
1665             {
1666               /* FIXME: A find_reader_locked() along with separate
1667                * lock calls might be a better appaoched here.  */
1668               struct reader_context_s *ctx = find_reader (fds[i].fd);
1669
1670               if (!ctx)
1671                 TRACE_LOG  ("error: no reader for FD 0x%x (ignored)",
1672                             fds[i].fd);
1673               else
1674                 {
1675                   if (nwait >= DIM (waitbuf))
1676                     {
1677                       TRACE_END (dbg_help, "oops ]");
1678                       TRACE_LOG ("Too many objects for WFMO!");
1679                       /* FIXME: Should translate the error code.  */
1680                       gpg_err_set_errno (EIO);
1681                       return TRACE_SYSRES (-1);
1682                     }
1683                   waitidx[nwait] = i;
1684                   waitbuf[nwait++] = ctx->have_data_ev;
1685                 }
1686               TRACE_ADD1 (dbg_help, "r0x%x ", fds[i].fd);
1687               any = 1;
1688             }
1689           else if (fds[i].for_write)
1690             {
1691               struct writer_context_s *ctx = find_writer (fds[i].fd);
1692
1693               if (!ctx)
1694                 TRACE_LOG  ("error: no writer for FD 0x%x (ignored)",
1695                             fds[i].fd);
1696               else
1697                 {
1698                   if (nwait >= DIM (waitbuf))
1699                     {
1700                       TRACE_END (dbg_help, "oops ]");
1701                       TRACE_LOG ("Too many objects for WFMO!");
1702                       /* FIXME: Should translate the error code.  */
1703                       gpg_err_set_errno (EIO);
1704                       return TRACE_SYSRES (-1);
1705                     }
1706                   waitidx[nwait] = i;
1707                   waitbuf[nwait++] = ctx->is_empty;
1708                 }
1709               TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd);
1710               any = 1;
1711             }
1712         }
1713     }
1714   TRACE_END (dbg_help, "]");
1715   if (!any)
1716     return TRACE_SYSRES (0);
1717
1718   code = WaitForMultipleObjects (nwait, waitbuf, 0, nonblock ? 0 : 1000);
1719   if (code < WAIT_OBJECT_0 + nwait)
1720     {
1721       /* The WFMO is a really silly function: It does return either
1722          the index of the signaled object or if 2 objects have been
1723          signalled at the same time, the index of the object with the
1724          lowest object is returned - so and how do we find out how
1725          many objects have been signaled?.  The only solution I can
1726          imagine is to test each object starting with the returned
1727          index individually - how dull.  */
1728       any = 0;
1729       for (i = code - WAIT_OBJECT_0; i < nwait; i++)
1730         {
1731           if (wait_for_single_object (waitbuf[i], 0) == WAIT_OBJECT_0)
1732             {
1733               assert (waitidx[i] >=0 && waitidx[i] < nfds);
1734               fds[waitidx[i]].signaled = 1;
1735               any = 1;
1736               count++;
1737             }
1738         }
1739       if (!any)
1740         {
1741           TRACE_LOG ("no signaled objects found after WFMO");
1742           count = -1;
1743         }
1744     }
1745   else if (code == WAIT_TIMEOUT)
1746     TRACE_LOG ("WFMO timed out");
1747   else if (code == WAIT_FAILED)
1748     {
1749       int le = (int) GetLastError ();
1750 #if 0
1751       if (le == ERROR_INVALID_HANDLE)
1752         {
1753           int k;
1754           int j = handle_to_fd (waitbuf[i]);
1755
1756           TRACE_LOG  ("WFMO invalid handle %d removed", j);
1757           for (k = 0 ; k < nfds; k++)
1758             {
1759               if (fds[k].fd == j)
1760                 {
1761                   fds[k].for_read = fds[k].for_write = 0;
1762                   goto restart;
1763                 }
1764             }
1765           TRACE_LOG (" oops, or not???");
1766         }
1767 #endif
1768       TRACE_LOG  ("WFMO failed: %d", le);
1769       count = -1;
1770     }
1771   else
1772     {
1773       TRACE_LOG  ("WFMO returned %d", code);
1774       count = -1;
1775     }
1776
1777   if (count > 0)
1778     {
1779       TRACE_SEQ (dbg_help, "select OK [ ");
1780       for (i = 0; i < nfds; i++)
1781         {
1782           if (fds[i].fd == -1)
1783             continue;
1784           if ((fds[i].for_read || fds[i].for_write) && fds[i].signaled)
1785             TRACE_ADD2 (dbg_help, "%c0x%x ",
1786                         fds[i].for_read ? 'r' : 'w', fds[i].fd);
1787         }
1788       TRACE_END (dbg_help, "]");
1789     }
1790
1791   if (count < 0)
1792     {
1793       /* FIXME: Should determine a proper error code.  */
1794       gpg_err_set_errno (EIO);
1795     }
1796
1797   return TRACE_SYSRES (count);
1798 }
1799
1800
1801 void
1802 _gpgme_io_subsystem_init (void)
1803 {
1804   /* Nothing to do.  */
1805 }
1806
1807
1808 /* Write the printable version of FD to BUFFER which has an allocated
1809  * length of BUFLEN.  The printable version is the representation on
1810  * the command line that the child process expects.  Note that this
1811  * works closely together with the gpgme-32spawn wrapper process which
1812  * translates these command line args to the real handles. */
1813 int
1814 _gpgme_io_fd2str (char *buffer, int buflen, int fd)
1815 {
1816   return snprintf (buffer, buflen, "%d", fd);
1817 }
1818
1819
1820 int
1821 _gpgme_io_dup (int fd)
1822 {
1823   int newfd;
1824   struct reader_context_s *rd_ctx;
1825   struct writer_context_s *wt_ctx;
1826   int want_reader, want_writer;
1827
1828   TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_dup", fd, "");
1829
1830   LOCK (fd_table_lock);
1831   if (fd < 0 || fd >= fd_table_size || !fd_table[fd].used)
1832     {
1833       UNLOCK (fd_table_lock);
1834       gpg_err_set_errno (EBADF);
1835       return TRACE_SYSRES (-1);
1836     }
1837
1838   newfd = new_fd();
1839   if (newfd == -1)
1840     {
1841       UNLOCK (fd_table_lock);
1842       gpg_err_set_errno (EMFILE);
1843       return TRACE_SYSRES (-1);
1844     }
1845
1846   fd_table[newfd].hdd = ref_hddesc (fd_table[fd].hdd);
1847   fd_table[newfd].dup_from = fd;
1848   want_reader = fd_table[fd].want_reader;
1849   want_writer = fd_table[fd].want_writer;
1850
1851   UNLOCK (fd_table_lock);
1852
1853   rd_ctx = want_reader? find_reader (fd) : NULL;
1854   if (rd_ctx)
1855     {
1856       /* NEWFD initializes a freshly allocated slot and does not need
1857        * to be locked.  */
1858       LOCK (rd_ctx->mutex);
1859       rd_ctx->refcount++;
1860       UNLOCK (rd_ctx->mutex);
1861       fd_table[newfd].reader = rd_ctx;
1862     }
1863
1864   wt_ctx = want_writer? find_writer (fd) : NULL;
1865   if (wt_ctx)
1866     {
1867       LOCK (wt_ctx->mutex);
1868       wt_ctx->refcount++;
1869       UNLOCK (wt_ctx->mutex);
1870       fd_table[newfd].writer = wt_ctx;
1871     }
1872
1873   return TRACE_SYSRES (newfd);
1874 }
1875
1876 \f
1877 /* The following interface is only useful for GPGME Glib and Qt.  */
1878
1879 /* Compatibility interface, obsolete.  */
1880 void *
1881 gpgme_get_giochannel (int fd)
1882 {
1883   (void)fd;
1884   return NULL;
1885 }
1886
1887
1888 /* Look up the giochannel or qiodevice for file descriptor FD.  */
1889 void *
1890 gpgme_get_fdptr (int fd)
1891 {
1892   (void)fd;
1893   return NULL;
1894 }
1895
1896 \f
1897 static int
1898 wsa2errno (int err)
1899 {
1900   switch (err)
1901     {
1902     case WSAENOTSOCK:
1903       return EINVAL;
1904     case WSAEWOULDBLOCK:
1905       return EAGAIN;
1906     case ERROR_BROKEN_PIPE:
1907       return EPIPE;
1908     case WSANOTINITIALISED:
1909       return ENOSYS;
1910     default:
1911       return EIO;
1912     }
1913 }
1914
1915
1916 int
1917 _gpgme_io_socket (int domain, int type, int proto)
1918 {
1919   int res;
1920   int fd;
1921   hddesc_t hdd;
1922
1923   TRACE_BEG  (DEBUG_SYSIO, "_gpgme_io_socket", domain,
1924               "type=%i, protp=%i", type, proto);
1925
1926   fd = new_fd();
1927   if (fd == -1)
1928     return TRACE_SYSRES (-1);
1929   hdd = new_hddesc ();
1930   if (!hdd)
1931     {
1932       UNLOCK (fd_table_lock);
1933       release_fd (fd);
1934       gpg_err_set_errno (ENOMEM);
1935       return TRACE_SYSRES (-1);
1936     }
1937
1938   res = socket (domain, type, proto);
1939   if (res == INVALID_SOCKET)
1940     {
1941       release_fd (fd);
1942       gpg_err_set_errno (wsa2errno (WSAGetLastError ()));
1943       return TRACE_SYSRES (-1);
1944     }
1945   ref_hddesc (hdd)->sock = res;
1946   fd_table[fd].hdd = hdd;
1947   fd_table[fd].want_reader = 1;
1948   fd_table[fd].want_writer = 1;
1949
1950   TRACE_SUC ("hdd=%p, socket=0x%x (0x%x)", hdd, fd, hdd->sock);
1951
1952   return fd;
1953 }
1954
1955
1956 int
1957 _gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen)
1958 {
1959   int res;
1960   int sock;
1961
1962   TRACE_BEG  (DEBUG_SYSIO, "_gpgme_io_connect", fd,
1963               "addr=%p, addrlen=%i", addr, addrlen);
1964
1965   LOCK (fd_table_lock);
1966   if (fd < 0 || fd >= fd_table_size || !fd_table[fd].used || !fd_table[fd].hdd)
1967     {
1968       gpg_err_set_errno (EBADF);
1969       UNLOCK (fd_table_lock);
1970       return TRACE_SYSRES (-1);
1971     }
1972   sock = fd_table[fd].hdd->sock;
1973   UNLOCK (fd_table_lock);
1974
1975   res = connect (sock, addr, addrlen);
1976   if (res)
1977     {
1978       gpg_err_set_errno (wsa2errno (WSAGetLastError ()));
1979       return TRACE_SYSRES (-1);
1980     }
1981
1982   TRACE_SUC ("");
1983   return 0;
1984 }