a1995aba055874c233a8c05fca1303e662871f55
[reactos.git] / win32ss / user / ntuser / misc / registry.c
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
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
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
126 VOID
127 NTAPI
128 RegWriteSZ(HKEY hkey, PWSTR pwszValue, PWSTR pwszData)
129 {
130 UNICODE_STRING ustrValue;
131 UNICODE_STRING ustrData;
132
133 RtlInitUnicodeString(&ustrValue, pwszValue);
134 RtlInitUnicodeString(&ustrData, pwszData);
135 ZwSetValueKey(hkey, &ustrValue, 0, REG_SZ, &ustrData, ustrData.Length + sizeof(WCHAR));
136 }
137
138 VOID
139 NTAPI
140 RegWriteDWORD(HKEY hkey, PWSTR pwszValue, DWORD dwData)
141 {
142 UNICODE_STRING ustrValue;
143
144 RtlInitUnicodeString(&ustrValue, pwszValue);
145 ZwSetValueKey(hkey, &ustrValue, 0, REG_DWORD, &dwData, sizeof(DWORD));
146 }
147
148 BOOL
149 NTAPI
150 RegReadDWORD(HKEY hkey, PWSTR pwszValue, PDWORD pdwData)
151 {
152 NTSTATUS Status;
153 ULONG cbSize = sizeof(DWORD);
154 Status = RegQueryValue(hkey, pwszValue, REG_DWORD, pdwData, &cbSize);
155 return NT_SUCCESS(Status);
156 }
157
158 _Success_(return!=FALSE)
159 BOOL
160 NTAPI
161 RegReadUserSetting(
162 _In_z_ PCWSTR pwszKeyName,
163 _In_z_ PCWSTR pwszValueName,
164 _In_ ULONG ulType,
165 _Out_writes_(cbDataSize) _When_(ulType == REG_SZ, _Post_z_) PVOID pvData,
166 _In_ ULONG cbDataSize)
167 {
168 NTSTATUS Status;
169 OBJECT_ATTRIBUTES ObjectAttributes;
170 UNICODE_STRING usCurrentUserKey, usKeyName, usValueName;
171 WCHAR awcBuffer[MAX_PATH];
172 HKEY hkey;
173 PKEY_VALUE_PARTIAL_INFORMATION pInfo;
174 ULONG cbInfoSize, cbReqSize;
175
176 /* Get the path of the current user's profile */
177 Status = RtlFormatCurrentUserKeyPath(&usCurrentUserKey);
178 if (!NT_SUCCESS(Status))
179 {
180 return FALSE;
181 }
182
183 /* Initialize empty key name */
184 RtlInitEmptyUnicodeString(&usKeyName, awcBuffer, sizeof(awcBuffer));
185
186 /* Append the current user key name */
187 Status = RtlAppendUnicodeStringToString(&usKeyName, &usCurrentUserKey);
188
189 /* Free the current user key name */
190 RtlFreeUnicodeString(&usCurrentUserKey);
191
192 /* Check for success */
193 if (!NT_SUCCESS(Status))
194 {
195 return FALSE;
196 }
197
198 /* Append a '\', we can trust in enough space left. */
199 usKeyName.Buffer[usKeyName.Length / sizeof(WCHAR)] = '\\';
200 usKeyName.Length += sizeof(WCHAR);
201
202 /* Append the subkey name */
203 Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName);
204 if (!NT_SUCCESS(Status))
205 {
206 return FALSE;
207 }
208
209 /* Initialize object attributes */
210 InitializeObjectAttributes(&ObjectAttributes,
211 &usKeyName,
212 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
213 NULL,
214 NULL);
215
216 /* Open the key */
217 Status = ZwOpenKey((PHANDLE)&hkey, KEY_READ, &ObjectAttributes);
218 if (!NT_SUCCESS(Status))
219 {
220 return FALSE;
221 }
222
223 /* Check if the local buffer is sufficient */
224 cbInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + cbDataSize;
225 if (cbInfoSize <= sizeof(awcBuffer))
226 {
227 pInfo = (PVOID)awcBuffer;
228 }
229 else
230 {
231 /* It's not, allocate a sufficient buffer */
232 pInfo = ExAllocatePoolWithTag(PagedPool, cbInfoSize, TAG_TEMP);
233 if (!pInfo)
234 {
235 ZwClose(hkey);
236 return FALSE;
237 }
238 }
239
240 /* Query the value */
241 RtlInitUnicodeString(&usValueName, pwszValueName);
242 Status = ZwQueryValueKey(hkey,
243 &usValueName,
244 KeyValuePartialInformation,
245 (PVOID)pInfo,
246 cbInfoSize,
247 &cbReqSize);
248 if (NT_SUCCESS(Status))
249 {
250 /* Did we get the right type */
251 if (pInfo->Type == ulType)
252 {
253 /* Copy the contents to the caller */
254 RtlCopyMemory(pvData, pInfo->Data, cbDataSize);
255 }
256 }
257
258 /* Cleanup */
259 ZwClose(hkey);
260 if (pInfo != (PVOID)awcBuffer)
261 ExFreePoolWithTag(pInfo, TAG_TEMP);
262
263 return NT_SUCCESS(Status);
264 }
265
266 BOOL
267 NTAPI
268 RegWriteUserSetting(
269 IN PCWSTR pwszKeyName,
270 IN PCWSTR pwszValueName,
271 IN ULONG ulType,
272 OUT PVOID pvData,
273 IN ULONG cbDataSize)
274 {
275 NTSTATUS Status;
276 OBJECT_ATTRIBUTES ObjectAttributes;
277 UNICODE_STRING usCurrentUserKey, usKeyName, usValueName;
278 WCHAR awcBuffer[MAX_PATH];
279 HKEY hkey;
280
281 // FIXME: Logged in user versus current process user?
282 /* Get the path of the current user's profile */
283 Status = RtlFormatCurrentUserKeyPath(&usCurrentUserKey);
284 if (!NT_SUCCESS(Status))
285 {
286 DPRINT1("RtlFormatCurrentUserKeyPath failed\n");
287 return FALSE;
288 }
289
290 /* Initialize empty key name */
291 RtlInitEmptyUnicodeString(&usKeyName, awcBuffer, sizeof(awcBuffer));
292
293 /* Append the current user key name */
294 Status = RtlAppendUnicodeStringToString(&usKeyName, &usCurrentUserKey);
295 if (!NT_SUCCESS(Status))
296 {
297 return FALSE;
298 }
299
300 /* Free the current user key name */
301 RtlFreeUnicodeString(&usCurrentUserKey);
302
303 /* Append a '\', we can trust in enough space left. */
304 usKeyName.Buffer[usKeyName.Length / sizeof(WCHAR)] = '\\';
305 usKeyName.Length += sizeof(WCHAR);
306
307 /* Append the subkey name */
308 Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName);
309 if (!NT_SUCCESS(Status))
310 {
311 DPRINT1("RtlAppendUnicodeToString failed with Status=0x%lx, buf:%u,%u\n",
312 Status, usKeyName.Length, usKeyName.MaximumLength);
313 return FALSE;
314 }
315
316 /* Initialize object attributes */
317 InitializeObjectAttributes(&ObjectAttributes,
318 &usKeyName,
319 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
320 NULL,
321 NULL);
322
323 /* Open or create the key */
324 Status = ZwCreateKey((PHANDLE)&hkey,
325 KEY_READ | KEY_WRITE,
326 &ObjectAttributes,
327 0,
328 NULL,
329 0,
330 NULL);
331 if(!NT_SUCCESS(Status))
332 {
333 DPRINT1("Failed to create key: 0x%x\n", Status);
334 return FALSE;
335 }
336
337 /* Initialize the value name string */
338 RtlInitUnicodeString(&usValueName, pwszValueName);
339
340 Status = ZwSetValueKey(hkey, &usValueName, 0, ulType, pvData, cbDataSize);
341 if(!NT_SUCCESS(Status))
342 {
343 DPRINT1("Failed to write reg key '%S' value '%S', Status = %lx\n",
344 pwszKeyName, pwszValueName, Status);
345 }
346
347 /* Cleanup */
348 ZwClose(hkey);
349
350 return NT_SUCCESS(Status);
351 }
352