1 /*
2 * COPYRIGHT: GPL, see COPYING in the top level directory
3 * PROJECT: ReactOS win32 kernel mode subsystem server
4 * PURPOSE: Registry loading and storing
5 * FILE: win32ss/user/ntuser/misc/registry.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 NTSTATUS
15 NTAPI
RegOpenKey(LPCWSTR pwszKeyName,PHKEY phkey)16 RegOpenKey(
17 LPCWSTR pwszKeyName,
18 PHKEY phkey)
19 {
20 NTSTATUS Status;
21 OBJECT_ATTRIBUTES ObjectAttributes;
22 UNICODE_STRING ustrKeyName;
23 HKEY hkey;
24
25 /* Initialize the key name */
26 RtlInitUnicodeString(&ustrKeyName, pwszKeyName);
27
28 /* Initialize object attributes */
29 InitializeObjectAttributes(&ObjectAttributes,
30 &ustrKeyName,
31 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
32 NULL,
33 NULL);
34
35 /* Open the key */
36 Status = ZwOpenKey((PHANDLE)&hkey, KEY_READ, &ObjectAttributes);
37 if (NT_SUCCESS(Status))
38 {
39 *phkey = hkey;
40 }
41
42 return Status;
43 }
44
45 NTSTATUS
46 NTAPI
RegQueryValue(IN HKEY hkey,IN PCWSTR pwszValueName,IN ULONG ulType,OUT PVOID pvData,IN OUT PULONG pcbValue)47 RegQueryValue(
48 IN HKEY hkey,
49 IN PCWSTR pwszValueName,
50 IN ULONG ulType,
51 OUT PVOID pvData,
52 IN OUT PULONG pcbValue)
53 {
54 NTSTATUS Status;
55 UNICODE_STRING ustrValueName;
56 BYTE ajBuffer[100];
57 PKEY_VALUE_PARTIAL_INFORMATION pInfo;
58 ULONG cbInfoSize, cbDataSize;
59
60 /* Check if the local buffer is sufficient */
61 cbInfoSize = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[*pcbValue]);
62 if (cbInfoSize <= sizeof(ajBuffer))
63 {
64 pInfo = (PVOID)ajBuffer;
65 }
66 else
67 {
68 /* It's not, allocate a sufficient buffer */
69 pInfo = ExAllocatePoolWithTag(PagedPool, cbInfoSize, TAG_TEMP);
70 if (!pInfo)
71 {
72 return STATUS_INSUFFICIENT_RESOURCES;
73 }
74 }
75
76 /* Query the value */
77 RtlInitUnicodeString(&ustrValueName, pwszValueName);
78 Status = ZwQueryValueKey(hkey,
79 &ustrValueName,
80 KeyValuePartialInformation,
81 (PVOID)pInfo,
82 cbInfoSize,
83 &cbInfoSize);
84
85 /* Note: STATUS_BUFFER_OVERFLOW is not a success */
86 if (NT_SUCCESS(Status))
87 {
88 cbDataSize = pInfo->DataLength;
89
90 /* Did we get the right type */
91 if (pInfo->Type != ulType)
92 {
93 Status = STATUS_OBJECT_TYPE_MISMATCH;
94 }
95 else if (cbDataSize > *pcbValue)
96 {
97 Status = STATUS_BUFFER_TOO_SMALL;
98 }
99 else
100 {
101 /* Copy the contents to the caller */
102 RtlCopyMemory(pvData, pInfo->Data, cbDataSize);
103 }
104 }
105 else if ((Status == STATUS_BUFFER_OVERFLOW) || (Status == STATUS_BUFFER_TOO_SMALL))
106 {
107 _PRAGMA_WARNING_SUPPRESS(6102); /* cbInfoSize is initialized here! */
108 cbDataSize = cbInfoSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
109 }
110 else
111 {
112 cbDataSize = 0;
113 }
114
115 /* Return the data size to the caller */
116 *pcbValue = cbDataSize;
117
118 /* Cleanup */
119 if (pInfo != (PVOID)ajBuffer)
120 ExFreePoolWithTag(pInfo, TAG_TEMP);
121
122 return Status;
123 }
124
125 VOID
126 NTAPI
RegWriteSZ(HKEY hkey,PCWSTR pwszValue,PWSTR pwszData)127 RegWriteSZ(HKEY hkey, PCWSTR pwszValue, PWSTR pwszData)
128 {
129 UNICODE_STRING ustrValue;
130 UNICODE_STRING ustrData;
131
132 RtlInitUnicodeString(&ustrValue, pwszValue);
133 RtlInitUnicodeString(&ustrData, pwszData);
134 ZwSetValueKey(hkey, &ustrValue, 0, REG_SZ, &ustrData, ustrData.Length + sizeof(WCHAR));
135 }
136
137 VOID
138 NTAPI
RegWriteDWORD(HKEY hkey,PCWSTR pwszValue,DWORD dwData)139 RegWriteDWORD(HKEY hkey, PCWSTR pwszValue, DWORD dwData)
140 {
141 UNICODE_STRING ustrValue;
142
143 RtlInitUnicodeString(&ustrValue, pwszValue);
144 ZwSetValueKey(hkey, &ustrValue, 0, REG_DWORD, &dwData, sizeof(DWORD));
145 }
146
147 BOOL
148 NTAPI
RegReadDWORD(HKEY hkey,PCWSTR pwszValue,PDWORD pdwData)149 RegReadDWORD(HKEY hkey, PCWSTR pwszValue, PDWORD pdwData)
150 {
151 NTSTATUS Status;
152 ULONG cbSize = sizeof(DWORD);
153 Status = RegQueryValue(hkey, pwszValue, REG_DWORD, pdwData, &cbSize);
154 return NT_SUCCESS(Status);
155 }
156
157 NTSTATUS
158 NTAPI
RegOpenSectionKey(LPCWSTR pszSection,PHKEY phkey)159 RegOpenSectionKey(
160 LPCWSTR pszSection,
161 PHKEY phkey)
162 {
163 WCHAR szKey[MAX_PATH] =
164 L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\";
165
166 RtlStringCchCatW(szKey, _countof(szKey), pszSection);
167 return RegOpenKey(szKey, phkey);
168 }
169
170 DWORD
171 NTAPI
RegGetSectionDWORD(LPCWSTR pszSection,PCWSTR pszValue,DWORD dwDefault)172 RegGetSectionDWORD(LPCWSTR pszSection, PCWSTR pszValue, DWORD dwDefault)
173 {
174 HKEY hKey;
175 DWORD dwValue;
176
177 if (NT_ERROR(RegOpenSectionKey(pszSection, &hKey)))
178 return dwDefault;
179
180 if (!RegReadDWORD(hKey, pszValue, &dwValue))
181 dwValue = dwDefault;
182
183 ZwClose(hKey);
184 return dwValue;
185 }
186
187 _Success_(return!=FALSE)
188 BOOL
189 NTAPI
190 RegReadUserSetting(
191 _In_z_ PCWSTR pwszKeyName,
192 _In_z_ PCWSTR pwszValueName,
193 _In_ ULONG ulType,
194 _Out_writes_(cbDataSize) _When_(ulType == REG_SZ, _Post_z_) PVOID pvData,
195 _In_ ULONG cbDataSize)
196 {
197 NTSTATUS Status;
198 OBJECT_ATTRIBUTES ObjectAttributes;
199 UNICODE_STRING usCurrentUserKey, usKeyName, usValueName;
200 WCHAR awcBuffer[MAX_PATH];
201 HKEY hkey;
202 PKEY_VALUE_PARTIAL_INFORMATION pInfo;
203 ULONG cbInfoSize, cbReqSize;
204
205 /* Get the path of the current user's profile */
206 Status = RtlFormatCurrentUserKeyPath(&usCurrentUserKey);
207 if (!NT_SUCCESS(Status))
208 {
209 return FALSE;
210 }
211
212 /* Initialize empty key name */
213 RtlInitEmptyUnicodeString(&usKeyName, awcBuffer, sizeof(awcBuffer));
214
215 /* Append the current user key name */
216 Status = RtlAppendUnicodeStringToString(&usKeyName, &usCurrentUserKey);
217
218 /* Free the current user key name */
219 RtlFreeUnicodeString(&usCurrentUserKey);
220
221 /* Check for success */
222 if (!NT_SUCCESS(Status))
223 {
224 return FALSE;
225 }
226
227 /* Append a '\', we can trust in enough space left. */
228 usKeyName.Buffer[usKeyName.Length / sizeof(WCHAR)] = '\\';
229 usKeyName.Length += sizeof(WCHAR);
230
231 /* Append the subkey name */
232 Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName);
233 if (!NT_SUCCESS(Status))
234 {
235 return FALSE;
236 }
237
238 /* Initialize object attributes */
239 InitializeObjectAttributes(&ObjectAttributes,
240 &usKeyName,
241 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
242 NULL,
243 NULL);
244
245 /* Open the key */
246 Status = ZwOpenKey((PHANDLE)&hkey, KEY_READ, &ObjectAttributes);
247 if (!NT_SUCCESS(Status))
248 {
249 return FALSE;
250 }
251
252 /* Check if the local buffer is sufficient */
253 cbInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + cbDataSize;
254 if (cbInfoSize <= sizeof(awcBuffer))
255 {
256 pInfo = (PVOID)awcBuffer;
257 }
258 else
259 {
260 /* It's not, allocate a sufficient buffer */
261 pInfo = ExAllocatePoolWithTag(PagedPool, cbInfoSize, TAG_TEMP);
262 if (!pInfo)
263 {
264 ZwClose(hkey);
265 return FALSE;
266 }
267 }
268
269 /* Query the value */
270 RtlInitUnicodeString(&usValueName, pwszValueName);
271 Status = ZwQueryValueKey(hkey,
272 &usValueName,
273 KeyValuePartialInformation,
274 (PVOID)pInfo,
275 cbInfoSize,
276 &cbReqSize);
277 if (NT_SUCCESS(Status))
278 {
279 /* Did we get the right type */
280 if (pInfo->Type == ulType)
281 {
282 /* Copy the contents to the caller */
283 RtlCopyMemory(pvData, pInfo->Data, cbDataSize);
284 }
285 }
286
287 /* Cleanup */
288 ZwClose(hkey);
289 if (pInfo != (PVOID)awcBuffer)
290 ExFreePoolWithTag(pInfo, TAG_TEMP);
291
292 return NT_SUCCESS(Status);
293 }
294
295 _Success_(return != FALSE)
296 BOOL
297 NTAPI
RegWriteUserSetting(_In_z_ PCWSTR pwszKeyName,_In_z_ PCWSTR pwszValueName,_In_ ULONG ulType,_In_reads_bytes_ (cjDataSize)const VOID * pvData,_In_ ULONG cbDataSize)298 RegWriteUserSetting(
299 _In_z_ PCWSTR pwszKeyName,
300 _In_z_ PCWSTR pwszValueName,
301 _In_ ULONG ulType,
302 _In_reads_bytes_(cjDataSize) const VOID *pvData,
303 _In_ ULONG cbDataSize)
304 {
305 NTSTATUS Status;
306 OBJECT_ATTRIBUTES ObjectAttributes;
307 UNICODE_STRING usCurrentUserKey, usKeyName, usValueName;
308 WCHAR awcBuffer[MAX_PATH];
309 HKEY hkey;
310
311 // FIXME: Logged in user versus current process user?
312 /* Get the path of the current user's profile */
313 Status = RtlFormatCurrentUserKeyPath(&usCurrentUserKey);
314 if (!NT_SUCCESS(Status))
315 {
316 DPRINT1("RtlFormatCurrentUserKeyPath failed\n");
317 return FALSE;
318 }
319
320 /* Initialize empty key name */
321 RtlInitEmptyUnicodeString(&usKeyName, awcBuffer, sizeof(awcBuffer));
322
323 /* Append the current user key name */
324 Status = RtlAppendUnicodeStringToString(&usKeyName, &usCurrentUserKey);
325 if (!NT_SUCCESS(Status))
326 {
327 return FALSE;
328 }
329
330 /* Free the current user key name */
331 RtlFreeUnicodeString(&usCurrentUserKey);
332
333 /* Append a '\', we can trust in enough space left. */
334 usKeyName.Buffer[usKeyName.Length / sizeof(WCHAR)] = '\\';
335 usKeyName.Length += sizeof(WCHAR);
336
337 /* Append the subkey name */
338 Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName);
339 if (!NT_SUCCESS(Status))
340 {
341 DPRINT1("RtlAppendUnicodeToString failed with Status=0x%lx, buf:%u,%u\n",
342 Status, usKeyName.Length, usKeyName.MaximumLength);
343 return FALSE;
344 }
345
346 /* Initialize object attributes */
347 InitializeObjectAttributes(&ObjectAttributes,
348 &usKeyName,
349 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
350 NULL,
351 NULL);
352
353 /* Open or create the key */
354 Status = ZwCreateKey((PHANDLE)&hkey,
355 KEY_READ | KEY_WRITE,
356 &ObjectAttributes,
357 0,
358 NULL,
359 0,
360 NULL);
361 if(!NT_SUCCESS(Status))
362 {
363 DPRINT1("Failed to create key: 0x%x\n", Status);
364 return FALSE;
365 }
366
367 /* Initialize the value name string */
368 RtlInitUnicodeString(&usValueName, pwszValueName);
369
370 Status = ZwSetValueKey(hkey, &usValueName, 0, ulType, (PVOID)pvData, cbDataSize);
371 if(!NT_SUCCESS(Status))
372 {
373 DPRINT1("Failed to write reg key '%S' value '%S', Status = %lx\n",
374 pwszKeyName, pwszValueName, Status);
375 }
376
377 /* Cleanup */
378 ZwClose(hkey);
379
380 return NT_SUCCESS(Status);
381 }
382
383