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