OSDN Git Service

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