diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32-util.c | 229 | 
1 files changed, 156 insertions, 73 deletions
| 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 <http://www.gnu.org/licenses/>. + **/  #ifdef HAVE_CONFIG_H  #include <config.h> @@ -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) -    return NULL; - -  result = malloc (strlen (tmp) + 1 + strlen (name) + 1); +  result = malloc (strlen (dir) + 1 + strlen (name) + 1);    if (!result) -    { -      free (tmp); -      return NULL; -    } +    return NULL; -  strcpy (stpcpy (stpcpy (result, tmp), "\\"), name); -  free (tmp); +  strcpy (stpcpy (stpcpy (result, dir), "\\"), name);    if (access (result, F_OK))      {        free (result); @@ -326,6 +366,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)  {    char path[MAX_PATH]; @@ -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*/ | 
