[svn] assuan - r396 - in trunk: . src

svn author wk cvs at cvs.gnupg.org
Mon Nov 15 07:54:15 CET 2010


Author: wk
Date: 2010-11-15 07:54:15 +0100 (Mon, 15 Nov 2010)
New Revision: 396

Modified:
   trunk/NEWS
   trunk/src/ChangeLog
   trunk/src/gpgcedev.c
   trunk/src/gpgcemgr.c
Log:
Add log device to gpgcedev


Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2010-11-02 09:19:03 UTC (rev 395)
+++ trunk/src/ChangeLog	2010-11-15 06:54:15 UTC (rev 396)
@@ -1,3 +1,30 @@
+2010-11-15  Werner Koch  <wk at g10code.com>
+
+	* gpgcedev.c (GPG_Init): Read debug settings.
+
+	* gpgcemgr.c (enable_debug, enable_log): New.
+	(main): Add options --enable-debug, --disable-debug, --enable-log,
+	--disable-log.
+
+2010-11-12  Werner Koch  <wk at g10code.com>
+
+	* gpgcedev.c (DEVCTX_VALUE): Rename to PIPECTX_VALUE.
+	(LOGCTX_VALUE): New.
+	(allocate_opnctx): Add arg IS_LOG.
+	(logimpl_t): New.
+	(openctx_t): Add field IS_LOG.
+	(struct logcontrol): New.
+	(enable_debug, enable_logging): New.
+	(log_debug): Make use of the ENABLE_DEBUG flag.
+	(create_log_id): New.
+	(logimpl_new, logimpl_unref, logimpl_flush, assert_logimpl): New.
+	(GPG_Init): Check for GPG2 device.
+	(GPG_Deinit): Close log stream.
+	(GPG_Open): Implement log device.
+	(GPG_Read): Return EOF for the GPG2 device
+	(GPG_Write): Implement GPG2 device.
+	(dllmain): Init logcontrol CS.
+
 2010-11-01  Werner Koch  <wk at g10code.com>
 
 	* assuan-socket.c (_assuan_sock_bind): Replace open/fdopen by

Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2010-11-02 09:19:03 UTC (rev 395)
+++ trunk/NEWS	2010-11-15 06:54:15 UTC (rev 396)
@@ -5,6 +5,8 @@
 
  * A new flag value may now be used to disable logging.
 
+ * The gpgcedev.c driver now provides a log device.
+
  * Interface changes relative to the 2.0.1 release:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ASSUAN_CONVEY_COMMENTS   NEW.

Modified: trunk/src/gpgcedev.c
===================================================================
--- trunk/src/gpgcedev.c	2010-11-02 09:19:03 UTC (rev 395)
+++ trunk/src/gpgcedev.c	2010-11-15 06:54:15 UTC (rev 396)
@@ -1,4 +1,4 @@
-/* gpgcedrv.c - WindowsCE device driver to implement a pipe.
+/* gpgcedrv.c - WindowsCE device driver to implement pipe and syslog.
    Copyright (C) 2010 Free Software Foundation, Inc.
 
    This file is part of Assuan.
@@ -20,14 +20,19 @@
 
 #include <stdio.h>
 #include <stdarg.h>
+#include <string.h>
 #include <windows.h>
 #include <devload.h>
 #include <winioctl.h>
 
-#define ENABLE_DEBUG
-#warning Cancel not handled.
+/* FIXME Cancel not handled. */
 
+#define DBGFILENAME "\\gpgcedev.dbg"
+#define LOGFILENAME L"\\gpgcedev.log"
+#define GPGCEDEV_KEY_NAME  L"Drivers\\GnuPG_Device"
+#define GPGCEDEV_KEY_NAME2 L"Drivers\\GnuPG_Log"
 
+
 /* Missing IOCTLs in the current mingw32ce.  */
 #ifndef IOCTL_PSL_NOTIFY
 # define FILE_DEVICE_PSL 259
@@ -74,6 +79,7 @@
   CTL_CODE (FILE_DEVICE_STREAMS, 2051, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
 
+/* An object to describe a pipe.  */
 struct pipeimpl_s
 {
   CRITICAL_SECTION critsect;  /* Lock for all members.  */
@@ -101,18 +107,39 @@
 typedef struct pipeimpl_s *pipeimpl_t;
 
 
+/* An object to describe a logging context.  We can't write directly
+   to the log stream because we want to do line buffering and thus we
+   need to store data until we see LF.  */
+struct logimpl_s;
+typedef struct logimpl_s *logimpl_t;
+struct logimpl_s
+{
+  unsigned long logid; /* An identifier for a log source.  */
+  unsigned long dsec;  /* Tenth of a second since system start.   */
+  char *line;          /* Malloced line buffer.  */
+  size_t linesize;     /* Allocated size of LINE.  */
+  size_t linelen;      /* Used length of the line.  */
+  int truncated;       /* Indicates a truncated log line.  */
+};
+
+
+
 /* An object to store information pertaining to an open-context.  */
 struct opnctx_s;
 typedef struct opnctx_s *opnctx_t;
 struct opnctx_s
 {
   int inuse;        /* True if this object has valid data.  */
+  int is_log;       /* True if this describes a log device.  */
   LONG rvid;        /* The unique rendezvous identifier.  */
   DWORD access_code;/* Value from OpenFile.  */
   DWORD share_mode; /* Value from OpenFile.  */
 
-  /* The state shared by all users.  */
+  /* The state shared by all pipe users.  Only used if IS_LOG is false. */
   pipeimpl_t pipeimpl;
+
+  /* The state used to implement a log stream.  Only used if IS_LOG is true. */
+  logimpl_t logimpl;
 };
 
 /* A malloced table of open-context and the number of allocated slots.  */
@@ -126,38 +153,52 @@
 /* A criticial section object used to protect the OPNCTX_TABLE.  */
 static CRITICAL_SECTION opnctx_table_cs;
 
-/* We don't need a device context thus we use the adress of the
-   critical section object for it.  */
-#define DEVCTX_VALUE ((DWORD)(&opnctx_table_cs))
 
-/* Constants used for our lock functions.  */
-#define LOCK_TRY  0
-#define LOCK_WAIT 1
+/* A global object to control the logging.  */
+struct {
+  CRITICAL_SECTION lock; /* Lock for this structure.  */
+  HANDLE filehd;         /* Handle of the log output file.  */
+  int references;        /* Number of objects references this one.  */
+} logcontrol;
 
 
+/* We don't need a device context for the pipe thus we use the adress
+   of the critical section object for it.  */
+#define PIPECTX_VALUE ((DWORD)(&opnctx_table_cs))
+
+/* The device context for the log device is the address of our
+   control structure.  */
+#define LOGCTX_VALUE ((DWORD)(&logcontrol))
+
+
+/* True if we have enabled debugging.  */
+static int enable_debug;
+
+/* True if logging has been enabled.  */
+static int enable_logging;
+
+
 
 static void
 log_debug (const char *fmt, ...)
 {
-#ifndef ENABLE_DEBUG
-  (void)fmt;
-#else
-  va_list arg_ptr;
-  FILE *fp;
-
-  fp = fopen ("\\gpgcedev.log", "a+");
-  if (!fp)
-    return;
-  va_start (arg_ptr, fmt);
-  vfprintf (fp, fmt, arg_ptr);
-  va_end (arg_ptr);
-  fclose (fp);
-#endif
+  if (enable_debug)
+    {
+      va_list arg_ptr;
+      FILE *fp;
+      
+      fp = fopen (DBGFILENAME, "a+");
+      if (!fp)
+        return;
+      va_start (arg_ptr, fmt);
+      vfprintf (fp, fmt, arg_ptr);
+      va_end (arg_ptr);
+      fclose (fp);
+    }
 }
 
 
-/* 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. */
+/* Return a new rendezvous id.  We will never return an RVID of 0. */
 static LONG
 create_rendezvous_id (void)
 {
@@ -169,7 +210,21 @@
   return rvid;
 }
 
+/* Return a new log id.  These log ids are used to identify log lines
+   send to the same device; ie. for each CreateFile("GPG2:") a new log
+   id is assigned.  We will ever return a log id of 0. */
+static LONG
+create_log_id (void)
+{
+  static LONG log_id;
+  LONG lid;
 
+  while (!(lid = InterlockedIncrement (&log_id)))
+    ;
+  return lid;
+}
+
+
 
 pipeimpl_t
 pipeimpl_new (void)
@@ -201,6 +256,9 @@
 {
   int release = 0;
 
+  if (!pimpl)
+    return;
+
   log_debug ("pipeimpl_unref (%p): dereference\n", pimpl);
 
   if (--pimpl->refcnt == 0)
@@ -232,14 +290,83 @@
 }
 
 
+
+/* Allocate a new log structure.  */
+logimpl_t
+logimpl_new (void)
+{
+  logimpl_t limpl;
 
+  limpl = calloc (1, sizeof *limpl);
+  if (!limpl)
+    return NULL;
+  limpl->logid = create_log_id ();
+  limpl->linesize = 256;
+  limpl->line = malloc (limpl->linesize);
+  if (!limpl->line)
+    {
+      free (limpl);
+      return NULL;
+    }
+
+  return limpl;
+}
+
+
+/* There is no need to lock LIMPL, thus is a dummy function.  */
+void
+logimpl_unref (logimpl_t limpl)
+{
+  (void)limpl;
+}
+
+
+/* Flush a pending log line.  */
+static void
+logimpl_flush (logimpl_t limpl)
+{
+  if (!limpl->linelen || !enable_logging)
+    return;
+
+  EnterCriticalSection (&logcontrol.lock);
+  if (logcontrol.filehd == INVALID_HANDLE_VALUE)
+    logcontrol.filehd = CreateFile (LOGFILENAME, GENERIC_WRITE,
+                                     FILE_SHARE_READ,
+                                     NULL, OPEN_ALWAYS,
+                                     FILE_ATTRIBUTE_NORMAL, NULL);
+  if (!logcontrol.filehd)
+    log_debug ("can't open log file: rc=%d\n", (int)GetLastError ());
+  else
+    {
+      char buf[50];
+      DWORD nwritten;
+
+      snprintf (buf, sizeof buf, 
+                "%06lu/%lu//", limpl->dsec % 1000000, limpl->logid);
+      if (!WriteFile (logcontrol.filehd, buf, strlen (buf), &nwritten, NULL))
+        log_debug ("error writing log file: rc=%d\n", (int)GetLastError ());
+      else if (!WriteFile (logcontrol.filehd,
+                           limpl->line, limpl->linelen, &nwritten, NULL))
+        log_debug ("error writing log file: rc=%d\n", (int)GetLastError ());
+
+      snprintf (buf, sizeof buf, "%s\n", limpl->truncated? "[...]":"");
+      if (!WriteFile (logcontrol.filehd, buf, strlen (buf), &nwritten, NULL))
+        log_debug ("error writing log file: rc=%d\n", (int)GetLastError ());
+    }
+
+  LeaveCriticalSection (&logcontrol.lock);
+  limpl->linelen = 0;
+  limpl->truncated = 0;
+}
+
+
 /* Return a new opnctx handle and mark it as used.  Returns NULL and
    sets LastError on memory failure etc.  opnctx_table_cs must be
    locked on entry and is locked on exit.  Note that the returned
    pointer is only valid as long as opnctx_table_cs stays locked, as
    it is not stable under table reallocation.  */
 static opnctx_t
-allocate_opnctx (void)
+allocate_opnctx (int is_log)
 {
   opnctx_t opnctx = NULL;
   int idx;
@@ -265,10 +392,12 @@
     }
   opnctx = &opnctx_table[idx];
   opnctx->inuse = 1;
+  opnctx->is_log = is_log;
   opnctx->rvid = 0;
   opnctx->access_code = 0;
   opnctx->share_mode = 0;
   opnctx->pipeimpl = 0;
+  opnctx->logimpl = 0;
 
  leave:
   return opnctx;
@@ -305,6 +434,12 @@
 {
   DWORD ctx_arg = OPNCTX_TO_IDX (ctx);
 
+  if (ctx->is_log)
+    {
+      log_debug ("  assert_pipeimpl (ctx=%i): "
+                 "error: not valid for a log device\n", ctx_arg);
+      return NULL;
+    }
   if (! ctx->pipeimpl)
     {
       ctx->pipeimpl = pipeimpl_new ();
@@ -321,42 +456,89 @@
 }
 
 
+static logimpl_t
+assert_logimpl (opnctx_t ctx)
+{
+  DWORD ctx_arg = OPNCTX_TO_IDX (ctx);
+
+  if (!ctx->is_log)
+    {
+      log_debug ("  assert_logimpl (ctx=%i): "
+                 "error: not valid for a pipe device\n", ctx_arg);
+      return NULL;
+    }
+  if (!ctx->logimpl)
+    {
+      ctx->logimpl = logimpl_new ();
+      if (!ctx->logimpl)
+	{
+	  log_debug ("  assert_logimpl (ctx=%i): error: can't create log\n",
+		     ctx_arg);
+	  return NULL;
+	}
+      log_debug ("  assert_logimpl (ctx=%i): created log 0x%p\n",
+		 ctx_arg, ctx->logimpl);
+    }
+  return ctx->logimpl;
+}
+
+
 /* Verify access CODE for context CTX_ARG, returning a reference to
-   the locked pipe implementation.  opnctx_table_cs must be unlocked
-   on entry and is unlocked on exit.  */
-pipeimpl_t
-access_opnctx (DWORD ctx_arg, DWORD code)
+   the locked pipe or the locked log implementation.  opnctx_table_cs
+   must be unlocked on entry and is unlocked on exit.  */
+int
+access_opnctx (DWORD ctx_arg, DWORD code, pipeimpl_t *r_pipe, logimpl_t *r_log)
 {
   opnctx_t ctx;
-  pipeimpl_t pimpl;
 
+  *r_pipe = NULL;
+  *r_log  = NULL;
+
   EnterCriticalSection (&opnctx_table_cs);
   ctx = verify_opnctx (ctx_arg);
   if (! ctx)
     {
       /* Error is set by verify_opnctx.  */
       LeaveCriticalSection (&opnctx_table_cs);
-      return NULL;
+      return -1;
     }
 
   if (! (ctx->access_code & code))
     {
       SetLastError (ERROR_INVALID_ACCESS);
       LeaveCriticalSection (&opnctx_table_cs);
-      return NULL;
+      return -1;
     }
 
-  pimpl = assert_pipeimpl (ctx);
-  if (! pimpl)
+  if (ctx->is_log)
     {
-      LeaveCriticalSection (&opnctx_table_cs);
-      return NULL;
+      logimpl_t limpl;
+
+      limpl = assert_logimpl (ctx);
+      if (!limpl)
+        {
+          LeaveCriticalSection (&opnctx_table_cs);
+          return -1;
+        }
+      *r_log = limpl;
     }
+  else
+    {
+      pipeimpl_t pimpl;
 
-  EnterCriticalSection (&pimpl->critsect);
-  pimpl->refcnt++;
+      pimpl = assert_pipeimpl (ctx);
+      if (! pimpl)
+        {
+          LeaveCriticalSection (&opnctx_table_cs);
+          return -1;
+        }
+      EnterCriticalSection (&pimpl->critsect);
+      pimpl->refcnt++;
+      *r_pipe = pimpl;
+    }
+
   LeaveCriticalSection (&opnctx_table_cs);
-  return pimpl;
+  return 0;
 }
 
 
@@ -388,16 +570,92 @@
 DWORD
 GPG_Init (LPCTSTR active_key, DWORD bus_context)
 {
-  char *tmpbuf;
+  static int firsttimedone;
+  HKEY handle;
+  wchar_t buffer[25];
+  DWORD buflen;
+  DWORD result;
+
   (void)bus_context;
-  
-  tmpbuf = wchar_to_utf8 (active_key);
-  log_debug ("GPG_Init (devctx=0x%p, %s)\n", DEVCTX_VALUE, tmpbuf);
-  free (tmpbuf);
 
-  /* We don't need any global data.  However, we need to return
-     something.  */
-  return DEVCTX_VALUE;
+  EnterCriticalSection (&logcontrol.lock);
+  if (!firsttimedone)
+    {
+      firsttimedone++;
+      if (!RegOpenKeyEx (HKEY_LOCAL_MACHINE, GPGCEDEV_KEY_NAME,
+                         0, KEY_READ, &handle))
+        {
+          buflen = sizeof buffer;
+          if (!RegQueryValueEx (handle, L"debugDriver", 0, NULL,
+                                (PBYTE)buffer, &buflen)
+              && wcstol (buffer, NULL, 10) > 0)
+            enable_debug = 1;
+          RegCloseKey (handle);
+        }
+      if (!RegOpenKeyEx (HKEY_LOCAL_MACHINE, GPGCEDEV_KEY_NAME2,
+                         0, KEY_READ, &handle))
+        {
+          buflen = sizeof buffer;
+          if (!RegQueryValueEx (handle, L"enableLog", 0, NULL,
+                                (PBYTE)buffer, &buflen)
+              && wcstol (buffer, NULL, 10) > 0)
+            enable_logging = 1;
+          RegCloseKey (handle);
+        }
+    }
+  LeaveCriticalSection (&logcontrol.lock);
+
+  if (enable_debug)
+    {
+      char *tmpbuf;
+      tmpbuf = wchar_to_utf8 (active_key);
+      log_debug ("GPG_Init (%s)\n", tmpbuf);
+      free (tmpbuf);
+    }
+
+  if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, active_key, 0, KEY_READ, &handle))
+    {
+      log_debug ("GPG_Init: error reading registry: rc=%d\n", 
+                 (int)GetLastError ());
+      return 0;
+    }
+
+  buflen = sizeof buffer;
+  if (RegQueryValueEx (handle, L"Name", 0, NULL, (PBYTE)buffer, &buflen))
+    {
+      log_debug ("GPG_Init: error reading registry value 'Name': rc=%d\n", 
+                 (int)GetLastError ());
+      result = 0;
+    }
+  else if (!wcscmp (buffer, L"GPG1:"))
+    {
+      /* This is the pipe device: We don't need any global data.
+         However, we need to return something.  */
+      log_debug ("GPG_Init: created pipe device (devctx=%p)\n", PIPECTX_VALUE);
+      result = PIPECTX_VALUE;
+    }
+  else if (!wcscmp (buffer, L"GPG2:"))
+    {
+      /* This is the log device.  Clear the object and return something.  */
+      logcontrol.filehd = INVALID_HANDLE_VALUE;
+      log_debug ("GPG_Init: created log device (devctx=%p)\n", 0);
+      result = LOGCTX_VALUE;
+    }
+  else
+    {
+      if (enable_debug)
+        {
+          char *tmpbuf;
+          tmpbuf = wchar_to_utf8 (buffer);
+          log_debug ("GPG_Init: device '%s' is not supported\n", tmpbuf);
+          free (tmpbuf);
+        }
+      SetLastError (ERROR_DEV_NOT_EXIST);
+      result = 0;
+    }
+
+  RegCloseKey (handle);
+  return result;
 }
 
 
@@ -407,29 +665,46 @@
 GPG_Deinit (DWORD devctx)
 {
   log_debug ("GPG_Deinit (devctx=0x%p)\n", (void*)devctx);
-  if (devctx != DEVCTX_VALUE)
+  if (devctx == PIPECTX_VALUE)
     {
+      /* No need to release resources.  */
+    }
+  else if (devctx == LOGCTX_VALUE)
+    {
+      EnterCriticalSection (&logcontrol.lock);
+      if (logcontrol.filehd != INVALID_HANDLE_VALUE)
+        {
+          CloseHandle (logcontrol.filehd);
+          logcontrol.filehd = INVALID_HANDLE_VALUE;
+        }
+      LeaveCriticalSection (&logcontrol.lock);
+    }
+  else
+    {
       SetLastError (ERROR_INVALID_PARAMETER);
       return FALSE; /* Error.  */
     }
   
-  /* FIXME: Release resources.  */
-
   return TRUE; /* Success.  */
 }
 
 
 
-/* Create a new open context.  This fucntion is called due to a
+/* Create a new open context.  This function is called due to a
    CreateFile from the application.  */
 DWORD
 GPG_Open (DWORD devctx, DWORD access_code, DWORD share_mode)
 {
   opnctx_t opnctx;
   DWORD ctx_arg = 0;
+  int is_log;
 
   log_debug ("GPG_Open (devctx=%p)\n", (void*)devctx);
-  if (devctx != DEVCTX_VALUE)
+  if (devctx == PIPECTX_VALUE)
+    is_log = 0;
+  else if (devctx == LOGCTX_VALUE)
+    is_log = 1;
+  else
     {
       log_debug ("GPG_Open (devctx=%p): error: wrong devctx (expected 0x%p)\n",
 		 (void*) devctx);
@@ -438,7 +713,7 @@
     }
 
   EnterCriticalSection (&opnctx_table_cs);
-  opnctx = allocate_opnctx ();
+  opnctx = allocate_opnctx (is_log);
   if (!opnctx)
     {
       log_debug ("GPG_Open (devctx=%p): error: could not allocate context\n",
@@ -451,8 +726,14 @@
 
   ctx_arg = OPNCTX_TO_IDX (opnctx);
 
-  log_debug ("GPG_Open (devctx=%p): success: created context %i\n",
-	     (void*) devctx, ctx_arg);
+  log_debug ("GPG_Open (devctx=%p, is_log=%d): success: created context %i\n",
+	     (void*) devctx, is_log, ctx_arg);
+  if (is_log)
+    {
+      EnterCriticalSection (&logcontrol.lock);
+      logcontrol.references++;
+      LeaveCriticalSection (&logcontrol.lock);
+    }
 
  leave:
   LeaveCriticalSection (&opnctx_table_cs);
@@ -496,6 +777,24 @@
       pipeimpl_unref (pimpl);
       opnctx->pipeimpl = 0;
     }
+  if (opnctx->logimpl)
+    {
+      logimpl_t limpl = opnctx->logimpl;
+
+      logimpl_flush (limpl);
+      logimpl_unref (limpl);
+      free (limpl->line);
+      free (limpl);
+      opnctx->logimpl = 0;
+      EnterCriticalSection (&logcontrol.lock);
+      logcontrol.references--;
+      if (!logcontrol.references && logcontrol.filehd)
+        {
+          CloseHandle (logcontrol.filehd);
+          logcontrol.filehd = INVALID_HANDLE_VALUE;
+        }
+      LeaveCriticalSection (&logcontrol.lock);
+    }
   opnctx->access_code = 0;
   opnctx->share_mode = 0;
   opnctx->rvid = 0;
@@ -514,6 +813,7 @@
 GPG_Read (DWORD opnctx_arg, void *buffer, DWORD count)
 {
   pipeimpl_t pimpl;
+  logimpl_t  limpl;
   const char *src;
   char *dst;
   int result = -1;
@@ -521,14 +821,20 @@
   log_debug ("GPG_Read (ctx=%i, buffer=0x%p, count=%d)\n",
 	     opnctx_arg, buffer, count);
 
-  pimpl = access_opnctx (opnctx_arg, GENERIC_READ);
-  if (!pimpl)
+  if (access_opnctx (opnctx_arg, GENERIC_READ, &pimpl, &limpl))
     {
       log_debug ("GPG_Read (ctx=%i): error: could not access context\n",
 		 opnctx_arg);
       return -1;
     }
 
+  if (limpl)
+    {
+      /* Reading from a log stream does not make sense.  Return EOF.  */
+      result = 0;
+      goto leave;
+    }
+
  retry:
   if (pimpl->buffer_pos == pimpl->buffer_len)
     {
@@ -584,6 +890,7 @@
 
  leave:
   pipeimpl_unref (pimpl);
+  logimpl_unref (limpl);
   return result;
 }
 
@@ -593,6 +900,7 @@
 GPG_Write (DWORD opnctx_arg, const void *buffer, DWORD count)
 {
   pipeimpl_t pimpl;
+  logimpl_t  limpl;
   int result = -1;
   const char *src;
   char *dst;
@@ -601,8 +909,7 @@
   log_debug ("GPG_Write (ctx=%i, buffer=0x%p, count=%d)\n", opnctx_arg,
 	     buffer, count);
 
-  pimpl = access_opnctx (opnctx_arg, GENERIC_WRITE);
-  if (!pimpl)
+  if (access_opnctx (opnctx_arg, GENERIC_WRITE, &pimpl, &limpl))
     {
       log_debug ("GPG_Write (ctx=%i): error: could not access context\n",
 		 opnctx_arg);
@@ -617,58 +924,86 @@
     }
 
  retry:
-  /* Check for broken pipe.  */
-  if (pimpl->flags & PIPE_FLAG_NO_READER)
+  if (limpl)
     {
-      log_debug ("GPG_Write (ctx=%i): error: broken pipe\n", opnctx_arg);
-      SetLastError (ERROR_BROKEN_PIPE);
-      goto leave;
+      /* Store it in our buffer up to a LF and print complete lines.  */
+      result = count;
+      if (!limpl->linelen)
+        limpl->dsec = GetTickCount () / 100;
+      dst = limpl->line + limpl->linelen;
+      for (src = buffer; count; count--, src++)
+        {
+          if (*src == '\n')
+            {
+              logimpl_flush (limpl);
+              dst = limpl->line + limpl->linelen;
+            }
+          else if (limpl->linelen >= limpl->linesize)
+            limpl->truncated = 1;
+          else
+            {
+              *dst++ = *src;
+              limpl->linelen++;
+            }
+        }
     }
-
-  /* Check for request to unblock once.  */
-  if (pimpl->flags & PIPE_FLAG_UNBLOCK_WRITER)
+  else /* pimpl */
     {
-      log_debug ("GPG_Write (ctx=%i): success: EBUSY (due to unblock)\n",
-		 opnctx_arg);
-      pimpl->flags &= ~PIPE_FLAG_UNBLOCK_WRITER;
-      SetLastError (ERROR_BUSY);
-      result = -1;
-      goto leave;
+      /* Check for broken pipe.  */
+      if (pimpl->flags & PIPE_FLAG_NO_READER)
+        {
+          log_debug ("GPG_Write (ctx=%i): error: broken pipe\n", opnctx_arg);
+          SetLastError (ERROR_BROKEN_PIPE);
+          goto leave;
+        }
+      
+      /* Check for request to unblock once.  */
+      if (pimpl->flags & PIPE_FLAG_UNBLOCK_WRITER)
+        {
+          log_debug ("GPG_Write (ctx=%i): success: EBUSY (due to unblock)\n",
+                     opnctx_arg);
+          pimpl->flags &= ~PIPE_FLAG_UNBLOCK_WRITER;
+          SetLastError (ERROR_BUSY);
+          result = -1;
+          goto leave;
+        }
+      
+      /* Write to our buffer.  */
+      if (pimpl->buffer_len == pimpl->buffer_size)
+        {
+          /* Buffer is full.  */
+          HANDLE space_available = pimpl->space_available;
+          LeaveCriticalSection (&pimpl->critsect);
+          log_debug ("GPG_Write (ctx=%i): waiting: space_available\n",
+                     opnctx_arg);
+          WaitForSingleObject (space_available, INFINITE);
+          log_debug ("GPG_Write (ctx=%i): resuming: space_available\n",
+                     opnctx_arg);
+          EnterCriticalSection (&pimpl->critsect);
+          goto retry;
+        }
+      
+      src = buffer;
+      dst = pimpl->buffer + pimpl->buffer_len;
+      while (count > 0 && pimpl->buffer_len < pimpl->buffer_size)
+        {
+          *dst++ = *src++;
+          count--;
+          pimpl->buffer_len++;
+          nwritten++;
+        }
+      result = nwritten;
+      
+      if (!SetEvent (pimpl->data_available))
+        log_debug ("GPG_Write (ctx=%i): warning: SetEvent(data_available) "
+                   "failed: rc=%d\n", opnctx_arg, (int)GetLastError ());
     }
-
-  /* Write to our buffer.  */
-  if (pimpl->buffer_len == pimpl->buffer_size)
-    {
-      /* Buffer is full.  */
-      HANDLE space_available = pimpl->space_available;
-      LeaveCriticalSection (&pimpl->critsect);
-      log_debug ("GPG_Write (ctx=%i): waiting: space_available\n", opnctx_arg);
-      WaitForSingleObject (space_available, INFINITE);
-      log_debug ("GPG_Write (ctx=%i): resuming: space_available\n",
-		 opnctx_arg);
-      EnterCriticalSection (&pimpl->critsect);
-      goto retry;
-    }
-
-  src = buffer;
-  dst = pimpl->buffer + pimpl->buffer_len;
-  while (count > 0 && pimpl->buffer_len < pimpl->buffer_size)
-    {
-      *dst++ = *src++;
-      count--;
-      pimpl->buffer_len++;
-      nwritten++;
-    }
-  result = nwritten;
-
-  if (!SetEvent (pimpl->data_available))
-    log_debug ("GPG_Write (ctx=%i): warning: SetEvent(data_available) "
-	       "failed: rc=%d\n", opnctx_arg, (int)GetLastError ());
-
+  
   log_debug ("GPG_Write (ctx=%i): success: result=%d\n", opnctx_arg, result);
 
  leave:
   pipeimpl_unref (pimpl);
+  logimpl_unref (limpl);
   return result;
 }
 
@@ -977,6 +1312,13 @@
 		 opnctx_arg);
       goto leave;
     }
+  if (opnctx->is_log)
+    {
+      log_debug ("GPG_IOControl (ctx=%i): error: invalid code for log device\n",
+                 opnctx_arg);
+      SetLastError (ERROR_INVALID_PARAMETER);
+      goto leave;
+    }
 
   switch (code)
     {
@@ -1081,6 +1423,7 @@
 void
 GPG_PowerUp (DWORD devctx)
 {
+  log_debug ("GPG_PowerUp (devctx=%i)\n", devctx);
 }
 
 
@@ -1088,9 +1431,12 @@
 void
 GPG_PowerDown (DWORD devctx)
 {
+  log_debug ("GPG_PowerDown (devctx=%i)\n", devctx);
 }
 
 
+
+
 
 /* Entry point called by the DLL loader.  */
 int WINAPI
@@ -1102,6 +1448,7 @@
     {
     case DLL_PROCESS_ATTACH:
       InitializeCriticalSection (&opnctx_table_cs);
+      InitializeCriticalSection (&logcontrol.lock);
       break;
 
     case DLL_THREAD_ATTACH:

Modified: trunk/src/gpgcemgr.c
===================================================================
--- trunk/src/gpgcemgr.c	2010-11-02 09:19:03 UTC (rev 395)
+++ trunk/src/gpgcemgr.c	2010-11-15 06:54:15 UTC (rev 396)
@@ -24,9 +24,10 @@
 
 #define PGM "gpgcemgr"
 
-#define GPGCEDEV_KEY_NAME L"Drivers\\GnuPG_Device"
-#define GPGCEDEV_DLL_NAME L"gpgcedev.dll"
-#define GPGCEDEV_PREFIX   L"GPG"
+#define GPGCEDEV_KEY_NAME  L"Drivers\\GnuPG_Device"
+#define GPGCEDEV_KEY_NAME2 L"Drivers\\GnuPG_Log"
+#define GPGCEDEV_DLL_NAME  L"gpgcedev.dll"
+#define GPGCEDEV_PREFIX    L"GPG"
 
 
 static int
@@ -38,7 +39,7 @@
   if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, GPGCEDEV_KEY_NAME, 0, NULL, 0,
                       KEY_WRITE, NULL, &handle, &disp))
     {
-      fprintf (stderr, PGM": error creating registry key: rc=%d\n", 
+      fprintf (stderr, PGM": error creating registry key 1: rc=%d\n", 
                (int)GetLastError ());
       return 1;
     }
@@ -53,15 +54,35 @@
   
   RegCloseKey (handle);
 
-  fprintf (stderr, PGM": registry key created\n");
+  fprintf (stderr, PGM": registry key 1 created\n");
 
+  if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, GPGCEDEV_KEY_NAME2, 0, NULL, 0,
+                      KEY_WRITE, NULL, &handle, &disp))
+    {
+      fprintf (stderr, PGM": error creating registry key 2: rc=%d\n", 
+               (int)GetLastError ());
+      return 1;
+    }
 
+  RegSetValueEx (handle, L"dll", 0, REG_SZ, 
+                 (void*)GPGCEDEV_DLL_NAME, sizeof (GPGCEDEV_DLL_NAME));
+  RegSetValueEx (handle, L"prefix", 0, REG_SZ,
+                 (void*)GPGCEDEV_PREFIX, sizeof (GPGCEDEV_PREFIX));
+
+  dw = 2;
+  RegSetValueEx (handle, L"Index", 0, REG_DWORD, (void*)&dw, sizeof dw);
+  
+  RegCloseKey (handle);
+
+  fprintf (stderr, PGM": registry key 2 created\n");
+
+
   return 0;
 }
 
 
 static int
-deinstall (void)
+deinstall (wchar_t *name)
 {
   int result = 0;
   HANDLE shd;
@@ -69,7 +90,7 @@
 
   memset (&dinfo, 0, sizeof dinfo);
   dinfo.dwSize = sizeof dinfo;
-  shd = FindFirstDevice (DeviceSearchByLegacyName, L"GPG1:", &dinfo);
+  shd = FindFirstDevice (DeviceSearchByLegacyName, name, &dinfo);
   if (shd == INVALID_HANDLE_VALUE)
     {
       if (GetLastError () == 18)
@@ -102,6 +123,49 @@
 }
 
 
+static int
+enable_debug (int yes)
+{
+  HKEY handle;
+  DWORD disp;
+  
+  if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, GPGCEDEV_KEY_NAME, 0, NULL, 0,
+                      KEY_WRITE, NULL, &handle, &disp))
+    {
+      fprintf (stderr, PGM": error creating debug registry key: rc=%d\n", 
+               (int)GetLastError ());
+      return 1;
+    }
+  
+  RegSetValueEx (handle, L"debugDriver", 0, REG_SZ, 
+                 (void*)(yes? L"1":L"0"), sizeof L"0");
+  RegCloseKey (handle);
+  return 0;
+}
+
+
+static int
+enable_log (int yes)
+{
+  HKEY handle;
+  DWORD disp;
+  
+  if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, GPGCEDEV_KEY_NAME2, 0, NULL, 0,
+                      KEY_WRITE, NULL, &handle, &disp))
+    {
+      fprintf (stderr, PGM": error creating debug registry key: rc=%d\n", 
+               (int)GetLastError ());
+      return 1;
+    }
+  
+  RegSetValueEx (handle, L"enableLog", 0, REG_SZ, 
+                 (void*)(yes? L"1":L"0"), sizeof L"0");
+  RegCloseKey (handle);
+  return 0;
+}
+
+
+
 /* Kudos to Scott Seligman <scott at scottandmichelle.net> for his work
    on the reverse engineering.  */
 struct htc_sensor_s
@@ -280,24 +344,111 @@
   if (argc > 1 && !strcmp (argv[1], "--register"))
     result = install ();
   else if (argc > 1 && !strcmp (argv[1], "--deactivate"))
-    result = deinstall ();
+    {
+      if (deinstall (L"GPG1:"))
+        result = 1;
+      if (deinstall (L"GPG2:"))
+        result = 1;
+    }
   else if (argc > 1 && !strcmp (argv[1], "--activate"))
     {
+      HANDLE hd;
+
       /* This is mainly for testing.  The activation is usually done
          right before the device is opened.  */
-      if (ActivateDevice (GPGCEDEV_DLL_NAME, 0) == INVALID_HANDLE_VALUE)
+      if (ActivateDevice (GPGCEDEV_KEY_NAME, 0) == INVALID_HANDLE_VALUE)
         {
-          fprintf (stderr, PGM": ActivateDevice failed: rc=%d\n",
+          fprintf (stderr, PGM": ActivateDevice 1 failed: rc=%d\n",
                    (int)GetLastError ());
           result = 1;
         }
+      else if (ActivateDevice (GPGCEDEV_KEY_NAME2, 0) == INVALID_HANDLE_VALUE)
+        {
+          fprintf (stderr, PGM": ActivateDevice 2 failed: rc=%d\n",
+                   (int)GetLastError ());
+          result = 1;
+        }
       else
-        fprintf (stderr, PGM": device activated\n");
+        {
+          fprintf (stderr, PGM": devices activated\n");
+          hd = CreateFile (L"GPG1:", GENERIC_WRITE,
+                           FILE_SHARE_READ | FILE_SHARE_WRITE,
+                           NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+          if (hd == INVALID_HANDLE_VALUE)
+            {
+              fprintf (stderr, PGM": opening `GPG1:' failed: rc=%d\n",
+                       (int)GetLastError ());
+              result = 1;
+            }
+          else
+            {
+              fprintf (stderr, PGM": device `GPG1:' seems to work\n");
+              CloseHandle (hd);
+            }
+
+          hd = CreateFile (L"GPG2:", GENERIC_WRITE,
+                           FILE_SHARE_READ | FILE_SHARE_WRITE,
+                           NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+          if (hd == INVALID_HANDLE_VALUE)
+            {
+              fprintf (stderr, PGM": opening `GPG2:' failed: rc=%d\n",
+                       (int)GetLastError ());
+              result = 1;
+            }
+          else
+            {
+              fprintf (stderr, PGM": device `GPG2:' seems to work\n");
+              CloseHandle (hd);
+            }
+          
+        }
     }
   else if (argc > 1 && !strcmp (argv[1], "--gravity"))
     result = gravity ();
   /* else if (argc > 1 && !strcmp (argv[1], "--gps")) */
   /*   result = gps (); */
+  else if (argc > 1 && !strcmp (argv[1], "--log"))
+    {
+      HANDLE hd;
+
+      hd = CreateFile (L"GPG2:", GENERIC_WRITE,
+                       FILE_SHARE_READ | FILE_SHARE_WRITE,
+                       NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+      if (hd == INVALID_HANDLE_VALUE)
+        {
+          fprintf (stderr, PGM": opening `GPG2:' failed: rc=%d\n",
+                   (int)GetLastError ());
+          result = 1;
+        }
+      else
+        {
+          char marktwain[] = "I have never let my schooling interfere"
+            " with my education.\n";
+          DWORD nwritten;
+          int i;
+
+          for (i=0; i < 5; i++) 
+            {
+              if (!WriteFile (hd, marktwain, strlen (marktwain),
+                              &nwritten, NULL))
+                {
+                  fprintf (stderr, PGM": writing `GPG2:' failed: rc=%d\n",
+                           (int)GetLastError ());
+                  result = 1;
+                }
+              Sleep (200);
+            }
+          CloseHandle (hd);
+        }
+    }
+  else if (argc > 1 && !strcmp (argv[1], "--enable-debug"))
+    result = enable_debug (1);
+  else if (argc > 1 && !strcmp (argv[1], "--disable-debug"))
+    result = enable_debug (0);
+  else if (argc > 1 && !strcmp (argv[1], "--enable-log"))
+    result = enable_log (1);
+  else if (argc > 1 && !strcmp (argv[1], "--disable-log"))
+    result = enable_log (0);
   else
     {
       fprintf (stderr, "usage: " PGM " --register|--deactivate|--activate\n");





More information about the Gnupg-commits mailing list