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 HANDLE KeyHandle
)
29 return NtClose(KeyHandle
);
34 SampRegCreateKey(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 SampRegDeleteKey(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 SampRegEnumerateSubKey(IN HANDLE KeyHandle
,
98 PKEY_BASIC_INFORMATION KeyInfo
= NULL
;
99 ULONG BufferLength
= 0;
100 ULONG ReturnedLength
;
103 /* Check if we have a name */
106 /* Allocate a buffer for it */
107 BufferLength
= sizeof(KEY_BASIC_INFORMATION
) + Length
* sizeof(WCHAR
);
109 KeyInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
111 return STATUS_NO_MEMORY
;
114 /* Enumerate the key */
115 Status
= ZwEnumerateKey(KeyHandle
,
121 if (NT_SUCCESS(Status
))
123 /* Check if the name fits */
124 if (KeyInfo
->NameLength
< (Length
* sizeof(WCHAR
)))
127 RtlMoveMemory(Buffer
,
129 KeyInfo
->NameLength
);
131 /* Terminate the string */
132 Buffer
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
136 /* Otherwise, we ran out of buffer space */
137 Status
= STATUS_BUFFER_OVERFLOW
;
141 /* Free the buffer and return status */
143 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
150 SampRegOpenKey(IN HANDLE ParentKeyHandle
,
152 IN ACCESS_MASK DesiredAccess
,
153 OUT HANDLE KeyHandle
)
155 OBJECT_ATTRIBUTES ObjectAttributes
;
158 RtlInitUnicodeString(&Name
, KeyName
);
160 InitializeObjectAttributes(&ObjectAttributes
,
162 OBJ_CASE_INSENSITIVE
,
166 return NtOpenKey(KeyHandle
,
173 SampRegQueryKeyInfo(IN HANDLE KeyHandle
,
174 OUT PULONG SubKeyCount
,
175 OUT PULONG ValueCount
)
177 KEY_FULL_INFORMATION FullInfoBuffer
;
181 FullInfoBuffer
.ClassLength
= 0;
182 FullInfoBuffer
.ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
184 Status
= NtQueryKey(KeyHandle
,
187 sizeof(KEY_FULL_INFORMATION
),
189 TRACE("NtQueryKey() returned status 0x%08lX\n", Status
);
190 if (!NT_SUCCESS(Status
))
193 if (SubKeyCount
!= NULL
)
194 *SubKeyCount
= FullInfoBuffer
.SubKeys
;
196 if (ValueCount
!= NULL
)
197 *ValueCount
= FullInfoBuffer
.Values
;
204 SampRegDeleteValue(IN HANDLE KeyHandle
,
205 IN LPCWSTR ValueName
)
209 RtlInitUnicodeString(&Name
,
212 return NtDeleteValueKey(KeyHandle
,
218 SampRegEnumerateValue(IN HANDLE KeyHandle
,
221 IN OUT PULONG NameLength
,
222 OUT PULONG Type OPTIONAL
,
223 OUT PVOID Data OPTIONAL
,
224 IN OUT PULONG DataLength OPTIONAL
)
226 PKEY_VALUE_FULL_INFORMATION ValueInfo
= NULL
;
227 ULONG BufferLength
= 0;
228 ULONG ReturnedLength
;
231 TRACE("Index: %lu\n", Index
);
233 /* Calculate the required buffer length */
234 BufferLength
= FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
);
235 BufferLength
+= (MAX_PATH
+ 1) * sizeof(WCHAR
);
237 BufferLength
+= *DataLength
;
239 /* Allocate the value buffer */
240 ValueInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
241 if (ValueInfo
== NULL
)
242 return STATUS_NO_MEMORY
;
244 /* Enumerate the value*/
245 Status
= ZwEnumerateValueKey(KeyHandle
,
247 KeyValueFullInformation
,
251 if (NT_SUCCESS(Status
))
255 /* Check if the name fits */
256 if (ValueInfo
->NameLength
< (*NameLength
* sizeof(WCHAR
)))
261 ValueInfo
->NameLength
);
263 /* Terminate the string */
264 Name
[ValueInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
268 /* Otherwise, we ran out of buffer space */
269 Status
= STATUS_BUFFER_OVERFLOW
;
276 /* Check if the data fits */
277 if (ValueInfo
->DataLength
<= *DataLength
)
281 (PVOID
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->DataOffset
),
282 ValueInfo
->DataLength
);
284 /* if the type is REG_SZ and data is not 0-terminated
285 * and there is enough space in the buffer NT appends a \0 */
286 if (IsStringType(ValueInfo
->Type
) &&
287 ValueInfo
->DataLength
<= *DataLength
- sizeof(WCHAR
))
289 WCHAR
*ptr
= (WCHAR
*)((ULONG_PTR
)Data
+ ValueInfo
->DataLength
);
290 if ((ptr
> (WCHAR
*)Data
) && ptr
[-1])
296 Status
= STATUS_BUFFER_OVERFLOW
;
303 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
306 *Type
= ValueInfo
->Type
;
308 if (NameLength
!= NULL
)
309 *NameLength
= ValueInfo
->NameLength
;
311 if (DataLength
!= NULL
)
312 *DataLength
= ValueInfo
->DataLength
;
315 /* Free the buffer and return status */
317 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo
);
324 SampRegQueryValue(IN HANDLE KeyHandle
,
325 IN LPCWSTR ValueName
,
326 OUT PULONG Type OPTIONAL
,
327 OUT PVOID Data OPTIONAL
,
328 IN OUT PULONG DataLength OPTIONAL
)
330 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
332 ULONG BufferLength
= 0;
335 RtlInitUnicodeString(&Name
,
338 if (DataLength
!= NULL
)
339 BufferLength
= *DataLength
;
341 BufferLength
+= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
);
343 /* Allocate memory for the value */
344 ValueInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
345 if (ValueInfo
== NULL
)
346 return STATUS_NO_MEMORY
;
348 /* Query the value */
349 Status
= ZwQueryValueKey(KeyHandle
,
351 KeyValuePartialInformation
,
355 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
358 *Type
= ValueInfo
->Type
;
360 if (DataLength
!= NULL
)
361 *DataLength
= ValueInfo
->DataLength
;
364 /* Check if the caller wanted data back, and we got it */
365 if ((NT_SUCCESS(Status
)) && (Data
!= NULL
))
370 ValueInfo
->DataLength
);
372 /* if the type is REG_SZ and data is not 0-terminated
373 * and there is enough space in the buffer NT appends a \0 */
374 if (IsStringType(ValueInfo
->Type
) &&
375 ValueInfo
->DataLength
<= *DataLength
- sizeof(WCHAR
))
377 WCHAR
*ptr
= (WCHAR
*)((ULONG_PTR
)Data
+ ValueInfo
->DataLength
);
378 if ((ptr
> (WCHAR
*)Data
) && ptr
[-1])
383 /* Free the memory and return status */
384 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo
);
386 if ((Data
== NULL
) && (Status
== STATUS_BUFFER_OVERFLOW
))
387 Status
= STATUS_SUCCESS
;
394 SampRegSetValue(HANDLE KeyHandle
,
402 RtlInitUnicodeString(&Name
,
405 return ZwSetValueKey(KeyHandle
,