Sync to trunk head (r42241)
[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 <w32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 BOOL
15 NTAPI
16 RegReadUserSetting(
17 IN PCWSTR pwszKeyName,
18 IN PCWSTR pwszValueName,
19 IN ULONG ulType,
20 OUT PVOID pvData,
21 IN ULONG cbDataSize)
22 {
23 NTSTATUS Status;
24 OBJECT_ATTRIBUTES ObjectAttributes;
25 UNICODE_STRING usCurrentUserKey, usKeyName, usValueName;
26 WCHAR awcBuffer[MAX_PATH];
27 HKEY hkey;
28 PKEY_VALUE_PARTIAL_INFORMATION pInfo;
29 ULONG cbInfoSize, cbReqSize;
30
31 /* Get the path of the current user's profile */
32 Status = RtlFormatCurrentUserKeyPath(&usCurrentUserKey);
33 if (!NT_SUCCESS(Status))
34 {
35 return FALSE;
36 }
37
38 /* Initialize empty key name */
39 RtlInitEmptyUnicodeString(&usKeyName, awcBuffer, sizeof(awcBuffer));
40
41 /* Append the current user key name */
42 Status = RtlAppendUnicodeStringToString(&usKeyName, &usCurrentUserKey);
43
44 /* Free the current user key name */
45 RtlFreeUnicodeString(&usCurrentUserKey);
46
47 /* Check for success */
48 if (!NT_SUCCESS(Status))
49 {
50 return FALSE;
51 }
52
53 /* Append a '\', we can trust in enough space left. */
54 usKeyName.Buffer[usKeyName.Length / sizeof(WCHAR)] = '\\';
55 usKeyName.Length += sizeof(WCHAR);
56
57 /* Append the subkey name */
58 Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName);
59 if (!NT_SUCCESS(Status))
60 {
61 return FALSE;
62 }
63
64 /* Initialize object attributes */
65 InitializeObjectAttributes(&ObjectAttributes,
66 &usKeyName,
67 OBJ_CASE_INSENSITIVE,
68 NULL,
69 NULL);
70
71 /* Open the key */
72 Status = ZwOpenKey(&hkey, KEY_READ, &ObjectAttributes);
73 if (!NT_SUCCESS(Status))
74 {
75 return FALSE;
76 }
77
78 /* Check if the local buffer is sufficient */
79 cbInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + cbDataSize;
80 if (cbInfoSize <= sizeof(awcBuffer))
81 {
82 pInfo = (PVOID)awcBuffer;
83 }
84 else
85 {
86 /* It's not, allocate a sufficient buffer */
87 pInfo = ExAllocatePoolWithTag(PagedPool, cbInfoSize, TAG_TEMP);
88 if (!pInfo)
89 {
90 ZwClose(hkey);
91 return FALSE;
92 }
93 }
94
95 /* Query the value */
96 RtlInitUnicodeString(&usValueName, pwszValueName);
97 Status = ZwQueryValueKey(hkey,
98 &usValueName,
99 KeyValuePartialInformation,
100 (PVOID)pInfo,
101 cbInfoSize,
102 &cbReqSize);
103 if (NT_SUCCESS(Status))
104 {
105 /* Did we get the right type */
106 if (pInfo->Type == ulType)
107 {
108 /* Copy the contents to the caller */
109 RtlCopyMemory(pvData, pInfo->Data, cbDataSize);
110 }
111 }
112
113 /* Cleanup */
114 ZwClose(hkey);
115 if (pInfo != (PVOID)awcBuffer)
116 ExFreePoolWithTag(pInfo, TAG_TEMP);
117
118 return NT_SUCCESS(Status);
119 }
120
121 BOOL
122 NTAPI
123 RegWriteUserSetting(
124 IN PCWSTR pwszKeyName,
125 IN PCWSTR pwszValueName,
126 IN ULONG ulType,
127 OUT PVOID pvData,
128 IN ULONG cbDataSize)
129 {
130 NTSTATUS Status;
131 OBJECT_ATTRIBUTES ObjectAttributes;
132 UNICODE_STRING usCurrentUserKey, usKeyName, usValueName;
133 WCHAR awcBuffer[MAX_PATH];
134 HKEY hkey;
135
136 // FIXME: logged in user versus current process user?
137 /* Get the path of the current user's profile */
138 Status = RtlFormatCurrentUserKeyPath(&usCurrentUserKey);
139 if (!NT_SUCCESS(Status))
140 {
141 DPRINT1("RtlFormatCurrentUserKeyPath failed\n");
142 return FALSE;
143 }
144
145 /* Initialize empty key name */
146 RtlInitEmptyUnicodeString(&usKeyName, awcBuffer, sizeof(awcBuffer));
147
148 /* Append the current user key name */
149 Status = RtlAppendUnicodeStringToString(&usKeyName, &usCurrentUserKey);
150 if (!NT_SUCCESS(Status))
151 {
152 return FALSE;
153 }
154
155 /* Free the current user key name */
156 RtlFreeUnicodeString(&usCurrentUserKey);
157
158 /* Append a '\', we can trust in enough space left. */
159 usKeyName.Buffer[usKeyName.Length / sizeof(WCHAR)] = '\\';
160 usKeyName.Length += sizeof(WCHAR);
161
162 /* Append the subkey name */
163 Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName);
164 if (!NT_SUCCESS(Status))
165 {
166 DPRINT1("RtlAppendUnicodeToString failed with Status=%lx, buf:%d,%d\n", Status, usKeyName.Length, usKeyName.MaximumLength);
167 return FALSE;
168 }
169
170 /* Initialize object attributes */
171 InitializeObjectAttributes(&ObjectAttributes,
172 &usKeyName,
173 OBJ_CASE_INSENSITIVE,
174 NULL,
175 NULL);
176
177 /* Open or create the key */
178 Status = ZwCreateKey(&hkey,
179 KEY_READ | KEY_WRITE,
180 &ObjectAttributes,
181 0,
182 NULL,
183 0,
184 NULL);
185 if(!NT_SUCCESS(Status))
186 {
187 DPRINT1("Failed to create key: 0x%x\n", Status);
188 return FALSE;
189 }
190
191 /* Initialize the value name string */
192 RtlInitUnicodeString(&usValueName, pwszValueName);
193
194 Status = ZwSetValueKey(hkey, &usValueName, 0, ulType, pvData, cbDataSize);
195 if(!NT_SUCCESS(Status))
196 {
197 DPRINT1("Failed to write reg key '%S' value '%S', Status = %lx\n",
198 pwszKeyName, pwszValueName, Status);
199 }
200
201 /* Cleanup */
202 ZwClose(hkey);
203
204 return NT_SUCCESS(Status);
205 }
206