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 SampRegCloseKey(IN OUT PHANDLE KeyHandle
)
27 if (KeyHandle
== NULL
|| *KeyHandle
== NULL
)
28 return STATUS_SUCCESS
;
30 Status
= NtClose(*KeyHandle
);
31 if (NT_SUCCESS(Status
))
39 SampRegCreateKey(IN HANDLE ParentKeyHandle
,
41 IN ACCESS_MASK DesiredAccess
,
42 OUT PHANDLE KeyHandle
)
44 OBJECT_ATTRIBUTES ObjectAttributes
;
48 RtlInitUnicodeString(&Name
, KeyName
);
50 InitializeObjectAttributes(&ObjectAttributes
,
52 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
57 return ZwCreateKey(KeyHandle
,
68 SampRegDeleteKey(IN HANDLE ParentKeyHandle
,
71 OBJECT_ATTRIBUTES ObjectAttributes
;
72 UNICODE_STRING SubKeyName
;
76 RtlInitUnicodeString(&SubKeyName
,
78 InitializeObjectAttributes(&ObjectAttributes
,
83 Status
= NtOpenKey(&TargetKey
,
86 if (!NT_SUCCESS(Status
))
89 Status
= NtDeleteKey(TargetKey
);
98 SampRegEnumerateSubKey(IN HANDLE KeyHandle
,
103 PKEY_BASIC_INFORMATION KeyInfo
= NULL
;
104 ULONG BufferLength
= 0;
105 ULONG ReturnedLength
;
108 /* Check if we have a name */
111 /* Allocate a buffer for it */
112 BufferLength
= sizeof(KEY_BASIC_INFORMATION
) + Length
* sizeof(WCHAR
);
114 KeyInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
116 return STATUS_NO_MEMORY
;
119 /* Enumerate the key */
120 Status
= ZwEnumerateKey(KeyHandle
,
126 if (NT_SUCCESS(Status
))
128 /* Check if the name fits */
129 if (KeyInfo
->NameLength
< (Length
* sizeof(WCHAR
)))
132 RtlMoveMemory(Buffer
,
134 KeyInfo
->NameLength
);
136 /* Terminate the string */
137 Buffer
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
141 /* Otherwise, we ran out of buffer space */
142 Status
= STATUS_BUFFER_OVERFLOW
;
146 /* Free the buffer and return status */
148 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
155 SampRegOpenKey(IN HANDLE ParentKeyHandle
,
157 IN ACCESS_MASK DesiredAccess
,
158 OUT PHANDLE KeyHandle
)
160 OBJECT_ATTRIBUTES ObjectAttributes
;
163 RtlInitUnicodeString(&Name
, KeyName
);
165 InitializeObjectAttributes(&ObjectAttributes
,
167 OBJ_CASE_INSENSITIVE
,
171 return NtOpenKey(KeyHandle
,
178 SampRegQueryKeyInfo(IN HANDLE KeyHandle
,
179 OUT PULONG SubKeyCount
,
180 OUT PULONG ValueCount
)
182 KEY_FULL_INFORMATION FullInfoBuffer
;
186 FullInfoBuffer
.ClassLength
= 0;
187 FullInfoBuffer
.ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
189 Status
= NtQueryKey(KeyHandle
,
192 sizeof(KEY_FULL_INFORMATION
),
194 TRACE("NtQueryKey() returned status 0x%08lX\n", Status
);
195 if (!NT_SUCCESS(Status
))
198 if (SubKeyCount
!= NULL
)
199 *SubKeyCount
= FullInfoBuffer
.SubKeys
;
201 if (ValueCount
!= NULL
)
202 *ValueCount
= FullInfoBuffer
.Values
;
209 SampRegDeleteValue(IN HANDLE KeyHandle
,
210 IN LPCWSTR ValueName
)
214 RtlInitUnicodeString(&Name
,
217 return NtDeleteValueKey(KeyHandle
,
223 SampRegEnumerateValue(IN HANDLE KeyHandle
,
226 IN OUT PULONG NameLength
,
227 OUT PULONG Type OPTIONAL
,
228 OUT PVOID Data OPTIONAL
,
229 IN OUT PULONG DataLength OPTIONAL
)
231 PKEY_VALUE_FULL_INFORMATION ValueInfo
= NULL
;
232 ULONG BufferLength
= 0;
233 ULONG ReturnedLength
;
236 TRACE("Index: %lu\n", Index
);
238 /* Calculate the required buffer length */
239 BufferLength
= FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
);
240 BufferLength
+= (MAX_PATH
+ 1) * sizeof(WCHAR
);
242 BufferLength
+= *DataLength
;
244 /* Allocate the value buffer */
245 ValueInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
246 if (ValueInfo
== NULL
)
247 return STATUS_NO_MEMORY
;
249 /* Enumerate the value*/
250 Status
= ZwEnumerateValueKey(KeyHandle
,
252 KeyValueFullInformation
,
256 if (NT_SUCCESS(Status
))
260 /* Check if the name fits */
261 if (ValueInfo
->NameLength
< (*NameLength
* sizeof(WCHAR
)))
266 ValueInfo
->NameLength
);
268 /* Terminate the string */
269 Name
[ValueInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
273 /* Otherwise, we ran out of buffer space */
274 Status
= STATUS_BUFFER_OVERFLOW
;
281 /* Check if the data fits */
282 if (ValueInfo
->DataLength
<= *DataLength
)
286 (PVOID
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->DataOffset
),
287 ValueInfo
->DataLength
);
289 /* if the type is REG_SZ and data is not 0-terminated
290 * and there is enough space in the buffer NT appends a \0 */
291 if (IsStringType(ValueInfo
->Type
) &&
292 ValueInfo
->DataLength
<= *DataLength
- sizeof(WCHAR
))
294 WCHAR
*ptr
= (WCHAR
*)((ULONG_PTR
)Data
+ ValueInfo
->DataLength
);
295 if ((ptr
> (WCHAR
*)Data
) && ptr
[-1])
301 Status
= STATUS_BUFFER_OVERFLOW
;
308 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
311 *Type
= ValueInfo
->Type
;
313 if (NameLength
!= NULL
)
314 *NameLength
= ValueInfo
->NameLength
;
316 if (DataLength
!= NULL
)
317 *DataLength
= ValueInfo
->DataLength
;
320 /* Free the buffer and return status */
322 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo
);
329 SampRegQueryValue(IN HANDLE KeyHandle
,
330 IN LPCWSTR ValueName
,
331 OUT PULONG Type OPTIONAL
,
332 OUT PVOID Data OPTIONAL
,
333 IN OUT PULONG DataLength OPTIONAL
)
335 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
337 ULONG BufferLength
= 0;
340 RtlInitUnicodeString(&Name
,
343 if (DataLength
!= NULL
)
344 BufferLength
= *DataLength
;
346 BufferLength
+= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
);
348 /* Allocate memory for the value */
349 ValueInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
350 if (ValueInfo
== NULL
)
351 return STATUS_NO_MEMORY
;
353 /* Query the value */
354 Status
= ZwQueryValueKey(KeyHandle
,
356 KeyValuePartialInformation
,
360 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
363 *Type
= ValueInfo
->Type
;
365 if (DataLength
!= NULL
)
366 *DataLength
= ValueInfo
->DataLength
;
369 /* Check if the caller wanted data back, and we got it */
370 if ((NT_SUCCESS(Status
)) && (Data
!= NULL
))
375 ValueInfo
->DataLength
);
377 /* if the type is REG_SZ and data is not 0-terminated
378 * and there is enough space in the buffer NT appends a \0 */
379 if (IsStringType(ValueInfo
->Type
) &&
380 ValueInfo
->DataLength
<= *DataLength
- sizeof(WCHAR
))
382 WCHAR
*ptr
= (WCHAR
*)((ULONG_PTR
)Data
+ ValueInfo
->DataLength
);
383 if ((ptr
> (WCHAR
*)Data
) && ptr
[-1])
388 /* Free the memory and return status */
389 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo
);
391 if ((Data
== NULL
) && (Status
== STATUS_BUFFER_OVERFLOW
))
392 Status
= STATUS_SUCCESS
;
399 SampRegSetValue(HANDLE KeyHandle
,
407 RtlInitUnicodeString(&Name
,
410 return ZwSetValueKey(KeyHandle
,