diff --git a/src/w32-util.c b/src/w32-util.c
index a90f4056..27dc5bcc 100644
--- a/src/w32-util.c
+++ b/src/w32-util.c
@@ -1,24 +1,23 @@
/* w32-util.c - Utility functions for the W32 API
- Copyright (C) 1999 Free Software Foundation, Inc
- Copyright (C) 2001 Werner Koch (dd9jn)
- Copyright (C) 2001, 2002, 2003, 2004, 2007 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. */
+ * Copyright (C) 1999 Free Software Foundation, Inc
+ * Copyright (C) 2001 Werner Koch (dd9jn)
+ * Copyright (C) 2001, 2002, 2003, 2004, 2007, 2013 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, see .
+ **/
#ifdef HAVE_CONFIG_H
#include
@@ -75,6 +74,12 @@
DEFINE_STATIC_LOCK (get_path_lock);
+/* The module handle of this DLL. If we are linked statically,
+ dllmain does not exists and thus the value of my_hmodule will be
+ NULL. The effect is that a GetModuleFileName always returns the
+ file name of the DLL or executable which contains the gpgme code. */
+static HMODULE my_hmodule;
+
#ifdef HAVE_ALLOW_SET_FOREGROUND_WINDOW
@@ -112,6 +117,39 @@ dlclose (void * hd)
}
#endif /* HAVE_ALLOW_SET_FOREGROUND_WINDOW */
+
+/* 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. */
+static 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;
+}
+
+
void
_gpgme_allow_set_foreground_window (pid_t pid)
{
@@ -270,51 +308,53 @@ read_w32_registry_string (const char *root, const char *dir, const char *name)
}
-#if 0
-static char *
-find_program_in_registry (const char *name)
+/* Return the name of the directory with the gpgme DLL or the EXE (if
+ statically linked). May return NULL on severe errors. */
+const char *
+_gpgme_get_inst_dir (void)
{
- char *program = NULL;
+ static char *inst_dir;
- program = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", name);
- if (program)
+ LOCK (get_path_lock);
+ if (!inst_dir)
{
- int i;
+ wchar_t *moddir;
- TRACE2 (DEBUG_CTX, "gpgme:find_program_in_registry", 0,
- "found %s in registry: `%s'", name, program);
- for (i = 0; program[i]; i++)
- {
- if (program[i] == '/')
- program[i] = '\\';
- }
+ moddir = malloc ((MAX_PATH+5) * sizeof *moddir);
+ if (moddir)
+ {
+ if (!GetModuleFileNameW (my_hmodule, moddir, MAX_PATH))
+ *moddir = 0;
+ if (!*moddir)
+ gpg_err_set_errno (ENOENT);
+ else
+ {
+ inst_dir = wchar_to_utf8 (moddir);
+ if (inst_dir)
+ {
+ char *p = strrchr (inst_dir, '\\');
+ if (p)
+ *p = 0;
+ }
+ }
+ free (moddir);
+ }
}
- return program;
+ UNLOCK (get_path_lock);
+ return inst_dir;
}
-#endif
static char *
-find_program_in_inst_dir (const char *name)
+find_program_in_dir (const char *dir, const char *name)
{
- char *result = NULL;
- char *tmp;
+ char *result;
- tmp = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
- "Software\\GNU\\GnuPG",
- "Install Directory");
- if (!tmp)
+ result = malloc (strlen (dir) + 1 + strlen (name) + 1);
+ if (!result)
return NULL;
- result = malloc (strlen (tmp) + 1 + strlen (name) + 1);
- if (!result)
- {
- free (tmp);
- return NULL;
- }
-
- strcpy (stpcpy (stpcpy (result, tmp), "\\"), name);
- free (tmp);
+ strcpy (stpcpy (stpcpy (result, dir), "\\"), name);
if (access (result, F_OK))
{
free (result);
@@ -325,6 +365,40 @@ find_program_in_inst_dir (const char *name)
}
+static char *
+find_program_in_inst_dir (const char *inst_dir, const char *name)
+{
+ char *result;
+ char *dir;
+
+ /* If an installation directory has been passed, this overrides a
+ location given bu the registry. The idea here is that we prefer
+ a a program installed alongside with gpgme. We don't want the
+ registry to override this to have a better isolation of an gpgme
+ aware applications for other effects. Note that the "Install
+ Directory" registry item has been used for ages in Gpg4win and
+ earlier GnuPG windows installers. It is technically not anymore
+ required. */
+ if (inst_dir)
+ {
+ result = find_program_in_dir (inst_dir, name);
+ if (result)
+ return result;
+ }
+
+ dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
+ "Software\\GNU\\GnuPG",
+ "Install Directory");
+ if (dir)
+ {
+ result = find_program_in_dir (dir, name);
+ free (dir);
+ return result;
+ }
+ return NULL;
+}
+
+
static char *
find_program_at_standard_place (const char *name)
{
@@ -353,14 +427,12 @@ const char *
_gpgme_get_gpg_path (void)
{
static char *gpg_program;
+ const char *inst_dir;
+ inst_dir = _gpgme_get_inst_dir ();
LOCK (get_path_lock);
-#if 0
if (!gpg_program)
- gpg_program = find_program_in_registry ("gpgProgram");
-#endif
- if (!gpg_program)
- gpg_program = find_program_in_inst_dir ("gpg.exe");
+ gpg_program = find_program_in_inst_dir (inst_dir, "gpg.exe");
if (!gpg_program)
gpg_program = find_program_at_standard_place ("GNU\\GnuPG\\gpg.exe");
UNLOCK (get_path_lock);
@@ -372,14 +444,12 @@ const char *
_gpgme_get_gpgsm_path (void)
{
static char *gpgsm_program;
+ const char *inst_dir;
+ inst_dir = _gpgme_get_inst_dir ();
LOCK (get_path_lock);
-#if 0
if (!gpgsm_program)
- gpgsm_program = find_program_in_registry ("gpgsmProgram");
-#endif
- if (!gpgsm_program)
- gpgsm_program = find_program_in_inst_dir ("gpgsm.exe");
+ gpgsm_program = find_program_in_inst_dir (inst_dir, "gpgsm.exe");
if (!gpgsm_program)
gpgsm_program = find_program_at_standard_place ("GNU\\GnuPG\\gpgsm.exe");
UNLOCK (get_path_lock);
@@ -391,14 +461,12 @@ const char *
_gpgme_get_gpgconf_path (void)
{
static char *gpgconf_program;
+ const char *inst_dir;
+ inst_dir = _gpgme_get_inst_dir ();
LOCK (get_path_lock);
-#if 0
if (!gpgconf_program)
- gpgconf_program = find_program_in_registry ("gpgconfProgram");
-#endif
- if (!gpgconf_program)
- gpgconf_program = find_program_in_inst_dir ("gpgconf.exe");
+ gpgconf_program = find_program_in_inst_dir (inst_dir, "gpgconf.exe");
if (!gpgconf_program)
gpgconf_program
= find_program_at_standard_place ("GNU\\GnuPG\\gpgconf.exe");
@@ -411,14 +479,12 @@ const char *
_gpgme_get_g13_path (void)
{
static char *g13_program;
+ const char *inst_dir;
+ inst_dir = _gpgme_get_inst_dir ();
LOCK (get_path_lock);
-#if 0
if (!g13_program)
- g13_program = find_program_in_registry ("g13Program");
-#endif
- if (!g13_program)
- g13_program = find_program_in_inst_dir ("g13.exe");
+ g13_program = find_program_in_inst_dir (inst_dir, "g13.exe");
if (!g13_program)
g13_program = find_program_at_standard_place ("GNU\\GnuPG\\g13.exe");
UNLOCK (get_path_lock);
@@ -453,10 +519,12 @@ const char *
_gpgme_get_w32spawn_path (void)
{
static char *w32spawn_program;
+ const char *inst_dir;
+ inst_dir = _gpgme_get_inst_dir ();
LOCK (get_path_lock);
if (!w32spawn_program)
- w32spawn_program = find_program_in_inst_dir ("gpgme-w32spawn.exe");
+ w32spawn_program = find_program_in_inst_dir (inst_dir,"gpgme-w32spawn.exe");
if (!w32spawn_program)
w32spawn_program
= find_program_at_standard_place ("GNU\\GnuPG\\gpgme-w32spawn.exe");
@@ -641,3 +709,18 @@ _gpgme_w32ce_get_debug_envvar (void)
return tmp;
}
#endif /*HAVE_W32CE_SYSTEM*/
+
+
+/* Entry point called by the DLL loader. */
+#ifdef DLL_EXPORT
+int WINAPI
+DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved)
+{
+ (void)reserved;
+
+ if (reason == DLL_PROCESS_ATTACH)
+ my_hmodule = hinst;
+
+ return TRUE;
+}
+#endif /*DLL_EXPORT*/