[WIN32K]
[reactos.git] / reactos / subsystems / win32 / win32k / 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: subsystem/win32/win32k/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,
32 NULL,
33 NULL);
34
35 /* Open the key */
36 Status = ZwOpenKey(&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 cbDataSize = cbInfoSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
86
87 if (NT_SUCCESS(Status))
88 {
89 /* Did we get the right type */
90 if (pInfo->Type == ulType)
91 {
92 /* Copy the contents to the caller. Make sure strings are null terminated */
93 if (ulType == REG_SZ || ulType == REG_MULTI_SZ || ulType == REG_EXPAND_SZ)
94 RtlStringCbCopyNW((LPWSTR)pvData, *pcbValue, (LPWSTR)pInfo->Data, cbDataSize);
95 else
96 RtlCopyMemory(pvData, pInfo->Data, cbDataSize);
97 }
98 else
99 Status = STATUS_OBJECT_TYPE_MISMATCH;
100 }
101
102 /* Return the data size to the caller */
103 *pcbValue = cbDataSize;
104
105 /* Cleanup */
106 if (pInfo != (PVOID)ajBuffer)
107 ExFreePoolWithTag(pInfo, TAG_TEMP);
108
109 return Status;
110
111 }
112
113 VOID
114 NTAPI
115 RegWriteSZ(HKEY hkey, PWSTR pwszValue, PWSTR pwszData)
116 {
117 UNICODE_STRING ustrValue;
118 UNICODE_STRING ustrData;
119
120 RtlInitUnicodeString(&ustrValue, pwszValue);
121 RtlInitUnicodeString(&ustrData, pwszData);
122 ZwSetValueKey(hkey, &ustrValue, 0, REG_SZ, &ustrData, ustrData.Length + sizeof(WCHAR));
123 }
124
125 VOID
126 NTAPI
127 RegWriteDWORD(HKEY hkey, PWSTR pwszValue, DWORD dwData)
128 {
129 UNICODE_STRING ustrValue;
130
131 RtlInitUnicodeString(&ustrValue, pwszValue);
132 ZwSetValueKey(hkey, &ustrValue, 0, REG_DWORD, &dwData, sizeof(DWORD));
133 }
134
135 BOOL
136 NTAPI
137 RegReadDWORD(HKEY hkey, PWSTR pwszValue, PDWORD pdwData)
138 {
139 NTSTATUS Status;
140 ULONG cbSize = sizeof(DWORD);
141 Status = RegQueryValue(hkey, pwszValue, REG_DWORD, pdwData, &cbSize);
142 return NT_SUCCESS(Status);
143 }
144
145 BOOL
146 NTAPI
147 RegReadUserSetting(
148 IN PCWSTR pwszKeyName,
149 IN PCWSTR pwszValueName,
150 IN ULONG ulType,
151 OUT PVOID pvData,
152 IN ULONG cbDataSize)
153 {
154 NTSTATUS Status;
155 OBJECT_ATTRIBUTES ObjectAttributes;
156 UNICODE_STRING usCurrentUserKey, usKeyName, usValueName;
157 WCHAR awcBuffer[MAX_PATH];
158 HKEY hkey;
159 PKEY_VALUE_PARTIAL_INFORMATION pInfo;
160 ULONG cbInfoSize, cbReqSize;
161
162 /* Get the path of the current user's profile */
163 Status = RtlFormatCurrentUserKeyPath(&usCurrentUserKey);
164 if (!NT_SUCCESS(Status))
165 {
166 return FALSE;
167 }
168
169 /* Initialize empty key name */
170 RtlInitEmptyUnicodeString(&usKeyName, awcBuffer, sizeof(awcBuffer));
171
172 /* Append the current user key name */
173 Status = RtlAppendUnicodeStringToString(&usKeyName, &usCurrentUserKey);
174
175 /* Free the current user key name */
176 RtlFreeUnicodeString(&usCurrentUserKey);
177
178 /* Check for success */
179 if (!NT_SUCCESS(Status))
180 {
181 return FALSE;
182 }
183
184 /* Append a '\', we can trust in enough space left. */
185 usKeyName.Buffer[usKeyName.Length / sizeof(WCHAR)] = '\\';
186 usKeyName.Length += sizeof(WCHAR);
187
188 /* Append the subkey name */
189 Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName);
190 if (!NT_SUCCESS(Status))
191 {
192 return FALSE;
193 }
194
195 /* Initialize object attributes */
196 InitializeObjectAttributes(&ObjectAttributes,
197 &usKeyName,
198 OBJ_CASE_INSENSITIVE,
199 NULL,
200 NULL);
201
202 /* Open the key */
203 Status = ZwOpenKey(&hkey, KEY_READ, &ObjectAttributes);
204 if (!NT_SUCCESS(Status))
205 {
206 return FALSE;
207 }
208
209 /* Check if the local buffer is sufficient */
210 cbInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + cbDataSize;
211 if (cbInfoSize <= sizeof(awcBuffer))
212 {
213 pInfo = (PVOID)awcBuffer;
214 }
215 else
216 {
217 /* It's not, allocate a sufficient buffer */
218 pInfo = ExAllocatePoolWithTag(PagedPool, cbInfoSize, TAG_TEMP);
219 if (!pInfo)
220 {
221 ZwClose(hkey);
222 return FALSE;
223 }
224 }
225
226 /* Query the value */
227 RtlInitUnicodeString(&usValueName, pwszValueName);
228 Status = ZwQueryValueKey(hkey,
229 &usValueName,
230 KeyValuePartialInformation,
231 (PVOID)pInfo,
232 cbInfoSize,
233 &cbReqSize);
234 if (NT_SUCCESS(Status))
235 {
236 /* Did we get the right type */
237 if (pInfo->Type == ulType)
238 {
239 /* Copy the contents to the caller */
240 RtlCopyMemory(pvData, pInfo->Data, cbDataSize);
241 }
242 }
243
244 /* Cleanup */
245 ZwClose(hkey);
246 if (pInfo != (PVOID)awcBuffer)
247 ExFreePoolWithTag(pInfo, TAG_TEMP);
248
249 return NT_SUCCESS(Status);
250 }
251
252 BOOL
253 NTAPI
254 RegWriteUserSetting(
255 IN PCWSTR pwszKeyName,
256 IN PCWSTR pwszValueName,
257 IN ULONG ulType,
258 OUT PVOID pvData,
259 IN ULONG cbDataSize)
260 {
261 NTSTATUS Status;
262 OBJECT_ATTRIBUTES ObjectAttributes;
263 UNICODE_STRING usCurrentUserKey, usKeyName, usValueName;
264 WCHAR awcBuffer[MAX_PATH];
265 HKEY hkey;
266
267 // FIXME: logged in user versus current process user?
268 /* Get the path of the current user's profile */
269 Status = RtlFormatCurrentUserKeyPath(&usCurrentUserKey);
270 if (!NT_SUCCESS(Status))
271 {
272 DPRINT1("RtlFormatCurrentUserKeyPath failed\n");
273 return FALSE;
274 }
275
276 /* Initialize empty key name */
277 RtlInitEmptyUnicodeString(&usKeyName, awcBuffer, sizeof(awcBuffer));
278
279 /* Append the current user key name */
280 Status = RtlAppendUnicodeStringToString(&usKeyName, &usCurrentUserKey);
281 if (!NT_SUCCESS(Status))
282 {
283 return FALSE;
284 }
285
286 /* Free the current user key name */
287 RtlFreeUnicodeString(&usCurrentUserKey);
288
289 /* Append a '\', we can trust in enough space left. */
290 usKeyName.Buffer[usKeyName.Length / sizeof(WCHAR)] = '\\';
291 usKeyName.Length += sizeof(WCHAR);
292
293 /* Append the subkey name */
294 Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName);
295 if (!NT_SUCCESS(Status))
296 {
297 DPRINT1("RtlAppendUnicodeToString failed with Status=%lx, buf:%d,%d\n",
298 Status, usKeyName.Length, usKeyName.MaximumLength);
299 return FALSE;
300 }
301
302 /* Initialize object attributes */
303 InitializeObjectAttributes(&ObjectAttributes,
304 &usKeyName,
305 OBJ_CASE_INSENSITIVE,
306 NULL,
307 NULL);
308
309 /* Open or create the key */
310 Status = ZwCreateKey(&hkey,
311 KEY_READ | KEY_WRITE,
312 &ObjectAttributes,
313 0,
314 NULL,
315 0,
316 NULL);
317 if(!NT_SUCCESS(Status))
318 {
319 DPRINT1("Failed to create key: 0x%x\n", Status);
320 return FALSE;
321 }
322
323 /* Initialize the value name string */
324 RtlInitUnicodeString(&usValueName, pwszValueName);
325
326 Status = ZwSetValueKey(hkey, &usValueName, 0, ulType, pvData, cbDataSize);
327 if(!NT_SUCCESS(Status))
328 {
329 DPRINT1("Failed to write reg key '%S' value '%S', Status = %lx\n",
330 pwszKeyName, pwszValueName, Status);
331 }
332
333 /* Cleanup */
334 ZwClose(hkey);
335
336 return NT_SUCCESS(Status);
337 }
338