~ubuntu-branches/ubuntu/lucid/gpgme1.0/lucid

« back to all changes in this revision

Viewing changes to gpgme/w32-util.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman, Bhavani Shankar, Scott Kitterman
  • Date: 2008-12-31 02:39:33 UTC
  • mfrom: (1.1.6 upstream) (3.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20081231023933-zi5r2w9vf7fdz0x9
Tags: 1.1.8-1ubuntu1
[ Bhavani Shankar ]
* Merge from debian unstable, remaining changes: LP: #311666
  - debian/rules: enable tests

[ Scott Kitterman ]
* Re-enable testsuite on armel since it's no longer a first build 

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
5
 
 
6
 
   This file is part of GPGME.
7
 
 
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.
12
 
   
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.
17
 
   
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
21
 
   02111-1307, USA.  */
22
 
 
23
 
#ifdef HAVE_CONFIG_H
24
 
#include <config.h>
25
 
#endif
26
 
#include <stdio.h>
27
 
#include <stdlib.h>
28
 
#include <string.h>
29
 
#include <assert.h>
30
 
#include <errno.h>
31
 
#include <sys/time.h>
32
 
#include <sys/types.h>
33
 
#include <signal.h>
34
 
#include <fcntl.h>
35
 
#include <windows.h>
36
 
#include <shlobj.h>
37
 
#include <io.h>
38
 
 
39
 
#include "util.h"
40
 
#include "sema.h"
41
 
#include "debug.h"
42
 
 
43
 
DEFINE_STATIC_LOCK (get_path_lock);
44
 
 
45
 
 
46
 
#define RTLD_LAZY 0
47
 
 
48
 
static __inline__ void *
49
 
dlopen (const char * name, int flag)
50
 
{
51
 
  void * hd = LoadLibrary (name);
52
 
  return hd;
53
 
}
54
 
 
55
 
static __inline__ void *
56
 
dlsym (void * hd, const char * sym)
57
 
{
58
 
  if (hd && sym)
59
 
    {
60
 
      void * fnc = GetProcAddress (hd, sym);
61
 
      if (!fnc)
62
 
        return NULL;
63
 
      return fnc;
64
 
    }
65
 
  return NULL;
66
 
}
67
 
 
68
 
static __inline__ int
69
 
dlclose (void * hd)
70
 
{
71
 
  if (hd)
72
 
    {
73
 
      FreeLibrary (hd);
74
 
      return 0;
75
 
    }
76
 
  return -1;
77
 
}  
78
 
 
79
 
 
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. */
83
 
static char *
84
 
read_w32_registry_string (const char *root, const char *dir, const char *name)
85
 
{
86
 
  HKEY root_key, key_handle;
87
 
  DWORD n1, nbytes, type;
88
 
  char *result = NULL;
89
 
        
90
 
  if ( !root )
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;
104
 
  else
105
 
    return NULL;
106
 
        
107
 
  if ( RegOpenKeyEx ( root_key, dir, 0, KEY_READ, &key_handle ) )
108
 
    {
109
 
      if (root)
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 */
114
 
    }
115
 
 
116
 
  nbytes = 1;
117
 
  if ( RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) )
118
 
    {
119
 
      if (root)
120
 
        goto leave;
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))
126
 
        goto leave;
127
 
    }
128
 
  result = malloc ( (n1=nbytes+1) );
129
 
  if ( !result )
130
 
    goto leave;
131
 
  if ( RegQueryValueEx ( key_handle, name, 0, &type, result, &n1 ) )
132
 
    {
133
 
      free(result); result = NULL;
134
 
      goto leave;
135
 
    }
136
 
  result[nbytes] = 0; /* Make sure it is really a string.  */
137
 
  if (type == REG_EXPAND_SZ && strchr (result, '%')) 
138
 
    {
139
 
      char *tmp;
140
 
        
141
 
      n1 += 1000;
142
 
      tmp = malloc (n1+1);
143
 
      if (!tmp)
144
 
        goto leave;
145
 
      nbytes = ExpandEnvironmentStrings (result, tmp, n1);
146
 
      if (nbytes && nbytes > n1)
147
 
        {
148
 
          free (tmp);
149
 
          n1 = nbytes;
150
 
          tmp = malloc (n1 + 1);
151
 
          if (!tmp)
152
 
            goto leave;
153
 
          nbytes = ExpandEnvironmentStrings (result, tmp, n1);
154
 
          if (nbytes && nbytes > n1) {
155
 
            free (tmp); /* Oops - truncated, better don't expand at all. */
156
 
            goto leave;
157
 
          }
158
 
          tmp[nbytes] = 0;
159
 
          free (result);
160
 
          result = tmp;
161
 
        }
162
 
      else if (nbytes)  /* Okay, reduce the length. */
163
 
        {
164
 
          tmp[nbytes] = 0;
165
 
          free (result);
166
 
          result = malloc (strlen (tmp)+1);
167
 
          if (!result)
168
 
            result = tmp;
169
 
          else 
170
 
            {
171
 
              strcpy (result, tmp);
172
 
              free (tmp);
173
 
            }
174
 
        }
175
 
      else  /* Error - don't expand. */
176
 
        {
177
 
          free (tmp);
178
 
        }
179
 
    }
180
 
 
181
 
 leave:
182
 
  RegCloseKey( key_handle );
183
 
  return result;
184
 
}
185
 
 
186
 
 
187
 
/* This is a helper function to load and run a Windows function from
188
 
   either of one DLLs. */
189
 
static HRESULT
190
 
w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e)
191
 
{
192
 
  static int initialized;
193
 
  static HRESULT (WINAPI * func)(HWND,int,HANDLE,DWORD,LPSTR);
194
 
 
195
 
  if (!initialized)
196
 
    {
197
 
      static char *dllnames[] = { "shell32.dll", "shfolder.dll", NULL };
198
 
      void *handle;
199
 
      int i;
200
 
 
201
 
      initialized = 1;
202
 
 
203
 
      for (i=0, handle = NULL; !handle && dllnames[i]; i++)
204
 
        {
205
 
          handle = dlopen (dllnames[i], RTLD_LAZY);
206
 
          if (handle)
207
 
            {
208
 
              func = dlsym (handle, "SHGetFolderPathA");
209
 
              if (!func)
210
 
                {
211
 
                  dlclose (handle);
212
 
                  handle = NULL;
213
 
                }
214
 
            }
215
 
        }
216
 
    }
217
 
 
218
 
  if (func)
219
 
    return func (a,b,c,d,e);
220
 
  else
221
 
    return -1;
222
 
}
223
 
 
224
 
 
225
 
static char *
226
 
find_program_in_registry (const char *name)
227
 
{
228
 
  char *program = NULL;
229
 
    
230
 
  program = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", name);
231
 
  if (program)
232
 
    {
233
 
      int i;
234
 
 
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++)
238
 
        {
239
 
          if (program[i] == '/')
240
 
            program[i] = '\\';
241
 
        }
242
 
    }
243
 
  return program;
244
 
}
245
 
 
246
 
 
247
 
static char *
248
 
find_program_in_inst_dir (const char *name)
249
 
{
250
 
  char *result = NULL;
251
 
  char *tmp;
252
 
 
253
 
  tmp = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
254
 
                                        "Software\\GNU\\GnuPG",
255
 
                                        "Install Directory");
256
 
  if (!tmp)
257
 
    return NULL;
258
 
 
259
 
  result = malloc (strlen (tmp) + 1 + strlen (name) + 1);
260
 
  if (!result)
261
 
    {
262
 
      free (tmp);
263
 
      return NULL;
264
 
    }
265
 
 
266
 
  strcpy (stpcpy (stpcpy (result, tmp), "\\"), name);
267
 
  free (tmp);
268
 
  if (access (result, F_OK))
269
 
    {
270
 
      free (result);
271
 
      return NULL;
272
 
    }
273
 
 
274
 
  return result;
275
 
}
276
 
 
277
 
 
278
 
static char *
279
 
find_program_at_standard_place (const char *name)
280
 
{
281
 
  char path[MAX_PATH];
282
 
  char *result = NULL;
283
 
      
284
 
  if (w32_shgetfolderpath (NULL, CSIDL_PROGRAM_FILES, NULL, 0, path) >= 0) 
285
 
    {
286
 
      result = malloc (strlen (path) + 1 + strlen (name) + 1);
287
 
      if (result)
288
 
        {
289
 
          strcpy (stpcpy (stpcpy (result, path), "\\"), name);
290
 
          if (access (result, F_OK))
291
 
            {
292
 
              free (result);
293
 
              result = NULL;
294
 
            }
295
 
        }
296
 
    }
297
 
  return result;
298
 
}
299
 
 
300
 
 
301
 
const char *
302
 
_gpgme_get_gpg_path (void)
303
 
{
304
 
  static char *gpg_program;
305
 
 
306
 
  LOCK (get_path_lock);
307
 
  if (!gpg_program)
308
 
    gpg_program = find_program_in_registry ("gpgProgram");
309
 
  if (!gpg_program)
310
 
    gpg_program = find_program_in_inst_dir ("gpg.exe");
311
 
  if (!gpg_program)
312
 
    gpg_program = find_program_at_standard_place ("GNU\\GnuPG\\gpg.exe");
313
 
  UNLOCK (get_path_lock);
314
 
  return gpg_program;
315
 
}
316
 
 
317
 
 
318
 
const char *
319
 
_gpgme_get_gpgsm_path (void)
320
 
{
321
 
  static char *gpgsm_program;
322
 
 
323
 
  LOCK (get_path_lock);
324
 
  if (!gpgsm_program)
325
 
    gpgsm_program = find_program_in_registry ("gpgsmProgram");
326
 
  if (!gpgsm_program)
327
 
    gpgsm_program = find_program_in_inst_dir ("gpgsm.exe");
328
 
  if (!gpgsm_program)
329
 
    gpgsm_program = find_program_at_standard_place ("GNU\\GnuPG\\gpgsm.exe");
330
 
  UNLOCK (get_path_lock);
331
 
  return gpgsm_program;
332
 
}
333
 
 
334
 
 
335
 
const char *
336
 
_gpgme_get_gpgconf_path (void)
337
 
{
338
 
  static char *gpgconf_program;
339
 
 
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)
346
 
    gpgconf_program
347
 
      = find_program_at_standard_place ("GNU\\GnuPG\\gpgconf.exe");
348
 
  UNLOCK (get_path_lock);
349
 
  return gpgconf_program;
350
 
}
351
 
 
352
 
 
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. */
356
 
int
357
 
_gpgme_get_conf_int (const char *key, int *value)
358
 
{
359
 
  char *tmp = read_w32_registry_string (NULL, "Software\\GNU\\gpgme", key);
360
 
  if (!tmp)
361
 
    return 0;
362
 
  *value = atoi (tmp);
363
 
  free (tmp);
364
 
  return 1;
365
 
}