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(samsrv
);
16 /* FUNCTIONS ***************************************************************/
20 IsStringType(ULONG Type
)
22 return (Type
== REG_SZ
) || (Type
== REG_EXPAND_SZ
) || (Type
== REG_MULTI_SZ
);
27 SampRegCloseKey(IN OUT PHANDLE KeyHandle
)
31 if (KeyHandle
== NULL
|| *KeyHandle
== NULL
)
32 return STATUS_SUCCESS
;
34 Status
= NtClose(*KeyHandle
);
35 if (NT_SUCCESS(Status
))
43 SampRegCreateKey(IN HANDLE ParentKeyHandle
,
45 IN ACCESS_MASK DesiredAccess
,
46 OUT PHANDLE KeyHandle
)
48 OBJECT_ATTRIBUTES ObjectAttributes
;
52 RtlInitUnicodeString(&Name
, KeyName
);
54 InitializeObjectAttributes(&ObjectAttributes
,
56 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
61 return ZwCreateKey(KeyHandle
,
72 SampRegDeleteKey(IN HANDLE ParentKeyHandle
,
75 OBJECT_ATTRIBUTES ObjectAttributes
;
76 UNICODE_STRING SubKeyName
;
80 RtlInitUnicodeString(&SubKeyName
,
82 InitializeObjectAttributes(&ObjectAttributes
,
87 Status
= NtOpenKey(&TargetKey
,
90 if (!NT_SUCCESS(Status
))
93 Status
= NtDeleteKey(TargetKey
);
102 SampRegEnumerateSubKey(IN HANDLE KeyHandle
,
107 PKEY_BASIC_INFORMATION KeyInfo
= NULL
;
108 ULONG BufferLength
= 0;
109 ULONG ReturnedLength
;
112 /* Check if we have a name */
115 /* Allocate a buffer for it */
116 BufferLength
= sizeof(KEY_BASIC_INFORMATION
) + Length
* sizeof(WCHAR
);
118 KeyInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
120 return STATUS_NO_MEMORY
;
123 /* Enumerate the key */
124 Status
= ZwEnumerateKey(KeyHandle
,
130 if (NT_SUCCESS(Status
))
132 /* Check if the name fits */
133 if (KeyInfo
->NameLength
< (Length
* sizeof(WCHAR
)))
136 RtlMoveMemory(Buffer
,
138 KeyInfo
->NameLength
);
140 /* Terminate the string */
141 Buffer
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
145 /* Otherwise, we ran out of buffer space */
146 Status
= STATUS_BUFFER_OVERFLOW
;
150 /* Free the buffer and return status */
152 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
159 SampRegOpenKey(IN HANDLE ParentKeyHandle
,
161 IN ACCESS_MASK DesiredAccess
,
162 OUT PHANDLE KeyHandle
)
164 OBJECT_ATTRIBUTES ObjectAttributes
;
167 RtlInitUnicodeString(&Name
, KeyName
);
169 InitializeObjectAttributes(&ObjectAttributes
,
171 OBJ_CASE_INSENSITIVE
,
175 return NtOpenKey(KeyHandle
,
182 SampRegQueryKeyInfo(IN HANDLE KeyHandle
,
183 OUT PULONG SubKeyCount
,
184 OUT PULONG ValueCount
)
186 KEY_FULL_INFORMATION FullInfoBuffer
;
190 FullInfoBuffer
.ClassLength
= 0;
191 FullInfoBuffer
.ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
193 Status
= NtQueryKey(KeyHandle
,
196 sizeof(KEY_FULL_INFORMATION
),
198 TRACE("NtQueryKey() returned status 0x%08lX\n", Status
);
199 if (!NT_SUCCESS(Status
))
202 if (SubKeyCount
!= NULL
)
203 *SubKeyCount
= FullInfoBuffer
.SubKeys
;
205 if (ValueCount
!= NULL
)
206 *ValueCount
= FullInfoBuffer
.Values
;
213 SampRegDeleteValue(IN HANDLE KeyHandle
,
214 IN LPCWSTR ValueName
)
218 RtlInitUnicodeString(&Name
,
221 return NtDeleteValueKey(KeyHandle
,
227 SampRegEnumerateValue(IN HANDLE KeyHandle
,
230 IN OUT PULONG NameLength
,
231 OUT PULONG Type OPTIONAL
,
232 OUT PVOID Data OPTIONAL
,
233 IN OUT PULONG DataLength OPTIONAL
)
235 PKEY_VALUE_FULL_INFORMATION ValueInfo
= NULL
;
236 ULONG BufferLength
= 0;
237 ULONG ReturnedLength
;
240 TRACE("Index: %lu\n", Index
);
242 /* Calculate the required buffer length */
243 BufferLength
= FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
);
244 BufferLength
+= (MAX_PATH
+ 1) * sizeof(WCHAR
);
246 BufferLength
+= *DataLength
;
248 /* Allocate the value buffer */
249 ValueInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
250 if (ValueInfo
== NULL
)
251 return STATUS_NO_MEMORY
;
253 /* Enumerate the value*/
254 Status
= ZwEnumerateValueKey(KeyHandle
,
256 KeyValueFullInformation
,
260 if (NT_SUCCESS(Status
))
264 /* Check if the name fits */
265 if (ValueInfo
->NameLength
< (*NameLength
* sizeof(WCHAR
)))
270 ValueInfo
->NameLength
);
272 /* Terminate the string */
273 Name
[ValueInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
277 /* Otherwise, we ran out of buffer space */
278 Status
= STATUS_BUFFER_OVERFLOW
;
285 /* Check if the data fits */
286 if (ValueInfo
->DataLength
<= *DataLength
)
290 (PVOID
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->DataOffset
),
291 ValueInfo
->DataLength
);
293 /* if the type is REG_SZ and data is not 0-terminated
294 * and there is enough space in the buffer NT appends a \0 */
295 if (IsStringType(ValueInfo
->Type
) &&
296 ValueInfo
->DataLength
<= *DataLength
- sizeof(WCHAR
))
298 WCHAR
*ptr
= (WCHAR
*)((ULONG_PTR
)Data
+ ValueInfo
->DataLength
);
299 if ((ptr
> (WCHAR
*)Data
) && ptr
[-1])
305 Status
= STATUS_BUFFER_OVERFLOW
;
312 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
315 *Type
= ValueInfo
->Type
;
317 if (NameLength
!= NULL
)
318 *NameLength
= ValueInfo
->NameLength
;
320 if (DataLength
!= NULL
)
321 *DataLength
= ValueInfo
->DataLength
;
324 /* Free the buffer and return status */
326 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo
);
333 SampRegQueryValue(IN HANDLE KeyHandle
,
334 IN LPCWSTR ValueName
,
335 OUT PULONG Type OPTIONAL
,
336 OUT PVOID Data OPTIONAL
,
337 IN OUT PULONG DataLength OPTIONAL
)
339 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
341 ULONG BufferLength
= 0;
344 RtlInitUnicodeString(&Name
,
347 if (DataLength
!= NULL
)
348 BufferLength
= *DataLength
;
350 BufferLength
+= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
);
352 /* Allocate memory for the value */
353 ValueInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
354 if (ValueInfo
== NULL
)
355 return STATUS_NO_MEMORY
;
357 /* Query the value */
358 Status
= ZwQueryValueKey(KeyHandle
,
360 KeyValuePartialInformation
,
364 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
367 *Type
= ValueInfo
->Type
;
369 if (DataLength
!= NULL
)
370 *DataLength
= ValueInfo
->DataLength
;
373 /* Check if the caller wanted data back, and we got it */
374 if ((NT_SUCCESS(Status
)) && (Data
!= NULL
))
379 ValueInfo
->DataLength
);
381 /* if the type is REG_SZ and data is not 0-terminated
382 * and there is enough space in the buffer NT appends a \0 */
383 if (IsStringType(ValueInfo
->Type
) &&
384 ValueInfo
->DataLength
<= *DataLength
- sizeof(WCHAR
))
386 WCHAR
*ptr
= (WCHAR
*)((ULONG_PTR
)Data
+ ValueInfo
->DataLength
);
387 if ((ptr
> (WCHAR
*)Data
) && ptr
[-1])
392 /* Free the memory and return status */
393 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo
);
395 if ((Data
== NULL
) && (Status
== STATUS_BUFFER_OVERFLOW
))
396 Status
= STATUS_SUCCESS
;
403 SampRegSetValue(HANDLE KeyHandle
,
411 RtlInitUnicodeString(&Name
,
414 return ZwSetValueKey(KeyHandle
,