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