diff --git a/src/ChangeLog b/src/ChangeLog index 361e6979..a832b0f9 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,11 @@ 2010-05-12 Marcus Brinkmann + * 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 * util.h: Likewise. diff --git a/src/Makefile.am b/src/Makefile.am index 1ecb7610..e557c7bb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 index 00000000..57590fa9 --- /dev/null +++ b/src/w32-ce.c @@ -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 +#endif + +#include +#include + +#include + +#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 index 00000000..2b761d65 --- /dev/null +++ b/src/w32-ce.h @@ -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 +#include + +/* For getaddrinfo. */ +#define _MSV_VER 0x401 +#include + + +/* 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 +#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 */