OSDN Git Service

* dcrt0.cc (dll_crt0_1): Move internal locale setting prior to potential
[pf3gnuchains/pf3gnuchains3x.git] / winsup / cygwin / registry.cc
1 /* registry.cc: registry interface
2
3    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4    2005, 2006, 2007, 2008, 2009 Red Hat, Inc.
5
6 This file is part of Cygwin.
7
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
10 details. */
11
12 #include "winsup.h"
13 #include "registry.h"
14 #include "cygerrno.h"
15 #include "path.h"
16 #include "fhandler.h"
17 #include "dtable.h"
18 #include "cygheap.h"
19 #include "tls_pbuf.h"
20 #include <wchar.h>
21
22 reg_key::reg_key (HKEY top, REGSAM access, ...): _disposition (0)
23 {
24   va_list av;
25   va_start (av, access);
26   build_reg (top, access, av);
27   va_end (av);
28 }
29
30 /* Opens a key under the appropriate Cygwin key.
31    Do not use HKCU per MS KB 199190  */
32
33 reg_key::reg_key (bool isHKLM, REGSAM access, ...): _disposition (0)
34 {
35   va_list av;
36   HKEY top;
37
38   if (isHKLM)
39     top = HKEY_LOCAL_MACHINE;
40   else
41     {
42       char name[128];
43       const char *names[2] = {cygheap->user.get_windows_id (name), ".DEFAULT"};
44       for (int i = 0; i < 2; i++)
45         {
46           key_is_invalid = RegOpenKeyEx (HKEY_USERS, names[i], 0, access, &top);
47           if (key_is_invalid == ERROR_SUCCESS)
48             goto OK;
49           debug_printf ("HKU\\%s failed, Win32 error %ld", names[i], key_is_invalid);
50         }
51       return;
52     }
53 OK:
54   new (this) reg_key (top, access, "SOFTWARE",
55                       CYGWIN_INFO_CYGWIN_REGISTRY_NAME, NULL);
56   if (top != HKEY_LOCAL_MACHINE)
57     RegCloseKey (top);
58   if (key_is_invalid)
59     return;
60
61   top = key;
62   va_start (av, access);
63   build_reg (top, access, av);
64   va_end (av);
65   if (top != key)
66     RegCloseKey (top);
67 }
68
69 void
70 reg_key::build_reg (HKEY top, REGSAM access, va_list av)
71 {
72   char *name;
73   HKEY r = top;
74   key_is_invalid = 0;
75
76   /* FIXME: Most of the time a valid mount area should exist.  Perhaps
77      we should just try an open of the correct key first and only resort
78      to this method in the unlikely situation that it's the first time
79      the current mount areas are being used. */
80
81   while ((name = va_arg (av, char *)) != NULL)
82     {
83       int res = RegCreateKeyExA (r,
84                                  name,
85                                  0,
86                                  NULL,
87                                  REG_OPTION_NON_VOLATILE,
88                                  access,
89                                  &sec_none_nih,
90                                  &key,
91                                  &_disposition);
92       if (r != top)
93         RegCloseKey (r);
94       r = key;
95       if (res != ERROR_SUCCESS)
96         {
97           key_is_invalid = res;
98           debug_printf ("failed to create key %s in the registry", name);
99           break;
100         }
101     }
102 }
103
104 /* Given the current registry key, return the specific int value
105    requested.  Return def on failure. */
106
107 int
108 reg_key::get_int (const char *name, int def)
109 {
110   DWORD type;
111   DWORD dst;
112   DWORD size = sizeof (dst);
113
114   if (key_is_invalid)
115     return def;
116
117   LONG res = RegQueryValueExA (key, name, 0, &type, (LPBYTE) &dst, &size);
118
119   if (type != REG_DWORD || res != ERROR_SUCCESS)
120     return def;
121
122   return dst;
123 }
124
125 int
126 reg_key::get_int (const PWCHAR name, int def)
127 {
128   DWORD type;
129   DWORD dst;
130   DWORD size = sizeof (dst);
131
132   if (key_is_invalid)
133     return def;
134
135   LONG res = RegQueryValueExW (key, name, 0, &type, (LPBYTE) &dst, &size);
136
137   if (type != REG_DWORD || res != ERROR_SUCCESS)
138     return def;
139
140   return dst;
141 }
142
143 /* Given the current registry key, set a specific int value. */
144
145 int
146 reg_key::set_int (const char *name, int val)
147 {
148   DWORD value = val;
149   if (key_is_invalid)
150     return key_is_invalid;
151
152   return (int) RegSetValueExA (key, name, 0, REG_DWORD,
153                                (const BYTE *) &value, sizeof (value));
154 }
155
156 int
157 reg_key::set_int (const PWCHAR name, int val)
158 {
159   DWORD value = val;
160   if (key_is_invalid)
161     return key_is_invalid;
162
163   return (int) RegSetValueExW (key, name, 0, REG_DWORD,
164                                (const BYTE *) &value, sizeof (value));
165 }
166
167 /* Given the current registry key, return the specific string value
168    requested.  Return zero on success, non-zero on failure. */
169
170 int
171 reg_key::get_string (const char *name, char *dst, size_t max, const char *def)
172 {
173   DWORD size = max;
174   DWORD type;
175   LONG res;
176
177   if (key_is_invalid)
178     res = key_is_invalid;
179   else
180     res = RegQueryValueExA (key, name, 0, &type, (LPBYTE) dst, &size);
181
182   if ((def != 0) && ((type != REG_SZ) || (res != ERROR_SUCCESS)))
183     strcpy (dst, def);
184   return (int) res;
185 }
186
187 int
188 reg_key::get_string (const PWCHAR name, PWCHAR dst, size_t max, const PWCHAR def)
189 {
190   DWORD size = max;
191   DWORD type;
192   LONG res;
193
194   if (key_is_invalid)
195     res = key_is_invalid;
196   else
197     res = RegQueryValueExW (key, name, 0, &type, (LPBYTE) dst, &size);
198
199   if ((def != 0) && ((type != REG_SZ) || (res != ERROR_SUCCESS)))
200     wcscpy (dst, def);
201   return (int) res;
202 }
203
204 /* Given the current registry key, set a specific string value. */
205
206 int
207 reg_key::set_string (const char *name, const char *src)
208 {
209   if (key_is_invalid)
210     return key_is_invalid;
211   return (int) RegSetValueExA (key, name, 0, REG_SZ, (const BYTE*) src,
212                                strlen (src) + 1);
213 }
214
215 int
216 reg_key::set_string (const PWCHAR name, const PWCHAR src)
217 {
218   if (key_is_invalid)
219     return key_is_invalid;
220   return (int) RegSetValueExW (key, name, 0, REG_SZ, (const BYTE*) src,
221                                (wcslen (src) + 1) * sizeof (WCHAR));
222 }
223
224 /* Return the handle to key. */
225
226 HKEY
227 reg_key::get_key ()
228 {
229   return key;
230 }
231
232 /* Delete subkey of current key.  Returns the error code from the
233    RegDeleteKeyA invocation. */
234
235 int
236 reg_key::kill (const char *name)
237 {
238   if (key_is_invalid)
239     return key_is_invalid;
240   return RegDeleteKeyA (key, name);
241 }
242
243 /* Delete the value specified by name of current key.  Returns the error code
244    from the RegDeleteValueA invocation. */
245
246 int
247 reg_key::killvalue (const char *name)
248 {
249   if (key_is_invalid)
250     return key_is_invalid;
251   return RegDeleteValueA (key, name);
252 }
253
254 reg_key::~reg_key ()
255 {
256   if (!key_is_invalid)
257     RegCloseKey (key);
258   key_is_invalid = 1;
259 }
260
261 PWCHAR
262 get_registry_hive_path (const PWCHAR name, PWCHAR path)
263 {
264   WCHAR key[256], *kend;
265   HKEY hkey;
266
267   if (!name || !path)
268     return NULL;
269   kend = wcpcpy (key, L"SOFTWARE\\Microsoft\\WindowsNT\\CurrentVersion\\ProfileList\\");
270   wcpcpy (kend, name);
271   if (!RegOpenKeyExW (HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hkey))
272     {
273       tmp_pathbuf tp;
274       PWCHAR buf = tp.w_get ();
275       DWORD type, siz;
276
277       path[0] = L'\0';
278       if (!RegQueryValueExW (hkey, L"ProfileImagePath", 0, &type,
279                              (BYTE *)buf, (siz = NT_MAX_PATH, &siz)))
280         ExpandEnvironmentStringsW (buf, path, NT_MAX_PATH);
281       RegCloseKey (hkey);
282       if (path[0])
283         return path;
284     }
285   debug_printf ("HKLM\\%W not found", key);
286   return NULL;
287 }
288
289 void
290 load_registry_hive (const PWCHAR name)
291 {
292   tmp_pathbuf tp;
293   PWCHAR path = tp.w_get ();
294   HKEY hkey;
295   LONG ret;
296
297   if (!name)
298     return;
299   /* Check if user hive is already loaded. */
300   if (!RegOpenKeyExW (HKEY_USERS, name, 0, KEY_READ, &hkey))
301     {
302       debug_printf ("User registry hive for %W already exists", name);
303       RegCloseKey (hkey);
304       return;
305     }
306   if (get_registry_hive_path (name, path))
307     {
308       wcscat (path, L"\\NTUSER.DAT");
309       if ((ret = RegLoadKeyW (HKEY_USERS, name, path)) != ERROR_SUCCESS)
310         debug_printf ("Loading user registry hive for %W failed: %d", name, ret);
311     }
312 }
313