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
10 /* INCLUDES ****************************************************************/
14 WINE_DEFAULT_DEBUG_CHANNEL(lsasrv
);
16 /* FUNCTIONS ***************************************************************/
20 IsStringType(ULONG Type
)
22 return (Type
== REG_SZ
) || (Type
== REG_EXPAND_SZ
) || (Type
== REG_MULTI_SZ
);
27 LsapRegCloseKey(IN HANDLE KeyHandle
)
29 return NtClose(KeyHandle
);
34 LsapRegCreateKey(IN HANDLE ParentKeyHandle
,
36 IN ACCESS_MASK DesiredAccess
,
39 OBJECT_ATTRIBUTES ObjectAttributes
;
43 RtlInitUnicodeString(&Name
, KeyName
);
45 InitializeObjectAttributes(&ObjectAttributes
,
47 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
52 return ZwCreateKey(KeyHandle
,
63 LsapRegDeleteSubKey(IN HANDLE ParentKeyHandle
,
66 OBJECT_ATTRIBUTES ObjectAttributes
;
67 UNICODE_STRING SubKeyName
;
71 RtlInitUnicodeString(&SubKeyName
,
73 InitializeObjectAttributes(&ObjectAttributes
,
78 Status
= NtOpenKey(&TargetKey
,
81 if (!NT_SUCCESS(Status
))
84 Status
= NtDeleteKey(TargetKey
);
93 LsapRegDeleteKey(IN HANDLE KeyHandle
)
95 return NtDeleteKey(KeyHandle
);
100 LsapRegEnumerateSubKey(IN HANDLE KeyHandle
,
105 PKEY_BASIC_INFORMATION KeyInfo
= NULL
;
106 ULONG BufferLength
= 0;
107 ULONG ReturnedLength
;
110 /* Check if we have a name */
113 /* Allocate a buffer for it */
114 BufferLength
= sizeof(KEY_BASIC_INFORMATION
) + Length
* sizeof(WCHAR
);
116 KeyInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
118 return STATUS_NO_MEMORY
;
121 /* Enumerate the key */
122 Status
= ZwEnumerateKey(KeyHandle
,
128 if (NT_SUCCESS(Status
))
130 /* Check if the name fits */
131 if (KeyInfo
->NameLength
< (Length
* sizeof(WCHAR
)))
134 RtlMoveMemory(Buffer
,
136 KeyInfo
->NameLength
);
138 /* Terminate the string */
139 Buffer
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
143 /* Otherwise, we ran out of buffer space */
144 Status
= STATUS_BUFFER_OVERFLOW
;
148 /* Free the buffer and return status */
150 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
157 LsapRegOpenKey(IN HANDLE ParentKeyHandle
,
159 IN ACCESS_MASK DesiredAccess
,
160 OUT HANDLE KeyHandle
)
162 OBJECT_ATTRIBUTES ObjectAttributes
;
165 RtlInitUnicodeString(&Name
, KeyName
);
167 InitializeObjectAttributes(&ObjectAttributes
,
169 OBJ_CASE_INSENSITIVE
,
173 return NtOpenKey(KeyHandle
,
180 LsapRegQueryKeyInfo(IN HANDLE KeyHandle
,
181 OUT PULONG SubKeyCount
,
182 OUT PULONG ValueCount
)
184 KEY_FULL_INFORMATION FullInfoBuffer
;
188 FullInfoBuffer
.ClassLength
= 0;
189 FullInfoBuffer
.ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
191 Status
= NtQueryKey(KeyHandle
,
194 sizeof(KEY_FULL_INFORMATION
),
196 TRACE("NtQueryKey() returned status 0x%08lX\n", Status
);
197 if (!NT_SUCCESS(Status
))
200 if (SubKeyCount
!= NULL
)
201 *SubKeyCount
= FullInfoBuffer
.SubKeys
;
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
)] = 0;
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
,