diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 34 | ||||
-rw-r--r-- | src/Makefile.am | 15 | ||||
-rw-r--r-- | src/assuan-defs.h | 1 | ||||
-rw-r--r-- | src/assuan-pipe-connect.c | 8 | ||||
-rw-r--r-- | src/assuan.h.in (renamed from src/assuan.h) | 12 | ||||
-rw-r--r-- | src/gpgcedev.c | 183 | ||||
-rw-r--r-- | src/libassuan.def | 2 | ||||
-rw-r--r-- | src/mkheader.c | 192 | ||||
-rw-r--r-- | src/system-w32.c | 27 | ||||
-rw-r--r-- | src/system-w32ce.c | 425 | ||||
-rw-r--r-- | src/system.c | 16 | ||||
-rw-r--r-- | src/sysutils.c | 81 |
12 files changed, 687 insertions, 309 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 1d5ff2e..6034272 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,39 @@ +2010-03-22 Werner Koch <[email protected]> + + * Makefile.am (mkheader, assuan.h): Build header file. + * mkheader.c: New. + * assuan.h: Rename to assuan.h.in. + +2010-03-18 Werner Koch <[email protected]> + + * libassuan.def (_assuan_w32ce_prepare_pipe) + (_assuan_w32ce_finish_pipe): New + * gpgcedev.c (struct opnctx_s): Replace HD by RVID. + (GPGCEDEV_IOCTL_SET_HANDLE): Remove. + (GPGCEDEV_IOCTL_GET_RVID): New. + (create_rendezvous_id): New. + (get_new_opnctx): Init the RVID. + (set_handle): Remove. + (find_and_lock_opnctx, make_pipe, GPG_IOControl): Change to new + method. + * system-w32ce.c (_assuan_w32ce_prepare_pipe) + (_assuan_w32ce_finish_pipe): New. + (_assuan_w32ce_create_pipe): Re-implement using the new functions. + (__assuan_pipe): Create an inheritable pipe. + (build_w32_commandline): New arg FD2_ISNULL. + * system.c (_assuan_close_inheritable): New. + * assuan-pipe-connect.c (pipe_connect): Use the new function. + + * sysutils.c (_assuan_w32ce_create_pipe): Move to system-w32ce.c. + 2010-03-16 Werner Koch <[email protected]> + * system-w32ce.c (build_w32_commandline): Add args to pass the + special options for the standard descriptors. + (utf8_to_wchar, free_wchar): New. + (__assuan_spawn): Adjust for changes. Convert strings for + CreateProcess to wchar_t. + * system.c: For better readability move platform dependend code to .. * system-posix.c, system-w32.c, system-w32ce.c: .. New. * Makefile.am (common_sources): Account for this change. diff --git a/src/Makefile.am b/src/Makefile.am index c946f11..6723648 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ # Assuan Makefile -# Copyright (C) 2001, 2002, 2003, 2009 Free Software Foundation, Inc. +# Copyright (C) 2001, 2002, 2003, 2009, 2010 Free Software Foundation, Inc. # # This file is part of Assuan. # @@ -18,7 +18,7 @@ ## Process this file with automake to produce Makefile.in EXTRA_DIST = libassuan-config.in libassuan.m4 libassuan.vers \ - versioninfo.rc.in libassuan.def + versioninfo.rc.in libassuan.def mkheader.c INCLUDES = -I.. -I$(top_srcdir)/include bin_SCRIPTS = libassuan-config @@ -37,8 +37,12 @@ else libassuan_version_script_cmd = endif +CLEANFILES = mkheader assuan.h + +BUILT_SOURCES = assuan.h common_sources = \ + assuan.h.in assuan.h w32ce-add.h \ assuan-defs.h \ assuan.c context.c system.c \ debug.c debug.h conversion.c sysutils.c \ @@ -121,3 +125,10 @@ libgpgcedev_la_DEPENDENCIES = gpgcedev.def gpgcemgr_SOURCES = gpgcemgr.c gpgcemgr_CPPFLAGS = $(AM_CPPFLAGS) endif + +mkheader: mkheader.c Makefile + $(CC_FOR_BUILD) -I. -I$(srcdir) -o $@ $(srcdir)/mkheader.c + +assuan.h: assuan.h.in mkheader w32ce-add.h + ./mkheader $(host_os) $(srcdir)/assuan.h.in >$@ + diff --git a/src/assuan-defs.h b/src/assuan-defs.h index dd91f09..63f0d10 100644 --- a/src/assuan-defs.h +++ b/src/assuan-defs.h @@ -230,6 +230,7 @@ void _assuan_free (assuan_context_t ctx, void *ptr); void _assuan_usleep (assuan_context_t ctx, unsigned int usec); int _assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx); int _assuan_close (assuan_context_t ctx, assuan_fd_t fd); +int _assuan_close_inheritable (assuan_context_t ctx, assuan_fd_t fd); ssize_t _assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size); ssize_t _assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer, diff --git a/src/assuan-pipe-connect.c b/src/assuan-pipe-connect.c index dec8ccc..4eccdde 100644 --- a/src/assuan-pipe-connect.c +++ b/src/assuan-pipe-connect.c @@ -175,7 +175,7 @@ pipe_connect (assuan_context_t ctx, if (_assuan_pipe (ctx, wp, 0) < 0) { _assuan_close (ctx, rp[0]); - _assuan_close (ctx, rp[1]); + _assuan_close_inheritable (ctx, rp[1]); return _assuan_error (ctx, gpg_err_code_from_syserror ()); } @@ -197,8 +197,8 @@ pipe_connect (assuan_context_t ctx, } /* Close the stdin/stdout child fds in the parent. */ - _assuan_close (ctx, rp[1]); - _assuan_close (ctx, wp[0]); + _assuan_close_inheritable (ctx, rp[1]); + _assuan_close_inheritable (ctx, wp[0]); ctx->engine.release = _assuan_client_release; ctx->engine.readfnc = _assuan_simple_read; @@ -393,7 +393,7 @@ socketpair_connect (assuan_context_t ctx, environment variables are set. To let the caller detect whether the child or the parent continues, the child returns "client" or "server" in *ARGV (but it is sufficient to check only the first - character). */ + character). This feature is only available on POSIX platforms. */ gpg_error_t assuan_pipe_connect (assuan_context_t ctx, const char *name, const char *argv[], diff --git a/src/assuan.h b/src/assuan.h.in index c275287..91b75ab 100644 --- a/src/assuan.h +++ b/src/assuan.h.in @@ -1,4 +1,4 @@ -/* assuan.h - Definitions for the Assuan IPC library +/* assuan.h - Definitions for the Assuan IPC library -*- c -*- Copyright (C) 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. @@ -16,6 +16,8 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. + + @configure_input@ */ #ifndef ASSUAN_H @@ -639,13 +641,7 @@ int __assuan_socketpair (assuan_context_t ctx, int _namespace, int style, extern struct assuan_system_hooks _assuan_system_pth; #define ASSUAN_SYSTEM_PTH &_assuan_system_pth -#ifdef __MINGW32CE__ -/* FIXME: Include this code only if build for this platform. */ -DWORD _assuan_w32ce_create_pipe (HANDLE *read_hd, HANDLE *write_hd, - LPSECURITY_ATTRIBUTES sec_attr, DWORD size); -#define CreatePipe(a,b,c,d) _assuan_w32ce_create_pipe ((a),(b),(c),(d)) - -#endif /*__MINGW32CE__*/ +@include:w32ce-add@ #ifdef __cplusplus } diff --git a/src/gpgcedev.c b/src/gpgcedev.c index 763ab29..fe9c80a 100644 --- a/src/gpgcedev.c +++ b/src/gpgcedev.c @@ -17,6 +17,7 @@ License along with this program; if not, see <http://www.gnu.org/licenses/>. */ + #include <stdio.h> #include <stdarg.h> #include <windows.h> @@ -35,19 +36,21 @@ #endif /*IOCTL_PSL_NOTIFY*/ -/* The IOCTL used to tell the device about the handle. +/* The IOCTL to return the rendezvous id of the handle. - The required inbuf parameter is the address of a variable holding - the handle. */ -#define GPGCEDEV_IOCTL_SET_HANDLE \ + The required outbuf parameter is the address of a variable to store + the rendezvous ID, which is a LONG value. */ +#define GPGCEDEV_IOCTL_GET_RVID \ CTL_CODE (FILE_DEVICE_STREAMS, 2048, METHOD_BUFFERED, FILE_ANY_ACCESS) /* The IOCTL used to create the pipe. - The caller sends this IOCTL to the read handle. The required inbuf - parameter is the address of variable holding the write handle. - Note that the SET_HANDLE IOCTLs must have been used prior to this - one. */ + The caller sends this IOCTL to the read or the write handle. The + required inbuf parameter is address of a variable holding the + rendezvous id of the pipe's other end. There is one possible + problem with eocdde: If a pipe is kept in non-rendezvous state + until after the rendezvous ids overflow, it is possible that the + wrong end will be used. However this is not a realistic scenario. */ #define GPGCEDEV_IOCTL_MAKE_PIPE \ CTL_CODE (FILE_DEVICE_STREAMS, 2049, METHOD_BUFFERED, FILE_ANY_ACCESS) @@ -62,7 +65,7 @@ struct opnctx_s other context; i.e. a pipe has been established. */ int is_write; /* True if this is the write end of the pipe. */ - HANDLE hd; /* The system's handle object or INVALID_HANDLE_VALUE. */ + LONG rvid; /* The unique rendezvous identifier. */ DWORD access_code;/* Value from OpenFile. */ DWORD share_mode; /* Value from OpenFile. */ CRITICAL_SECTION critsect; /* Lock for all operations. */ @@ -118,6 +121,19 @@ log_debug (const char *fmt, ...) } +/* Return a new rendezvous next command id. Command Ids are used to group + resources of one command. We will never return an RVID of 0. */ +static LONG +create_rendezvous_id (void) +{ + static LONG rendezvous_id; + LONG rvid; + + while (!(rvid = InterlockedIncrement (&rendezvous_id))) + ; + return rvid; +} + /* Return a new opnctx handle and mark it as used. Returns NULL and @@ -152,8 +168,7 @@ get_new_opnctx (void) } opnctx = opnctx_table + idx; opnctx->assoc = NULL; - opnctx->hd = INVALID_HANDLE_VALUE; - opnctx->assoc = 0; + opnctx->rvid = create_rendezvous_id (); opnctx->buffer_size = 512; opnctx->buffer = malloc (opnctx->buffer_size); if (!opnctx->buffer) @@ -173,36 +188,45 @@ get_new_opnctx (void) leave: LeaveCriticalSection (&opnctx_table_cs); - log_debug ("get_new_opnctx -> %p\n", opnctx); + if (opnctx) + log_debug ("get_new_opnctx -> %p (rvid=%ld)\n", opnctx, opnctx->rvid); + else + log_debug ("get_new_opnctx -> failed\n"); return opnctx; } -/* Find the OPNCTX for handle HD. */ +/* Find the OPNCTX object with the rendezvous id RVID. */ static opnctx_t -find_and_lock_opnctx (HANDLE hd) +find_and_lock_opnctx (LONG rvid) { opnctx_t result = NULL; int idx; EnterCriticalSection (&opnctx_table_cs); for (idx=0; idx < opnctx_table_size; idx++) - if (opnctx_table[idx].inuse && opnctx_table[idx].hd == hd) + if (opnctx_table[idx].inuse && opnctx_table[idx].rvid == rvid) { result = opnctx_table + idx; break; } LeaveCriticalSection (&opnctx_table_cs); if (!result) - SetLastError (ERROR_INVALID_HANDLE); + { + SetLastError (ERROR_INVALID_HANDLE); + log_debug ("find_opnctx -> invalid rendezvous id\n"); + } else if (TryEnterCriticalSection (&result->critsect)) - result->locked++; + { + result->locked++; + log_debug ("find_opnctx -> %p (rvid=%ld)\n", result, result->rvid); + } else { SetLastError (ERROR_BUSY); result = NULL; + log_debug ("find_opnctx -> busy\n"); } - log_debug ("find_opnctx -> %p\n", result); return result; } @@ -353,14 +377,10 @@ GPG_Close (DWORD opnctx_arg) for (idx=0; idx < opnctx_table_size; idx++) if (opnctx_table[idx].inuse && (opnctx_table + idx) == opnctx) { - if (opnctx->hd != INVALID_HANDLE_VALUE) + if (opnctx->assoc) { - if (opnctx->assoc) - { - opnctx->assoc->assoc = NULL; - opnctx->assoc = NULL; - } - opnctx->hd = INVALID_HANDLE_VALUE; + opnctx->assoc->assoc = NULL; + opnctx->assoc = NULL; } if (opnctx->locked) { @@ -419,7 +439,7 @@ GPG_Read (DWORD opnctx_arg, void *buffer, DWORD count) SetLastError (ERROR_INVALID_ACCESS); goto leave; } - if (rctx->hd == INVALID_HANDLE_VALUE || !rctx->assoc) + if (!rctx->assoc) { SetLastError (ERROR_BROKEN_PIPE); goto leave; @@ -490,7 +510,7 @@ GPG_Write (DWORD opnctx_arg, const void *buffer, DWORD count) SetLastError (ERROR_INVALID_ACCESS); goto leave; } - if (wctx->hd == INVALID_HANDLE_VALUE || !wctx->assoc) + if (!wctx->assoc) { SetLastError (ERROR_BROKEN_PIPE); goto leave; @@ -546,79 +566,78 @@ GPG_Seek (DWORD opnctx, long amount, WORD type) static BOOL -set_handle (opnctx_t opnctx, HANDLE hd) -{ - log_debug (" set_handle(%p, hd=%p)\n", opnctx, hd); - if (opnctx->hd != INVALID_HANDLE_VALUE) - { - SetLastError (ERROR_ALREADY_ASSIGNED); - return FALSE; - } - opnctx->hd = hd; - return TRUE; -} - -static BOOL -make_pipe (opnctx_t rctx, HANDLE hd) +make_pipe (opnctx_t ctx, LONG rvid) { BOOL result = FALSE; - opnctx_t wctx = NULL; + opnctx_t peerctx = NULL; - log_debug (" make_pipe(%p, hd=%p)\n", rctx, hd); - if (rctx->hd == INVALID_HANDLE_VALUE) - { - SetLastError (ERROR_NOT_READY); - goto leave; - } - if (rctx->assoc) + log_debug (" make_pipe(%p, rvid=%ld)\n", ctx, rvid); + if (ctx->assoc) { SetLastError (ERROR_ALREADY_ASSIGNED); goto leave; } - if (!(rctx->access_code & GENERIC_READ)) - { - SetLastError (ERROR_INVALID_ACCESS); - goto leave; - } - wctx = find_and_lock_opnctx (hd); - if (!wctx) + peerctx = find_and_lock_opnctx (rvid); + if (!peerctx) { SetLastError (ERROR_NOT_FOUND); goto leave; } - if (wctx == rctx) + if (peerctx == ctx) { SetLastError (ERROR_INVALID_TARGET_HANDLE); goto leave; } - if (wctx->hd == INVALID_HANDLE_VALUE) + if (peerctx->assoc) { - SetLastError (ERROR_NOT_READY); + SetLastError (ERROR_ALREADY_ASSIGNED); goto leave; } - if (wctx->assoc) + + if ((ctx->access_code & GENERIC_READ)) { - SetLastError (ERROR_ALREADY_ASSIGNED); - goto leave; + /* Check that the peer is a write end. */ + if (!(peerctx->access_code & GENERIC_WRITE)) + { + SetLastError (ERROR_INVALID_ACCESS); + goto leave; + } + peerctx->space_available = CreateEvent (NULL, FALSE, FALSE, NULL); + peerctx->data_available = CreateEvent (NULL, FALSE, FALSE, NULL); + + ctx->assoc = peerctx; + peerctx->assoc = ctx; + ctx->is_write = 0; + peerctx->is_write = 1; + result = TRUE; + } + else if ((ctx->access_code & GENERIC_WRITE)) + { + /* Check that the peer is a read end. */ + if (!(peerctx->access_code & GENERIC_READ)) + { + SetLastError (ERROR_INVALID_ACCESS); + goto leave; + } + ctx->space_available = CreateEvent (NULL, FALSE, FALSE, NULL); + ctx->data_available = CreateEvent (NULL, FALSE, FALSE, NULL); + + ctx->assoc = peerctx; + peerctx->assoc = ctx; + ctx->is_write = 1; + peerctx->is_write = 0; + result = TRUE; } - if (!(wctx->access_code & GENERIC_WRITE)) + else { SetLastError (ERROR_INVALID_ACCESS); goto leave; } - wctx->space_available = CreateEvent (NULL, FALSE, FALSE, NULL); - wctx->data_available = CreateEvent (NULL, FALSE, FALSE, NULL); - - rctx->assoc = wctx; - wctx->assoc = rctx; - rctx->is_write = 0; - wctx->is_write = 1; - result = TRUE; leave: - if (wctx) - unlock_opnctx (wctx); + if (peerctx) + unlock_opnctx (peerctx); return result; } @@ -629,6 +648,7 @@ GPG_IOControl (DWORD opnctx_arg, DWORD code, void *inbuf, DWORD inbuflen, { opnctx_t opnctx = (opnctx_t)opnctx_arg; BOOL result = FALSE; + LONG rvid; log_debug ("GPG_IOControl(%p, %d)\n", (void*)opnctx, code); if (!validate_and_lock_opnctx (opnctx, LOCK_TRY)) @@ -636,25 +656,28 @@ GPG_IOControl (DWORD opnctx_arg, DWORD code, void *inbuf, DWORD inbuflen, switch (code) { - case GPGCEDEV_IOCTL_SET_HANDLE: - if (!opnctx || !inbuf || inbuflen < sizeof (HANDLE) - || outbuf || outbuflen || actualoutlen ) + case GPGCEDEV_IOCTL_GET_RVID: + if (!opnctx || inbuf || inbuflen + || !outbuf || outbuflen < sizeof (LONG)) { SetLastError (ERROR_INVALID_PARAMETER); goto leave; } - if (set_handle (opnctx, *(HANDLE*)inbuf)) - result = TRUE; + memcpy (outbuf, &opnctx->rvid, sizeof (LONG)); + if (actualoutlen) + *actualoutlen = sizeof (LONG); + result = TRUE; break; case GPGCEDEV_IOCTL_MAKE_PIPE: - if (!opnctx || !inbuf || inbuflen < sizeof (HANDLE) + if (!opnctx || !inbuf || inbuflen < sizeof (LONG) || outbuf || outbuflen || actualoutlen ) { SetLastError (ERROR_INVALID_PARAMETER); goto leave; } - if (make_pipe (opnctx, *(HANDLE*)inbuf)) + memcpy (&rvid, inbuf, sizeof (LONG)); + if (make_pipe (opnctx, rvid)) result = TRUE; break; diff --git a/src/libassuan.def b/src/libassuan.def index ba8ed8d..59aba41 100644 --- a/src/libassuan.def +++ b/src/libassuan.def @@ -99,6 +99,8 @@ EXPORTS assuan_set_sock_nonce @78 _assuan_w32ce_create_pipe @79 assuan_free @80 + _assuan_w32ce_prepare_pipe @81 + _assuan_w32ce_finish_pipe @82 ; END diff --git a/src/mkheader.c b/src/mkheader.c new file mode 100644 index 0000000..22cdc94 --- /dev/null +++ b/src/mkheader.c @@ -0,0 +1,192 @@ +/* mkheader.c - Create a header file for libassuan. + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * This file is free software; as a special exception the author gives + * unlimited permission to copy and/or distribute it, with or without + * modifications, as long as this notice is preserved. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#define PGM "mkheader" + +#define LINESIZE 1024 + +static const char *host_os; +static char *srcdir; + + +/* Include the file NAME form the source directory. The included file + is not further expanded. It may have comments indicated by a + double hash masrk at the begin of a line. */ +static void +include_file (const char *fname, int lnr, const char *name) +{ + FILE *fp; + char *incfname; + char line[LINESIZE]; + + incfname = malloc (strlen (srcdir) + strlen (name) + 1); + if (!incfname) + { + fputs (PGM ": out of core\n", stderr); + exit (1); + } + strcpy (incfname, srcdir); + strcat (incfname, name); + + fp = fopen (incfname, "r"); + if (!fp) + { + fprintf (stderr, "%s:%d: error including `%s': %s\n", + fname, lnr, incfname, strerror (errno)); + exit (1); + } + + while (fgets (line, LINESIZE, fp)) + { + if (line[0] != '#' && line[1] != '#') + fputs (line, stdout); + } + if (ferror (fp)) + { + fprintf (stderr, "%s:%d: error reading `%s': %s\n", + fname, lnr, incfname, strerror (errno)); + exit (1); + } + fclose (fp); + free (incfname); +} + + +static int +write_special (const char *fname, int lnr, const char *tag) +{ + if (!strcmp (tag, "include:w32ce-add")) + { + if (!strcmp (host_os, "mingw32ce")) + include_file (fname, lnr, "w32ce-add.h"); + } + else + return 0; /* Unknown tag. */ + + return 1; /* Tag processed. */ +} + + +int +main (int argc, char **argv) +{ + FILE *fp; + char line[LINESIZE]; + int lnr = 0; + const char *fname, *s; + char *p1, *p2; + + if (argc) + { + argc--; argv++; + } + + if (argc != 2) + { + fputs ("usage: " PGM " host_os template.h\n", stderr); + return 1; + } + host_os = argv[0]; + fname = argv[1]; + + srcdir = malloc (strlen (fname) + 2 + 1); + if (!srcdir) + { + fputs (PGM ": out of core\n", stderr); + return 1; + } + strcpy (srcdir, fname); + p1 = strrchr (srcdir, '/'); + if (p1) + p1[1] = 0; + else + strcpy (srcdir, "./"); + + fp = fopen (fname, "r"); + if (!fp) + { + fprintf (stderr, "%s:%d: can't open file: %s", + fname, lnr, strerror (errno)); + return 1; + } + + while (fgets (line, LINESIZE, fp)) + { + size_t n = strlen (line); + + lnr++; + if (!n || line[n-1] != '\n') + { + fprintf (stderr, + "%s:%d: trailing linefeed missing, line too long or " + "embedded Nul character", fname, lnr); + break; + } + line[--n] = 0; + + p1 = strchr (line, '@'); + p2 = p1? strchr (p1+1, '@') : NULL; + if (!p1 || !p2 || p2-p1 == 1) + { + puts (line); + continue; + } + *p1++ = 0; + *p2++ = 0; + fputs (line, stdout); + + if (!strcmp (p1, "configure_input")) + { + s = strrchr (fname, '/'); + printf ("Do not edit. Generated from %s by %s for %s.", + s? s+1 : fname, PGM, host_os); + } + else if (!write_special (fname, lnr, p1)) + { + putchar ('@'); + fputs (p1, stdout); + putchar ('@'); + } + + fputs (p2, stdout); + putchar ('\n'); + } + + if (ferror (fp)) + { + fprintf (stderr, "%s:%d: error reading file: %s\n", + fname, lnr, strerror (errno)); + return 1; + } + + fputs ("/*\n" + "Local Variables:\n" + "buffer-read-only: t\n" + "End:\n" + "*/\n", stdout); + + if (ferror (stdout)) + { + fprintf (stderr, PGM ": error writing stdout: %s\n", strerror (errno)); + return 1; + } + + fclose (fp); + + return 0; +} diff --git a/src/system-w32.c b/src/system-w32.c index 31da194..85f0e40 100644 --- a/src/system-w32.c +++ b/src/system-w32.c @@ -64,6 +64,33 @@ __assuan_usleep (assuan_context_t ctx, unsigned int usec) +/* Three simple wrappers, only used because thes function are named in + the def file. */ +HANDLE +_assuan_w32ce_prepare_pipe (int *r_rvid, int write_end) +{ + (void)r_rvid; + (void)write_end; + return INVALID_HANDLE_VALUE; +} + +HANDLE +_assuan_w32ce_finish_pipe (int rvid, int write_end) +{ + (void)rvid; + (void)write_end; + return INVALID_HANDLE_VALUE; +} + +DWORD +_assuan_w32ce_create_pipe (HANDLE *read_hd, HANDLE *write_hd, + LPSECURITY_ATTRIBUTES sec_attr, DWORD size) +{ + return CreatePipe (read_hd, write_hd, sec_attr, size); +} + + + /* Create a pipe with one inheritable end. Default implementation. */ int __assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx) diff --git a/src/system-w32ce.c b/src/system-w32ce.c index ce0796c..1ecb4d8 100644 --- a/src/system-w32ce.c +++ b/src/system-w32ce.c @@ -27,26 +27,72 @@ #include <time.h> #include <fcntl.h> #include <windows.h> +#include <winioctl.h> +#include <devload.h> #include "assuan-defs.h" #include "debug.h" +#define GPGCEDEV_IOCTL_GET_RVID \ + CTL_CODE (FILE_DEVICE_STREAMS, 2048, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define GPGCEDEV_IOCTL_MAKE_PIPE \ + CTL_CODE (FILE_DEVICE_STREAMS, 2049, METHOD_BUFFERED, FILE_ANY_ACCESS) + + + -assuan_fd_t -assuan_fdopen (int fd) +static wchar_t * +utf8_to_wchar (const char *string) { - assuan_fd_t ifd = (assuan_fd_t)fd; - assuan_fd_t ofd; + int n; + size_t nbytes; + wchar_t *result; + + if (!string) + return NULL; - if (! DuplicateHandle(GetCurrentProcess(), ifd, - GetCurrentProcess(), &ofd, 0, - TRUE, DUPLICATE_SAME_ACCESS)) + n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0); + if (n < 0) { - gpg_err_set_errno (EIO); - return ASSUAN_INVALID_FD; + gpg_err_set_errno (EINVAL); + return NULL; + } + + nbytes = (size_t)(n+1) * sizeof(*result); + if (nbytes / sizeof(*result) != (n+1)) + { + gpg_err_set_errno (ENOMEM); + return NULL; + } + result = malloc (nbytes); + if (!result) + return NULL; + + n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n); + if (n < 0) + { + free (result); + gpg_err_set_errno (EINVAL); + result = NULL; } - return ofd; + return result; +} + +/* Convenience function. */ +static void +free_wchar (wchar_t *string) +{ + if (string) + free (string); +} + + + +assuan_fd_t +assuan_fdopen (int fd) +{ + return (assuan_fd_t)fd; } @@ -56,60 +102,149 @@ assuan_fdopen (int fd) void __assuan_usleep (assuan_context_t ctx, unsigned int usec) { - if (!usec) - return; - - Sleep (usec / 1000); + if (usec) + Sleep (usec / 1000); } -/* Create a pipe with one inheritable end. Default implementation. */ -int -__assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx) +/* Prepare a pipe. Returns a handle which is, depending on WRITE_END, + will either act the read or as the write end of the pipe. The + other value returned is a rendezvous id used to complete the pipe + creation with _assuan_w32ce_finish_pipe. The rendezvous id may be + passed to another process and that process may finish the pipe + creation. This creates the interprocess pipe. The rendezvous id + is not a handle but a plain number; there is no release function + and care should be taken not to pass it to a function expecting a + handle. */ +HANDLE +_assuan_w32ce_prepare_pipe (int *r_rvid, int write_end) { - HANDLE rh; - HANDLE wh; - HANDLE th; - SECURITY_ATTRIBUTES sec_attr; + HANDLE hd; + LONG rvid; + + ActivateDevice (L"Drivers\\GnuPG_Device", 0); + + /* Note: Using "\\$device\\GPG1" should be identical to "GPG1:". + However this returns an invalid parameter error without having + called GPG_Init in the driver. The docs mention something about + RegisterAFXEx but that API is not documented. */ + hd = CreateFile (L"GPG1:", write_end? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hd != INVALID_HANDLE_VALUE) + { + if (!DeviceIoControl (hd, GPGCEDEV_IOCTL_GET_RVID, + NULL, 0, &rvid, sizeof rvid, NULL, NULL)) + { + DWORD lastrc = GetLastError (); + CloseHandle (hd); + hd = INVALID_HANDLE_VALUE; + SetLastError (lastrc); + } + else + *r_rvid = rvid; + } + + return hd; +} + - memset (&sec_attr, 0, sizeof (sec_attr)); - sec_attr.nLength = sizeof (sec_attr); - sec_attr.bInheritHandle = FALSE; +/* Create a pipe. WRITE_END shall have the opposite value of the one + pssed to _assuan_w32ce_prepare_pipe; see there for more + details. */ +HANDLE +_assuan_w32ce_finish_pipe (int rvid, int write_end) +{ + HANDLE hd; - if (!CreatePipe (&rh, &wh, &sec_attr, 0)) + hd = CreateFile (L"GPG1:", write_end? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL); + if (hd != INVALID_HANDLE_VALUE) { - TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_pipe", ctx, - "CreatePipe failed: %s", _assuan_w32_strerror (ctx, -1)); - gpg_err_set_errno (EIO); - return -1; + if (!DeviceIoControl (hd, GPGCEDEV_IOCTL_MAKE_PIPE, + &rvid, sizeof rvid, NULL, 0, NULL, NULL)) + { + DWORD lastrc = GetLastError (); + CloseHandle (hd); + hd = INVALID_HANDLE_VALUE; + SetLastError (lastrc); + } + } + + return hd; +} + + +/* WindowsCE does not provide a pipe feature. However we need + something like a pipe to convey data between processes and in some + cases within a process. This replacement is not only used by + libassuan but exported and thus usable by gnupg and gpgme as well. */ +DWORD +_assuan_w32ce_create_pipe (HANDLE *read_hd, HANDLE *write_hd, + LPSECURITY_ATTRIBUTES sec_attr, DWORD size) +{ + HANDLE hd[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; + int rvid; + int rc = 0; + + hd[0] = _assuan_w32ce_prepare_pipe (&rvid, 0); + if (hd[0] != INVALID_HANDLE_VALUE) + { + hd[1] = _assuan_w32ce_finish_pipe (rvid, 1); + if (hd[1] != INVALID_HANDLE_VALUE) + rc = 1; + else + { + DWORD lastrc = GetLastError (); + CloseHandle (hd[0]); + hd[0] = INVALID_HANDLE_VALUE; + SetLastError (lastrc); + } } + + *read_hd = hd[0]; + *write_hd = hd[1]; + return rc; +} + - if (! DuplicateHandle (GetCurrentProcess(), (inherit_idx == 0) ? rh : wh, - GetCurrentProcess(), &th, 0, - TRUE, DUPLICATE_SAME_ACCESS )) +/* Create a pipe with one inheritable end. Default implementation. + If INHERIT_IDX is 0, the read end of the pipe is made inheritable; + with INHERIT_IDX is 1 the write end will be inheritable. The + question now is how we create an inheritable pipe end under windows + CE were handles are process local objects? The trick we employ is + to defer the actual creation to the other end: We create an + incomplete pipe and pass a rendezvous id to the other end + (process). The other end now uses the rendezvous id to lookup the + pipe in our device driver, creates a new handle and uses that one + to finally establish the pipe. */ +int +__assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx) +{ + HANDLE hd; + int rvid; + + hd = _assuan_w32ce_prepare_pipe (&rvid, !inherit_idx); + if (hd == INVALID_HANDLE_VALUE) { TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_pipe", ctx, - "DuplicateHandle failed: %s", _assuan_w32_strerror (ctx, -1)); - CloseHandle (rh); - CloseHandle (wh); + "CreatePipe failed: %s", _assuan_w32_strerror (ctx, -1)); gpg_err_set_errno (EIO); return -1; } - if (inherit_idx == 0) + + if (inherit_idx) { - CloseHandle (rh); - rh = th; + fd[0] = hd; + fd[1] = (void*)rvid; } else { - CloseHandle (wh); - wh = th; + fd[0] = (void*)rvid; + fd[1] = hd; } - - fd[0] = rh; - fd[1] = wh; - return 0; } @@ -143,9 +278,13 @@ __assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size) read if recv detects that it is not a network socket. */ int res; + TRACE_BEG3 (ctx, ASSUAN_LOG_SYSIO, "__assuan_read", ctx, + "fd=0x%x, buffer=%p, size=%i", fd, buffer, size); + res = recv (HANDLE2SOCKET (fd), buffer, size, 0); if (res == -1) { + TRACE_LOG1 ("recv failed: rc=%d", (int)WSAGetLastError ()); switch (WSAGetLastError ()) { case WSAENOTSOCK: @@ -155,6 +294,7 @@ __assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size) res = ReadFile (fd, buffer, size, &nread, NULL); if (! res) { + TRACE_LOG1 ("ReadFile failed: rc=%d", (int)GetLastError ()); switch (GetLastError ()) { case ERROR_BROKEN_PIPE: @@ -184,7 +324,7 @@ __assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size) break; } } - return res; + return TRACE_SYSRES (res); } @@ -198,14 +338,19 @@ __assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer, write if send detects that it is not a network socket. */ int res; - res = send (HANDLE2SOCKET (fd), buffer, size, 0); + TRACE_BEG3 (ctx, ASSUAN_LOG_SYSIO, "__assuan_write", ctx, + "fd=0x%x, buffer=%p, size=%i", fd, buffer, size); + + res = send ((int)fd, buffer, size, 0); if (res == -1 && WSAGetLastError () == WSAENOTSOCK) { DWORD nwrite; + TRACE_LOG ("send call failed - trying WriteFile"); res = WriteFile (fd, buffer, size, &nwrite, NULL); if (! res) { + TRACE_LOG1 ("WriteFile failed: rc=%d", (int)GetLastError ()); switch (GetLastError ()) { case ERROR_BROKEN_PIPE: @@ -222,7 +367,9 @@ __assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer, else res = (int) nwrite; } - return res; + else if (res == -1) + TRACE_LOG1 ("send call failed: rc=%d", (int)GetLastError ()); + return TRACE_SYSRES (res); } @@ -253,17 +400,43 @@ __assuan_sendmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg, CMDLINE gets the address of a newly allocated string. */ static int build_w32_commandline (assuan_context_t ctx, const char * const *argv, - char **cmdline) + assuan_fd_t fd0, assuan_fd_t fd1, assuan_fd_t fd2, + int fd2_isnull, + char **cmdline) { int i, n; const char *s; char *buf, *p; + char fdbuf[3*30]; + p = fdbuf; + *p = 0; + if (fd0 != ASSUAN_INVALID_FD) + { + snprintf (p, 25, "-&S0=%d ", (int)fd0); + p += strlen (p); + } + if (fd1 != ASSUAN_INVALID_FD) + { + snprintf (p, 25, "-&S1=%d ", (int)fd1); + p += strlen (p); + } + if (fd2 != ASSUAN_INVALID_FD) + { + if (fd2_isnull) + strcpy (p, "-&S2=null "); + else + snprintf (p, 25, "-&S2=%d ", (int)fd2); + p += strlen (p); + } + *cmdline = NULL; - n = 0; + n = strlen (fdbuf); for (i=0; (s = argv[i]); i++) { - n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */ + if (!i) + continue; /* Ignore argv[0]. */ + n += strlen (s) + 1 + 2; /* (1 space, 2 quoting) */ for (; *s; s++) if (*s == '\"') n++; /* Need to double inner quotes. */ @@ -274,10 +447,14 @@ build_w32_commandline (assuan_context_t ctx, const char * const *argv, if (! buf) return -1; + p = stpcpy (p, fdbuf); for (i = 0; argv[i]; i++) { - if (i) + if (!i) + continue; /* Ignore argv[0]. */ + if (i > 1) p = stpcpy (p, " "); + if (! *argv[i]) /* Empty string. */ p = stpcpy (p, "\"\""); else if (strpbrk (argv[i], " \t\n\v\f\"")) @@ -296,7 +473,7 @@ build_w32_commandline (assuan_context_t ctx, const char * const *argv, p = stpcpy (p, argv[i]); } - *cmdline= buf; + *cmdline = buf; return 0; } @@ -309,7 +486,6 @@ __assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name, void (*atfork) (void *opaque, int reserved), void *atforkvalue, unsigned int flags) { - SECURITY_ATTRIBUTES sec_attr; PROCESS_INFORMATION pi = { NULL, /* Returns process handle. */ @@ -317,117 +493,95 @@ __assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name, 0, /* Returns pid. */ 0 /* Returns tid. */ }; - STARTUPINFO si; assuan_fd_t fd; assuan_fd_t *fdp; + assuan_fd_t fd_err; + int fd_err_isnull = 0; char *cmdline; - HANDLE nullfd = INVALID_HANDLE_VALUE; - - /* fixme: Actually we should set the "_assuan_pipe_connect_pid" env - variable. However this requires us to write a full environment - handler, because the strings are expected in sorted order. The - suggestion given in the MS Reference Library, to save the old - value, changeit, create proces and restore it, is not thread - safe. */ - /* Build the command line. */ - if (build_w32_commandline (ctx, argv, &cmdline)) - return -1; + /* Dup stderr to /dev/null unless it is in the list of FDs to be + passed to the child. Well we don't actually open nul because + that is not available on Windows, but use our hack for it. + Because an RVID of 0 is an invalid value and HANDLES will never + have this value either, we test for this as well. */ - /* Start the process. */ - memset (&sec_attr, 0, sizeof sec_attr); - sec_attr.nLength = sizeof sec_attr; - sec_attr.bInheritHandle = FALSE; - - memset (&si, 0, sizeof si); - si.cb = sizeof (si); - si.dwFlags = STARTF_USESTDHANDLES; - /* FIXME: Dup to nul if ASSUAN_INVALID_FD. */ - si.hStdInput = fd_in; - si.hStdOutput = fd_out; + /* FIXME: CHECKOUT WHAT TO DO WITH STDERR HERE. WE NEED TO DEFINE + WHETHER THE FD_CHILD_LIST HAS HANDLES OR RENDEZVOUS IDS. */ - /* Dup stderr to /dev/null unless it is in the list of FDs to be - passed to the child. */ fd = assuan_fd_from_posix_fd (fileno (stderr)); fdp = fd_child_list; if (fdp) { - for (; *fdp != ASSUAN_INVALID_FD && *fdp != fd; fdp++) + for (; *fdp != ASSUAN_INVALID_FD && *fdp != 0 && *fdp != fd; fdp++) ; } if (!fdp || *fdp == ASSUAN_INVALID_FD) + fd_err_isnull = 1; + fd_err = fd; + + if (build_w32_commandline (ctx, argv, fd_in, fd_out, fd_err, fd_err_isnull, + &cmdline)) { - nullfd = CreateFileW (L"nul", GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - if (nullfd == INVALID_HANDLE_VALUE) - { - TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx, - "can't open `nul': %s", _assuan_w32_strerror (ctx, -1)); - _assuan_free (ctx, cmdline); - gpg_err_set_errno (EIO); - return -1; - } - si.hStdError = nullfd; + return -1; } - else - si.hStdError = fd; - - /* Note: We inherit all handles flagged as inheritable. This seems - to be a security flaw but there seems to be no way of selecting - handles to inherit. */ - /* _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", */ - /* name, cmdline); */ - if (!CreateProcess (name, /* Program to start. */ - cmdline, /* Command line arguments. */ - &sec_attr, /* Process security attributes. */ - &sec_attr, /* Thread security attributes. */ - TRUE, /* Inherit handles. */ - (CREATE_DEFAULT_ERROR_MODE - | CREATE_SUSPENDED), /* Creation flags. */ - NULL, /* Environment. */ - NULL, /* Use current drive/directory. */ - &si, /* Startup information. */ - &pi /* Returns process information. */ - )) - { - TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_w32", ctx, - "CreateProcess failed: %s", _assuan_w32_strerror (ctx, -1)); - _assuan_free (ctx, cmdline); - if (nullfd != INVALID_HANDLE_VALUE) - CloseHandle (nullfd); - gpg_err_set_errno (EIO); + TRACE2 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx, + "path=`%s' cmdline=`%s'", name, cmdline); + + { + wchar_t *wcmdline, *wname; + + wcmdline = utf8_to_wchar (cmdline); + _assuan_free (ctx, cmdline); + if (!wcmdline) return -1; - } - _assuan_free (ctx, cmdline); - if (nullfd != INVALID_HANDLE_VALUE) - CloseHandle (nullfd); + wname = utf8_to_wchar (name); + if (!wname) + { + free_wchar (wcmdline); + return -1; + } + + if (!CreateProcess (wname, /* Program to start. */ + wcmdline, /* Command line arguments. */ + NULL, /* (not supported) */ + NULL, /* (not supported) */ + FALSE, /* (not supported) */ + (CREATE_SUSPENDED), /* Creation flags. */ + NULL, /* (not supported) */ + NULL, /* (not supported) */ + NULL, /* (not supported) */ + &pi /* Returns process information.*/ + )) + { + TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx, + "CreateProcess failed: %s", _assuan_w32_strerror (ctx, -1)); + free_wchar (wname); + free_wchar (wcmdline); + gpg_err_set_errno (EIO); + return -1; + } + free_wchar (wname); + free_wchar (wcmdline); + } ResumeThread (pi.hThread); - CloseHandle (pi.hThread); - /* _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" */ - /* " dwProcessID=%d dwThreadId=%d\n", */ - /* pi.hProcess, pi.hThread, */ - /* (int) pi.dwProcessId, (int) pi.dwThreadId); */ + TRACE4 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx, + "CreateProcess ready: hProcess=%p hThread=%p" + " dwProcessID=%d dwThreadId=%d\n", + pi.hProcess, pi.hThread, (int) pi.dwProcessId, (int) pi.dwThreadId); + CloseHandle (pi.hThread); + *r_pid = (pid_t) pi.hProcess; - - /* No need to modify peer process, as we don't change the handle - names. However this also means we are not safe, as we inherit - too many handles. Should use approach similar to gpgme and glib - using a helper process. */ - return 0; } -/* FIXME: Add some sort of waitpid function that covers GPGME and - gpg-agent's use of assuan. */ static pid_t __assuan_waitpid (assuan_context_t ctx, pid_t pid, int nowait, int *status, int options) @@ -446,6 +600,7 @@ __assuan_socketpair (assuan_context_t ctx, int namespace, int style, return -1; } + /* The default system hooks for assuan contexts. */ struct assuan_system_hooks _assuan_system_hooks = diff --git a/src/system.c b/src/system.c index 22d7a0b..1f180e9 100644 --- a/src/system.c +++ b/src/system.c @@ -170,6 +170,22 @@ _assuan_close (assuan_context_t ctx, assuan_fd_t fd) } +/* Same as assuan_close but used for the inheritable end of a + pipe. */ +int +_assuan_close_inheritable (assuan_context_t ctx, assuan_fd_t fd) +{ + TRACE1 (ctx, ASSUAN_LOG_SYSIO, "_assuan_close", ctx, + "fd=0x%x", fd); + +#ifdef HAVE_W32CE_SYSTEM + return 0; /* Nothing to do because it is a rendezvous id. */ +#else + return (ctx->system.close) (ctx, fd); +#endif +} + + ssize_t _assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size) diff --git a/src/sysutils.c b/src/sysutils.c index c7e20a8..1760f44 100644 --- a/src/sysutils.c +++ b/src/sysutils.c @@ -34,17 +34,9 @@ #include "assuan-defs.h" -#ifdef HAVE_W32CE_SYSTEM -#define GPGCEDEV_IOCTL_SET_HANDLE \ - CTL_CODE (FILE_DEVICE_STREAMS, 2048, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define GPGCEDEV_IOCTL_MAKE_PIPE \ - CTL_CODE (FILE_DEVICE_STREAMS, 2049, METHOD_BUFFERED, FILE_ANY_ACCESS) -#endif /*HAVE_W32CE_SYSTEM*/ - - /* This is actually a dummy function to make sure that is module is - not empty. Sokme compilers barf on that. */ + not empty. Some compilers barf on empty modules. */ const char * _assuan_sysutils_blurb (void) { @@ -141,74 +133,3 @@ _assuan_getenv (const char *name) } #endif /*HAVE_W32CE_SYSTEM*/ - -#ifdef HAVE_W32_SYSTEM -/* WindowsCE does not provide a pipe feature. However we need - something like a pipe to convey data between processes and in some - cases within a process. This replacement is not only used by - libassuan but exported and thus usable by gnupg and gpgme as well. */ -DWORD -_assuan_w32ce_create_pipe (HANDLE *read_hd, HANDLE *write_hd, - LPSECURITY_ATTRIBUTES sec_attr, DWORD size) -{ -#ifdef HAVE_W32CE_SYSTEM - HANDLE hd[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; - - *read_hd = *write_hd = INVALID_HANDLE_VALUE; - - ActivateDevice (L"Drivers\\GnuPG_Device", 0); - - /* Note: Using "\\$device\\GPG1" should be identical to "GPG1:". - However this returns an invalid parameter error without having - called GPG_Init in the driver. The docs mention something about - RegisterAFXEx but that API is not documented. */ - hd[0] = CreateFile (L"GPG1:", GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hd[0] == INVALID_HANDLE_VALUE) - return 0; - - if (!DeviceIoControl (hd[0], GPGCEDEV_IOCTL_SET_HANDLE, - &hd[0], sizeof hd[0], NULL, 0, NULL, NULL)) - fprintf (stderr, "GPGCEDEV_IOCTL_SET_HANDLE(0) failed: %d\n", - (int)GetLastError ()); - - hd[1] = CreateFile (L"GPG1:", GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL); - if (hd[1] == INVALID_HANDLE_VALUE) - { - DWORD lasterr = GetLastError (); - CloseHandle (hd[0]); - SetLastError (lasterr); - return 0; - } - if (!DeviceIoControl (hd[1], GPGCEDEV_IOCTL_SET_HANDLE, - &hd[1], sizeof hd[1], NULL, 0, NULL, NULL)) - fprintf (stderr, "GPGCEDEV_IOCTL_SET_HANDLE(1) failed: %d\n", - (int)GetLastError ()); - - if (!DeviceIoControl (hd[0], GPGCEDEV_IOCTL_MAKE_PIPE, - &hd[1], sizeof hd[1], NULL, 0, NULL, NULL)) - { - fprintf (stderr, "GPGCEDEV_IOCTL_MAKE_PIPE failed: %d\n", - (int)GetLastError ()); - if (hd[0] != INVALID_HANDLE_VALUE) - CloseHandle (hd[0]); - if (hd[1] != INVALID_HANDLE_VALUE) - CloseHandle (hd[1]); - return 0; - } - else - { - *read_hd = hd[0]; - *write_hd = hd[1]; - return 1; - } -#else /*!HAVE_W32CE_SYSTEM*/ - return CreatePipe (read_hd, write_hd, sec_attr, size); -#endif /*!HAVE_W32CE_SYSTEM*/ -} - -#endif /*!HAVE_W32_SYSTEM*/ - |