Fixed a nasty bug in scdaemon which led to a card reset if the card was
[gnupg.git] / jnlib / 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 JNLIB.
5  *
6  * JNLIB is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 3 of
9  * the License, or (at your option) any later version.
10  *
11  * JNLIB is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #ifdef HAVE_W32_SYSTEM
22  /* This module is only used in this environment */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdarg.h>
28 #include <windows.h>
29
30 #include "libjnlib-config.h"
31 #include "w32help.h"
32
33 static HKEY
34 get_root_key(const char *root)
35 {
36   HKEY root_key;
37   
38   if (!root)
39     root_key = HKEY_CURRENT_USER;
40   else if (!strcmp( root, "HKEY_CLASSES_ROOT" ) )
41     root_key = HKEY_CLASSES_ROOT;
42   else if (!strcmp( root, "HKEY_CURRENT_USER" ) )
43     root_key = HKEY_CURRENT_USER;
44   else if (!strcmp( root, "HKEY_LOCAL_MACHINE" ) )
45     root_key = HKEY_LOCAL_MACHINE;
46   else if (!strcmp( root, "HKEY_USERS" ) )
47     root_key = HKEY_USERS;
48   else if (!strcmp( root, "HKEY_PERFORMANCE_DATA" ) )
49     root_key = HKEY_PERFORMANCE_DATA;
50   else if (!strcmp( root, "HKEY_CURRENT_CONFIG" ) )
51     root_key = HKEY_CURRENT_CONFIG;
52   else
53     return NULL;
54   
55   return root_key;
56 }
57
58
59 /* Return a string from the Win32 Registry or NULL in case of error.
60    Caller must release the return value.  A NULL for root is an alias
61    for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn.  */
62 char *
63 read_w32_registry_string (const char *root, const char *dir, const char *name)
64 {
65   HKEY root_key, key_handle;
66   DWORD n1, nbytes, type;
67   char *result = NULL;
68   
69   if ( !(root_key = get_root_key(root) ) )
70     return NULL;
71   
72   if ( RegOpenKeyEx( root_key, dir, 0, KEY_READ, &key_handle ) )
73     {
74       if (root)
75         return NULL; /* No need for a RegClose, so return immediately. */
76       /* It seems to be common practise to fall back to HKLM. */
77       if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) )
78         return NULL; /* Still no need for a RegClose. */
79     }
80
81   nbytes = 1;
82   if (RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) )
83     goto leave;
84   result = jnlib_malloc ((n1=nbytes+1));
85   if (!result)
86     goto leave;
87   if (RegQueryValueEx( key_handle, name, 0, &type, result, &n1 ))
88     {
89       jnlib_free (result);
90       result = NULL;
91       goto leave;
92     }
93   result[nbytes] = 0; /* Make sure it is a string.  */
94   if (type == REG_EXPAND_SZ && strchr (result, '%'))
95     {
96       char *tmp;
97       
98       n1 += 1000;
99       tmp = jnlib_malloc (n1+1);
100       if (!tmp)
101         goto leave;
102       nbytes = ExpandEnvironmentStrings (result, tmp, n1);
103       if (nbytes && nbytes > n1)
104         {
105           jnlib_free (tmp);
106           n1 = nbytes;
107           tmp = jnlib_malloc (n1 + 1);
108           if (!tmp)
109             goto leave;
110           nbytes = ExpandEnvironmentStrings (result, tmp, n1);
111           if (nbytes && nbytes > n1)
112             {
113               /* Oops - truncated, better don't expand at all.  */
114               jnlib_free (tmp); 
115               goto leave;
116             }
117           tmp[nbytes] = 0;
118           jnlib_free (result);
119           result = tmp;
120         }
121       else if (nbytes)
122         {
123           /* Okay, reduce the length.  */
124           tmp[nbytes] = 0;
125           jnlib_free (result);
126           result = jnlib_malloc (strlen (tmp)+1);
127           if (!result)
128             result = tmp;
129             else 
130               {
131                 strcpy (result, tmp);
132                 jnlib_free (tmp);
133               }
134         }
135       else 
136         {  
137           /* Error - don't expand.  */
138           jnlib_free (tmp);
139         }
140     }
141
142  leave:
143   RegCloseKey (key_handle);
144   return result;
145 }
146
147
148 int
149 write_w32_registry_string (const char *root, const char *dir, 
150                            const char *name, const char *value)
151 {
152   HKEY root_key, reg_key;
153   
154   if ( !(root_key = get_root_key(root) ) )
155     return -1;
156   
157   if ( RegOpenKeyEx( root_key, dir, 0, KEY_WRITE, &reg_key ) 
158        != ERROR_SUCCESS )
159     return -1;
160   
161   if ( RegSetValueEx (reg_key, name, 0, REG_SZ, (BYTE *)value, 
162                       strlen( value ) ) != ERROR_SUCCESS )
163     {
164       if ( RegCreateKey( root_key, name, &reg_key ) != ERROR_SUCCESS ) 
165         {
166           RegCloseKey(reg_key);
167           return -1;
168         }
169       if ( RegSetValueEx (reg_key, name, 0, REG_SZ, (BYTE *)value,
170                           strlen( value ) ) != ERROR_SUCCESS )
171         {
172           RegCloseKey(reg_key);
173           return -1;
174         }
175     }
176   
177   RegCloseKey (reg_key);
178   
179   return 0;
180 }
181
182 #endif /*HAVE_W32_SYSTEM*/