a6dfdbcf5b60cffc452e60fab3b94ffa00422396
[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 hanlder.  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       TRACE2 (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       TRACE2 (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 intialized (in which case
234        * REFCOUNT would be -1 here).  */
235       TRACE_BEG3 (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_LOG1 ("closing socket %d", hdd->sock);
245           if (closesocket (hdd->sock))
246             {
247               TRACE_LOG1 ("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 intialized 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       TRACE1 (DEBUG_SYSIO, "gpgme:get_desired_thread_priority", 0,
335               "%d (default)", value);
336     }
337   else
338     {
339       TRACE1 (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_BEG4 (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_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ());
377             }
378           UNLOCK (ctx->mutex);
379           TRACE_LOG1 ("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_LOG2 ("%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_LOG1 ("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_LOG1 ("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_LOG2 ("got %u 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_LOG2 ("SetEvent (0x%x) 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_LOG2 ("SetEvent (0x%x) 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   return TRACE_SUC ();
501 }
502
503
504 /* Create a new reader thread and return its context object.  The
505  * input is the handle descriptor HDD.  This function may not call any
506  * fd based functions because the caller already holds a lock on the
507  * fd_table.  */
508 static struct reader_context_s *
509 create_reader (hddesc_t hdd)
510 {
511   struct reader_context_s *ctx;
512   SECURITY_ATTRIBUTES sec_attr;
513   DWORD tid;
514
515   TRACE_BEG3 (DEBUG_SYSIO, "gpgme:create_reader", hdd,
516               "handle=%p sock=%d refhdd=%d",
517               hdd->hd, hdd->sock, hdd->refcount);
518
519   memset (&sec_attr, 0, sizeof sec_attr);
520   sec_attr.nLength = sizeof sec_attr;
521   sec_attr.bInheritHandle = FALSE;
522
523   ctx = calloc (1, sizeof *ctx);
524   if (!ctx)
525     {
526       TRACE_SYSERR_NR (errno);
527       return NULL;
528     }
529
530   ctx->hdd = ref_hddesc (hdd);
531
532   ctx->refcount = 1;
533   ctx->have_data_ev = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
534   if (ctx->have_data_ev)
535     ctx->have_space_ev = CreateEvent (&sec_attr, FALSE, TRUE, NULL);
536   if (ctx->have_space_ev)
537     ctx->close_ev = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
538   if (!ctx->have_data_ev || !ctx->have_space_ev || !ctx->close_ev)
539     {
540       TRACE_LOG1 ("CreateEvent failed: ec=%d", (int) GetLastError ());
541       if (ctx->have_data_ev)
542         close_handle (ctx->have_data_ev);
543       if (ctx->have_space_ev)
544         close_handle (ctx->have_space_ev);
545       if (ctx->close_ev)
546         close_handle (ctx->close_ev);
547       release_hddesc (ctx->hdd);
548       free (ctx);
549       TRACE_SYSERR_NR (EIO);
550       return NULL;
551     }
552
553   INIT_LOCK (ctx->mutex);
554
555   ctx->thread_hd = CreateThread (&sec_attr, 0, reader, ctx, 0, &tid);
556
557   if (!ctx->thread_hd)
558     {
559       TRACE_LOG1 ("CreateThread failed: ec=%d", (int) GetLastError ());
560       DESTROY_LOCK (ctx->mutex);
561       if (ctx->have_data_ev)
562         close_handle (ctx->have_data_ev);
563       if (ctx->have_space_ev)
564         close_handle (ctx->have_space_ev);
565       if (ctx->close_ev)
566         close_handle (ctx->close_ev);
567       release_hddesc (ctx->hdd);
568       free (ctx);
569       TRACE_SYSERR_NR (EIO);
570       return NULL;
571     }
572   else
573     {
574       /* We set the priority of the thread higher because we know that
575          it only runs for a short time.  This greatly helps to
576          increase the performance of the I/O.  */
577       SetThreadPriority (ctx->thread_hd, get_desired_thread_priority ());
578     }
579
580   TRACE_SUC ();
581   return ctx;
582 }
583
584
585 /* Prepare destruction of the reader thread for CTX.  Returns 0 if a
586    call to this function is sufficient and destroy_reader_finish shall
587    not be called.  */
588 static void
589 destroy_reader (struct reader_context_s *ctx)
590 {
591   LOCK (ctx->mutex);
592   ctx->refcount--;
593   if (ctx->refcount != 0)
594     {
595       TRACE2 (DEBUG_SYSIO, "gpgme:destroy_reader", ctx,
596               "hdd=%p refcount now %d", ctx->hdd, ctx->refcount);
597       UNLOCK (ctx->mutex);
598       return;
599     }
600   ctx->stop_me = 1;
601   if (ctx->have_space_ev)
602     SetEvent (ctx->have_space_ev);
603   TRACE1 (DEBUG_SYSIO, "gpgme:destroy_reader", ctx,
604           "hdd=%p close triggered", ctx->hdd);
605   UNLOCK (ctx->mutex);
606
607   /* The reader thread is usually blocking in recv or ReadFile.  If
608      the peer does not send an EOF or breaks the pipe the WFSO might
609      get stuck waiting for the termination of the reader thread.  This
610      happens quite often with sockets, thus we definitely need to get
611      out of the recv.  A shutdown does this nicely.  For handles
612      (i.e. pipes) it would also be nice to cancel the operation, but
613      such a feature is only available since Vista.  Thus we need to
614      dlopen that syscall.  */
615   assert (ctx->hdd);
616   if (ctx->hdd && ctx->hdd->hd != INVALID_HANDLE_VALUE)
617     {
618       _gpgme_w32_cancel_synchronous_io (ctx->thread_hd);
619     }
620   else if (ctx->hdd && ctx->hdd->sock != INVALID_SOCKET)
621     {
622       if (shutdown (ctx->hdd->sock, 2))
623         TRACE2 (DEBUG_SYSIO, "gpgme:destroy_reader", ctx,
624                 "shutdown socket %d failed: %s",
625                 ctx->hdd->sock, (int) WSAGetLastError ());
626     }
627
628   /* After setting this event CTX is void. */
629   SetEvent (ctx->close_ev);
630 }
631
632
633
634 /* Find a reader context or create a new one.  Note that the reader
635  * context will last until a _gpgme_io_close.  NULL is returned for a
636  * bad FD or for other errors.  */
637 static struct reader_context_s *
638 find_reader (int fd)
639 {
640   struct reader_context_s *rd = NULL;
641
642   TRACE_BEG0 (DEBUG_SYSIO, "gpgme:find_reader", fd, "");
643
644   LOCK (fd_table_lock);
645   if (fd < 0 || fd >= fd_table_size || !fd_table[fd].used)
646     {
647       UNLOCK (fd_table_lock);
648       gpg_err_set_errno (EBADF);
649       TRACE_SUC0 ("EBADF");
650       return NULL;
651     }
652
653   rd = fd_table[fd].reader;
654   if (rd)
655     {
656       UNLOCK (fd_table_lock);
657       TRACE_SUC1 ("rd=%p", rd);
658       return rd;  /* Return already initialized reader thread object.  */
659     }
660
661   /* Create a new reader thread.  */
662   TRACE_LOG3 ("fd=%d -> hdd=%p dupfrom=%d creating reader",
663               fd, fd_table[fd].hdd, fd_table[fd].dup_from);
664   rd = create_reader (fd_table[fd].hdd);
665   if (!rd)
666     gpg_err_set_errno (EIO);
667   else
668     fd_table[fd].reader = rd;
669
670   UNLOCK (fd_table_lock);
671   TRACE_SUC1 ("rd=%p (new)", rd);
672   return rd;
673 }
674
675
676 int
677 _gpgme_io_read (int fd, void *buffer, size_t count)
678 {
679   int nread;
680   struct reader_context_s *ctx;
681   TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd,
682               "buffer=%p, count=%u", buffer, count);
683
684   ctx = find_reader (fd);
685   if (!ctx)
686     return TRACE_SYSRES (-1);
687   if (ctx->eof_shortcut)
688     return TRACE_SYSRES (0);
689
690   LOCK (ctx->mutex);
691   if (ctx->readpos == ctx->writepos && !ctx->error)
692     {
693       /* No data available.  */
694       UNLOCK (ctx->mutex);
695       TRACE_LOG1 ("waiting for data from thread %p", ctx->thread_hd);
696       wait_for_single_object (ctx->have_data_ev, INFINITE);
697       TRACE_LOG1 ("data from thread %p available", ctx->thread_hd);
698       LOCK (ctx->mutex);
699     }
700
701   if (ctx->readpos == ctx->writepos || ctx->error)
702     {
703       UNLOCK (ctx->mutex);
704       ctx->eof_shortcut = 1;
705       if (ctx->eof)
706         return TRACE_SYSRES (0);
707       if (!ctx->error)
708         {
709           TRACE_LOG ("EOF but ctx->eof flag not set");
710           return 0;
711         }
712       gpg_err_set_errno (ctx->error_code);
713       return TRACE_SYSRES (-1);
714     }
715
716   nread = ctx->readpos < ctx->writepos
717     ? ctx->writepos - ctx->readpos
718     : READBUF_SIZE - ctx->readpos;
719   if (nread > count)
720     nread = count;
721   memcpy (buffer, ctx->buffer + ctx->readpos, nread);
722   ctx->readpos = (ctx->readpos + nread) % READBUF_SIZE;
723   if (ctx->readpos == ctx->writepos && !ctx->eof)
724     {
725       if (!ResetEvent (ctx->have_data_ev))
726         {
727           TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ());
728           UNLOCK (ctx->mutex);
729           /* FIXME: Should translate the error code.  */
730           gpg_err_set_errno (EIO);
731           return TRACE_SYSRES (-1);
732         }
733     }
734   if (!SetEvent (ctx->have_space_ev))
735     {
736       TRACE_LOG2 ("SetEvent (0x%x) failed: ec=%d",
737                   ctx->have_space_ev, (int) GetLastError ());
738       UNLOCK (ctx->mutex);
739       /* FIXME: Should translate the error code.  */
740       gpg_err_set_errno (EIO);
741       return TRACE_SYSRES (-1);
742     }
743   UNLOCK (ctx->mutex);
744
745   TRACE_LOGBUFX (buffer, nread);
746   return TRACE_SYSRES (nread);
747 }
748
749
750 /* The writer does use a simple buffering strategy so that we are
751    informed about write errors as soon as possible (i. e. with the the
752    next call to the write function.  */
753 static DWORD CALLBACK
754 writer (void *arg)
755 {
756   struct writer_context_s *ctx = arg;
757   DWORD nwritten;
758   int sock;
759   TRACE_BEG4 (DEBUG_SYSIO, "gpgme:writer", ctx->hdd,
760               "hd=%p, sock=%d, thread=%p, refcount=%d",
761               ctx->hdd->hd, ctx->hdd->sock, ctx->thread_hd, ctx->refcount);
762
763   if (ctx->hdd->hd != INVALID_HANDLE_VALUE)
764     sock = 0;
765   else
766     sock = 1;
767
768   for (;;)
769     {
770       LOCK (ctx->mutex);
771       if (ctx->stop_me && !ctx->nbytes)
772         {
773           UNLOCK (ctx->mutex);
774           break;
775         }
776       if (!ctx->nbytes)
777         {
778           if (!SetEvent (ctx->is_empty))
779             TRACE_LOG1 ("SetEvent failed: ec=%d", (int) GetLastError ());
780           if (!ResetEvent (ctx->have_data))
781             TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ());
782           UNLOCK (ctx->mutex);
783           TRACE_LOG ("idle");
784           wait_for_single_object (ctx->have_data, INFINITE);
785           TRACE_LOG ("got data to send");
786           LOCK (ctx->mutex);
787         }
788       if (ctx->stop_me && !ctx->nbytes)
789         {
790           UNLOCK (ctx->mutex);
791           break;
792         }
793       UNLOCK (ctx->mutex);
794
795       TRACE_LOG2 ("%s %d bytes", sock?"sending":"writing", ctx->nbytes);
796
797       /* Note that CTX->nbytes is not zero at this point, because
798          _gpgme_io_write always writes at least 1 byte before waking
799          us up, unless CTX->stop_me is true, which we catch above.  */
800       if (sock)
801         {
802           /* We need to try send first because a socket handle can't
803              be used with WriteFile.  */
804           int n;
805
806           n = send (ctx->hdd->sock, ctx->buffer, ctx->nbytes, 0);
807           if (n < 0)
808             {
809               ctx->error_code = (int) WSAGetLastError ();
810               ctx->error = 1;
811               TRACE_LOG1 ("send error: ec=%d", ctx->error_code);
812               break;
813             }
814           nwritten = n;
815         }
816       else
817         {
818           if (!WriteFile (ctx->hdd->hd, ctx->buffer,
819                           ctx->nbytes, &nwritten, NULL))
820             {
821               if (GetLastError () == ERROR_BUSY)
822                 {
823                   /* Probably stop_me is set now.  */
824                   TRACE_LOG ("pipe busy (unblocked?)");
825                   continue;
826                 }
827
828               ctx->error_code = (int) GetLastError ();
829               ctx->error = 1;
830               TRACE_LOG1 ("write error: ec=%d", ctx->error_code);
831               break;
832             }
833         }
834       TRACE_LOG1 ("wrote %d bytes", (int) nwritten);
835
836       LOCK (ctx->mutex);
837       ctx->nbytes -= nwritten;
838       UNLOCK (ctx->mutex);
839     }
840   /* Indicate that we have an error.  */
841   if (!SetEvent (ctx->is_empty))
842     TRACE_LOG1 ("SetEvent failed: ec=%d", (int) GetLastError ());
843
844   TRACE_LOG ("waiting for close");
845   wait_for_single_object (ctx->close_ev, INFINITE);
846
847   if (ctx->nbytes)
848     TRACE_LOG1 ("still %d bytes in buffer at close time", ctx->nbytes);
849
850   release_hddesc (ctx->hdd);
851   close_handle (ctx->close_ev);
852   close_handle (ctx->have_data);
853   close_handle (ctx->is_empty);
854   close_handle (ctx->thread_hd);
855   DESTROY_LOCK (ctx->mutex);
856   free (ctx);
857
858   return TRACE_SUC ();
859 }
860
861
862 static struct writer_context_s *
863 create_writer (hddesc_t hdd)
864 {
865   struct writer_context_s *ctx;
866   SECURITY_ATTRIBUTES sec_attr;
867   DWORD tid;
868
869
870 TRACE_BEG3 (DEBUG_SYSIO, "gpgme:create_writer", hdd,
871              "handle=%p sock=%d refhdd=%d",
872              hdd->hd, hdd->sock, hdd->refcount);
873
874   memset (&sec_attr, 0, sizeof sec_attr);
875   sec_attr.nLength = sizeof sec_attr;
876   sec_attr.bInheritHandle = FALSE;
877
878   ctx = calloc (1, sizeof *ctx);
879   if (!ctx)
880     {
881       TRACE_SYSERR_NR (errno);
882       return NULL;
883     }
884
885   ctx->hdd = ref_hddesc (hdd);
886
887   ctx->refcount = 1;
888   ctx->have_data = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
889   if (ctx->have_data)
890     ctx->is_empty  = CreateEvent (&sec_attr, TRUE, TRUE, NULL);
891   if (ctx->is_empty)
892     ctx->close_ev = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
893   if (!ctx->have_data || !ctx->is_empty || !ctx->close_ev)
894     {
895       TRACE_LOG1 ("CreateEvent failed: ec=%d", (int) GetLastError ());
896       if (ctx->have_data)
897         close_handle (ctx->have_data);
898       if (ctx->is_empty)
899         close_handle (ctx->is_empty);
900       if (ctx->close_ev)
901         close_handle (ctx->close_ev);
902       release_hddesc (ctx->hdd);
903       free (ctx);
904       TRACE_SYSERR_NR (EIO);
905       return NULL;
906     }
907
908   INIT_LOCK (ctx->mutex);
909
910   ctx->thread_hd = CreateThread (&sec_attr, 0, writer, ctx, 0, &tid );
911   if (!ctx->thread_hd)
912     {
913       TRACE_LOG1 ("CreateThread failed: ec=%d", (int) GetLastError ());
914       DESTROY_LOCK (ctx->mutex);
915       if (ctx->have_data)
916         close_handle (ctx->have_data);
917       if (ctx->is_empty)
918         close_handle (ctx->is_empty);
919       if (ctx->close_ev)
920         close_handle (ctx->close_ev);
921       release_hddesc (ctx->hdd);
922       free (ctx);
923       TRACE_SYSERR_NR (EIO);
924       return NULL;
925     }
926   else
927     {
928       /* We set the priority of the thread higher because we know
929          that it only runs for a short time.  This greatly helps to
930          increase the performance of the I/O.  */
931       SetThreadPriority (ctx->thread_hd, get_desired_thread_priority ());
932     }
933
934   TRACE_SUC ();
935   return ctx;
936 }
937
938
939 static void
940 destroy_writer (struct writer_context_s *ctx)
941 {
942   LOCK (ctx->mutex);
943   ctx->refcount--;
944   if (ctx->refcount != 0)
945     {
946       TRACE2 (DEBUG_SYSIO, "gpgme:destroy_writer", ctx,
947               "hdd=%p refcount now %d", ctx->hdd, ctx->refcount);
948       UNLOCK (ctx->mutex);
949       return;
950     }
951   ctx->stop_me = 1;
952   if (ctx->have_data)
953     SetEvent (ctx->have_data);
954   TRACE1 (DEBUG_SYSIO, "gpgme:destroy_writer", ctx,
955           "hdd=%p close triggered", ctx->hdd);
956   UNLOCK (ctx->mutex);
957
958   /* Give the writer a chance to flush the buffer.  */
959   wait_for_single_object (ctx->is_empty, INFINITE);
960
961   /* After setting this event CTX is void.  */
962   SetEvent (ctx->close_ev);
963 }
964
965
966 /* Find a writer context or create a new one.  Note that the writer
967  * context will last until a _gpgme_io_close.  NULL is returned for a
968  * bad FD or for other errors.  */
969 static struct writer_context_s *
970 find_writer (int fd)
971 {
972   struct writer_context_s *wt = NULL;
973
974   TRACE_BEG0 (DEBUG_SYSIO, "gpgme:find_writer", fd, "");
975
976   LOCK (fd_table_lock);
977   if (fd < 0 || fd >= fd_table_size || !fd_table[fd].used)
978     {
979       UNLOCK (fd_table_lock);
980       gpg_err_set_errno (EBADF);
981       TRACE_SUC0 ("EBADF");
982       return NULL;
983     }
984
985   wt = fd_table[fd].writer;
986   if (wt)
987     {
988       UNLOCK (fd_table_lock);
989       TRACE_SUC1 ("wt=%p", wt);
990       return wt;  /* Return already initialized writer thread object.  */
991     }
992
993   /* Create a new writer thread.  */
994   TRACE_LOG4 ("fd=%d -> handle=%p socket=%d dupfrom=%d creating writer",
995               fd, fd_table[fd].hdd->hd, fd_table[fd].hdd->sock,
996               fd_table[fd].dup_from);
997   wt = create_writer (fd_table[fd].hdd);
998   if (!wt)
999     gpg_err_set_errno (EIO);
1000   else
1001     fd_table[fd].writer = wt;
1002
1003   UNLOCK (fd_table_lock);
1004   TRACE_SUC1 ("wt=%p (new)", wt);
1005   return wt;
1006 }
1007
1008
1009 int
1010 _gpgme_io_write (int fd, const void *buffer, size_t count)
1011 {
1012   struct writer_context_s *ctx;
1013   TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd,
1014               "buffer=%p, count=%u", buffer, count);
1015   TRACE_LOGBUFX (buffer, count);
1016
1017   if (count == 0)
1018     return TRACE_SYSRES (0);
1019
1020   ctx = find_writer (fd);
1021   if (!ctx)
1022     return TRACE_SYSRES (-1);
1023
1024   LOCK (ctx->mutex);
1025   if (!ctx->error && ctx->nbytes)
1026     {
1027       /* Bytes are pending for send.  */
1028
1029       /* Reset the is_empty event.  Better safe than sorry.  */
1030       if (!ResetEvent (ctx->is_empty))
1031         {
1032           TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ());
1033           UNLOCK (ctx->mutex);
1034           /* FIXME: Should translate the error code.  */
1035           gpg_err_set_errno (EIO);
1036           return TRACE_SYSRES (-1);
1037         }
1038       UNLOCK (ctx->mutex);
1039       TRACE_LOG1 ("waiting for empty buffer in thread %p", ctx->thread_hd);
1040       wait_for_single_object (ctx->is_empty, INFINITE);
1041       TRACE_LOG1 ("thread %p buffer is empty", ctx->thread_hd);
1042       LOCK (ctx->mutex);
1043     }
1044
1045   if (ctx->error)
1046     {
1047       UNLOCK (ctx->mutex);
1048       if (ctx->error_code == ERROR_NO_DATA)
1049         gpg_err_set_errno (EPIPE);
1050       else
1051         gpg_err_set_errno (EIO);
1052       return TRACE_SYSRES (-1);
1053     }
1054
1055   /* If no error occurred, the number of bytes in the buffer must be
1056      zero.  */
1057   assert (!ctx->nbytes);
1058
1059   if (count > WRITEBUF_SIZE)
1060     count = WRITEBUF_SIZE;
1061   memcpy (ctx->buffer, buffer, count);
1062   ctx->nbytes = count;
1063
1064   /* We have to reset the is_empty event early, because it is also
1065    * used by the select() implementation to probe the channel.  */
1066   if (!ResetEvent (ctx->is_empty))
1067     {
1068       TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ());
1069       UNLOCK (ctx->mutex);
1070       /* FIXME: Should translate the error code.  */
1071       gpg_err_set_errno (EIO);
1072       return TRACE_SYSRES (-1);
1073     }
1074   if (!SetEvent (ctx->have_data))
1075     {
1076       TRACE_LOG1 ("SetEvent failed: ec=%d", (int) GetLastError ());
1077       UNLOCK (ctx->mutex);
1078       /* FIXME: Should translate the error code.  */
1079       gpg_err_set_errno (EIO);
1080       return TRACE_SYSRES (-1);
1081     }
1082   UNLOCK (ctx->mutex);
1083
1084   return TRACE_SYSRES ((int) count);
1085 }
1086
1087
1088 int
1089 _gpgme_io_pipe (int filedes[2], int inherit_idx)
1090 {
1091   int rfd;
1092   int wfd;
1093   HANDLE rh;
1094   HANDLE wh;
1095   hddesc_t rhdesc;
1096   hddesc_t whdesc;
1097   SECURITY_ATTRIBUTES sec_attr;
1098
1099   TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes,
1100               "inherit_idx=%i (GPGME uses it for %s)",
1101               inherit_idx, inherit_idx ? "reading" : "writing");
1102
1103   /* Get a new empty file descriptor.  */
1104   rfd = new_fd ();
1105   if (rfd == -1)
1106     return TRACE_SYSRES (-1);
1107   wfd = new_fd ();
1108   if (wfd == -1)
1109     {
1110       release_fd (rfd);
1111       return TRACE_SYSRES (-1);
1112     }
1113   rhdesc = new_hddesc ();
1114   if (!rhdesc)
1115     {
1116       release_fd (rfd);
1117       release_fd (wfd);
1118       return TRACE_SYSRES (-1);
1119     }
1120   whdesc = new_hddesc ();
1121   if (!whdesc)
1122     {
1123       release_fd (rfd);
1124       release_fd (wfd);
1125       release_hddesc (rhdesc);
1126       return TRACE_SYSRES (-1);
1127     }
1128
1129   /* Create a pipe.  */
1130   memset (&sec_attr, 0, sizeof (sec_attr));
1131   sec_attr.nLength = sizeof (sec_attr);
1132   sec_attr.bInheritHandle = FALSE;
1133
1134   if (!CreatePipe (&rh, &wh, &sec_attr, PIPEBUF_SIZE))
1135     {
1136       TRACE_LOG1 ("CreatePipe failed: ec=%d", (int) GetLastError ());
1137       release_fd (rfd);
1138       release_fd (wfd);
1139       release_hddesc (rhdesc);
1140       release_hddesc (whdesc);
1141       gpg_err_set_errno (EIO);
1142       return TRACE_SYSRES (-1);
1143     }
1144
1145   /* Make one end inheritable.  */
1146   if (inherit_idx == 0)
1147     {
1148       HANDLE hd;
1149       if (!DuplicateHandle (GetCurrentProcess(), rh,
1150                             GetCurrentProcess(), &hd, 0,
1151                             TRUE, DUPLICATE_SAME_ACCESS))
1152         {
1153           TRACE_LOG1 ("DuplicateHandle failed: ec=%d",
1154                       (int) GetLastError ());
1155           release_fd (rfd);
1156           release_fd (wfd);
1157           close_handle (rh);
1158           close_handle (wh);
1159           release_hddesc (rhdesc);
1160           release_hddesc (whdesc);
1161           gpg_err_set_errno (EIO);
1162           return TRACE_SYSRES (-1);
1163         }
1164       close_handle (rh);
1165       rh = hd;
1166     }
1167   else if (inherit_idx == 1)
1168     {
1169       HANDLE hd;
1170       if (!DuplicateHandle( GetCurrentProcess(), wh,
1171                             GetCurrentProcess(), &hd, 0,
1172                             TRUE, DUPLICATE_SAME_ACCESS))
1173         {
1174           TRACE_LOG1 ("DuplicateHandle failed: ec=%d",
1175                       (int) GetLastError ());
1176           release_fd (rfd);
1177           release_fd (wfd);
1178           close_handle (rh);
1179           close_handle (wh);
1180           release_hddesc (rhdesc);
1181           release_hddesc (whdesc);
1182           gpg_err_set_errno (EIO);
1183           return TRACE_SYSRES (-1);
1184         }
1185       close_handle (wh);
1186       wh = hd;
1187     }
1188
1189   /* Put the HANDLEs of the new pipe into the file descriptor table.
1190    * Note that we don't need to lock the table because we have just
1191    * acquired these two fresh fds and they are not known by any other
1192    * thread.  */
1193   fd_table[rfd].want_reader = 1;
1194   ref_hddesc (rhdesc)->hd = rh;
1195   fd_table[rfd].hdd = rhdesc;
1196
1197   fd_table[wfd].want_writer = 1;
1198   ref_hddesc (whdesc)->hd = wh;
1199   fd_table[wfd].hdd = whdesc;
1200
1201   filedes[0] = rfd;
1202   filedes[1] = wfd;
1203   return TRACE_SUC6 ("read=0x%x (hdd=%p,hd=%p), write=0x%x (hdd=%p,hd=%p)",
1204                      rfd, fd_table[rfd].hdd, fd_table[rfd].hdd->hd,
1205                      wfd, fd_table[wfd].hdd, fd_table[wfd].hdd->hd);
1206 }
1207
1208
1209 /* Close out File descriptor FD.  */
1210 int
1211 _gpgme_io_close (int fd)
1212 {
1213   _gpgme_close_notify_handler_t handler = NULL;
1214   void *value = NULL;
1215
1216   TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd);
1217
1218   if (fd < 0)
1219     {
1220       gpg_err_set_errno (EBADF);
1221       return TRACE_SYSRES (-1);
1222     }
1223
1224   LOCK (fd_table_lock);
1225   /* Check the size in the locked state because we may eventually add
1226    * code to change that size.  */
1227   if (fd >= fd_table_size || !fd_table[fd].used)
1228     {
1229       UNLOCK (fd_table_lock);
1230       gpg_err_set_errno (EBADF);
1231       return TRACE_SYSRES (-1);
1232     }
1233
1234   TRACE_LOG2 ("hdd=%p dupfrom=%d", fd_table[fd].hdd, fd_table[fd].dup_from);
1235
1236   if (fd_table[fd].reader)
1237     {
1238       TRACE_LOG1 ("destroying reader %p", fd_table[fd].reader);
1239       destroy_reader (fd_table[fd].reader);
1240       fd_table[fd].reader = NULL;
1241     }
1242
1243   if (fd_table[fd].writer)
1244     {
1245       TRACE_LOG1 ("destroying writer %p", fd_table[fd].writer);
1246       destroy_writer (fd_table[fd].writer);
1247       fd_table[fd].writer = NULL;
1248     }
1249
1250   /* The handler may not use any fd fucntion because the table is
1251    * locked.  Can we avoid this?  */
1252   handler = fd_table[fd].notify.handler;
1253   value   = fd_table[fd].notify.value;
1254
1255   /* Release our reference to the handle descripor.  Note that if no
1256    * reader or writer threads were used this release will also take
1257    * care that the handle descriptor is closed
1258    * (i.e. CloseHandle(hdd->hd) is called).  */
1259   release_hddesc (fd_table[fd].hdd);
1260   fd_table[fd].hdd = NULL;
1261
1262   UNLOCK (fd_table_lock);
1263
1264   /* Run the notification callback.  */
1265   if (handler)
1266     handler (fd, value);
1267
1268   release_fd (fd);  /* FIXME: We should have a release_fd_locked () */
1269
1270   return TRACE_SYSRES (0);
1271 }
1272
1273
1274 /* Set a close notification callback which is called right after FD
1275  * has been closed but before its slot (ie. the FD number) is beeing
1276  * released.  Tha HANDLER may thus use the provided value of the FD
1277  * but it may not pass it to any I/O functions.  Note: Only the last
1278  * handler set for an FD is used.  */
1279 int
1280 _gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler,
1281                             void *value)
1282 {
1283   TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_set_close_notify", fd,
1284               "close_handler=%p/%p", handler, value);
1285
1286   LOCK (fd_table_lock);
1287   if (fd < 0 || fd >= fd_table_size || !fd_table[fd].used)
1288     {
1289       UNLOCK (fd_table_lock);
1290       gpg_err_set_errno (EBADF);
1291       return TRACE_SYSRES (-1);;
1292     }
1293
1294   fd_table[fd].notify.handler = handler;
1295   fd_table[fd].notify.value = value;
1296   UNLOCK (fd_table_lock);
1297   return TRACE_SYSRES (0);
1298 }
1299
1300
1301 int
1302 _gpgme_io_set_nonblocking (int fd)
1303 {
1304   TRACE (DEBUG_SYSIO, "_gpgme_io_set_nonblocking", fd);
1305   return 0;
1306 }
1307
1308
1309 static char *
1310 build_commandline (char **argv)
1311 {
1312   int i;
1313   int n = 0;
1314   char *buf;
1315   char *p;
1316
1317   /* We have to quote some things because under Windows the program
1318      parses the commandline and does some unquoting.  We enclose the
1319      whole argument in double-quotes, and escape literal double-quotes
1320      as well as backslashes with a backslash.  We end up with a
1321      trailing space at the end of the line, but that is harmless.  */
1322   for (i = 0; argv[i]; i++)
1323     {
1324       p = argv[i];
1325       /* The leading double-quote.  */
1326       n++;
1327       while (*p)
1328         {
1329           /* An extra one for each literal that must be escaped.  */
1330           if (*p == '\\' || *p == '"')
1331             n++;
1332           n++;
1333           p++;
1334         }
1335       /* The trailing double-quote and the delimiter.  */
1336       n += 2;
1337     }
1338   /* And a trailing zero.  */
1339   n++;
1340
1341   buf = p = malloc (n);
1342   if (!buf)
1343     return NULL;
1344   for (i = 0; argv[i]; i++)
1345     {
1346       char *argvp = argv[i];
1347
1348       *(p++) = '"';
1349       while (*argvp)
1350         {
1351           if (*argvp == '\\' || *argvp == '"')
1352             *(p++) = '\\';
1353           *(p++) = *(argvp++);
1354         }
1355       *(p++) = '"';
1356       *(p++) = ' ';
1357     }
1358   *(p++) = 0;
1359
1360   return buf;
1361 }
1362
1363
1364 int
1365 _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
1366                  struct spawn_fd_item_s *fd_list,
1367                  void (*atfork) (void *opaque, int reserved),
1368                  void *atforkvalue, pid_t *r_pid)
1369 {
1370   PROCESS_INFORMATION pi =
1371     {
1372       NULL,      /* returns process handle */
1373       0,         /* returns primary thread handle */
1374       0,         /* returns pid */
1375       0          /* returns tid */
1376     };
1377   int i;
1378
1379   SECURITY_ATTRIBUTES sec_attr;
1380   STARTUPINFOA si;
1381   int cr_flags = CREATE_DEFAULT_ERROR_MODE;
1382   char **args;
1383   char *arg_string;
1384   /* FIXME.  */
1385   int debug_me = 0;
1386   int tmp_fd;
1387   char *tmp_name;
1388   const char *spawnhelper;
1389
1390   TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_spawn", path,
1391               "path=%s", path);
1392
1393   (void)atfork;
1394   (void)atforkvalue;
1395
1396   i = 0;
1397   while (argv[i])
1398     {
1399       TRACE_LOG2 ("argv[%2i] = %s", i, argv[i]);
1400       i++;
1401     }
1402
1403   /* We do not inherit any handles by default, and just insert those
1404      handles we want the child to have afterwards.  But some handle
1405      values occur on the command line, and we need to move
1406      stdin/out/err to the right location.  So we use a wrapper program
1407      which gets the information from a temporary file.  */
1408   if (_gpgme_mkstemp (&tmp_fd, &tmp_name) < 0)
1409     {
1410       TRACE_LOG1 ("_gpgme_mkstemp failed: %s", strerror (errno));
1411       return TRACE_SYSRES (-1);
1412     }
1413   TRACE_LOG1 ("tmp_name = %s", tmp_name);
1414
1415   args = calloc (2 + i + 1, sizeof (*args));
1416   args[0] = (char *) _gpgme_get_w32spawn_path ();
1417   args[1] = tmp_name;
1418   args[2] = (char *)path;
1419   memcpy (&args[3], &argv[1], i * sizeof (*args));
1420
1421   memset (&sec_attr, 0, sizeof sec_attr);
1422   sec_attr.nLength = sizeof sec_attr;
1423   sec_attr.bInheritHandle = FALSE;
1424
1425   arg_string = build_commandline (args);
1426   free (args);
1427   if (!arg_string)
1428     {
1429       close (tmp_fd);
1430       DeleteFileA (tmp_name);
1431       free (tmp_name);
1432       return TRACE_SYSRES (-1);
1433     }
1434
1435   memset (&si, 0, sizeof si);
1436   si.cb = sizeof (si);
1437   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
1438   si.wShowWindow = debug_me ? SW_SHOW : SW_HIDE;
1439   si.hStdInput = INVALID_HANDLE_VALUE;
1440   si.hStdOutput = INVALID_HANDLE_VALUE;
1441   si.hStdError = INVALID_HANDLE_VALUE;
1442
1443   cr_flags |= CREATE_SUSPENDED;
1444   if ((flags & IOSPAWN_FLAG_DETACHED))
1445     cr_flags |= DETACHED_PROCESS;
1446   cr_flags |= GetPriorityClass (GetCurrentProcess ());
1447   spawnhelper = _gpgme_get_w32spawn_path ();
1448   if (!spawnhelper)
1449     {
1450       /* This is a common mistake for new users of gpgme not to include
1451          gpgme-w32spawn.exe with their binary. So we want to make
1452          this transparent to developers. If users have somehow messed
1453          up their installation this should also be properly communicated
1454          as otherwise calls to gnupg will result in unsupported protocol
1455          errors that do not explain a lot. */
1456       char *msg;
1457       gpgrt_asprintf (&msg, "gpgme-w32spawn.exe was not found in the "
1458                             "detected installation directory of GpgME"
1459                             "\n\t\"%s\"\n\n"
1460                             "Crypto operations will not work.\n\n"
1461                             "If you see this it indicates a problem "
1462                             "with your installation.\n"
1463                             "Please report the problem to your "
1464                             "distributor of GpgME.\n\n"
1465                             "Developer's Note: The install dir can be "
1466                             "manually set with: gpgme_set_global_flag",
1467                             _gpgme_get_inst_dir ());
1468       MessageBoxA (NULL, msg, "GpgME not installed correctly", MB_OK);
1469       gpgrt_free (msg);
1470       gpg_err_set_errno (EIO);
1471       close (tmp_fd);
1472       DeleteFileA (tmp_name);
1473       free (tmp_name);
1474       return TRACE_SYSRES (-1);
1475     }
1476   if (!CreateProcessA (spawnhelper,
1477                        arg_string,
1478                        &sec_attr,     /* process security attributes */
1479                        &sec_attr,     /* thread security attributes */
1480                        FALSE,         /* inherit handles */
1481                        cr_flags,      /* creation flags */
1482                        NULL,          /* environment */
1483                        NULL,          /* use current drive/directory */
1484                        &si,           /* startup information */
1485                        &pi))          /* returns process information */
1486     {
1487       int lasterr = (int)GetLastError ();
1488       TRACE_LOG1 ("CreateProcess failed: ec=%d", lasterr);
1489       free (arg_string);
1490       close (tmp_fd);
1491       DeleteFileA (tmp_name);
1492       free (tmp_name);
1493
1494       /* FIXME: Should translate the error code.  */
1495       gpg_err_set_errno (EIO);
1496       return TRACE_SYSRES (-1);
1497     }
1498
1499   if (flags & IOSPAWN_FLAG_ALLOW_SET_FG)
1500     _gpgme_allow_set_foreground_window ((pid_t)pi.dwProcessId);
1501
1502   /* Insert the inherited handles.  */
1503   LOCK (fd_table_lock);
1504   for (i = 0; fd_list[i].fd != -1; i++)
1505     {
1506       int fd = fd_list[i].fd;
1507       HANDLE ohd = INVALID_HANDLE_VALUE;
1508       HANDLE hd = INVALID_HANDLE_VALUE;
1509
1510       /* Make it inheritable for the wrapper process.  */
1511       if (fd >= 0 && fd < fd_table_size && fd_table[fd].used
1512           && fd_table[fd].hdd)
1513         ohd = fd_table[fd].hdd->hd;
1514
1515       if (!DuplicateHandle (GetCurrentProcess(), ohd,
1516                             pi.hProcess, &hd, 0, TRUE, DUPLICATE_SAME_ACCESS))
1517         {
1518           TRACE_LOG1 ("DuplicateHandle failed: ec=%d", (int) GetLastError ());
1519           TerminateProcess (pi.hProcess, 0);
1520           /* Just in case TerminateProcess didn't work, let the
1521              process fail on its own.  */
1522           ResumeThread (pi.hThread);
1523           close_handle (pi.hThread);
1524           close_handle (pi.hProcess);
1525
1526           close (tmp_fd);
1527           DeleteFileA (tmp_name);
1528           free (tmp_name);
1529
1530           /* FIXME: Should translate the error code.  */
1531           gpg_err_set_errno (EIO);
1532           UNLOCK (fd_table_lock);
1533           return TRACE_SYSRES (-1);
1534         }
1535       /* Return the child name of this handle.  */
1536       fd_list[i].peer_name = handle_to_fd (hd);
1537     }
1538
1539   /* Write the handle translation information to the temporary
1540      file.  */
1541   {
1542     /* Hold roughly MAX_TRANS quadruplets of 64 bit numbers in hex
1543        notation: "0xFEDCBA9876543210" with an extra white space after
1544        every quadruplet.  10*(19*4 + 1) - 1 = 769.  This plans ahead
1545        for a time when a HANDLE is 64 bit.  */
1546 #define BUFFER_MAX 810
1547     char line[BUFFER_MAX + 1];
1548     int res;
1549     int written;
1550     size_t len;
1551
1552     if (flags)
1553       snprintf (line, BUFFER_MAX, "~%i \n", flags);
1554     else
1555       strcpy (line, "\n");
1556     for (i = 0; fd_list[i].fd != -1; i++)
1557       {
1558         /* Strip the newline.  */
1559         len = strlen (line) - 1;
1560
1561         /* Format is: Local name, stdin/stdout/stderr, peer name, argv idx.  */
1562         snprintf (&line[len], BUFFER_MAX - len, "0x%x %d 0x%x %d  \n",
1563                   fd_list[i].fd, fd_list[i].dup_to,
1564                   fd_list[i].peer_name, fd_list[i].arg_loc);
1565         /* Rather safe than sorry.  */
1566         line[BUFFER_MAX - 1] = '\n';
1567         line[BUFFER_MAX] = '\0';
1568       }
1569     len = strlen (line);
1570     written = 0;
1571     do
1572       {
1573         res = write (tmp_fd, &line[written], len - written);
1574         if (res > 0)
1575           written += res;
1576       }
1577     while (res > 0 || (res < 0 && errno == EAGAIN));
1578   }
1579   close (tmp_fd);
1580   /* The temporary file is deleted by the gpgme-w32spawn process
1581      (hopefully).  */
1582
1583   free (tmp_name);
1584   free (arg_string);
1585
1586   UNLOCK (fd_table_lock);
1587
1588   TRACE_LOG4 ("CreateProcess ready: hProcess=%p, hThread=%p, "
1589               "dwProcessID=%d, dwThreadId=%d",
1590               pi.hProcess, pi.hThread,
1591               (int) pi.dwProcessId, (int) pi.dwThreadId);
1592
1593   if (r_pid)
1594     *r_pid = (pid_t)pi.dwProcessId;
1595
1596
1597   if (ResumeThread (pi.hThread) == (DWORD)(-1))
1598     TRACE_LOG1 ("ResumeThread failed: ec=%d", (int) GetLastError ());
1599
1600   close_handle (pi.hThread);
1601
1602   TRACE_LOG1 ("process=%p", pi.hProcess);
1603
1604   /* We don't need to wait for the process.  */
1605   close_handle (pi.hProcess);
1606
1607   if (! (flags & IOSPAWN_FLAG_NOCLOSE))
1608     {
1609       for (i = 0; fd_list[i].fd != -1; i++)
1610         _gpgme_io_close (fd_list[i].fd);
1611     }
1612
1613   for (i = 0; fd_list[i].fd != -1; i++)
1614     if (fd_list[i].dup_to == -1)
1615       TRACE_LOG3 ("fd[%i] = 0x%x -> 0x%x", i, fd_list[i].fd,
1616                   fd_list[i].peer_name);
1617     else
1618       TRACE_LOG4 ("fd[%i] = 0x%x -> 0x%x (std%s)", i, fd_list[i].fd,
1619                   fd_list[i].peer_name, (fd_list[i].dup_to == 0) ? "in" :
1620                   ((fd_list[i].dup_to == 1) ? "out" : "err"));
1621
1622   return TRACE_SYSRES (0);
1623 }
1624
1625
1626 /* Select on the list of fds.  Returns: -1 = error, 0 = timeout or
1627    nothing to select, > 0 = number of signaled fds.  */
1628 int
1629 _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
1630 {
1631   HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS];
1632   int waitidx[MAXIMUM_WAIT_OBJECTS];
1633   int code;
1634   int nwait;
1635   int i;
1636   int any;
1637   int count;
1638   void *dbg_help;
1639   TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_select", fds,
1640               "nfds=%u, nonblock=%u", nfds, nonblock);
1641
1642 #if 0
1643  restart:
1644 #endif
1645   TRACE_SEQ (dbg_help, "select on [ ");
1646   any = 0;
1647   nwait = 0;
1648   count = 0;
1649   for (i=0; i < nfds; i++)
1650     {
1651       if (fds[i].fd == -1)
1652         continue;
1653       fds[i].signaled = 0;
1654       if (fds[i].for_read || fds[i].for_write)
1655         {
1656           if (fds[i].for_read)
1657             {
1658               /* FIXME: A find_reader_locked() along with separate
1659                * lock calls might be a better appaoched here.  */
1660               struct reader_context_s *ctx = find_reader (fds[i].fd);
1661
1662               if (!ctx)
1663                 TRACE_LOG1 ("error: no reader for FD 0x%x (ignored)",
1664                             fds[i].fd);
1665               else
1666                 {
1667                   if (nwait >= DIM (waitbuf))
1668                     {
1669                       TRACE_END (dbg_help, "oops ]");
1670                       TRACE_LOG ("Too many objects for WFMO!");
1671                       /* FIXME: Should translate the error code.  */
1672                       gpg_err_set_errno (EIO);
1673                       return TRACE_SYSRES (-1);
1674                     }
1675                   waitidx[nwait] = i;
1676                   waitbuf[nwait++] = ctx->have_data_ev;
1677                 }
1678               TRACE_ADD1 (dbg_help, "r0x%x ", fds[i].fd);
1679               any = 1;
1680             }
1681           else if (fds[i].for_write)
1682             {
1683               struct writer_context_s *ctx = find_writer (fds[i].fd);
1684
1685               if (!ctx)
1686                 TRACE_LOG1 ("error: no writer for FD 0x%x (ignored)",
1687                             fds[i].fd);
1688               else
1689                 {
1690                   if (nwait >= DIM (waitbuf))
1691                     {
1692                       TRACE_END (dbg_help, "oops ]");
1693                       TRACE_LOG ("Too many objects for WFMO!");
1694                       /* FIXME: Should translate the error code.  */
1695                       gpg_err_set_errno (EIO);
1696                       return TRACE_SYSRES (-1);
1697                     }
1698                   waitidx[nwait] = i;
1699                   waitbuf[nwait++] = ctx->is_empty;
1700                 }
1701               TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd);
1702               any = 1;
1703             }
1704         }
1705     }
1706   TRACE_END (dbg_help, "]");
1707   if (!any)
1708     return TRACE_SYSRES (0);
1709
1710   code = WaitForMultipleObjects (nwait, waitbuf, 0, nonblock ? 0 : 1000);
1711   if (code < WAIT_OBJECT_0 + nwait)
1712     {
1713       /* The WFMO is a really silly function: It does return either
1714          the index of the signaled object or if 2 objects have been
1715          signalled at the same time, the index of the object with the
1716          lowest object is returned - so and how do we find out how
1717          many objects have been signaled?.  The only solution I can
1718          imagine is to test each object starting with the returned
1719          index individually - how dull.  */
1720       any = 0;
1721       for (i = code - WAIT_OBJECT_0; i < nwait; i++)
1722         {
1723           if (wait_for_single_object (waitbuf[i], 0) == WAIT_OBJECT_0)
1724             {
1725               assert (waitidx[i] >=0 && waitidx[i] < nfds);
1726               fds[waitidx[i]].signaled = 1;
1727               any = 1;
1728               count++;
1729             }
1730         }
1731       if (!any)
1732         {
1733           TRACE_LOG ("no signaled objects found after WFMO");
1734           count = -1;
1735         }
1736     }
1737   else if (code == WAIT_TIMEOUT)
1738     TRACE_LOG ("WFMO timed out");
1739   else if (code == WAIT_FAILED)
1740     {
1741       int le = (int) GetLastError ();
1742 #if 0
1743       if (le == ERROR_INVALID_HANDLE)
1744         {
1745           int k;
1746           int j = handle_to_fd (waitbuf[i]);
1747
1748           TRACE_LOG1 ("WFMO invalid handle %d removed", j);
1749           for (k = 0 ; k < nfds; k++)
1750             {
1751               if (fds[k].fd == j)
1752                 {
1753                   fds[k].for_read = fds[k].for_write = 0;
1754                   goto restart;
1755                 }
1756             }
1757           TRACE_LOG (" oops, or not???");
1758         }
1759 #endif
1760       TRACE_LOG1 ("WFMO failed: %d", le);
1761       count = -1;
1762     }
1763   else
1764     {
1765       TRACE_LOG1 ("WFMO returned %d", code);
1766       count = -1;
1767     }
1768
1769   if (count > 0)
1770     {
1771       TRACE_SEQ (dbg_help, "select OK [ ");
1772       for (i = 0; i < nfds; i++)
1773         {
1774           if (fds[i].fd == -1)
1775             continue;
1776           if ((fds[i].for_read || fds[i].for_write) && fds[i].signaled)
1777             TRACE_ADD2 (dbg_help, "%c0x%x ",
1778                         fds[i].for_read ? 'r' : 'w', fds[i].fd);
1779         }
1780       TRACE_END (dbg_help, "]");
1781     }
1782
1783   if (count < 0)
1784     {
1785       /* FIXME: Should determine a proper error code.  */
1786       gpg_err_set_errno (EIO);
1787     }
1788
1789   return TRACE_SYSRES (count);
1790 }
1791
1792
1793 void
1794 _gpgme_io_subsystem_init (void)
1795 {
1796   /* Nothing to do.  */
1797 }
1798
1799
1800 /* Write the printable version of FD to BUFFER which has an allocated
1801  * length of BUFLEN.  The printable version is the representation on
1802  * the command line that the child process expects.  Note that this
1803  * works closely together with the gpgme-32spawn wrapper process which
1804  * translates these command line args to the real handles. */
1805 int
1806 _gpgme_io_fd2str (char *buffer, int buflen, int fd)
1807 {
1808   return snprintf (buffer, buflen, "%d", fd);
1809 }
1810
1811
1812 int
1813 _gpgme_io_dup (int fd)
1814 {
1815   int newfd;
1816   struct reader_context_s *rd_ctx;
1817   struct writer_context_s *wt_ctx;
1818   int want_reader, want_writer;
1819
1820   TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_dup", fd);
1821
1822   LOCK (fd_table_lock);
1823   if (fd < 0 || fd >= fd_table_size || !fd_table[fd].used)
1824     {
1825       UNLOCK (fd_table_lock);
1826       gpg_err_set_errno (EBADF);
1827       return TRACE_SYSRES (-1);
1828     }
1829
1830   newfd = new_fd();
1831   if (newfd == -1)
1832     {
1833       UNLOCK (fd_table_lock);
1834       gpg_err_set_errno (EMFILE);
1835       return TRACE_SYSRES (-1);
1836     }
1837
1838   fd_table[newfd].hdd = ref_hddesc (fd_table[fd].hdd);
1839   fd_table[newfd].dup_from = fd;
1840   want_reader = fd_table[fd].want_reader;
1841   want_writer = fd_table[fd].want_writer;
1842
1843   UNLOCK (fd_table_lock);
1844
1845   rd_ctx = want_reader? find_reader (fd) : NULL;
1846   if (rd_ctx)
1847     {
1848       /* NEWFD initializes a freshly allocated slot and does not need
1849        * to be locked.  */
1850       LOCK (rd_ctx->mutex);
1851       rd_ctx->refcount++;
1852       UNLOCK (rd_ctx->mutex);
1853       fd_table[newfd].reader = rd_ctx;
1854     }
1855
1856   wt_ctx = want_writer? find_writer (fd) : NULL;
1857   if (wt_ctx)
1858     {
1859       LOCK (wt_ctx->mutex);
1860       wt_ctx->refcount++;
1861       UNLOCK (wt_ctx->mutex);
1862       fd_table[newfd].writer = wt_ctx;
1863     }
1864
1865   return TRACE_SYSRES (newfd);
1866 }
1867
1868 \f
1869 /* The following interface is only useful for GPGME Glib and Qt.  */
1870
1871 /* Compatibility interface, obsolete.  */
1872 void *
1873 gpgme_get_giochannel (int fd)
1874 {
1875   (void)fd;
1876   return NULL;
1877 }
1878
1879
1880 /* Look up the giochannel or qiodevice for file descriptor FD.  */
1881 void *
1882 gpgme_get_fdptr (int fd)
1883 {
1884   (void)fd;
1885   return NULL;
1886 }
1887
1888 \f
1889 static int
1890 wsa2errno (int err)
1891 {
1892   switch (err)
1893     {
1894     case WSAENOTSOCK:
1895       return EINVAL;
1896     case WSAEWOULDBLOCK:
1897       return EAGAIN;
1898     case ERROR_BROKEN_PIPE:
1899       return EPIPE;
1900     case WSANOTINITIALISED:
1901       return ENOSYS;
1902     default:
1903       return EIO;
1904     }
1905 }
1906
1907
1908 int
1909 _gpgme_io_socket (int domain, int type, int proto)
1910 {
1911   int res;
1912   int fd;
1913   hddesc_t hdd;
1914
1915   TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_socket", domain,
1916               "type=%i, protp=%i", type, proto);
1917
1918   fd = new_fd();
1919   if (fd == -1)
1920     return TRACE_SYSRES (-1);
1921   hdd = new_hddesc ();
1922   if (!hdd)
1923     {
1924       UNLOCK (fd_table_lock);
1925       release_fd (fd);
1926       gpg_err_set_errno (ENOMEM);
1927       return TRACE_SYSRES (-1);
1928     }
1929
1930   res = socket (domain, type, proto);
1931   if (res == INVALID_SOCKET)
1932     {
1933       release_fd (fd);
1934       gpg_err_set_errno (wsa2errno (WSAGetLastError ()));
1935       return TRACE_SYSRES (-1);
1936     }
1937   ref_hddesc (hdd)->sock = res;
1938   fd_table[fd].hdd = hdd;
1939   fd_table[fd].want_reader = 1;
1940   fd_table[fd].want_writer = 1;
1941
1942   TRACE_SUC3 ("hdd=%p, socket=0x%x (0x%x)", hdd, fd, hdd->sock);
1943
1944   return fd;
1945 }
1946
1947
1948 int
1949 _gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen)
1950 {
1951   int res;
1952   int sock;
1953
1954   TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_connect", fd,
1955               "addr=%p, addrlen=%i", addr, addrlen);
1956
1957   LOCK (fd_table_lock);
1958   if (fd < 0 || fd >= fd_table_size || !fd_table[fd].used || !fd_table[fd].hdd)
1959     {
1960       gpg_err_set_errno (EBADF);
1961       UNLOCK (fd_table_lock);
1962       return TRACE_SYSRES (-1);
1963     }
1964   sock = fd_table[fd].hdd->sock;
1965   UNLOCK (fd_table_lock);
1966
1967   res = connect (sock, addr, addrlen);
1968   if (res)
1969     {
1970       gpg_err_set_errno (wsa2errno (WSAGetLastError ()));
1971       return TRACE_SYSRES (-1);
1972     }
1973
1974   return TRACE_SUC ();
1975 }