ReactOS  0.4.14-dev-297-g23e575c
registry.c
Go to the documentation of this file.
1 /*
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
6  *
7  * PROGRAMMERS: Eric Kohl
8  */
9 
10 #include "samsrv.h"
11 
12 #include <ndk/cmfuncs.h>
13 #include <ndk/obfuncs.h>
14 
15 /* FUNCTIONS ***************************************************************/
16 
17 static
18 BOOLEAN
20 {
21  return (Type == REG_SZ) || (Type == REG_EXPAND_SZ) || (Type == REG_MULTI_SZ);
22 }
23 
24 
27 {
29 
30  if (KeyHandle == NULL || *KeyHandle == NULL)
31  return STATUS_SUCCESS;
32 
34  if (NT_SUCCESS(Status))
35  *KeyHandle = NULL;
36 
37  return Status;
38 }
39 
40 
42 SampRegCreateKey(IN HANDLE ParentKeyHandle,
46 {
50 
52 
54  &Name,
56  ParentKeyHandle,
57  NULL);
58 
59  /* Create the key */
60  return ZwCreateKey(KeyHandle,
63  0,
64  NULL,
65  0,
66  &Disposition);
67 }
68 
69 
71 SampRegDeleteKey(IN HANDLE ParentKeyHandle,
73 {
76  HANDLE TargetKey;
78 
80  (LPWSTR)KeyName);
82  &SubKeyName,
84  ParentKeyHandle,
85  NULL);
86  Status = NtOpenKey(&TargetKey,
87  DELETE,
89  if (!NT_SUCCESS(Status))
90  return Status;
91 
92  Status = NtDeleteKey(TargetKey);
93 
94  NtClose(TargetKey);
95 
96  return Status;
97 }
98 
99 
100 NTSTATUS
102  IN ULONG Index,
103  IN ULONG Length,
104  OUT LPWSTR Buffer)
105 {
106  PKEY_BASIC_INFORMATION KeyInfo = NULL;
107  ULONG BufferLength = 0;
110 
111  /* Check if we have a name */
112  if (Length)
113  {
114  /* Allocate a buffer for it */
115  BufferLength = sizeof(KEY_BASIC_INFORMATION) + Length * sizeof(WCHAR);
116 
117  KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
118  if (KeyInfo == NULL)
119  return STATUS_NO_MEMORY;
120  }
121 
122  /* Enumerate the key */
123  Status = ZwEnumerateKey(KeyHandle,
124  Index,
126  KeyInfo,
127  BufferLength,
128  &ReturnedLength);
129  if (NT_SUCCESS(Status))
130  {
131  /* Check if the name fits */
132  if (KeyInfo->NameLength < (Length * sizeof(WCHAR)))
133  {
134  /* Copy it */
136  KeyInfo->Name,
137  KeyInfo->NameLength);
138 
139  /* Terminate the string */
140  Buffer[KeyInfo->NameLength / sizeof(WCHAR)] = 0;
141  }
142  else
143  {
144  /* Otherwise, we ran out of buffer space */
146  }
147  }
148 
149  /* Free the buffer and return status */
150  if (KeyInfo)
151  RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
152 
153  return Status;
154 }
155 
156 
157 NTSTATUS
158 SampRegOpenKey(IN HANDLE ParentKeyHandle,
162 {
165 
167 
169  &Name,
171  ParentKeyHandle,
172  NULL);
173 
174  return NtOpenKey(KeyHandle,
177 }
178 
179 
180 NTSTATUS
182  OUT PULONG SubKeyCount,
183  OUT PULONG ValueCount)
184 {
185  KEY_FULL_INFORMATION FullInfoBuffer;
186  ULONG Length;
188 
189  FullInfoBuffer.ClassLength = 0;
191 
194  &FullInfoBuffer,
195  sizeof(KEY_FULL_INFORMATION),
196  &Length);
197  TRACE("NtQueryKey() returned status 0x%08lX\n", Status);
198  if (!NT_SUCCESS(Status))
199  return Status;
200 
201  if (SubKeyCount != NULL)
202  *SubKeyCount = FullInfoBuffer.SubKeys;
203 
204  if (ValueCount != NULL)
205  *ValueCount = FullInfoBuffer.Values;
206 
207  return Status;
208 }
209 
210 
211 NTSTATUS
214 {
216 
218  ValueName);
219 
221  &Name);
222 }
223 
224 
225 NTSTATUS
227  IN ULONG Index,
228  OUT LPWSTR Name,
229  IN OUT PULONG NameLength,
233 {
234  PKEY_VALUE_FULL_INFORMATION ValueInfo = NULL;
235  ULONG BufferLength = 0;
238 
239  TRACE("Index: %lu\n", Index);
240 
241  /* Calculate the required buffer length */
243  BufferLength += (MAX_PATH + 1) * sizeof(WCHAR);
244  if (Data != NULL)
246 
247  /* Allocate the value buffer */
248  ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
249  if (ValueInfo == NULL)
250  return STATUS_NO_MEMORY;
251 
252  /* Enumerate the value*/
253  Status = ZwEnumerateValueKey(KeyHandle,
254  Index,
256  ValueInfo,
257  BufferLength,
258  &ReturnedLength);
259  if (NT_SUCCESS(Status))
260  {
261  if (Name != NULL)
262  {
263  /* Check if the name fits */
264  if (ValueInfo->NameLength < (*NameLength * sizeof(WCHAR)))
265  {
266  /* Copy it */
268  ValueInfo->Name,
269  ValueInfo->NameLength);
270 
271  /* Terminate the string */
272  Name[ValueInfo->NameLength / sizeof(WCHAR)] = 0;
273  }
274  else
275  {
276  /* Otherwise, we ran out of buffer space */
278  goto done;
279  }
280  }
281 
282  if (Data != NULL)
283  {
284  /* Check if the data fits */
285  if (ValueInfo->DataLength <= *DataLength)
286  {
287  /* Copy it */
289  (PVOID)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset),
290  ValueInfo->DataLength);
291 
292  /* if the type is REG_SZ and data is not 0-terminated
293  * and there is enough space in the buffer NT appends a \0 */
294  if (IsStringType(ValueInfo->Type) &&
295  ValueInfo->DataLength <= *DataLength - sizeof(WCHAR))
296  {
297  WCHAR *ptr = (WCHAR *)((ULONG_PTR)Data + ValueInfo->DataLength);
298  if ((ptr > (WCHAR *)Data) && ptr[-1])
299  *ptr = 0;
300  }
301  }
302  else
303  {
305  goto done;
306  }
307  }
308  }
309 
310 done:
312  {
313  if (Type != NULL)
314  *Type = ValueInfo->Type;
315 
316  if (NameLength != NULL)
317  *NameLength = ValueInfo->NameLength;
318 
319  if (DataLength != NULL)
320  *DataLength = ValueInfo->DataLength;
321  }
322 
323  /* Free the buffer and return status */
324  if (ValueInfo)
325  RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
326 
327  return Status;
328 }
329 
330 
331 NTSTATUS
337 {
340  ULONG BufferLength = 0;
342 
344  ValueName);
345 
346  if (DataLength != NULL)
348 
350 
351  /* Allocate memory for the value */
352  ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
353  if (ValueInfo == NULL)
354  return STATUS_NO_MEMORY;
355 
356  /* Query the value */
357  Status = ZwQueryValueKey(KeyHandle,
358  &Name,
360  ValueInfo,
361  BufferLength,
362  &BufferLength);
364  {
365  if (Type != NULL)
366  *Type = ValueInfo->Type;
367 
368  if (DataLength != NULL)
369  *DataLength = ValueInfo->DataLength;
370  }
371 
372  /* Check if the caller wanted data back, and we got it */
373  if ((NT_SUCCESS(Status)) && (Data != NULL))
374  {
375  /* Copy it */
377  ValueInfo->Data,
378  ValueInfo->DataLength);
379 
380  /* if the type is REG_SZ and data is not 0-terminated
381  * and there is enough space in the buffer NT appends a \0 */
382  if (IsStringType(ValueInfo->Type) &&
383  ValueInfo->DataLength <= *DataLength - sizeof(WCHAR))
384  {
385  WCHAR *ptr = (WCHAR *)((ULONG_PTR)Data + ValueInfo->DataLength);
386  if ((ptr > (WCHAR *)Data) && ptr[-1])
387  *ptr = 0;
388  }
389  }
390 
391  /* Free the memory and return status */
392  RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
393 
394  if ((Data == NULL) && (Status == STATUS_BUFFER_OVERFLOW))
396 
397  return Status;
398 }
399 
400 
401 NTSTATUS
404  ULONG Type,
405  LPVOID Data,
407 {
409 
411  ValueName);
412 
413  return ZwSetValueKey(KeyHandle,
414  &Name,
415  0,
416  Type,
417  Data,
418  DataLength);
419 }
NTSTATUS SampRegEnumerateValue(IN HANDLE KeyHandle, IN ULONG Index, OUT LPWSTR Name, IN OUT PULONG NameLength, OUT PULONG Type OPTIONAL, OUT PVOID Data OPTIONAL, IN OUT PULONG DataLength OPTIONAL)
Definition: registry.c:226
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING KeyName
Definition: ndis.h:4711
#define IN
Definition: typedefs.h:38
Type
Definition: Type.h:6
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING SubKeyName
Definition: ndis.h:4723
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4711
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
struct _KEY_BASIC_INFORMATION KEY_BASIC_INFORMATION
NTSTATUS SampRegDeleteValue(IN HANDLE KeyHandle, IN LPCWSTR ValueName)
Definition: registry.c:212
NTSTATUS NTAPI NtQueryKey(IN HANDLE KeyHandle, IN KEY_INFORMATION_CLASS KeyInformationClass, OUT PVOID KeyInformation, IN ULONG Length, OUT PULONG ResultLength)
Definition: ntapi.c:632
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Reserved_ ULONG _In_opt_ PUNICODE_STRING _In_ ULONG _Out_opt_ PULONG Disposition
Definition: cmfuncs.h:50
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
NTSTATUS SampRegCloseKey(IN OUT PHANDLE KeyHandle)
Definition: registry.c:26
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define OBJ_OPENIF
Definition: winternl.h:229
_In_ PUNICODE_STRING ValueName
Definition: cmfuncs.h:264
_In_ ULONG BufferLength
Definition: usbdlib.h:225
#define REG_MULTI_SZ
Definition: nt_native.h:1501
static PVOID ptr
Definition: dispmode.c:27
struct NameRec_ * Name
Definition: cdprocs.h:464
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS SampRegQueryKeyInfo(IN HANDLE KeyHandle, OUT PULONG SubKeyCount, OUT PULONG ValueCount)
Definition: registry.c:181
Definition: bufpool.h:45
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
NTSYSAPI NTSTATUS NTAPI NtDeleteValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName)
Definition: ntapi.c:994
#define TRACE(s)
Definition: solgame.cpp:4
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTATUS SampRegEnumerateSubKey(IN HANDLE KeyHandle, IN ULONG Index, IN ULONG Length, OUT LPWSTR Buffer)
Definition: registry.c:101
#define MAX_PATH
Definition: compat.h:26
static const UCHAR Index[8]
Definition: usbohci.c:18
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSTATUS SampRegDeleteKey(IN HANDLE ParentKeyHandle, IN LPCWSTR KeyName)
Definition: registry.c:71
NTSTATUS SampRegQueryValue(IN HANDLE KeyHandle, IN LPCWSTR ValueName, OUT PULONG Type OPTIONAL, OUT PVOID Data OPTIONAL, IN OUT PULONG DataLength OPTIONAL)
Definition: registry.c:332
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
_In_ ULONG _In_ BATTERY_QUERY_INFORMATION_LEVEL _In_ LONG _In_ ULONG _Out_ PULONG ReturnedLength
Definition: batclass.h:187
Status
Definition: gdiplustypes.h:24
NTSTATUS NTAPI NtDeleteKey(IN HANDLE KeyHandle)
Definition: ntapi.c:408
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
NTSTATUS SampRegOpenKey(IN HANDLE ParentKeyHandle, IN LPCWSTR KeyName, IN ACCESS_MASK DesiredAccess, OUT PHANDLE KeyHandle)
Definition: registry.c:158
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK DesiredAccess
Definition: create.c:4157
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
unsigned int * PULONG
Definition: retypes.h:1
NTSTATUS SampRegSetValue(HANDLE KeyHandle, LPCWSTR ValueName, ULONG Type, LPVOID Data, ULONG DataLength)
Definition: registry.c:402
NTSYSAPI NTSTATUS NTAPI NtOpenKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: ntapi.c:336
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
WCHAR * LPWSTR
Definition: xmlstorage.h:184
NTSTATUS SampRegCreateKey(IN HANDLE ParentKeyHandle, IN LPCWSTR KeyName, IN ACCESS_MASK DesiredAccess, OUT PHANDLE KeyHandle)
Definition: registry.c:42
_Must_inspect_result_ _Out_writes_to_ DataLength PHIDP_DATA _Inout_ PULONG DataLength
Definition: hidpi.h:333
return STATUS_SUCCESS
Definition: btrfs.c:2966
ULONG ACCESS_MASK
Definition: nt_native.h:40
static BOOLEAN IsStringType(ULONG Type)
Definition: registry.c:19
#define DELETE
Definition: nt_native.h:57
#define REG_SZ
Definition: layer.c:22
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68