2010-05-12 Marcus Brinkmann <marcus@g10code.de>
authorMarcus Brinkmann <mb@g10code.com>
Wed, 12 May 2010 17:21:36 +0000 (17:21 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Wed, 12 May 2010 17:21:36 +0000 (17:21 +0000)
* Makefile.am (system_components): Remove custom cppflags from
RCCOMPILE (because gpg-error adds -idirafter that makes RC bail.
[HAVE_W32CE_SYSTEM]: Add w32-ce.h and w32-ce.c, clear
libexec_PROGRAMS.
* w32-ce.h, w32-ce.c: New files.

src/ChangeLog
src/Makefile.am
src/w32-ce.c [new file with mode: 0644]
src/w32-ce.h [new file with mode: 0644]

index 361e697..a832b0f 100644 (file)
@@ -1,5 +1,11 @@
 2010-05-12  Marcus Brinkmann  <marcus@g10code.de>
 
+       * Makefile.am (system_components): Remove custom cppflags from
+       RCCOMPILE (because gpg-error adds -idirafter that makes RC bail.
+       [HAVE_W32CE_SYSTEM]: Add w32-ce.h and w32-ce.c, clear
+       libexec_PROGRAMS.
+       * w32-ce.h, w32-ce.c: New files.
+
        * priv-io.h: Include <sys/types.h>
        * util.h: Likewise.
 
index 1ecb761..e557c7b 100644 (file)
@@ -68,6 +68,10 @@ system_components = ath.h posix-util.c posix-sema.c posix-io.c
 system_components_not_extra =
 endif
 
+if HAVE_W32CE_SYSTEM
+system_components += w32-ce.h w32-ce.c
+endif
+
 if HAVE_GPGSM
 gpgsm_components = engine-gpgsm.c
 else
@@ -155,14 +159,17 @@ AM_CPPFLAGS = @GPG_ERROR_CFLAGS@ @PTH_CPPFLAGS@ \
 AM_CFLAGS = @LIBASSUAN_CFLAGS@ @PTH_CFLAGS@ @GLIB_CFLAGS@ @QT4_CORE_CFLAGS@
 
 if HAVE_W32_SYSTEM
-
 # Windows provides us with an endless stream of Tough Love.  To spawn
 # processes with a controlled set of inherited handles, we need a
 # wrapper process.
+# Except on Windows CE.  There nothing is inheritable anyway.
+if HAVE_W32CE_SYSTEM
+libexec_PROGRAMS =
+else
 libexec_PROGRAMS = gpgme-w32spawn
+endif
 
-RCCOMPILE = $(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
-       $(AM_CPPFLAGS) $(CPPFLAGS)
+RCCOMPILE = $(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)
 LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RCCOMPILE)
 
 SUFFIXES = .rc .lo
diff --git a/src/w32-ce.c b/src/w32-ce.c
new file mode 100644 (file)
index 0000000..57590fa
--- /dev/null
@@ -0,0 +1,405 @@
+/* w32-ce.h 
+   Copyright (C) 2010 g10 Code GmbH
+
+   This file is part of GPGME.
+   GPGME 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.
+   
+   GPGME 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <assert.h>
+
+#include <gpg-error.h>
+
+#include "w32-ce.h"
+
+
+/* Return a malloced string encoded in UTF-8 from the wide char input
+   string STRING.  Caller must free this value.  Returns NULL and sets
+   ERRNO on failure.  Calling this function with STRING set to NULL is
+   not defined.  */
+char *
+wchar_to_utf8 (const wchar_t *string)
+{
+  int n;
+  char *result;
+
+  n = WideCharToMultiByte (CP_UTF8, 0, string, -1, NULL, 0, NULL, NULL);
+  if (n < 0)
+    {
+      gpg_err_set_errno (EINVAL);
+      return NULL;
+    }
+
+  result = malloc (n+1);
+  if (!result)
+    return NULL;
+
+  n = WideCharToMultiByte (CP_UTF8, 0, string, -1, result, n, NULL, NULL);
+  if (n < 0)
+    {
+      free (result);
+      gpg_err_set_errno (EINVAL);
+      result = NULL;
+    }
+  return result;
+}
+
+
+/* Return a malloced wide char string from an UTF-8 encoded input
+   string STRING.  Caller must free this value.  Returns NULL and sets
+   ERRNO on failure.  Calling this function with STRING set to NULL is
+   not defined.  */
+wchar_t *
+utf8_to_wchar (const char *string)
+{
+  int n;
+  size_t nbytes;
+  wchar_t *result;
+
+  n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0);
+  if (n < 0)
+    {
+      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 result;
+}
+
+
+#define MAX_ENV 30
+
+char *environ[MAX_ENV + 1];
+
+char *
+getenv (const char *name)
+{
+  static char *past_result;
+  char **envp;
+
+  if (past_result)
+    {
+      free (past_result);
+      past_result = NULL;
+    }
+
+#if 0
+  if (! strcmp (name, "DBUS_VERBOSE"))
+    return past_result = get_verbose_setting ();
+  else if (! strcmp (name, "HOMEPATH"))
+    return past_result = find_my_documents_folder ();
+  else if (! strcmp (name, "DBUS_DATADIR"))
+    return past_result = find_inst_subdir ("share");
+#endif
+
+  for (envp = environ; *envp != 0; envp++)
+    {
+      const char *varp = name;
+      char *ep = *envp;
+
+      while (*varp == *ep && *varp != '\0')
+       {
+         ++ep;
+         ++varp;
+       };
+
+      if (*varp == '\0' && *ep == '=')
+       return ep + 1;
+    }
+
+  return NULL;
+}
+
+
+void
+GetSystemTimeAsFileTime (LPFILETIME ftp)
+{
+  SYSTEMTIME st;
+  GetSystemTime (&st);
+  SystemTimeToFileTime (&st, ftp);
+}
+
+
+BOOL
+DeleteFileA (LPCSTR lpFileName)
+{
+  wchar_t *filename;
+  BOOL result;
+  int err;
+
+  filename = utf8_to_wchar (lpFileName);
+  if (!filename)
+    return FALSE;
+
+  result = DeleteFileW (filename);
+
+  err = GetLastError ();
+  free (filename);
+  SetLastError (err);
+  return result;
+}
+
+
+BOOL
+CreateProcessA (LPCSTR pszImageName, LPSTR pszCmdLine,
+                LPSECURITY_ATTRIBUTES psaProcess,
+                LPSECURITY_ATTRIBUTES psaThread, BOOL fInheritHandles,
+                DWORD fdwCreate, PVOID pvEnvironment, LPCSTR pszCurDir,
+                LPSTARTUPINFOA psiStartInfo,
+                LPPROCESS_INFORMATION pProcInfo)
+{
+  wchar_t *image_name = NULL;
+  wchar_t *cmd_line = NULL;
+  BOOL result;
+  int err;
+
+  assert (psaProcess == NULL);
+  assert (psaThread == NULL);
+  assert (fInheritHandles == FALSE);
+  assert (pvEnvironment == NULL);
+  assert (pszCurDir == NULL);
+  /* psiStartInfo is generally not NULL.  */
+
+  if (pszImageName)
+    {
+      image_name = utf8_to_wchar (pszImageName);
+      if (!image_name)
+       return 0;
+    }
+  if (pszCmdLine)
+    {
+      cmd_line = utf8_to_wchar (pszCmdLine);
+      if (!cmd_line)
+        {
+          if (image_name)
+            free (image_name);
+          return 0;
+        }
+    }
+
+  result = CreateProcessW (image_name, cmd_line, NULL, NULL, FALSE,
+                           fdwCreate, NULL, NULL, NULL, pProcInfo);
+
+  err = GetLastError ();
+  free (image_name);
+  free (cmd_line);
+  SetLastError (err);
+  return result;
+}
+
+
+LONG
+RegOpenKeyExA (HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions,
+               REGSAM samDesired, PHKEY phkResult)
+{
+  wchar_t *subkey;
+  LONG result;
+  int err;
+
+  if (lpSubKey)
+    {
+      subkey = utf8_to_wchar (lpSubKey);
+      if (!subkey)
+       return 0;
+    }
+  else
+    subkey = NULL;
+
+  result = RegOpenKeyEx (hKey, subkey, ulOptions, samDesired, phkResult);
+
+  err = GetLastError ();
+  free (subkey);
+  SetLastError (err);
+  return result;
+}
+
+
+LONG
+RegQueryValueExA (HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved,
+                  LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
+{
+  wchar_t *name;
+  LONG err;
+  BYTE *data;
+  DWORD data_len;
+  DWORD type;
+
+  if (lpValueName)
+    {
+      name = utf8_to_wchar (lpValueName);
+      if (!name)
+       return GetLastError ();
+    }
+  else
+    name = NULL;
+
+  data_len = 0;
+  err = RegQueryValueExW (hKey, name, lpReserved, lpType, NULL, &data_len);
+  if (err || !lpcbData)
+    {
+      free (name);
+      return err;
+    }
+
+  data = malloc (data_len + sizeof (wchar_t));
+  if (!data)
+    {
+      free (name);
+      return ERROR_NOT_ENOUGH_MEMORY;
+    }
+  
+  err = RegQueryValueExW (hKey, name, lpReserved, &type, data, &data_len);
+  if (lpType)
+    *lpType = type;
+  free (name);
+  /* If err is ERROR_MORE_DATA, there probably was a race condition.
+     We can punt this to the caller just as well.  */
+  if (err)
+    return err;
+
+  /* NOTE: REG_MULTI_SZ and REG_EXPAND_SZ not supported, because they
+     are not needed in this module.  */
+  if (type == REG_SZ)
+    {
+      char *data_c;
+      int data_c_len;
+
+      /* This is valid since we allocated one more above.  */
+      data[data_len] = '\0';
+      data[data_len + 1] = '\0';
+      
+      data_c = wchar_to_utf8 ((wchar_t*) data);
+      if (!data_c)
+        return GetLastError();
+
+      data_c_len = strlen (data_c) + 1;
+      assert (data_c_len <= data_len + sizeof (wchar_t));
+      memcpy (data, data_c, data_c_len);
+      data_len = data_c_len;
+      free (data_c);
+    }
+
+  /* DATA and DATA_LEN now contain the result.  */
+  if (lpData)
+    {
+      if (data_len > *lpcbData)
+        err = ERROR_MORE_DATA;
+      else
+        memcpy (lpData, data, data_len);
+    }
+  *lpcbData = data_len;
+  return err;
+}
+
+
+DWORD
+GetTempPathA (DWORD nBufferLength, LPSTR lpBuffer)
+{
+  wchar_t dummy[1];
+  DWORD len;
+
+  len = GetTempPathW (0, dummy);
+  if (len == 0)
+    return 0;
+
+  assert (len <= MAX_PATH);
+
+  /* Better be safe than sorry.  MSDN doesn't say if len is with or
+     without terminating 0.  */
+  len++;
+
+  {
+    wchar_t *buffer_w;
+    DWORD len_w;
+    char *buffer_c;
+    DWORD len_c;
+
+    buffer_w = malloc (sizeof (wchar_t) * len);
+    if (! buffer_w)
+      return 0;
+
+    len_w = GetTempPathW (len, buffer_w);
+    /* Give up if we still can't get at it.  */
+    if (len_w == 0 || len_w >= len)
+      {
+        free (buffer_w);
+        return 0;
+      }
+
+    /* Better be really safe.  */
+    buffer_w[len_w] = '\0';
+
+    buffer_c = wchar_to_utf8 (buffer_w);
+    free (buffer_w);
+    if (! buffer_c)
+      return 0;
+
+    /* strlen is correct (not _mbstrlen), because we want storage and
+       not string length.  */
+    len_c = strlen (buffer_c) + 1;
+    if (len_c > nBufferLength)
+      return len_c;
+
+    strcpy (lpBuffer, buffer_c);
+    free (buffer_c);
+    return len_c - 1;
+  }
+}
+
+
+BOOL
+SHGetSpecialFolderPathA (HWND hwndOwner, LPSTR lpszPath, int nFolder,
+                         BOOL fCreate)
+{
+  wchar_t path[MAX_PATH];
+  char *path_c;
+  BOOL result;
+
+  path[0] = (wchar_t) 0;
+  result = SHGetSpecialFolderPathW (hwndOwner, path, nFolder, fCreate);
+  /* Note: May return false even if succeeds.  */
+
+  path[MAX_PATH - 1] = (wchar_t) 0;
+  path_c = wchar_to_utf8 (path);
+  if (! path_c)
+    return 0;
+  
+  strncpy (lpszPath, path_c, MAX_PATH);
+  free (path_c);
+  lpszPath[MAX_PATH - 1] = '\0';
+  return result;
+}
diff --git a/src/w32-ce.h b/src/w32-ce.h
new file mode 100644 (file)
index 0000000..2b761d6
--- /dev/null
@@ -0,0 +1,70 @@
+/* w32-ce.h 
+   Copyright (C) 2010 g10 Code GmbH
+
+   This file is part of GPGME.
+   GPGME 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.
+   
+   GPGME 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#ifndef GPGME_W32_CE_H
+#define GPGME_W32_CE_H
+
+#include <time.h>
+#include <stdarg.h>
+
+/* For getaddrinfo.  */
+#define _MSV_VER 0x401
+#include <windows.h>
+
+
+/* shlobj.h declares these only for _WIN32_IE that we don't want to define.
+   In any case, with mingw32ce we only get a SHGetSpecialFolderPath.  */
+#define SHGetSpecialFolderPathW SHGetSpecialFolderPath
+BOOL WINAPI SHGetSpecialFolderPathA(HWND,LPSTR,int,BOOL);
+BOOL WINAPI SHGetSpecialFolderPathW(HWND,LPWSTR,int,BOOL);
+
+
+#define getenv _gpgme_wince_getenv
+char *getenv (const char *name);
+
+#include <io.h>
+#define isatty(fd) 0
+
+
+/* Windows CE is missing some Windows functions that we want.  */
+
+#define GetSystemTimeAsFileTime _gpgme_wince_GetSystemTimeAsFileTime
+void GetSystemTimeAsFileTime (LPFILETIME ftp);
+
+#define DeleteFileA _gpgme_wince_DeleteFileA
+BOOL DeleteFileA(LPCSTR);
+
+#define CreateProcessA _gpgme_wince_CreateProcessA
+BOOL CreateProcessA(LPCSTR,LPSTR,LPSECURITY_ATTRIBUTES,LPSECURITY_ATTRIBUTES,BOOL,DWORD,PVOID,LPCSTR,LPSTARTUPINFOA,LPPROCESS_INFORMATION);
+
+#define RegOpenKeyExA _gpgme_wince_RegOpenKeyExA
+LONG RegOpenKeyExA(HKEY,LPCSTR,DWORD,REGSAM,PHKEY);
+
+#define RegQueryValueExA _gpgme_wince_RegQueryValueExA
+LONG WINAPI RegQueryValueExA(HKEY,LPCSTR,LPDWORD,LPDWORD,LPBYTE,LPDWORD);
+
+#define GetTempPathA _gpgme_wince_GetTempPathA
+DWORD GetTempPathA(DWORD,LPSTR);
+
+#define SHGetSpecialFolderPathA _gpgme_wince_SHGetSpecialFolderPathA
+BOOL SHGetSpecialFolderPathA(HWND,LPSTR,int,BOOL);
+
+
+#endif /* GPGME_W32_CE_H */