[svn] w32pth - r32 - in trunk: . m4

svn author wk cvs at cvs.gnupg.org
Thu Feb 25 20:47:37 CET 2010


Author: wk
Date: 2010-02-25 20:47:37 +0100 (Thu, 25 Feb 2010)
New Revision: 32

Added:
   trunk/m4/gpg-error.m4
   trunk/utils.h
Modified:
   trunk/ChangeLog
   trunk/Makefile.am
   trunk/NEWS
   trunk/autogen.sh
   trunk/configure.ac
   trunk/ltmain.sh
   trunk/m4/libtool.m4
   trunk/pth.h
   trunk/w32-io.c
   trunk/w32-pth.c
Log:
Ported to Windows CE


Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2009-12-08 21:23:52 UTC (rev 31)
+++ trunk/ChangeLog	2010-02-25 19:47:37 UTC (rev 32)
@@ -1,3 +1,35 @@
+2010-02-25  Werner Koch  <wk at g10code.com>
+
+	* utils.h: New.
+	(set_errno): New.  Always use it to change ERRNO.
+	* w32-io.c (pth_pipe) [W32CE]: Take care of handles being global.
+	(create_pipe): New.  Taken from libassuan.
+	(pth_pipe): Use it.
+
+	* w32-pth.c: Include utils.h.
+	[!HAVE_SIGNAL_H]: Don't include signal.h.
+	(w32_read_registry, getenv) [W32CE]: New.
+	(destroy_timer): New.
+	(do_pth_event_free): Use it instead of a CloseHandle.
+	(w32ce_timer_thread): New.
+	(create_timer) [W32CE]: Add CE implementation.
+	(do_pth_wait) <PTH_EVENT_TIME>: Move timer setting to ...
+	(set_timer): New.  Add code for W32CE.
+	(w32_strerror, wsa_strerror) [W32CE]: Do not use FormatMessage.
+	(create_event) [W32CE]: Don't set to synchronize.
+
+	* Makefile.am (libw32pth_la_LIBADD): Use NETLIBS.
+	* configure.ac [W32CE]: Require gpg-error.
+	(NETLIBS): New.
+	* configure.ac: Test for signal.h.
+
+2010-02-24  Werner Koch  <wk at g10code.com>
+
+	* ltmain.sh (wrappers_required): Don't set for mingw32ce.
+	* ltmain.sh: Updated.
+
+	* autogen.sh: Modernized.
+
 2009-12-08  Marcus Brinkmann  <marcus at g10code.de>
 
 	* libw32pth.def: Add pth_cancel.
@@ -21,11 +53,11 @@
 	(w32pth_la_LDFLAGS): Remove w32pth_res_ldflag usage.
 	(w32pth_la_LIBADD): Add w32pth_res.
 	* depcomp, compile, INSTALL, missing: Update from automake 1.10.
-	
+
 2008-10-17  Marcus Brinkmann  <marcus at g10code.com>
 
 	Released 2.0.2.
-	
+
 	* configure.ac (W32PTH_LT_CURRENT, W32PTH_LT_AGE): Bump.
 	(W32PTH_LT_REVISION): Reset.
 
@@ -50,7 +82,7 @@
 2008-05-27  Werner Koch  <wk at g10code.com>
 
 	* w32-pth.c (_pth_malloc, _pth_calloc, _pth_free): New.  Always
-	use these wrappers to be prepared to change the allocators. 
+	use these wrappers to be prepared to change the allocators.
 
 2008-05-26  Werner Koch  <wk at g10code.com>
 
@@ -60,7 +92,7 @@
 	* w32-pth.c (pth_thread_id): New.
 
 	* libw32pth.def (pth_thread_id): New.
-	
+
 2008-03-25  Marcus Brinkmann  <marcus at g10code.de>
 
 	* debug.h (DEBUG_INFO, DEBUG_CALLS): New macros.
@@ -146,11 +178,11 @@
 
 2007-07-05  Werner Koch  <wk at g10code.com>
 
-	Released 2.0.0 (first release). 
+	Released 2.0.0 (first release).
 
 2007-07-04  Werner Koch  <wk at g10code.com>
 
-	* w32-pth.c: Major rewrite of the event stuff. 
+	* w32-pth.c: Major rewrite of the event stuff.
 
 2007-07-03  Werner Koch  <wk at g10code.com>
 
@@ -189,9 +221,9 @@
 	Package created.
 	* w32-pth.c, w32-pth.h: Taken from GnuPG 2.0.4
 
-	
- Copyright 2007 g10 Code GmbH
 
+ Copyright 2007, 2010 g10 Code GmbH
+
  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.

Modified: trunk/Makefile.am
===================================================================
--- trunk/Makefile.am	2009-12-08 21:23:52 UTC (rev 31)
+++ trunk/Makefile.am	2010-02-25 19:47:37 UTC (rev 32)
@@ -20,7 +20,7 @@
 
 ## Process this file with automake to produce Makefile.in
 
-ACLOCAL_AMFLAGS = 
+ACLOCAL_AMFLAGS = -I m4
 AUTOMAKE_OPTIONS = no-dist-gzip dist-bzip2
 DISTCHECK_CONFIGURE_FLAGS = --host=i586-mingw32msvc 
 
@@ -49,12 +49,15 @@
 uninstall-def-file:
 	-rm $(DESTDIR)$(libdir)/libw32pth.def
 
+# Note that the GPG_ERROR_CFLAGS are only required for W32CE and not
+# defined on plain Windows.
+libw32pth_la_CFLAGS = $(GPG_ERROR_CFLAGS)
 libw32pth_la_LDFLAGS = $(no_undefined) $(export_symbols) \
       -version-info \
       @W32PTH_LT_CURRENT@:@W32PTH_LT_REVISION@:@W32PTH_LT_AGE@
 libw32pth_la_DEPENDENCIES = $(w32pth_res) libw32pth.def
-libw32pth_la_LIBADD = $(w32pth_res) @LTLIBOBJS@ -lws2_32
-libw32pth_la_SOURCES = pth.h debug.h w32-pth.c w32-io.h w32-io.c
+libw32pth_la_LIBADD = $(w32pth_res) @LTLIBOBJS@ $(NETLIBS) $(GPG_ERROR_LIBS)
+libw32pth_la_SOURCES = pth.h debug.h w32-pth.c w32-io.h w32-io.c utils.h
 
 
 install-data-local: install-def-file

Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2009-12-08 21:23:52 UTC (rev 31)
+++ trunk/NEWS	2010-02-25 19:47:37 UTC (rev 32)
@@ -1,3 +1,9 @@
+Noteworthy changes in version 2.0.3
+------------------------------------------------
+
+ * Support WindowsCE.
+
+
 Noteworthy changes in version 2.0.2 (2008-10-17)
 ------------------------------------------------
 

Modified: trunk/autogen.sh
===================================================================
--- trunk/autogen.sh	2009-12-08 21:23:52 UTC (rev 31)
+++ trunk/autogen.sh	2010-02-25 19:47:37 UTC (rev 32)
@@ -35,10 +35,26 @@
   shift
 fi
 
+# Convenience option to use certain configure options for some hosts.
+myhost="" 
+myhostsub=""
+case "$1" in
+    --build-w32)
+        myhost="w32"
+        ;;
+    --build-w32ce)
+        myhost="w32"
+        myhostsub="ce"
+        ;;
+    *)
+     ;;
+esac
 
+
+
 # ***** W32 build script *******
 # Used to cross-compile for Windows.
-if test "$1" = "--build-w32"; then
+if [ "$myhost" = "w32" ]; then
     tmp=`dirname $0`
     tsdir=`cd "$tmp"; pwd`
     shift
@@ -48,11 +64,22 @@
     fi
     build=`$tsdir/config.guess`
 
-    [ -z "$w32root" ] && w32root="$HOME/w32root"
+    case $myhostsub in
+        ce)
+          [ -z "$w32root" ] && w32root="$HOME/w32ce_root"
+          toolprefixes="arm-mingw32ce"
+          extra_options="--with-gpg-error-prefix=${w32root}"
+          ;;
+        *)
+          [ -z "$w32root" ] && w32root="$HOME/w32root"
+          toolprefixes="i586-mingw32msvc i386-mingw32msvc"
+          extra_options=""
+          ;;
+    esac
     echo "Using $w32root as standard install directory" >&2
     
     crossbindir=
-    for host in i586-mingw32msvc i386-mingw32msvc mingw32; do
+    for host in $toolprefixes; do
         if ${host}-gcc --version >/dev/null 2>&1 ; then
             crossbindir=/usr/${host}/bin
             conf_CC="CC=${host}-gcc"
@@ -61,8 +88,10 @@
     done
     if [ -z "$crossbindir" ]; then
         echo "Cross compiler kit not installed" >&2
-        echo "Under Debian GNU/Linux, you may install it using" >&2
-        echo "  apt-get install mingw32 mingw32-runtime mingw32-binutils" >&2 
+        if [ -z "$sub" ]; then 
+          echo "Under Debian GNU/Linux, you may install it using" >&2
+          echo "  apt-get install mingw32 mingw32-runtime mingw32-binutils" >&2 
+        fi
         echo "Stop." >&2
         exit 1
     fi
@@ -76,7 +105,7 @@
     fi
 
     ./configure --enable-maintainer-mode  --prefix=${w32root}  \
-            --host=${host} --build=${build} "$@"
+            --host=${host} --build=${build} ${extra_options} "$@"
 
     exit $?
 fi
@@ -140,8 +169,8 @@
     exit 1
 fi
 
-echo "Running aclocal ${ACLOCAL_FLAGS:+$ACLOCAL_FLAGS }..."
-$ACLOCAL  $ACLOCAL_FLAGS
+echo "Running aclocal -I m4 ${ACLOCAL_FLAGS:+$ACLOCAL_FLAGS }..."
+$ACLOCAL -I m4  $ACLOCAL_FLAGS
 echo "Running autoheader..."
 $AUTOHEADER
 echo "Running automake --gnu ..."
@@ -149,4 +178,6 @@
 echo "Running autoconf${FORCE} ..."
 $AUTOCONF${FORCE}
 
-echo "You may now run \"./autogen.sh --build-w32 && make\"."
+echo "You may now run 
+  ./autogen.sh --build-w32 && make
+"

Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac	2009-12-08 21:23:52 UTC (rev 31)
+++ trunk/configure.ac	2010-02-25 19:47:37 UTC (rev 32)
@@ -26,8 +26,8 @@
 # Remember to change the version number immediately *after* a release.
 # Set my_issvn to "yes" for non-released code.  Remember to run an
 # "svn up" and "autogen.sh" right before creating a distribution.
-m4_define([my_version], [2.0.2])
-m4_define([my_issvn], [no])
+m4_define([my_version], [2.0.3])
+m4_define([my_issvn], [yes])
 
 m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \
           || echo 'Revision: 0')|sed -n '/^Revision:/ s/[^0-9]//gp'|head -1)]))
@@ -46,6 +46,8 @@
 # If the API is changed in an incompatible way: increment the next counter.
 W32PTH_CONFIG_API_VERSION=1
 
+NEED_GPG_ERROR_VERSION=1.8
+
 BUILD_REVISION=svn_revision
 PACKAGE=$PACKAGE_NAME
 VERSION=$PACKAGE_VERSION
@@ -71,10 +73,23 @@
 AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package])
 AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package])
 
+#
+# Initialize libtool
+#
+LT_PREREQ([2.2.6])
+LT_INIT([win32-dll disable-static])
+LT_LANG([Windows Resource])
 
+
+
 # Setup some stuff depending on host/target.
 have_w32_system=no
+have_w32ce_system=no
 case "${host}" in
+    *-mingw32ce*)
+        have_w32_system=yes
+        have_w32ce_system=yes
+        ;;
     *-*-mingw32*)
       have_w32_system=yes
       ;;
@@ -84,9 +99,14 @@
 esac
 if test "$have_w32_system" = yes; then
    AC_DEFINE(HAVE_W32_SYSTEM,1, [Defined if we run on a W32 API based system])
+   if test "$have_w32ce_system" = yes; then
+      AC_DEFINE(HAVE_W32CE_SYSTEM,1,[Defined if we run on WindowsCE])
+   fi
 fi
 AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes)
+AM_CONDITIONAL(HAVE_W32CE_SYSTEM, test "$have_w32ce_system" = yes)
 
+
 # Checks for programs.
 missing_dir=`cd $ac_aux_dir && pwd`
 AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
@@ -106,9 +126,6 @@
 AC_PROG_MAKE_SET
 AC_C_INLINE
 
-LT_PREREQ([2.2.6])
-LT_INIT([win32-dll disable-static])
-LT_LANG([Windows Resource])
 
 if test "$GCC" = yes; then
     CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes"
@@ -135,10 +152,32 @@
 
 fi
 
+#
+# On W32CE we need gpg-error because this provides our errno.h replacement.
+#
+if test "$have_w32ce_system" = yes; then
+  AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION")
+  if test "x$GPG_ERROR_LIBS" = "x"; then
+    AC_MSG_ERROR([libgpg-error is needed for Windows CE.
+                  See ftp://ftp.gnupg.org/gcrypt/libgpg-error/ .])
+  fi
+fi
 
+
+#
+# Set NETLIBS
+#
+if test "$have_w32ce_system" = yes; then
+   NETLIBS="-lws2 $NETLIBS"
+else
+   NETLIBS="-lws2_32 $NETLIBS"
+fi
+AC_SUBST(NETLIBS)
+
+
 # Checks for header files.
 AC_HEADER_STDC
-AC_CHECK_HEADERS([string.h])
+AC_CHECK_HEADERS([string.h signal.h])
 
 # Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST

Modified: trunk/ltmain.sh
===================================================================
--- trunk/ltmain.sh	2009-12-08 21:23:52 UTC (rev 31)
+++ trunk/ltmain.sh	2010-02-25 19:47:37 UTC (rev 32)
@@ -65,7 +65,7 @@
 #       compiler:		$LTCC
 #       compiler flags:		$LTCFLAGS
 #       linker:		$LD (gnu? $with_gnu_ld)
-#       $progname:		(GNU libtool) 2.2.6 Debian-2.2.6a-4
+#       $progname:		(GNU libtool) 2.2.6 Debian-2.2.6a-1ubuntu1
 #       automake:		$automake_version
 #       autoconf:		$autoconf_version
 #
@@ -73,7 +73,7 @@
 
 PROGRAM=ltmain.sh
 PACKAGE=libtool
-VERSION="2.2.6 Debian-2.2.6a-4"
+VERSION="2.2.6 Debian-2.2.6a-1ubuntu1"
 TIMESTAMP=""
 package_revision=1.3012
 
@@ -5347,19 +5347,19 @@
 	    # It is a libtool convenience library, so add in its objects.
 	    convenience="$convenience $ladir/$objdir/$old_library"
 	    old_convenience="$old_convenience $ladir/$objdir/$old_library"
-	    tmp_libs=
-	    for deplib in $dependency_libs; do
-	      deplibs="$deplib $deplibs"
-	      if $opt_duplicate_deps ; then
-		case "$tmp_libs " in
-		*" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
-		esac
-	      fi
-	      tmp_libs="$tmp_libs $deplib"
-	    done
 	  elif test "$linkmode" != prog && test "$linkmode" != lib; then
 	    func_fatal_error "\`$lib' is not a convenience library"
 	  fi
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    deplibs="$deplib $deplibs"
+	    if $opt_duplicate_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done
 	  continue
 	fi # $pass = conv
 
@@ -5896,7 +5896,6 @@
 	  if test "$link_all_deplibs" != no; then
 	    # Add the search paths of all dependency libraries
 	    for deplib in $dependency_libs; do
-	      path=
 	      case $deplib in
 	      -L*) path="$deplib" ;;
 	      *.la)
@@ -7681,15 +7680,15 @@
 
       wrappers_required=yes
       case $host in
+      *cegcc | *mingw32ce*)
+        # Disable wrappers for cegcc/mingw32ce, we are cross compiling anyway.
+        wrappers_required=no
+        ;;
       *cygwin* | *mingw* )
         if test "$build_libtool_libs" != yes; then
           wrappers_required=no
         fi
         ;;
-      *cegcc)
-        # Disable wrappers for cegcc, we are cross compiling anyway.
-        wrappers_required=no
-        ;;
       *)
         if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
           wrappers_required=no

Added: trunk/m4/gpg-error.m4
===================================================================
--- trunk/m4/gpg-error.m4	                        (rev 0)
+++ trunk/m4/gpg-error.m4	2010-02-25 19:47:37 UTC (rev 32)
@@ -0,0 +1,65 @@
+# gpg-error.m4 - autoconf macro to detect libgpg-error.
+# Copyright (C) 2002, 2003, 2004 g10 Code GmbH
+#
+# 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.
+
+dnl AM_PATH_GPG_ERROR([MINIMUM-VERSION,
+dnl                   [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
+dnl Test for libgpg-error and define GPG_ERROR_CFLAGS and GPG_ERROR_LIBS
+dnl
+AC_DEFUN([AM_PATH_GPG_ERROR],
+[ AC_ARG_WITH(gpg-error-prefix,
+            AC_HELP_STRING([--with-gpg-error-prefix=PFX],
+                           [prefix where GPG Error is installed (optional)]),
+     gpg_error_config_prefix="$withval", gpg_error_config_prefix="")
+  if test x$gpg_error_config_prefix != x ; then
+     if test x${GPG_ERROR_CONFIG+set} != xset ; then
+        GPG_ERROR_CONFIG=$gpg_error_config_prefix/bin/gpg-error-config
+     fi
+  fi
+
+  AC_PATH_PROG(GPG_ERROR_CONFIG, gpg-error-config, no)
+  min_gpg_error_version=ifelse([$1], ,0.0,$1)
+  AC_MSG_CHECKING(for GPG Error - version >= $min_gpg_error_version)
+  ok=no
+  if test "$GPG_ERROR_CONFIG" != "no" ; then
+    req_major=`echo $min_gpg_error_version | \
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
+    req_minor=`echo $min_gpg_error_version | \
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
+    gpg_error_config_version=`$GPG_ERROR_CONFIG $gpg_error_config_args --version`
+    major=`echo $gpg_error_config_version | \
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
+    minor=`echo $gpg_error_config_version | \
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
+    if test "$major" -gt "$req_major"; then
+        ok=yes
+    else 
+        if test "$major" -eq "$req_major"; then
+            if test "$minor" -ge "$req_minor"; then
+               ok=yes
+            fi
+        fi
+    fi
+  fi
+  if test $ok = yes; then
+    GPG_ERROR_CFLAGS=`$GPG_ERROR_CONFIG $gpg_error_config_args --cflags`
+    GPG_ERROR_LIBS=`$GPG_ERROR_CONFIG $gpg_error_config_args --libs`
+    AC_MSG_RESULT([yes ($gpg_error_config_version)])
+    ifelse([$2], , :, [$2])
+  else
+    GPG_ERROR_CFLAGS=""
+    GPG_ERROR_LIBS=""
+    AC_MSG_RESULT(no)
+    ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(GPG_ERROR_CFLAGS)
+  AC_SUBST(GPG_ERROR_LIBS)
+])
+

Modified: trunk/m4/libtool.m4
===================================================================
--- trunk/m4/libtool.m4	2009-12-08 21:23:52 UTC (rev 31)
+++ trunk/m4/libtool.m4	2010-02-25 19:47:37 UTC (rev 32)
@@ -3007,6 +3007,17 @@
   lt_cv_file_magic_cmd='func_win32_libid'
   ;;
 
+
+mingw32ce*)
+  # Windows CE is often used with non-x86 platforms and thus the below
+  # mingw and cegcc checks don't work.  It would be possible to
+  # support other architectures in these checks.  However x86 is pretty
+  # hard coded and changing this would require quite some tests on all
+  # the platforms to be sure not to break something.  Thus we take the
+  # easy way out and don't check at all.
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
 mingw* | pw32*)
   # Base MSYS/MinGW do not provide the 'file' command needed by
   # func_win32_libid shell function, so use a weaker test based on 'objdump',
@@ -4261,9 +4272,6 @@
   openbsd*)
     with_gnu_ld=no
     ;;
-  linux* | k*bsd*-gnu)
-    _LT_TAGVAR(link_all_deplibs, $1)=no
-    ;;
   esac
 
   _LT_TAGVAR(ld_shlibs, $1)=yes

Modified: trunk/pth.h
===================================================================
--- trunk/pth.h	2009-12-08 21:23:52 UTC (rev 31)
+++ trunk/pth.h	2010-02-25 19:47:37 UTC (rev 32)
@@ -1,6 +1,6 @@
 /* pth.h - GNU Pth emulation for W32 (MS Windows).
  * Copyright (c) 1999-2003 Ralf S. Engelschall <rse at engelschall.com>
- * Copyright (C) 2004, 2006, 2007, 2008 g10 Code GmbH
+ * Copyright (C) 2004, 2006, 2007, 2008, 2010 g10 Code GmbH
  *
  * This file is part of W32PTH.
  *
@@ -15,9 +15,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * ------------------------------------------------------------------
  * This code is based on Ralf Engelschall's GNU Pth, a non-preemptive
@@ -281,7 +279,7 @@
 
 
 /* Special W32 function to cope with the problem that pth_self returns
-   just a pseudo handle which is not very usefule for debugging.  */
+   just a pseudo handle which is not very useful for debugging.  */
 unsigned long pth_thread_id (void);
 #define PTH_HAVE_PTH_THREAD_ID 1
 

Added: trunk/utils.h
===================================================================
--- trunk/utils.h	                        (rev 0)
+++ trunk/utils.h	2010-02-25 19:47:37 UTC (rev 32)
@@ -0,0 +1,48 @@
+/* utils.h - Internal definitions.
+ * Copyright (C) 2010 g10 Code GmbH
+ *
+ * This file is part of W32PTH.
+ *
+ * W32PTH is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * W32PTH is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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/>.
+ */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#ifdef HAVE_W32CE_SYSTEM
+# include <gpg-error.h>  /* Required for gpg_err_set_errno().  */
+#endif
+
+
+static inline void
+set_errno (int value)
+{
+#ifdef HAVE_W32CE_SYSTEM
+  gpg_err_set_errno (value);
+#else
+  errno = value;
+#endif
+}
+
+#define DIM(v)		     (sizeof(v)/sizeof((v)[0]))
+#define DIMof(type,member)   DIM(((type *)0)->member)
+
+
+/*-- w32-pth.c --*/
+void *_pth_malloc (size_t n);
+void *_pth_calloc (size_t n, size_t m);
+void _pth_free (void *p);
+
+
+#endif /*UTILS_H*/

Modified: trunk/w32-io.c
===================================================================
--- trunk/w32-io.c	2009-12-08 21:23:52 UTC (rev 31)
+++ trunk/w32-io.c	2010-02-25 19:47:37 UTC (rev 32)
@@ -29,9 +29,23 @@
 
 #include <assert.h>
 
+#ifdef HAVE_W32CE_SYSTEM
+# include <winioctl.h>
+# include <devload.h>
+# 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*/
+
+
+
+#include "utils.h"
 #include "debug.h"
 #include "w32-io.h"
 
+
+
 
 struct critsect_s
 {
@@ -178,7 +192,7 @@
   UNLOCK (debug_lock);
   fflush (dbgfp);
 
-  errno = saved_errno;
+  set_errno (saved_errno);
 }
 
 
@@ -281,7 +295,7 @@
       TRACE1 (DEBUG_SYSIO, "pth:set_synchronize", hd,
 	      "DuplicateHandle failed: ec=%d", (int) GetLastError ());
       /* FIXME: Should translate the error code.  */
-      errno = EIO;
+      set_errno (EIO);
       return INVALID_HANDLE_VALUE;
     }
 
@@ -544,7 +558,7 @@
   ctx = find_reader (fd, 0);
   if (!ctx)
     {
-      errno = EBADF;
+      set_errno (EBADF);
       return TRACE_SYSRES (-1);
     }
   if (ctx->eof_shortcut)
@@ -572,7 +586,7 @@
 	  TRACE_LOG ("EOF but ctx->eof flag not set");
 	  return 0;
 	}
-      errno = ctx->error_code;
+      set_errno (ctx->error_code);
       return TRACE_SYSRES (-1);
     }
   
@@ -590,7 +604,7 @@
 	  TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ());
 	  UNLOCK (ctx->mutex);
 	  /* FIXME: Should translate the error code.  */
-	  errno = EIO;
+	  set_errno (EIO);
 	  return TRACE_SYSRES (-1);
 	}
     }
@@ -599,7 +613,7 @@
       TRACE_LOG1 ("SetEvent failed: ec=%d", (int) GetLastError ());
       UNLOCK (ctx->mutex);
       /* FIXME: Should translate the error code.  */
-      errno = EIO;
+      set_errno (EIO);
       return TRACE_SYSRES (-1);
     }
   UNLOCK (ctx->mutex);
@@ -865,7 +879,7 @@
 	  TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ());
 	  UNLOCK (ctx->mutex);
 	  /* FIXME: Should translate the error code.  */
-	  errno = EIO;
+	  set_errno (EIO);
 	  return TRACE_SYSRES (-1);
 	}
       UNLOCK (ctx->mutex);
@@ -879,9 +893,9 @@
     {
       UNLOCK (ctx->mutex);
       if (ctx->error_code == ERROR_NO_DATA)
-        errno = EPIPE;
+        set_errno (EPIPE);
       else
-        errno = EIO;
+        set_errno (EIO);
       return TRACE_SYSRES (-1);
     }
 
@@ -901,7 +915,7 @@
       TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ());
       UNLOCK (ctx->mutex);
       /* FIXME: Should translate the error code.  */
-      errno = EIO;
+      set_errno (EIO);
       return TRACE_SYSRES (-1);
     }
   if (!SetEvent (ctx->have_data))
@@ -909,7 +923,7 @@
       TRACE_LOG1 ("SetEvent failed: ec=%d", (int) GetLastError ());
       UNLOCK (ctx->mutex);
       /* FIXME: Should translate the error code.  */
-      errno = EIO;
+      set_errno (EIO);
       return TRACE_SYSRES (-1);
     }
   UNLOCK (ctx->mutex);
@@ -918,6 +932,76 @@
 }
 
 
+/* 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.  */
+static DWORD
+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};
+  TRACE_BEG (DEBUG_SYSIO, "pth:create_pipe", read_hd);
+
+  *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))
+    TRACE_LOG1 ("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))
+    TRACE_LOG1 ("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))
+    {
+      TRACE_LOG1 ("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]);
+      TRACE_SUC ();
+      return 0;
+    }
+  else
+    {
+      *read_hd = hd[0];
+      *write_hd = hd[1];
+      TRACE_SUC ();
+      return 1;
+    }
+#else /*!HAVE_W32CE_SYSTEM*/
+  return CreatePipe (read_hd, write_hd, sec_attr, size);
+#endif /*!HAVE_W32CE_SYSTEM*/
+}
+
 int
 pth_pipe (int filedes[2], int inherit_idx)
 {
@@ -932,17 +1016,20 @@
   sec_attr.nLength = sizeof (sec_attr);
   sec_attr.bInheritHandle = FALSE;
   
-  if (!CreatePipe (&rh, &wh, &sec_attr, PIPEBUF_SIZE))
+  if (!create_pipe (&rh, &wh, &sec_attr, PIPEBUF_SIZE))
     {
       TRACE_LOG1 ("CreatePipe failed: ec=%d", (int) GetLastError ());
       /* FIXME: Should translate the error code.  */
-      errno = EIO;
+      set_errno (EIO);
       return TRACE_SYSRES (-1);
     }
 
   /* Make one end inheritable.  */
   if (inherit_idx == 0)
     {
+      /* Under Windows CE < 6 handles are global without a concept of
+         inheritable handles.  */
+#ifndef HAVE_W32CE_SYSTEM
       HANDLE hd;
       if (!DuplicateHandle (GetCurrentProcess(), rh,
 			    GetCurrentProcess(), &hd, 0,
@@ -953,16 +1040,18 @@
 	  CloseHandle (rh);
 	  CloseHandle (wh);
 	  /* FIXME: Should translate the error code.  */
-	  errno = EIO;
+	  set_errno (EIO);
 	  return TRACE_SYSRES (-1);
         }
       CloseHandle (rh);
       rh = hd;
+#endif /*!HAVE_W32CE_SYSTEM*/
       /* Pre-create the writer thread.  */
       find_reader (handle_to_fd (wh), 1);
     }
   else if (inherit_idx == 1)
     {
+#ifndef HAVE_W32CE_SYSTEM
       HANDLE hd;
       if (!DuplicateHandle( GetCurrentProcess(), wh,
 			    GetCurrentProcess(), &hd, 0,
@@ -973,11 +1062,12 @@
 	  CloseHandle (rh);
 	  CloseHandle (wh);
 	  /* FIXME: Should translate the error code.  */
-	  errno = EIO;
+	  set_errno (EIO);
 	  return TRACE_SYSRES (-1);
         }
       CloseHandle (wh);
       wh = hd;
+#endif /*!HAVE_W32CE_SYSTEM*/
       /* Pre-create the reader thread.  */
       find_reader (handle_to_fd (rh), 1);
     }
@@ -995,7 +1085,7 @@
 
   if (fd == -1)
     {
-      errno = EBADF;
+      set_errno (EBADF);
       return TRACE_SYSRES (-1);
     }
 
@@ -1006,7 +1096,7 @@
     { 
       TRACE_LOG1 ("CloseHandle failed: ec=%d", (int) GetLastError ());
       /* FIXME: Should translate the error code.  */
-      errno = EIO;
+      set_errno (EIO);
       return TRACE_SYSRES (-1);
     }
 

Modified: trunk/w32-pth.c
===================================================================
--- trunk/w32-pth.c	2009-12-08 21:23:52 UTC (rev 31)
+++ trunk/w32-pth.c	2010-02-25 19:47:37 UTC (rev 32)
@@ -1,6 +1,6 @@
 /* w32-pth.c - GNU Pth emulation for W32 (MS Windows).
  * Copyright (c) 1999-2003 Ralf S. Engelschall <rse at engelschall.com>
- * Copyright (C) 2004, 2006, 2007, 2008 g10 Code GmbH
+ * Copyright (C) 2004, 2006, 2007, 2008, 2010 g10 Code GmbH
  *
  * This file is part of W32PTH.
  *
@@ -15,9 +15,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * ------------------------------------------------------------------
  * This code is based on Ralf Engelschall's GNU Pth, a non-preemptive
@@ -32,9 +30,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <io.h>
-#include <signal.h>
+#ifdef HAVE_SIGNAL_H
+# include <signal.h>
+#endif
 #include <errno.h>
 
+#include "utils.h"
 #include "debug.h"
 #include "w32-io.h"
 
@@ -86,6 +87,22 @@
 };
 
 
+#ifdef HAVE_W32CE_SYSTEM
+/* W32CE timer implementation.  */
+static HANDLE w32ce_timer_ev;           /* Event to kick the timer thread.  */
+static CRITICAL_SECTION w32ce_timer_cs; /* Protect the objects below.  */
+static int w32ce_timer_thread_lauchend; /* True if the timer thread has
+                                           been launched.  */
+static struct               /* The timer array.  */
+{
+  HANDLE event;             /* Event to be signaled for this timer or
+                               NULL for an unused slot.  */
+  int active;               /* Timer is active.  */
+  unsigned long remaining;  /* Remaining time in milliseconds. */
+} w32ce_timer[32];
+#endif /*HAVE_W32CE_SYSTEM*/
+
+
 /* Pth events are store in a double linked event ring.  */
 struct pth_event_s
 {
@@ -187,23 +204,111 @@
 }
 
 
+/* Return a string from the Win32 Registry or NULL in case of error.
+   The returned string is allocated using a plain malloc and thus the
+   caller needs to call the standard free().  The string is looked up
+   under HKEY_LOCAL_MACHINE.  */
+#ifdef HAVE_W32CE_SYSTEM
 static char *
+w32_read_registry (const wchar_t *dir, const wchar_t *name)
+{
+  HKEY handle;
+  DWORD n, nbytes;
+  wchar_t *buffer = NULL;
+  char *result = NULL;
+  
+  if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &handle))
+    return NULL; /* No need for a RegClose, so return immediately. */
+
+  nbytes = 1;
+  if (RegQueryValueEx (handle, name, 0, NULL, NULL, &nbytes))
+    goto leave;
+  buffer = malloc ((n=nbytes+2));
+  if (!buffer)
+    goto leave;
+  if (RegQueryValueEx (handle, name, 0, NULL, (PBYTE)buffer, &n))
+    {
+      free (buffer);
+      buffer = NULL;
+      goto leave;
+    }
+  
+  n = WideCharToMultiByte (CP_UTF8, 0, buffer, nbytes, NULL, 0, NULL, NULL);
+  if (n < 0 || (n+1) <= 0)
+    goto leave;
+  result = malloc (n+1);
+  if (!result)
+    goto leave;
+  n = WideCharToMultiByte (CP_UTF8, 0, buffer, nbytes, result, n, NULL, NULL);
+  if (n < 0)
+    {
+      free (result);
+      result = NULL;
+      goto leave;
+    }
+  result[n] = 0;
+
+ leave:
+  free (buffer);
+  RegCloseKey (handle);
+  return result;
+}
+#endif /*HAVE_W32CE_SYSTEM*/
+
+#ifdef HAVE_W32CE_SYSTEM
+/* Replacement for getenv which takes care of the our use of getenv.
+   The code is not thread safe but we expect it to work in all cases
+   because it is called for the first time early enough.  */
+static char *
+getenv (const char *name)
+{
+  static int initialized;
+  static char *val_debug;
+
+  if (!initialized)
+    {
+      val_debug = w32_read_registry (L"\\Software\\GNU\\w32pth",
+                                     L"debug");
+      initialized = 1;
+    }
+
+
+  if (!strcmp (name, "PTH_DEBUG"))
+    return val_debug;
+  else
+    return NULL;
+}
+#endif /*HAVE_W32CE_SYSTEM*/
+
+
+
+static char *
 w32_strerror (char *strerr, size_t strerrsize)
 {
+#ifdef HAVE_W32CE_SYSTEM
+  /* There is only a wchar_t FormatMessage.  It does not make much
+     sense to play the conversion game; we print only the code.  */
+  snprintf (strerr, strerrsize, "ec=%d", (int)GetLastError ());
+#else
   if (strerrsize > 1)
     FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, (int)GetLastError (),
                    MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
                    strerr, strerrsize, NULL);
+#endif
   return strerr;
 }
 
 static char *
 wsa_strerror (char *strerr, size_t strerrsize)
 {
+#ifdef HAVE_W32CE_SYSTEM
+  snprintf (strerr, strerrsize, "ec=%d", (int)WSAGetLastError ());
+#else
   if (strerrsize > 1)
     FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, (int)WSAGetLastError (),
                    MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
                    strerr, strerrsize, NULL);
+#endif
   return strerr;
 }
 
@@ -331,6 +436,9 @@
                  w32_strerror (strerr, sizeof strerr));
       return NULL;
     }
+#ifdef HAVE_W32CE_SYSTEM
+  h2 = h;
+#else
   if (!DuplicateHandle (GetCurrentProcess(), h,
                         GetCurrentProcess(), &h2,
                         EVENT_MODIFY_STATE|SYNCHRONIZE, FALSE, 0 ) ) 
@@ -344,6 +452,7 @@
       return NULL;
     }
   CloseHandle (h);
+#endif
   if (DBG_INFO)
     {
       fprintf (dbgfp, "%s: CreateEvent(%p) succeeded\n",
@@ -352,7 +461,8 @@
   return h2;
 }
 
-#if 0 /* Not yet used.  */
+
+#ifdef TEST
 static void
 set_event (HANDLE h)
 {
@@ -393,29 +503,140 @@
 }
 
 
+#ifdef HAVE_W32CE_SYSTEM
+/* WindowsCE does not provide CreateWaitableTimer et al.  Thus we have
+   to roll our own.  The timer is not fully correct because we use
+   GetTickCount and don't adjust for the time it takes to call it.  */
+static DWORD CALLBACK 
+w32ce_timer_thread (void *arg)
+{
+  int idx;
+  DWORD timeout, elapsed, lasttick;
 
+  (void)arg;
+
+  lasttick = GetTickCount ();
+  for (;;)
+    {
+      elapsed = lasttick;  /* Get start time.  */
+      timeout = 0;
+      EnterCriticalSection (&w32ce_timer_cs);
+      for (idx=0; idx < DIM (w32ce_timer); idx++)
+        {
+          if (w32ce_timer[idx].event && w32ce_timer[idx].active
+              && w32ce_timer[idx].remaining > timeout)
+            timeout = w32ce_timer[idx].remaining;
+        }
+      LeaveCriticalSection (&w32ce_timer_cs);
+      if (timeout > 0x7fffffff)
+        timeout = 0x7fffffff;
+      switch (WaitForSingleObject (w32ce_timer_ev, (DWORD)timeout))
+        {
+        case WAIT_OBJECT_0:
+          break;
+        case WAIT_TIMEOUT:
+          break;
+        case WAIT_FAILED:
+          if (DBG_ERROR)
+            fprintf (dbgfp, 
+                     "%s:w32ce_timer_thread: WFSO failed: rc=%d\n",
+                     log_get_prefix (NULL), (int)GetLastError ());
+          /* This is likely to happen if a handle has been closed
+             while we are waiting for it.  */
+          break;
+        }
+      EnterCriticalSection (&w32ce_timer_cs);
+      lasttick = GetTickCount ();
+      elapsed = lasttick - elapsed;
+      for (idx=0; idx < DIM (w32ce_timer); idx++)
+        {
+          if (w32ce_timer[idx].event && w32ce_timer[idx].active)
+            {
+              if (w32ce_timer[idx].remaining > elapsed)
+                w32ce_timer[idx].remaining -= elapsed;
+              else
+                {
+                  w32ce_timer[idx].remaining = 0;
+                  w32ce_timer[idx].active = 0;
+                  if (!SetEvent (w32ce_timer[idx].event))
+                    {
+                      if (DBG_ERROR)
+                        fprintf (dbgfp, "%s:w32ce_timer_thread: SetEvent(%p) "
+                                 "failed: rc=%d\n",
+                                 log_get_prefix (NULL), (int)GetLastError ());
+                    }
+                }
+            }
+        }
+      LeaveCriticalSection (&w32ce_timer_cs);
+    }
+  
+  return 0; /*NOTREACHED*/
+}
+#endif /*HAVE_W32CE_SYSTEM*/
+
+
 /* Create a timer event. */
 static HANDLE
 create_timer (void)
 {
-  SECURITY_ATTRIBUTES sa;
   HANDLE h;
-  char strerr[256];
 
+#ifdef HAVE_W32CE_SYSTEM
+  int idx;
+
+  EnterCriticalSection (&w32ce_timer_cs);
+  if (!w32ce_timer_thread_lauchend)
+    {
+      h = CreateThread (NULL, 0, w32ce_timer_thread, NULL, 0, NULL);
+      if (!h)
+        {
+          if (DBG_ERROR)
+            fprintf (dbgfp, "%s:create_timer: CreateThread failed: rc=%d\n",
+                     log_get_prefix (NULL), (int)GetLastError ());
+          goto leave;
+        }
+      CloseHandle (h);
+      w32ce_timer_thread_lauchend = 1;
+    }
+  h = NULL;
+  for (idx = 0; idx < DIM (w32ce_timer); idx++)
+    if (!w32ce_timer[idx].event)
+      break;
+  if (idx == DIM (w32ce_timer))
+    {
+      SetLastError (ERROR_TOO_MANY_OPEN_FILES);
+      goto leave;
+    }
+  /* We create a manual reset event.  */
+  w32ce_timer[idx].event = CreateEvent (NULL, TRUE, FALSE, NULL);
+  if (!w32ce_timer[idx].event)
+    goto leave;
+  w32ce_timer[idx].active = 0;
+  h = w32ce_timer[idx].event;
+
+leave:
+  LeaveCriticalSection (&w32ce_timer_cs);
+
+#else /* Plain Windows.  */
+
+  SECURITY_ATTRIBUTES sa;
+
   memset (&sa, 0, sizeof sa);
   sa.bInheritHandle = TRUE;
   sa.lpSecurityDescriptor = NULL;
   sa.nLength = sizeof sa;
   h = CreateWaitableTimer (&sa, TRUE, NULL);
+
+#endif /* Plain Windows.  */
+
   if (!h)
     {
       if (DBG_ERROR)
-        fprintf (dbgfp, "%s: CreateWaitableTimer failed: %s\n",
-                 log_get_prefix (NULL), 
-                 w32_strerror (strerr, sizeof strerr));
-      return NULL;
+        fprintf (dbgfp, "%s: CreateWaitableTimer failed: rc=%d\n",
+                 log_get_prefix (NULL), (int)GetLastError ());
     }
-  if (DBG_INFO)
+  else if (DBG_INFO)
     {
       fprintf (dbgfp, "%s: CreateWaitableTimer(%p) succeeded\n",
                log_get_prefix (NULL), h);
@@ -423,7 +644,84 @@
   return h;
 }
 
+static int
+set_timer (HANDLE hd, DWORD milliseconds)
+{
+#ifdef HAVE_W32CE_SYSTEM
+  int idx;
+  int result = -1;
 
+  EnterCriticalSection (&w32ce_timer_cs);
+  for (idx = 0; idx < DIM (w32ce_timer); idx++)
+    if (hd && w32ce_timer[idx].event == hd)
+      {
+        w32ce_timer[idx].remaining = milliseconds;
+        if (!ResetEvent (w32ce_timer[idx].event))
+          {
+            if (DBG_ERROR)
+              fprintf (dbgfp, "%s:set_timer: ResetEvent(%p) failed: rc=%d\n",
+                       log_get_prefix (NULL), (int)GetLastError ());
+          }
+        else if (!SetEvent (w32ce_timer_ev))
+          {
+            if (DBG_ERROR)
+              fprintf (dbgfp, "%s:set_timer: SetEvent(%p) failed: rc=%d\n",
+                       log_get_prefix (NULL), (int)GetLastError ());
+          }
+        else
+          {
+            w32ce_timer[idx].active = 1;
+            result = 0;
+          }
+        break;
+      }
+  if (idx == DIM (w32ce_timer))
+    SetLastError (ERROR_INVALID_HANDLE);
+  LeaveCriticalSection (&w32ce_timer_cs);
+  return result;
+#else /* Plain Windows.  */
+  LARGE_INTEGER ll;
+  char strerr[256];
+  
+  ll.QuadPart = - (milliseconds * 10000);
+  if (!SetWaitableTimer (hd, &ll, 0, NULL, NULL, FALSE))
+    {
+      if (DBG_ERROR)
+        fprintf (dbgfp,"%s: %s: SetWaitableTimer failed: %s\n",
+                 log_get_prefix (NULL), __func__,
+                 w32_strerror (strerr, sizeof strerr));
+      return -1;
+    }
+  return 0;
+#endif /* Plain Windows.  */
+}
+
+static void
+destroy_timer (HANDLE h)
+{
+#ifdef HAVE_W32CE_SYSTEM
+  int idx;
+
+  EnterCriticalSection (&w32ce_timer_cs);
+  for (idx = 0; idx < DIM (w32ce_timer); idx++)
+    if (w32ce_timer[idx].event == h)
+      {
+        CloseHandle (w32ce_timer[idx].event);
+        w32ce_timer[idx].event = NULL;
+        break;
+      }
+  LeaveCriticalSection (&w32ce_timer_cs);
+#else /* Plain Windows.  */
+  CloseHandle (h);
+#endif /* Plain Windows.  */
+}
+
+
+
+
+
+
+
 int
 pth_init (void)
 {
@@ -473,7 +771,15 @@
   pth_signo_ev = create_event ();
   if (!pth_signo_ev)
     return FALSE;
-  
+
+#ifdef HAVE_W32CE_SYSTEM
+  InitializeCriticalSection (&w32ce_timer_cs);
+  w32ce_timer_ev = CreateEvent (NULL, FALSE, FALSE, NULL);
+  if (!w32ce_timer_ev)
+    return FALSE;
+#endif /*HAVE_W32CE_SYSTEM*/  
+
+
   pth_initialized = 1;
   thread_counter = 1;
   EnterCriticalSection (&pth_shd);
@@ -491,7 +797,12 @@
       pth_signo_ev = NULL;
     }
   if (pth_initialized)
-    DeleteCriticalSection (&pth_shd);
+    {
+#ifdef HAVE_W32CE_SYSTEM
+      DeleteCriticalSection (&w32ce_timer_cs);
+#endif /*HAVE_W32CE_SYSTEM*/  
+      DeleteCriticalSection (&pth_shd);
+    }
   WSACleanup ();
   pth_initialized = 0;
   return TRUE;
@@ -597,13 +908,13 @@
 			 log_get_prefix (NULL), fd,
 			 w32_strerror (strerr, sizeof strerr));
 	      n = -1;
-	      errno = map_w32_to_errno (GetLastError ());
+	      set_errno (map_w32_to_errno (GetLastError ()));
 	    }
 	  else
 	    n = (int) nread;
 	}
       else if (n == -1)
-	errno = map_wsa_to_errno (WSAGetLastError ());
+	set_errno (map_wsa_to_errno (WSAGetLastError ()));
     }
 
   return n;
@@ -643,7 +954,7 @@
 #ifdef NO_PTH_MODE_STATIC
 	  do_pth_event_free (ev, PTH_FREE_THIS);
 #endif
-	  errno = EINTR;
+	  set_errno (EINTR);
 	  leave_pth (__FUNCTION__);
 	  return -1;
 	}
@@ -698,7 +1009,7 @@
 	  if (!WriteFile ((HANDLE)fd, buffer, size, &nwrite, NULL))
 	    {
 	      n = -1;
-	      errno = map_w32_to_errno (GetLastError ());
+	      set_errno (map_w32_to_errno (GetLastError ()));
 	      if (DBG_ERROR)
 		fprintf (dbgfp, "%s: pth_write(%d) failed in write: %s\n",
 			 log_get_prefix (NULL), fd,
@@ -708,7 +1019,7 @@
 	    n = (int) nwrite;
 	}
       else if (n == -1)
-	errno = map_wsa_to_errno (WSAGetLastError ());
+	set_errno (map_wsa_to_errno (WSAGetLastError ()));
     }
 
   return n;
@@ -746,9 +1057,9 @@
       if (pth_event_status(ev) != PTH_STATUS_OCCURRED)
 	{
 #ifdef NO_PTH_MODE_STATIC
-  do_pth_event_free (ev, PTH_FREE_THIS);
+          do_pth_event_free (ev, PTH_FREE_THIS);
 #endif
-	  errno = EINTR;
+          set_errno (EINTR);
 	  leave_pth (__FUNCTION__);
 	  return -1;
 	}
@@ -870,7 +1181,7 @@
   if (ev_extra && !selected)
     {
       rc = -1;
-      errno = EINTR;
+      set_errno (EINTR);
     }
 
  leave:
@@ -1744,7 +2055,9 @@
       do
         {
           pth_event_t next = cur->next;
-          if (cur->u_type != PTH_EVENT_HANDLE)
+          if (cur->u_type == PTH_EVENT_TIME)
+            destroy_timer (cur->hd);
+          else if (cur->u_type != PTH_EVENT_HANDLE)
             CloseHandle (cur->hd);
           cur->hd = NULL;
           _pth_free (cur);
@@ -1756,7 +2069,9 @@
     {
       ev->prev->next = ev->next;
       ev->next->prev = ev->prev;
-      if (ev->u_type != PTH_EVENT_HANDLE)
+      if (ev->u_type == PTH_EVENT_TIME)
+        destroy_timer (ev->hd);
+      else if (ev->u_type != PTH_EVENT_HANDLE)
         CloseHandle (ev->hd);
       ev->hd = NULL;	    
       _pth_free (ev);
@@ -1946,22 +2261,11 @@
           
         case PTH_EVENT_TIME:
           TRACE_LOG ("adding timer event");
-          {
-            LARGE_INTEGER ll;
-
-            ll.QuadPart = - (r->u.tv.tv_sec * 10000000ll
-                             + r->u.tv.tv_usec * 10); 
-            if (!SetWaitableTimer (r->hd, &ll, 0, NULL, NULL, FALSE))
-              {
-                if (DBG_ERROR)
-                  fprintf (dbgfp,"%s: %s: SetWaitableTimer failed: %s\n",
-                           log_get_prefix (NULL), __func__,
-                           w32_strerror (strerr, sizeof strerr));
-                return TRACE_SYSRES (-1);
-              }
-            evarray[pos] = r;  
-            waitbuf[pos++] = r->hd;
-          }
+          if (set_timer (r->hd, (r->u.tv.tv_sec * 1000
+                                 + (r->u.tv.tv_usec+500) / 1000 )))
+            return TRACE_SYSRES (-1);
+          evarray[pos] = r;  
+          waitbuf[pos++] = r->hd;
           break;
 
         case PTH_EVENT_SELECT:
@@ -2253,7 +2557,8 @@
 #ifdef TEST
 #include <stdio.h>
 
-void * thread (void * c)
+void *
+thread (void * c)
 {
 
   Sleep (2000);
@@ -2264,7 +2569,8 @@
 }
 
 
-int main_1 (int argc, char ** argv)
+int
+main_1 (int argc, char ** argv)
 {
   pth_attr_t t;
   pth_t hd;
@@ -2287,6 +2593,7 @@
 }
 
 
+#ifndef HAVE_W32CE_SYSTEM
 static pth_event_t 
 setup_signals (struct sigset_s *sigs, int *signo)
 {
@@ -2348,17 +2655,12 @@
   pth_kill ();
   return 0;
 }
+#endif
 
 int
 main (int argc, char ** argv)
 {
-  pth_event_t ev;
-  pth_key_t ev_key;
-
   pth_init ();
-  /*ev = pth_event (PTH_EVENT_TIME, &ev_key, pth_timeout (5, 0));
-    pth_wait (ev);
-    pth_event_free (ev, PTH_FREE_ALL);*/
   pth_sleep (5);
   pth_kill ();
   return 0;




More information about the Gnupg-commits mailing list