OSDN Git Service

2923cbe86c82a9e04558d4292b42af34f353266f
[pf3gnuchains/pf3gnuchains4x.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, 2010, 2011 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 "ntdll.h"
21 #include <wchar.h>
22 #include <alloca.h>
23
24 /* Opens a key under the appropriate Cygwin key.
25    Do not use HKCU per MS KB 199190  */
26 static NTSTATUS
27 top_key (bool isHKLM, REGSAM access, PHANDLE top)
28 {
29   WCHAR rbuf[PATH_MAX], *p;
30   UNICODE_STRING rpath;
31   OBJECT_ATTRIBUTES attr;
32   NTSTATUS status;
33
34   InitializeObjectAttributes (&attr, &rpath, OBJ_CASE_INSENSITIVE, NULL, NULL);
35   if (isHKLM)
36     {
37       wcpcpy (rbuf, L"\\Registry\\Machine");
38       RtlInitUnicodeString (&rpath, rbuf);
39       status = NtOpenKey (top, access, &attr);
40     }
41   else
42     {
43       WCHAR name[128];
44       PCWSTR names[2] = {cygheap->user.get_windows_id (name),
45                          L".DEFAULT"};
46
47       p = wcpcpy (rbuf, L"\\Registry\\User\\");
48       for (int i = 0; i < 2; i++)
49         {
50           wcpcpy (p, names[i]);
51           RtlInitUnicodeString (&rpath, rbuf);
52           status = NtOpenKey (top, access, &attr);
53           if (NT_SUCCESS (status))
54             break;
55         }
56     }
57   return status;
58 }
59
60 reg_key::reg_key (HKEY top, REGSAM access, ...): _disposition (0)
61 {
62   va_list av;
63   va_start (av, access);
64   build_reg (top, access, av);
65   va_end (av);
66 }
67
68 reg_key::reg_key (bool isHKLM, REGSAM access, ...): _disposition (0)
69 {
70   va_list av;
71   HANDLE top;
72
73   key_is_invalid = top_key (isHKLM, access, &top);
74   if (NT_SUCCESS (key_is_invalid))
75     {
76       new (this) reg_key ((HKEY) top, access, L"SOFTWARE",
77                           _WIDE (CYGWIN_INFO_CYGWIN_REGISTRY_NAME), NULL);
78       NtClose (top);
79       if (key_is_invalid)
80         return;
81       top = key;
82       va_start (av, access);
83       build_reg ((HKEY) top, access, av);
84       va_end (av);
85       if (top != key)
86         NtClose (top);
87     }
88 }
89
90 void
91 reg_key::build_reg (HKEY top, REGSAM access, va_list av)
92 {
93   PWCHAR name;
94   HANDLE r;
95   UNICODE_STRING uname;
96   OBJECT_ATTRIBUTES attr;
97   NTSTATUS status;
98
99   if (top != HKEY_LOCAL_MACHINE && top != HKEY_CURRENT_USER)
100     r = (HANDLE) top;
101   else if (!NT_SUCCESS (top_key (top == HKEY_LOCAL_MACHINE, access, &r)))
102     return;
103   key_is_invalid = 0;
104   while ((name = va_arg (av, PWCHAR)) != NULL)
105     {
106       RtlInitUnicodeString (&uname, name);
107       InitializeObjectAttributes (&attr, &uname,
108                                   OBJ_CASE_INSENSITIVE | OBJ_OPENIF, r, NULL);
109
110       status = NtCreateKey (&key, access, &attr, 0, NULL,
111                             REG_OPTION_NON_VOLATILE, &_disposition);
112       if (r != (HANDLE) top)
113         NtClose (r);
114       r = key;
115       if (!NT_SUCCESS (status))
116         {
117           key_is_invalid = status;
118           debug_printf ("failed to create key %S in the registry", uname);
119           break;
120         }
121     }
122 }
123
124 /* Given the current registry key, return the specific DWORD value
125    requested.  Return def on failure. */
126
127 DWORD
128 reg_key::get_dword (PCWSTR name, DWORD def)
129 {
130   if (key_is_invalid)
131     return def;
132
133   NTSTATUS status;
134   UNICODE_STRING uname;
135   ULONG size = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + sizeof (DWORD);
136   ULONG rsize;
137   PKEY_VALUE_PARTIAL_INFORMATION vbuf = (PKEY_VALUE_PARTIAL_INFORMATION)
138                                       alloca (size);
139
140   RtlInitUnicodeString (&uname, name);
141   status = NtQueryValueKey (key, &uname, KeyValuePartialInformation, vbuf,
142                             size, &rsize);
143   if (status != STATUS_SUCCESS || vbuf->Type != REG_DWORD)
144     return def;
145   DWORD *dst = (DWORD *) vbuf->Data;
146   return *dst;
147 }
148
149 /* Given the current registry key, set a specific DWORD value. */
150
151 NTSTATUS
152 reg_key::set_dword (PCWSTR name, DWORD val)
153 {
154   if (key_is_invalid)
155     return key_is_invalid;
156
157   DWORD value = (DWORD) val;
158   UNICODE_STRING uname;
159   RtlInitUnicodeString (&uname, name);
160   return NtSetValueKey (key, &uname, 0, REG_DWORD, &value, sizeof (value));
161 }
162
163 /* Given the current registry key, return the specific string value
164    requested.  Return zero on success, non-zero on failure. */
165
166 NTSTATUS
167 reg_key::get_string (PCWSTR name, PWCHAR dst, size_t max, PCWSTR def)
168 {
169   NTSTATUS status;
170
171   if (key_is_invalid)
172     {
173       status = key_is_invalid;
174       if (def != NULL)
175         wcpncpy (dst, def, max);
176     }
177   else
178     {
179       UNICODE_STRING uname;
180       ULONG size = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + max * sizeof (WCHAR);
181       ULONG rsize;
182       PKEY_VALUE_PARTIAL_INFORMATION vbuf = (PKEY_VALUE_PARTIAL_INFORMATION)
183                                           alloca (size);
184
185       RtlInitUnicodeString (&uname, name);
186       status = NtQueryValueKey (key, &uname, KeyValuePartialInformation, vbuf,
187                                 size, &rsize);
188       if (status != STATUS_SUCCESS || vbuf->Type != REG_SZ)
189         wcpncpy (dst, def, max);
190       else
191         wcpncpy (dst, (PWCHAR) vbuf->Data, max);
192     }
193   return status;
194 }
195
196 /* Given the current registry key, set a specific string value. */
197
198 NTSTATUS
199 reg_key::set_string (PCWSTR name, PCWSTR src)
200 {
201   if (key_is_invalid)
202     return key_is_invalid;
203
204   UNICODE_STRING uname;
205   RtlInitUnicodeString (&uname, name);
206   return NtSetValueKey (key, &uname, 0, REG_SZ, (PVOID) src,
207                         (wcslen (src) + 1) * sizeof (WCHAR));
208 }
209
210 reg_key::~reg_key ()
211 {
212   if (!key_is_invalid)
213     NtClose (key);
214   key_is_invalid = 1;
215 }
216
217 PWCHAR
218 get_registry_hive_path (PCWSTR name, PWCHAR path)
219 {
220   if (!name || !path)
221     return NULL;
222
223   WCHAR key[256];
224   UNICODE_STRING buf;
225   tmp_pathbuf tp;
226   tp.u_get (&buf);
227   NTSTATUS status;
228
229   RTL_QUERY_REGISTRY_TABLE tab[2] = {
230     { NULL, RTL_QUERY_REGISTRY_NOEXPAND | RTL_QUERY_REGISTRY_DIRECT
231             | RTL_QUERY_REGISTRY_REQUIRED,
232       L"ProfileImagePath", &buf, REG_NONE, NULL, 0 },
233     { NULL, 0, NULL, NULL, 0, NULL, 0 }
234   };
235   wcpcpy (wcpcpy (key, L"ProfileList\\"), name);
236   status = RtlQueryRegistryValues (RTL_REGISTRY_WINDOWS_NT, key, tab,
237                                    NULL, NULL);
238   if (!NT_SUCCESS (status) || buf.Length == 0)
239     {
240       debug_printf ("ProfileImagePath for %W not found, status %p", name,
241                     status);
242       return NULL;
243     }
244   wcpcpy (path, L"\\??\\");
245   ExpandEnvironmentStringsW (buf.Buffer, path + 4, NT_MAX_PATH - 4);
246   debug_printf ("ProfileImagePath for %W: %W", name, path);
247   return path;
248 }
249
250 void
251 load_registry_hive (PCWSTR name)
252 {
253   if (!name)
254     return;
255
256   /* Fetch the path. */
257   tmp_pathbuf tp;
258   PWCHAR path = tp.w_get ();
259   if (!get_registry_hive_path (name, path))
260     return;
261
262   WCHAR key[256];
263   UNICODE_STRING ukey, upath;
264   OBJECT_ATTRIBUTES key_attr, path_attr;
265   NTSTATUS status;
266
267   /* Create the object attributes for key and path. */
268   wcpcpy (wcpcpy (key, L"\\Registry\\User\\"), name);
269   RtlInitUnicodeString (&ukey, key);
270   InitializeObjectAttributes (&key_attr, &ukey, OBJ_CASE_INSENSITIVE,
271                               NULL, NULL);
272   wcscat (path, L"\\NTUSER.DAT");
273   RtlInitUnicodeString (&upath, path);
274   InitializeObjectAttributes (&path_attr, &upath, OBJ_CASE_INSENSITIVE,
275                               NULL, NULL);
276   /* Load file into key. */
277   status = NtLoadKey (&key_attr, &path_attr);
278   if (!NT_SUCCESS (status))
279     debug_printf ("Loading user registry hive %S into %S failed: %p",
280                   &upath, &ukey, status);
281   else
282     debug_printf ("Loading user registry hive %S into %S SUCCEEDED: %p",
283                   &upath, &ukey, status);
284 }