chiark / gitweb /
gpg agent lockup fix: Interrupt main loop when active_connections_value==0
[gnupg2.git] / common / w32-reg.c
1 /* w32-reg.c -  MS-Windows Registry access
2  * Copyright (C) 1999, 2002, 2007 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify it
7  * under the terms of either
8  *
9  *   - the GNU Lesser General Public License as published by the Free
10  *     Software Foundation; either version 3 of the License, or (at
11  *     your option) any later version.
12  *
13  * or
14  *
15  *   - the GNU General Public License as published by the Free
16  *     Software Foundation; either version 2 of the License, or (at
17  *     your option) any later version.
18  *
19  * or both in parallel, as here.
20  *
21  * GnuPG is distributed in the hope that it will be useful, but
22  * WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * General Public License for more details.
25  *
26  * You should have received a copies of the GNU General Public License
27  * and the GNU Lesser General Public License along with this program;
28  * if not, see <https://www.gnu.org/licenses/>.
29  */
30
31 #include <config.h>
32 #ifdef HAVE_W32_SYSTEM
33  /* This module is only used in this environment */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <stdarg.h>
39 #ifdef HAVE_WINSOCK2_H
40 # include <winsock2.h>
41 #endif
42 #include <windows.h>
43
44 #include "util.h"
45 #include "common-defs.h"
46 #include "utf8conv.h"
47 #include "w32help.h"
48
49
50 static HKEY
51 get_root_key(const char *root)
52 {
53   HKEY root_key;
54
55   if (!root)
56     root_key = HKEY_CURRENT_USER;
57   else if (!strcmp( root, "HKEY_CLASSES_ROOT" ) )
58     root_key = HKEY_CLASSES_ROOT;
59   else if (!strcmp( root, "HKEY_CURRENT_USER" ) )
60     root_key = HKEY_CURRENT_USER;
61   else if (!strcmp( root, "HKEY_LOCAL_MACHINE" ) )
62     root_key = HKEY_LOCAL_MACHINE;
63   else if (!strcmp( root, "HKEY_USERS" ) )
64     root_key = HKEY_USERS;
65   else if (!strcmp( root, "HKEY_PERFORMANCE_DATA" ) )
66     root_key = HKEY_PERFORMANCE_DATA;
67   else if (!strcmp( root, "HKEY_CURRENT_CONFIG" ) )
68     root_key = HKEY_CURRENT_CONFIG;
69   else
70     return NULL;
71
72   return root_key;
73 }
74
75
76 /* Return a string from the Win32 Registry or NULL in case of error.
77    Caller must release the return value.  A NULL for root is an alias
78    for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn.  */
79 char *
80 read_w32_registry_string (const char *root, const char *dir, const char *name)
81 {
82 #ifdef HAVE_W32CE_SYSTEM
83   HKEY root_key, key_handle;
84   DWORD n1, nbytes, type;
85   char *result = NULL;
86   wchar_t *wdir, *wname;
87
88   if ( !(root_key = get_root_key(root) ) )
89     return NULL;
90
91   wdir = utf8_to_wchar (dir);
92   if (!wdir)
93     return NULL;
94
95   if (RegOpenKeyEx (root_key, wdir, 0, KEY_READ, &key_handle) )
96     {
97       if (root)
98         {
99           xfree (wdir);
100           return NULL; /* No need for a RegClose, so return immediately. */
101         }
102       /* It seems to be common practise to fall back to HKLM. */
103       if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, wdir, 0, KEY_READ, &key_handle) )
104         {
105           xfree (wdir);
106           return NULL; /* Still no need for a RegClose. */
107         }
108     }
109   xfree (wdir);
110
111   if (name)
112     {
113       wname = utf8_to_wchar (name);
114       if (!wname)
115         goto leave;
116     }
117   else
118     wname = NULL;
119
120   nbytes = 2;
121   if (RegQueryValueEx (key_handle, wname, 0, NULL, NULL, &nbytes))
122     goto leave;
123   result = xtrymalloc ((n1=nbytes+2));
124   if (!result)
125     goto leave;
126   if (RegQueryValueEx (key_handle, wname, 0, &type, result, &n1))
127     {
128       xfree (result);
129       result = NULL;
130       goto leave;
131     }
132   result[nbytes] = 0;   /* Make sure it is a string.  */
133   result[nbytes+1] = 0;
134   if (type == REG_SZ || type == REG_EXPAND_SZ)
135     {
136       wchar_t *tmp = (void*)result;
137       result = wchar_to_utf8 (tmp);
138       xfree (tmp);
139     }
140
141  leave:
142   xfree (wname);
143   RegCloseKey (key_handle);
144   return result;
145 #else /*!HAVE_W32CE_SYSTEM*/
146   HKEY root_key, key_handle;
147   DWORD n1, nbytes, type;
148   char *result = NULL;
149
150   if ( !(root_key = get_root_key(root) ) )
151     return NULL;
152
153   if (RegOpenKeyEx (root_key, dir, 0, KEY_READ, &key_handle) )
154     {
155       if (root)
156         return NULL; /* No need for a RegClose, so return immediately. */
157       /* It seems to be common practise to fall back to HKLM. */
158       if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) )
159         return NULL; /* Still no need for a RegClose. */
160     }
161
162   nbytes = 1;
163   if (RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) )
164     goto leave;
165   result = xtrymalloc ((n1=nbytes+1));
166   if (!result)
167     goto leave;
168   if (RegQueryValueEx( key_handle, name, 0, &type, result, &n1 ))
169     {
170       xfree (result);
171       result = NULL;
172       goto leave;
173     }
174   result[nbytes] = 0; /* Make sure it is a string.  */
175   if (type == REG_EXPAND_SZ && strchr (result, '%'))
176     {
177       char *tmp;
178
179       n1 += 1000;
180       tmp = xtrymalloc (n1+1);
181       if (!tmp)
182         goto leave;
183       nbytes = ExpandEnvironmentStrings (result, tmp, n1);
184       if (nbytes && nbytes > n1)
185         {
186           xfree (tmp);
187           n1 = nbytes;
188           tmp = xtrymalloc (n1 + 1);
189           if (!tmp)
190             goto leave;
191           nbytes = ExpandEnvironmentStrings (result, tmp, n1);
192           if (nbytes && nbytes > n1)
193             {
194               /* Oops - truncated, better don't expand at all.  */
195               xfree (tmp);
196               goto leave;
197             }
198           tmp[nbytes] = 0;
199           xfree (result);
200           result = tmp;
201         }
202       else if (nbytes)
203         {
204           /* Okay, reduce the length.  */
205           tmp[nbytes] = 0;
206           xfree (result);
207           result = xtrymalloc (strlen (tmp)+1);
208           if (!result)
209             result = tmp;
210             else
211               {
212                 strcpy (result, tmp);
213                 xfree (tmp);
214               }
215         }
216       else
217         {
218           /* Error - don't expand.  */
219           xfree (tmp);
220         }
221     }
222
223  leave:
224   RegCloseKey (key_handle);
225   return result;
226 #endif /*!HAVE_W32CE_SYSTEM*/
227 }
228
229
230 #endif /*HAVE_W32_SYSTEM*/