1
/* w32-util.c - Utility functions for the W32 API
2
Copyright (C) 1999 Free Software Foundation, Inc
3
Copyright (C) 2001 Werner Koch (dd9jn)
4
Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH
6
This file is part of GPGME.
8
GPGME is free software; you can redistribute it and/or modify it
9
under the terms of the GNU Lesser General Public License as
10
published by the Free Software Foundation; either version 2.1 of
11
the License, or (at your option) any later version.
13
GPGME is distributed in the hope that it will be useful, but
14
WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
Lesser General Public License for more details.
18
You should have received a copy of the GNU Lesser General Public
19
License along with this program; if not, write to the Free Software
20
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
32
#include <sys/types.h>
43
DEFINE_STATIC_LOCK (get_path_lock);
48
static __inline__ void *
49
dlopen (const char * name, int flag)
51
void * hd = LoadLibrary (name);
55
static __inline__ void *
56
dlsym (void * hd, const char * sym)
60
void * fnc = GetProcAddress (hd, sym);
80
/* Return a string from the W32 Registry or NULL in case of error.
81
Caller must release the return value. A NULL for root is an alias
82
for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. */
84
read_w32_registry_string (const char *root, const char *dir, const char *name)
86
HKEY root_key, key_handle;
87
DWORD n1, nbytes, type;
91
root_key = HKEY_CURRENT_USER;
92
else if ( !strcmp( root, "HKEY_CLASSES_ROOT" ) )
93
root_key = HKEY_CLASSES_ROOT;
94
else if ( !strcmp( root, "HKEY_CURRENT_USER" ) )
95
root_key = HKEY_CURRENT_USER;
96
else if ( !strcmp( root, "HKEY_LOCAL_MACHINE" ) )
97
root_key = HKEY_LOCAL_MACHINE;
98
else if ( !strcmp( root, "HKEY_USERS" ) )
99
root_key = HKEY_USERS;
100
else if ( !strcmp( root, "HKEY_PERFORMANCE_DATA" ) )
101
root_key = HKEY_PERFORMANCE_DATA;
102
else if ( !strcmp( root, "HKEY_CURRENT_CONFIG" ) )
103
root_key = HKEY_CURRENT_CONFIG;
107
if ( RegOpenKeyEx ( root_key, dir, 0, KEY_READ, &key_handle ) )
110
return NULL; /* no need for a RegClose, so return direct */
111
/* It seems to be common practise to fall back to HKLM. */
112
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) )
113
return NULL; /* still no need for a RegClose, so return direct */
117
if ( RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) )
121
/* Try to fallback to HKLM also vor a missing value. */
122
RegCloseKey (key_handle);
123
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) )
124
return NULL; /* Nope. */
125
if (RegQueryValueEx ( key_handle, name, 0, NULL, NULL, &nbytes))
128
result = malloc ( (n1=nbytes+1) );
131
if ( RegQueryValueEx ( key_handle, name, 0, &type, result, &n1 ) )
133
free(result); result = NULL;
136
result[nbytes] = 0; /* Make sure it is really a string. */
137
if (type == REG_EXPAND_SZ && strchr (result, '%'))
145
nbytes = ExpandEnvironmentStrings (result, tmp, n1);
146
if (nbytes && nbytes > n1)
150
tmp = malloc (n1 + 1);
153
nbytes = ExpandEnvironmentStrings (result, tmp, n1);
154
if (nbytes && nbytes > n1) {
155
free (tmp); /* Oops - truncated, better don't expand at all. */
162
else if (nbytes) /* Okay, reduce the length. */
166
result = malloc (strlen (tmp)+1);
171
strcpy (result, tmp);
175
else /* Error - don't expand. */
182
RegCloseKey( key_handle );
187
/* This is a helper function to load and run a Windows function from
188
either of one DLLs. */
190
w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e)
192
static int initialized;
193
static HRESULT (WINAPI * func)(HWND,int,HANDLE,DWORD,LPSTR);
197
static char *dllnames[] = { "shell32.dll", "shfolder.dll", NULL };
203
for (i=0, handle = NULL; !handle && dllnames[i]; i++)
205
handle = dlopen (dllnames[i], RTLD_LAZY);
208
func = dlsym (handle, "SHGetFolderPathA");
219
return func (a,b,c,d,e);
226
find_program_in_registry (const char *name)
228
char *program = NULL;
230
program = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", name);
235
TRACE2 (DEBUG_CTX, "gpgme:find_program_in_registry", 0,
236
"found %s in registry: `%s'", name, program);
237
for (i = 0; program[i]; i++)
239
if (program[i] == '/')
248
find_program_in_inst_dir (const char *name)
253
tmp = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
254
"Software\\GNU\\GnuPG",
255
"Install Directory");
259
result = malloc (strlen (tmp) + 1 + strlen (name) + 1);
266
strcpy (stpcpy (stpcpy (result, tmp), "\\"), name);
268
if (access (result, F_OK))
279
find_program_at_standard_place (const char *name)
284
if (w32_shgetfolderpath (NULL, CSIDL_PROGRAM_FILES, NULL, 0, path) >= 0)
286
result = malloc (strlen (path) + 1 + strlen (name) + 1);
289
strcpy (stpcpy (stpcpy (result, path), "\\"), name);
290
if (access (result, F_OK))
302
_gpgme_get_gpg_path (void)
304
static char *gpg_program;
306
LOCK (get_path_lock);
308
gpg_program = find_program_in_registry ("gpgProgram");
310
gpg_program = find_program_in_inst_dir ("gpg.exe");
312
gpg_program = find_program_at_standard_place ("GNU\\GnuPG\\gpg.exe");
313
UNLOCK (get_path_lock);
319
_gpgme_get_gpgsm_path (void)
321
static char *gpgsm_program;
323
LOCK (get_path_lock);
325
gpgsm_program = find_program_in_registry ("gpgsmProgram");
327
gpgsm_program = find_program_in_inst_dir ("gpgsm.exe");
329
gpgsm_program = find_program_at_standard_place ("GNU\\GnuPG\\gpgsm.exe");
330
UNLOCK (get_path_lock);
331
return gpgsm_program;
336
_gpgme_get_gpgconf_path (void)
338
static char *gpgconf_program;
340
LOCK (get_path_lock);
341
if (!gpgconf_program)
342
gpgconf_program = find_program_in_registry ("gpgconfProgram");
343
if (!gpgconf_program)
344
gpgconf_program = find_program_in_inst_dir ("gpgconf.exe");
345
if (!gpgconf_program)
347
= find_program_at_standard_place ("GNU\\GnuPG\\gpgconf.exe");
348
UNLOCK (get_path_lock);
349
return gpgconf_program;
353
/* Return an integer value from gpgme specific configuration
354
entries. VALUE receives that value; function returns true if a value
355
has been configured and false if not. */
357
_gpgme_get_conf_int (const char *key, int *value)
359
char *tmp = read_w32_registry_string (NULL, "Software\\GNU\\gpgme", key);