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