w32: Try to locate gpg in the gpgme installation dir.

* src/w32-util.c (my_hmodule): New.
(wchar_to_utf8): New.
(DllMain): New.
(_gpgme_get_inst_dir): New.
(find_program_in_dir): New.
(find_program_in_inst_dir): Add arg INST_DIR.
(_gpgme_get_gpg_path): Get inst_dir before acquiring the lock.
(_gpgme_get_gpgconf_path): Ditto.
(_gpgme_get_g13_path): Ditto.
(_gpgme_get_w32spawn_path): Ditto.
This commit is contained in:
Werner Koch 2013-08-02 12:48:30 +02:00
parent 393a9471f2
commit 3881ea4e83

View File

@ -1,24 +1,23 @@
/* w32-util.c - Utility functions for the W32 API /* w32-util.c - Utility functions for the W32 API
Copyright (C) 1999 Free Software Foundation, Inc * Copyright (C) 1999 Free Software Foundation, Inc
Copyright (C) 2001 Werner Koch (dd9jn) * Copyright (C) 2001 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH * Copyright (C) 2001, 2002, 2003, 2004, 2007, 2013 g10 Code GmbH
*
This file is part of GPGME. * This file is part of GPGME.
*
GPGME is free software; you can redistribute it and/or modify it * GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as * under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of * published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version. * the License, or (at your option) any later version.
*
GPGME is distributed in the hope that it will be useful, but * GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details. * Lesser General Public License for more details.
*
You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software * License along with this program; if not, see <http://www.gnu.org/licenses/>.
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA **/
02111-1307, USA. */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>
@ -75,6 +74,12 @@
DEFINE_STATIC_LOCK (get_path_lock); 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 #ifdef HAVE_ALLOW_SET_FOREGROUND_WINDOW
@ -112,6 +117,39 @@ dlclose (void * hd)
} }
#endif /* HAVE_ALLOW_SET_FOREGROUND_WINDOW */ #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 void
_gpgme_allow_set_foreground_window (pid_t pid) _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 /* Return the name of the directory with the gpgme DLL or the EXE (if
static char * statically linked). May return NULL on severe errors. */
find_program_in_registry (const char *name) const char *
_gpgme_get_inst_dir (void)
{ {
char *program = NULL; static char *inst_dir;
program = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", name); LOCK (get_path_lock);
if (program) if (!inst_dir)
{ {
int i; wchar_t *moddir;
TRACE2 (DEBUG_CTX, "gpgme:find_program_in_registry", 0, moddir = malloc ((MAX_PATH+5) * sizeof *moddir);
"found %s in registry: `%s'", name, program); if (moddir)
for (i = 0; program[i]; i++)
{ {
if (program[i] == '/') if (!GetModuleFileNameW (my_hmodule, moddir, MAX_PATH))
program[i] = '\\'; *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;
} }
} }
return program; free (moddir);
}
}
UNLOCK (get_path_lock);
return inst_dir;
} }
#endif
static char * static char *
find_program_in_inst_dir (const char *name) find_program_in_dir (const char *dir, const char *name)
{ {
char *result = NULL; char *result;
char *tmp;
tmp = read_w32_registry_string ("HKEY_LOCAL_MACHINE", result = malloc (strlen (dir) + 1 + strlen (name) + 1);
"Software\\GNU\\GnuPG",
"Install Directory");
if (!tmp)
return NULL;
result = malloc (strlen (tmp) + 1 + strlen (name) + 1);
if (!result) if (!result)
{
free (tmp);
return NULL; return NULL;
}
strcpy (stpcpy (stpcpy (result, tmp), "\\"), name); strcpy (stpcpy (stpcpy (result, dir), "\\"), name);
free (tmp);
if (access (result, F_OK)) if (access (result, F_OK))
{ {
free (result); 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 * static char *
find_program_at_standard_place (const char *name) find_program_at_standard_place (const char *name)
{ {
@ -353,14 +427,12 @@ const char *
_gpgme_get_gpg_path (void) _gpgme_get_gpg_path (void)
{ {
static char *gpg_program; static char *gpg_program;
const char *inst_dir;
inst_dir = _gpgme_get_inst_dir ();
LOCK (get_path_lock); LOCK (get_path_lock);
#if 0
if (!gpg_program) if (!gpg_program)
gpg_program = find_program_in_registry ("gpgProgram"); gpg_program = find_program_in_inst_dir (inst_dir, "gpg.exe");
#endif
if (!gpg_program)
gpg_program = find_program_in_inst_dir ("gpg.exe");
if (!gpg_program) if (!gpg_program)
gpg_program = find_program_at_standard_place ("GNU\\GnuPG\\gpg.exe"); gpg_program = find_program_at_standard_place ("GNU\\GnuPG\\gpg.exe");
UNLOCK (get_path_lock); UNLOCK (get_path_lock);
@ -372,14 +444,12 @@ const char *
_gpgme_get_gpgsm_path (void) _gpgme_get_gpgsm_path (void)
{ {
static char *gpgsm_program; static char *gpgsm_program;
const char *inst_dir;
inst_dir = _gpgme_get_inst_dir ();
LOCK (get_path_lock); LOCK (get_path_lock);
#if 0
if (!gpgsm_program) if (!gpgsm_program)
gpgsm_program = find_program_in_registry ("gpgsmProgram"); gpgsm_program = find_program_in_inst_dir (inst_dir, "gpgsm.exe");
#endif
if (!gpgsm_program)
gpgsm_program = find_program_in_inst_dir ("gpgsm.exe");
if (!gpgsm_program) if (!gpgsm_program)
gpgsm_program = find_program_at_standard_place ("GNU\\GnuPG\\gpgsm.exe"); gpgsm_program = find_program_at_standard_place ("GNU\\GnuPG\\gpgsm.exe");
UNLOCK (get_path_lock); UNLOCK (get_path_lock);
@ -391,14 +461,12 @@ const char *
_gpgme_get_gpgconf_path (void) _gpgme_get_gpgconf_path (void)
{ {
static char *gpgconf_program; static char *gpgconf_program;
const char *inst_dir;
inst_dir = _gpgme_get_inst_dir ();
LOCK (get_path_lock); LOCK (get_path_lock);
#if 0
if (!gpgconf_program) if (!gpgconf_program)
gpgconf_program = find_program_in_registry ("gpgconfProgram"); gpgconf_program = find_program_in_inst_dir (inst_dir, "gpgconf.exe");
#endif
if (!gpgconf_program)
gpgconf_program = find_program_in_inst_dir ("gpgconf.exe");
if (!gpgconf_program) if (!gpgconf_program)
gpgconf_program gpgconf_program
= find_program_at_standard_place ("GNU\\GnuPG\\gpgconf.exe"); = find_program_at_standard_place ("GNU\\GnuPG\\gpgconf.exe");
@ -411,14 +479,12 @@ const char *
_gpgme_get_g13_path (void) _gpgme_get_g13_path (void)
{ {
static char *g13_program; static char *g13_program;
const char *inst_dir;
inst_dir = _gpgme_get_inst_dir ();
LOCK (get_path_lock); LOCK (get_path_lock);
#if 0
if (!g13_program) if (!g13_program)
g13_program = find_program_in_registry ("g13Program"); g13_program = find_program_in_inst_dir (inst_dir, "g13.exe");
#endif
if (!g13_program)
g13_program = find_program_in_inst_dir ("g13.exe");
if (!g13_program) if (!g13_program)
g13_program = find_program_at_standard_place ("GNU\\GnuPG\\g13.exe"); g13_program = find_program_at_standard_place ("GNU\\GnuPG\\g13.exe");
UNLOCK (get_path_lock); UNLOCK (get_path_lock);
@ -453,10 +519,12 @@ const char *
_gpgme_get_w32spawn_path (void) _gpgme_get_w32spawn_path (void)
{ {
static char *w32spawn_program; static char *w32spawn_program;
const char *inst_dir;
inst_dir = _gpgme_get_inst_dir ();
LOCK (get_path_lock); LOCK (get_path_lock);
if (!w32spawn_program) 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) if (!w32spawn_program)
w32spawn_program w32spawn_program
= find_program_at_standard_place ("GNU\\GnuPG\\gpgme-w32spawn.exe"); = find_program_at_standard_place ("GNU\\GnuPG\\gpgme-w32spawn.exe");
@ -641,3 +709,18 @@ _gpgme_w32ce_get_debug_envvar (void)
return tmp; return tmp;
} }
#endif /*HAVE_W32CE_SYSTEM*/ #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*/