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 /* FUNCTIONS ***************************************************************/
16 IsStringType(ULONG Type
)
18 return (Type
== REG_SZ
) || (Type
== REG_EXPAND_SZ
) || (Type
== REG_MULTI_SZ
);
23 LsapRegCloseKey(IN HANDLE KeyHandle
)
25 return NtClose(KeyHandle
);
30 LsapRegCreateKey(IN HANDLE ParentKeyHandle
,
32 IN ACCESS_MASK DesiredAccess
,
35 OBJECT_ATTRIBUTES ObjectAttributes
;
39 RtlInitUnicodeString(&Name
, KeyName
);
41 InitializeObjectAttributes(&ObjectAttributes
,
43 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
48 return ZwCreateKey(KeyHandle
,
59 LsapRegDeleteSubKey(IN HANDLE ParentKeyHandle
,
62 OBJECT_ATTRIBUTES ObjectAttributes
;
63 UNICODE_STRING SubKeyName
;
67 RtlInitUnicodeString(&SubKeyName
,
69 InitializeObjectAttributes(&ObjectAttributes
,
74 Status
= NtOpenKey(&TargetKey
,
77 if (!NT_SUCCESS(Status
))
80 Status
= NtDeleteKey(TargetKey
);
89 LsapRegDeleteKey(IN HANDLE KeyHandle
)
91 return NtDeleteKey(KeyHandle
);
96 LsapRegEnumerateSubKey(IN HANDLE KeyHandle
,
101 PKEY_BASIC_INFORMATION KeyInfo
= NULL
;
102 ULONG BufferLength
= 0;
103 ULONG ReturnedLength
;
106 /* Check if we have a name */
109 /* Allocate a buffer for it */
110 BufferLength
= sizeof(KEY_BASIC_INFORMATION
) + Length
* sizeof(WCHAR
);
112 KeyInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
114 return STATUS_NO_MEMORY
;
117 /* Enumerate the key */
118 Status
= ZwEnumerateKey(KeyHandle
,
124 if (NT_SUCCESS(Status
))
126 /* Check if the name fits */
127 if (KeyInfo
->NameLength
< (Length
* sizeof(WCHAR
)))
130 RtlMoveMemory(Buffer
,
132 KeyInfo
->NameLength
);
134 /* Terminate the string */
135 Buffer
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
139 /* Otherwise, we ran out of buffer space */
140 Status
= STATUS_BUFFER_OVERFLOW
;
144 /* Free the buffer and return status */
146 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
153 LsapRegOpenKey(IN HANDLE ParentKeyHandle
,
155 IN ACCESS_MASK DesiredAccess
,
156 OUT HANDLE KeyHandle
)
158 OBJECT_ATTRIBUTES ObjectAttributes
;
161 RtlInitUnicodeString(&Name
, KeyName
);
163 InitializeObjectAttributes(&ObjectAttributes
,
165 OBJ_CASE_INSENSITIVE
,
169 return NtOpenKey(KeyHandle
,
176 LsapRegQueryKeyInfo(IN HANDLE KeyHandle
,
177 OUT PULONG SubKeyCount
,
178 OUT PULONG MaxSubKeyNameLength
,
179 OUT PULONG ValueCount
)
181 KEY_FULL_INFORMATION FullInfoBuffer
;
185 FullInfoBuffer
.ClassLength
= 0;
186 FullInfoBuffer
.ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
188 Status
= NtQueryKey(KeyHandle
,
191 sizeof(KEY_FULL_INFORMATION
),
193 TRACE("NtQueryKey() returned status 0x%08lX\n", Status
);
194 if (!NT_SUCCESS(Status
))
197 if (SubKeyCount
!= NULL
)
198 *SubKeyCount
= FullInfoBuffer
.SubKeys
;
200 if (MaxSubKeyNameLength
!= NULL
)
201 *MaxSubKeyNameLength
= FullInfoBuffer
.MaxNameLen
;
203 if (ValueCount
!= NULL
)
204 *ValueCount
= FullInfoBuffer
.Values
;
211 LsapRegDeleteValue(IN HANDLE KeyHandle
,
216 RtlInitUnicodeString(&Name
,
219 return NtDeleteValueKey(KeyHandle
,
225 LsapRegEnumerateValue(IN HANDLE KeyHandle
,
228 IN OUT PULONG NameLength
,
229 OUT PULONG Type OPTIONAL
,
230 OUT PVOID Data OPTIONAL
,
231 IN OUT PULONG DataLength OPTIONAL
)
233 PKEY_VALUE_FULL_INFORMATION ValueInfo
= NULL
;
234 ULONG BufferLength
= 0;
235 ULONG ReturnedLength
;
238 TRACE("Index: %lu\n", Index
);
240 /* Calculate the required buffer length */
241 BufferLength
= FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
);
242 BufferLength
+= (MAX_PATH
+ 1) * sizeof(WCHAR
);
244 BufferLength
+= *DataLength
;
246 /* Allocate the value buffer */
247 ValueInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
248 if (ValueInfo
== NULL
)
249 return STATUS_NO_MEMORY
;
251 /* Enumerate the value*/
252 Status
= ZwEnumerateValueKey(KeyHandle
,
254 KeyValueFullInformation
,
258 if (NT_SUCCESS(Status
))
262 /* Check if the name fits */
263 if (ValueInfo
->NameLength
< (*NameLength
* sizeof(WCHAR
)))
268 ValueInfo
->NameLength
);
270 /* Terminate the string */
271 Name
[ValueInfo
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
275 /* Otherwise, we ran out of buffer space */
276 Status
= STATUS_BUFFER_OVERFLOW
;
283 /* Check if the data fits */
284 if (ValueInfo
->DataLength
<= *DataLength
)
288 (PVOID
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->DataOffset
),
289 ValueInfo
->DataLength
);
291 /* if the type is REG_SZ and data is not 0-terminated
292 * and there is enough space in the buffer NT appends a \0 */
293 if (IsStringType(ValueInfo
->Type
) &&
294 ValueInfo
->DataLength
<= *DataLength
- sizeof(WCHAR
))
296 WCHAR
*ptr
= (WCHAR
*)((ULONG_PTR
)Data
+ ValueInfo
->DataLength
);
297 if ((ptr
> (WCHAR
*)Data
) && ptr
[-1])
303 Status
= STATUS_BUFFER_OVERFLOW
;
310 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
313 *Type
= ValueInfo
->Type
;
315 if (NameLength
!= NULL
)
316 *NameLength
= ValueInfo
->NameLength
;
318 if (DataLength
!= NULL
)
319 *DataLength
= ValueInfo
->DataLength
;
322 /* Free the buffer and return status */
324 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo
);
331 LsapRegQueryValue(IN HANDLE KeyHandle
,
333 OUT PULONG Type OPTIONAL
,
334 OUT PVOID Data OPTIONAL
,
335 IN OUT PULONG DataLength OPTIONAL
)
337 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
339 ULONG BufferLength
= 0;
342 RtlInitUnicodeString(&Name
,
345 if (DataLength
!= NULL
)
346 BufferLength
= *DataLength
;
348 BufferLength
+= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
);
350 /* Allocate memory for the value */
351 ValueInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
352 if (ValueInfo
== NULL
)
353 return STATUS_NO_MEMORY
;
355 /* Query the value */
356 Status
= ZwQueryValueKey(KeyHandle
,
358 KeyValuePartialInformation
,
362 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
365 *Type
= ValueInfo
->Type
;
367 if (DataLength
!= NULL
)
368 *DataLength
= ValueInfo
->DataLength
;
371 /* Check if the caller wanted data back, and we got it */
372 if ((NT_SUCCESS(Status
)) && (Data
!= NULL
))
377 ValueInfo
->DataLength
);
379 /* if the type is REG_SZ and data is not 0-terminated
380 * and there is enough space in the buffer NT appends a \0 */
381 if (IsStringType(ValueInfo
->Type
) &&
382 ValueInfo
->DataLength
<= *DataLength
- sizeof(WCHAR
))
384 WCHAR
*ptr
= (WCHAR
*)((ULONG_PTR
)Data
+ ValueInfo
->DataLength
);
385 if ((ptr
> (WCHAR
*)Data
) && ptr
[-1])
390 /* Free the memory and return status */
391 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo
);
393 if ((Data
== NULL
) && (Status
== STATUS_BUFFER_OVERFLOW
))
394 Status
= STATUS_SUCCESS
;
401 LsapRegSetValue(HANDLE KeyHandle
,
409 RtlInitUnicodeString(&Name
,
412 return ZwSetValueKey(KeyHandle
,