diff options
Diffstat (limited to '')
-rw-r--r-- | src/w32-util.c | 175 |
1 files changed, 111 insertions, 64 deletions
diff --git a/src/w32-util.c b/src/w32-util.c index daf3bd2d..a27955b5 100644 --- a/src/w32-util.c +++ b/src/w32-util.c @@ -85,7 +85,10 @@ static HMODULE my_hmodule; binaries. The are set only once by gpgme_set_global_flag. */ static char *default_gpg_name; static char *default_gpgconf_name; - +/* If this variable is not NULL the value is assumed to be the + installation directory. The variable may only be set once by + gpgme_set_global_flag and accessed by _gpgme_get_inst_dir. */ +static char *override_inst_dir; #ifdef HAVE_ALLOW_SET_FOREGROUND_WINDOW @@ -347,6 +350,9 @@ _gpgme_get_inst_dir (void) { static char *inst_dir; + if (override_inst_dir) + return override_inst_dir; + LOCK (get_path_lock); if (!inst_dir) { @@ -398,47 +404,18 @@ find_program_in_dir (const char *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 by the registry. The idea here is that we prefer - 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) { char path[MAX_PATH]; char *result = NULL; - /* See http://wiki.tcl.tk/17492 for details on compatibility. */ - if (SHGetSpecialFolderPathA (NULL, path, CSIDL_PROGRAM_FILES, 0)) + /* See http://wiki.tcl.tk/17492 for details on compatibility. + + We First try the generic place and then fallback to the x86 + (i.e. 32 bit) place. This will prefer a 64 bit of the program + over a 32 bit version on 64 bit Windows if installed. */ + if (SHGetSpecialFolderPathA (NULL, path, CSIDL_PROGRAM_FILES, 0) + || SHGetSpecialFolderPathA (NULL, path, CSIDL_PROGRAM_FILESX86, 0)) { result = malloc (strlen (path) + 1 + strlen (name) + 1); if (result) @@ -490,30 +467,73 @@ _gpgme_set_default_gpgconf_name (const char *name) } +/* Set the override installation directory. This function may only be + called by gpgme_set_global_flag. Returns 0 on success. */ +int +_gpgme_set_override_inst_dir (const char *dir) +{ + if (!override_inst_dir) + { + override_inst_dir = malloc (strlen (dir) + 1); + if (override_inst_dir) + { + strcpy (override_inst_dir, dir); + replace_slashes (override_inst_dir); + /* Remove a trailing slash. */ + if (*override_inst_dir + && override_inst_dir[strlen (override_inst_dir)-1] == '\\') + override_inst_dir[strlen (override_inst_dir)-1] = 0; + } + } + return !override_inst_dir; +} + + /* Return the full file name of the GPG binary. This function is used - if gpgconf was not found and thus it can be assumed that gpg2 is + iff gpgconf was not found and thus it can be assumed that gpg2 is not installed. This function is only called by get_gpgconf_item and may not be called concurrently. */ char * _gpgme_get_gpg_path (void) { - char *gpg; - const char *inst_dir, *name; + char *gpg = NULL; + const char *name, *inst_dir; + name = default_gpg_name? get_basename (default_gpg_name) : "gpg.exe"; + + /* 1. Try to find gpg.exe in the installation directory of gpgme. */ inst_dir = _gpgme_get_inst_dir (); - gpg = find_program_in_inst_dir - (inst_dir, - default_gpg_name? get_basename (default_gpg_name) : "gpg.exe"); + if (inst_dir) + { + gpg = find_program_in_dir (inst_dir, name); + } + + /* 2. Try to find gpg.exe using that ancient registry key. */ + if (!gpg) + { + char *dir; + + dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", + "Software\\GNU\\GnuPG", + "Install Directory"); + if (dir) + { + gpg = find_program_in_dir (dir, name); + free (dir); + } + } + + /* 3. Try to find gpg.exe below CSIDL_PROGRAM_FILES. */ if (!gpg) { - name = (default_gpg_name? default_gpg_name - /* */ : "GNU\\GnuPG\\gpg.exe"); + name = default_gpg_name? default_gpg_name : "GNU\\GnuPG\\gpg.exe"; gpg = find_program_at_standard_place (name); - if (!gpg) - _gpgme_debug (DEBUG_ENGINE, "_gpgme_get_gpg_path: '%s' not found", - name); } + /* 4. Print a debug message if not found. */ + if (!gpg) + _gpgme_debug (DEBUG_ENGINE, "_gpgme_get_gpg_path: '%s' not found", name); + return gpg; } @@ -523,22 +543,52 @@ _gpgme_get_gpg_path (void) char * _gpgme_get_gpgconf_path (void) { - char *gpgconf; + char *gpgconf = NULL; const char *inst_dir, *name; + name = default_gpgconf_name? get_basename(default_gpgconf_name):"gpgconf.exe"; + + /* 1. Try to find gpgconf.exe in the installation directory of gpgme. */ inst_dir = _gpgme_get_inst_dir (); - gpgconf = find_program_in_inst_dir - (inst_dir, - default_gpgconf_name? get_basename (default_gpgconf_name) : "gpgconf.exe"); + if (inst_dir) + { + gpgconf = find_program_in_dir (inst_dir, name); + } + + /* 2. Try to find gpgconf.exe from GnuPG >= 2.1 below CSIDL_PROGRAM_FILES. */ if (!gpgconf) { - name = (default_gpgconf_name? default_gpgconf_name - /* */ : "GNU\\GnuPG\\gpgconf.exe"); - gpgconf = find_program_at_standard_place (name); - if (!gpgconf) - _gpgme_debug (DEBUG_ENGINE, "_gpgme_get_gpgconf_path: '%s' not found", - name); + const char *name2 = (default_gpgconf_name ? default_gpgconf_name + /**/ : "GnuPG\\bin\\gpgconf.exe"); + gpgconf = find_program_at_standard_place (name2); } + + /* 3. Try to find gpgconf.exe using that ancient registry key. This + should eventually be removed. */ + if (!gpgconf) + { + char *dir; + + dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", + "Software\\GNU\\GnuPG", + "Install Directory"); + if (dir) + { + gpgconf = find_program_in_dir (dir, name); + free (dir); + } + } + + /* 4. Try to find gpgconf.exe from Gpg4win below CSIDL_PROGRAM_FILES. */ + if (!gpgconf) + { + gpgconf = find_program_at_standard_place ("GNU\\GnuPG\\gpgconf.exe"); + } + + /* 5. Print a debug message if not found. */ + if (!gpgconf) + _gpgme_debug (DEBUG_ENGINE, "_gpgme_get_gpgconf_path: '%s' not found",name); + return gpgconf; } @@ -552,10 +602,7 @@ _gpgme_get_w32spawn_path (void) inst_dir = _gpgme_get_inst_dir (); LOCK (get_path_lock); if (!w32spawn_program) - 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"); + w32spawn_program = find_program_in_dir (inst_dir, "gpgme-w32spawn.exe"); UNLOCK (get_path_lock); return w32spawn_program; } @@ -600,7 +647,7 @@ static const char letters[] = does not exist at the time of the call to mkstemp. TMPL is overwritten with the result. */ static int -mkstemp (char *tmpl) +my_mkstemp (char *tmpl) { int len; char *XXXXXX; @@ -708,7 +755,7 @@ _gpgme_mkstemp (int *fd, char **name) if (!tmpname) return -1; strcpy (stpcpy (tmpname, tmp), "\\gpgme-XXXXXX"); - *fd = mkstemp (tmpname); + *fd = my_mkstemp (tmpname); if (fd < 0) { free (tmpname); |