2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: Security Account Manager (SAM) Server
4 * FILE: reactos/dll/win32/samsrv/registry.c
5 * PURPOSE: Registry helper functions
7 * PROGRAMMERS: Eric Kohl
12 #include <ndk/cmfuncs.h>
13 #include <ndk/obfuncs.h>
15 /* FUNCTIONS ***************************************************************/
19 IsStringType(ULONG Type
)
21 return (Type
== REG_SZ
) || (Type
== REG_EXPAND_SZ
) || (Type
== REG_MULTI_SZ
);
26 SampRegCloseKey(IN OUT PHANDLE KeyHandle
)
30 if (KeyHandle
== NULL
|| *KeyHandle
== NULL
)
31 return STATUS_SUCCESS
;
33 Status
= NtClose(*KeyHandle
);
34 if (NT_SUCCESS(Status
))
42 SampRegCreateKey(IN HANDLE ParentKeyHandle
,
44 IN ACCESS_MASK DesiredAccess
,
45 OUT PHANDLE KeyHandle
)
47 OBJECT_ATTRIBUTES ObjectAttributes
;
51 RtlInitUnicodeString(&Name
, KeyName
);
53 InitializeObjectAttributes(&ObjectAttributes
,
55 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
60 return ZwCreateKey(KeyHandle
,
71 SampRegDeleteKey(IN HANDLE ParentKeyHandle
,
74 OBJECT_ATTRIBUTES ObjectAttributes
;
75 UNICODE_STRING SubKeyName
;
79 RtlInitUnicodeString(&SubKeyName
,
81 InitializeObjectAttributes(&ObjectAttributes
,
86 Status
= NtOpenKey(&TargetKey
,
89 if (!NT_SUCCESS(Status
))
92 Status
= NtDeleteKey(TargetKey
);
101 SampRegEnumerateSubKey(IN HANDLE KeyHandle
,
106 PKEY_BASIC_INFORMATION KeyInfo
= NULL
;
107 ULONG BufferLength
= 0;
108 ULONG ReturnedLength
;
111 /* Check if we have a name */
114 /* Allocate a buffer for it */
115 BufferLength
= sizeof(KEY_BASIC_INFORMATION
) + Length
* sizeof(WCHAR
);
117 KeyInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
119 return STATUS_NO_MEMORY
;
122 /* Enumerate the key */
123 Status
= ZwEnumerateKey(KeyHandle
,
129 if (NT_SUCCESS(Status
))
131 /* Check if the name fits */
132 if (KeyInfo
->NameLength
< (Length
* sizeof(WCHAR
)))
135 RtlMoveMemory(Buffer
,
137 KeyInfo
->NameLength
);
139 /* Terminate the string */
140 Buffer
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
144 /* Otherwise, we ran out of buffer space */
145 Status
= STATUS_BUFFER_OVERFLOW
;
149 /* Free the buffer and return status */
151 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
158 SampRegOpenKey(IN HANDLE ParentKeyHandle
,
160 IN ACCESS_MASK DesiredAccess
,
161 OUT PHANDLE KeyHandle
)
163 OBJECT_ATTRIBUTES ObjectAttributes
;
166 RtlInitUnicodeString(&Name
, KeyName
);
168 InitializeObjectAttributes(&ObjectAttributes
,
170 OBJ_CASE_INSENSITIVE
,
174 return NtOpenKey(KeyHandle
,
181 SampRegQueryKeyInfo(IN HANDLE KeyHandle
,
182 OUT PULONG SubKeyCount
,
183 OUT PULONG ValueCount
)
185 KEY_FULL_INFORMATION FullInfoBuffer
;
189 FullInfoBuffer
.ClassLength
= 0;
190 FullInfoBuffer
.ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
192 Status
= NtQueryKey(KeyHandle
,
195 sizeof(KEY_FULL_INFORMATION
),
197 TRACE("NtQueryKey() returned status 0x%08lX\n", Status
);
198 if (!NT_SUCCESS(Status
))
201 if (SubKeyCount
!= NULL
)
202 *SubKeyCount
= FullInfoBuffer
.SubKeys
;
204 if (ValueCount
!= NULL
)
205 *ValueCount
= FullInfoBuffer
.Values
;
212 SampRegDeleteValue(IN HANDLE KeyHandle
,
213 IN LPCWSTR ValueName
)
217 RtlInitUnicodeString(&Name
,
220 return NtDeleteValueKey(KeyHandle
,
226 SampRegEnumerateValue(IN HANDLE KeyHandle
,
229 IN OUT PULONG NameLength
,
230 OUT PULONG Type OPTIONAL
,
231 OUT PVOID Data OPTIONAL
,
232 IN OUT PULONG DataLength OPTIONAL
)
234 PKEY_VALUE_FULL_INFORMATION ValueInfo
= NULL
;
235 ULONG BufferLength
= 0;
236 ULONG ReturnedLength
;
239 TRACE("Index: %lu\n", Index
);
241 /* Calculate the required buffer length */
242 BufferLength
= FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
);
243 BufferLength
+= (MAX_PATH
+ 1) * sizeof(WCHAR
);
245 BufferLength
+= *DataLength
;
247 /* Allocate the value buffer */
248 ValueInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
249 if (ValueInfo
== NULL
)
250 return STATUS_NO_MEMORY
;
252 /* Enumerate the value*/
253 Status
= ZwEnumerateValueKey(KeyHandle
,
255 KeyValueFullInformation
,
259 if (NT_SUCCESS(Status
))
263 /* Check if the name fits */
264 if (ValueInfo
->NameLength
< (*NameLength
* sizeof(WCHAR
)))
269 ValueInfo
->NameLength
);
271 /* Terminate the string */
272 Name
[ValueInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
276 /* Otherwise, we ran out of buffer space */
277 Status
= STATUS_BUFFER_OVERFLOW
;
284 /* Check if the data fits */
285 if (ValueInfo
->DataLength
<= *DataLength
)
289 (PVOID
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->DataOffset
),
290 ValueInfo
->DataLength
);
292 /* if the type is REG_SZ and data is not 0-terminated
293 * and there is enough space in the buffer NT appends a \0 */
294 if (IsStringType(ValueInfo
->Type
) &&
295 ValueInfo
->DataLength
<= *DataLength
- sizeof(WCHAR
))
297 WCHAR
*ptr
= (WCHAR
*)((ULONG_PTR
)Data
+ ValueInfo
->DataLength
);
298 if ((ptr
> (WCHAR
*)Data
) && ptr
[-1])
304 Status
= STATUS_BUFFER_OVERFLOW
;
311 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
314 *Type
= ValueInfo
->Type
;
316 if (NameLength
!= NULL
)
317 *NameLength
= ValueInfo
->NameLength
;
319 if (DataLength
!= NULL
)
320 *DataLength
= ValueInfo
->DataLength
;
323 /* Free the buffer and return status */
325 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo
);
332 SampRegQueryValue(IN HANDLE KeyHandle
,
333 IN LPCWSTR ValueName
,
334 OUT PULONG Type OPTIONAL
,
335 OUT PVOID Data OPTIONAL
,
336 IN OUT PULONG DataLength OPTIONAL
)
338 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
340 ULONG BufferLength
= 0;
343 RtlInitUnicodeString(&Name
,
346 if (DataLength
!= NULL
)
347 BufferLength
= *DataLength
;
349 BufferLength
+= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
);
351 /* Allocate memory for the value */
352 ValueInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
353 if (ValueInfo
== NULL
)
354 return STATUS_NO_MEMORY
;
356 /* Query the value */
357 Status
= ZwQueryValueKey(KeyHandle
,
359 KeyValuePartialInformation
,
363 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
366 *Type
= ValueInfo
->Type
;
368 if (DataLength
!= NULL
)
369 *DataLength
= ValueInfo
->DataLength
;
372 /* Check if the caller wanted data back, and we got it */
373 if ((NT_SUCCESS(Status
)) && (Data
!= NULL
))
378 ValueInfo
->DataLength
);
380 /* if the type is REG_SZ and data is not 0-terminated
381 * and there is enough space in the buffer NT appends a \0 */
382 if (IsStringType(ValueInfo
->Type
) &&
383 ValueInfo
->DataLength
<= *DataLength
- sizeof(WCHAR
))
385 WCHAR
*ptr
= (WCHAR
*)((ULONG_PTR
)Data
+ ValueInfo
->DataLength
);
386 if ((ptr
> (WCHAR
*)Data
) && ptr
[-1])
391 /* Free the memory and return status */
392 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo
);
394 if ((Data
== NULL
) && (Status
== STATUS_BUFFER_OVERFLOW
))
395 Status
= STATUS_SUCCESS
;
402 SampRegSetValue(HANDLE KeyHandle
,
410 RtlInitUnicodeString(&Name
,
413 return ZwSetValueKey(KeyHandle
,