xref: /reactos/dll/win32/samsrv/registry.c (revision c2c66aff)
1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * COPYRIGHT:       See COPYING in the top level directory
3*c2c66affSColin Finck  * PROJECT:         Security Account Manager (SAM) Server
4*c2c66affSColin Finck  * FILE:            reactos/dll/win32/samsrv/registry.c
5*c2c66affSColin Finck  * PURPOSE:         Registry helper functions
6*c2c66affSColin Finck  *
7*c2c66affSColin Finck  * PROGRAMMERS:     Eric Kohl
8*c2c66affSColin Finck  */
9*c2c66affSColin Finck 
10*c2c66affSColin Finck #include "samsrv.h"
11*c2c66affSColin Finck 
12*c2c66affSColin Finck #include <ndk/cmfuncs.h>
13*c2c66affSColin Finck #include <ndk/obfuncs.h>
14*c2c66affSColin Finck 
15*c2c66affSColin Finck /* FUNCTIONS ***************************************************************/
16*c2c66affSColin Finck 
17*c2c66affSColin Finck static
18*c2c66affSColin Finck BOOLEAN
IsStringType(ULONG Type)19*c2c66affSColin Finck IsStringType(ULONG Type)
20*c2c66affSColin Finck {
21*c2c66affSColin Finck     return (Type == REG_SZ) || (Type == REG_EXPAND_SZ) || (Type == REG_MULTI_SZ);
22*c2c66affSColin Finck }
23*c2c66affSColin Finck 
24*c2c66affSColin Finck 
25*c2c66affSColin Finck NTSTATUS
SampRegCloseKey(IN OUT PHANDLE KeyHandle)26*c2c66affSColin Finck SampRegCloseKey(IN OUT PHANDLE KeyHandle)
27*c2c66affSColin Finck {
28*c2c66affSColin Finck     NTSTATUS Status;
29*c2c66affSColin Finck 
30*c2c66affSColin Finck     if (KeyHandle == NULL || *KeyHandle == NULL)
31*c2c66affSColin Finck         return STATUS_SUCCESS;
32*c2c66affSColin Finck 
33*c2c66affSColin Finck     Status = NtClose(*KeyHandle);
34*c2c66affSColin Finck     if (NT_SUCCESS(Status))
35*c2c66affSColin Finck         *KeyHandle = NULL;
36*c2c66affSColin Finck 
37*c2c66affSColin Finck     return Status;
38*c2c66affSColin Finck }
39*c2c66affSColin Finck 
40*c2c66affSColin Finck 
41*c2c66affSColin Finck NTSTATUS
SampRegCreateKey(IN HANDLE ParentKeyHandle,IN LPCWSTR KeyName,IN ACCESS_MASK DesiredAccess,OUT PHANDLE KeyHandle)42*c2c66affSColin Finck SampRegCreateKey(IN HANDLE ParentKeyHandle,
43*c2c66affSColin Finck                  IN LPCWSTR KeyName,
44*c2c66affSColin Finck                  IN ACCESS_MASK DesiredAccess,
45*c2c66affSColin Finck                  OUT PHANDLE KeyHandle)
46*c2c66affSColin Finck {
47*c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
48*c2c66affSColin Finck     UNICODE_STRING Name;
49*c2c66affSColin Finck     ULONG Disposition;
50*c2c66affSColin Finck 
51*c2c66affSColin Finck     RtlInitUnicodeString(&Name, KeyName);
52*c2c66affSColin Finck 
53*c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
54*c2c66affSColin Finck                                &Name,
55*c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
56*c2c66affSColin Finck                                ParentKeyHandle,
57*c2c66affSColin Finck                                NULL);
58*c2c66affSColin Finck 
59*c2c66affSColin Finck     /* Create the key */
60*c2c66affSColin Finck     return ZwCreateKey(KeyHandle,
61*c2c66affSColin Finck                        DesiredAccess,
62*c2c66affSColin Finck                        &ObjectAttributes,
63*c2c66affSColin Finck                        0,
64*c2c66affSColin Finck                        NULL,
65*c2c66affSColin Finck                        0,
66*c2c66affSColin Finck                        &Disposition);
67*c2c66affSColin Finck }
68*c2c66affSColin Finck 
69*c2c66affSColin Finck 
70*c2c66affSColin Finck NTSTATUS
SampRegDeleteKey(IN HANDLE ParentKeyHandle,IN LPCWSTR KeyName)71*c2c66affSColin Finck SampRegDeleteKey(IN HANDLE ParentKeyHandle,
72*c2c66affSColin Finck                  IN LPCWSTR KeyName)
73*c2c66affSColin Finck {
74*c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
75*c2c66affSColin Finck     UNICODE_STRING SubKeyName;
76*c2c66affSColin Finck     HANDLE TargetKey;
77*c2c66affSColin Finck     NTSTATUS Status;
78*c2c66affSColin Finck 
79*c2c66affSColin Finck     RtlInitUnicodeString(&SubKeyName,
80*c2c66affSColin Finck                          (LPWSTR)KeyName);
81*c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
82*c2c66affSColin Finck                                &SubKeyName,
83*c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
84*c2c66affSColin Finck                                ParentKeyHandle,
85*c2c66affSColin Finck                                NULL);
86*c2c66affSColin Finck     Status = NtOpenKey(&TargetKey,
87*c2c66affSColin Finck                        DELETE,
88*c2c66affSColin Finck                        &ObjectAttributes);
89*c2c66affSColin Finck     if (!NT_SUCCESS(Status))
90*c2c66affSColin Finck         return Status;
91*c2c66affSColin Finck 
92*c2c66affSColin Finck     Status = NtDeleteKey(TargetKey);
93*c2c66affSColin Finck 
94*c2c66affSColin Finck     NtClose(TargetKey);
95*c2c66affSColin Finck 
96*c2c66affSColin Finck     return Status;
97*c2c66affSColin Finck }
98*c2c66affSColin Finck 
99*c2c66affSColin Finck 
100*c2c66affSColin Finck NTSTATUS
SampRegEnumerateSubKey(IN HANDLE KeyHandle,IN ULONG Index,IN ULONG Length,OUT LPWSTR Buffer)101*c2c66affSColin Finck SampRegEnumerateSubKey(IN HANDLE KeyHandle,
102*c2c66affSColin Finck                        IN ULONG Index,
103*c2c66affSColin Finck                        IN ULONG Length,
104*c2c66affSColin Finck                        OUT LPWSTR Buffer)
105*c2c66affSColin Finck {
106*c2c66affSColin Finck     PKEY_BASIC_INFORMATION KeyInfo = NULL;
107*c2c66affSColin Finck     ULONG BufferLength = 0;
108*c2c66affSColin Finck     ULONG ReturnedLength;
109*c2c66affSColin Finck     NTSTATUS Status;
110*c2c66affSColin Finck 
111*c2c66affSColin Finck     /* Check if we have a name */
112*c2c66affSColin Finck     if (Length)
113*c2c66affSColin Finck     {
114*c2c66affSColin Finck         /* Allocate a buffer for it */
115*c2c66affSColin Finck         BufferLength = sizeof(KEY_BASIC_INFORMATION) + Length * sizeof(WCHAR);
116*c2c66affSColin Finck 
117*c2c66affSColin Finck         KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
118*c2c66affSColin Finck         if (KeyInfo == NULL)
119*c2c66affSColin Finck             return STATUS_NO_MEMORY;
120*c2c66affSColin Finck     }
121*c2c66affSColin Finck 
122*c2c66affSColin Finck     /* Enumerate the key */
123*c2c66affSColin Finck     Status = ZwEnumerateKey(KeyHandle,
124*c2c66affSColin Finck                             Index,
125*c2c66affSColin Finck                             KeyBasicInformation,
126*c2c66affSColin Finck                             KeyInfo,
127*c2c66affSColin Finck                             BufferLength,
128*c2c66affSColin Finck                             &ReturnedLength);
129*c2c66affSColin Finck     if (NT_SUCCESS(Status))
130*c2c66affSColin Finck     {
131*c2c66affSColin Finck         /* Check if the name fits */
132*c2c66affSColin Finck         if (KeyInfo->NameLength < (Length * sizeof(WCHAR)))
133*c2c66affSColin Finck         {
134*c2c66affSColin Finck             /* Copy it */
135*c2c66affSColin Finck             RtlMoveMemory(Buffer,
136*c2c66affSColin Finck                           KeyInfo->Name,
137*c2c66affSColin Finck                           KeyInfo->NameLength);
138*c2c66affSColin Finck 
139*c2c66affSColin Finck             /* Terminate the string */
140*c2c66affSColin Finck             Buffer[KeyInfo->NameLength / sizeof(WCHAR)] = 0;
141*c2c66affSColin Finck         }
142*c2c66affSColin Finck         else
143*c2c66affSColin Finck         {
144*c2c66affSColin Finck             /* Otherwise, we ran out of buffer space */
145*c2c66affSColin Finck             Status = STATUS_BUFFER_OVERFLOW;
146*c2c66affSColin Finck         }
147*c2c66affSColin Finck     }
148*c2c66affSColin Finck 
149*c2c66affSColin Finck     /* Free the buffer and return status */
150*c2c66affSColin Finck     if (KeyInfo)
151*c2c66affSColin Finck         RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
152*c2c66affSColin Finck 
153*c2c66affSColin Finck     return Status;
154*c2c66affSColin Finck }
155*c2c66affSColin Finck 
156*c2c66affSColin Finck 
157*c2c66affSColin Finck NTSTATUS
SampRegOpenKey(IN HANDLE ParentKeyHandle,IN LPCWSTR KeyName,IN ACCESS_MASK DesiredAccess,OUT PHANDLE KeyHandle)158*c2c66affSColin Finck SampRegOpenKey(IN HANDLE ParentKeyHandle,
159*c2c66affSColin Finck                IN LPCWSTR KeyName,
160*c2c66affSColin Finck                IN ACCESS_MASK DesiredAccess,
161*c2c66affSColin Finck                OUT PHANDLE KeyHandle)
162*c2c66affSColin Finck {
163*c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
164*c2c66affSColin Finck     UNICODE_STRING Name;
165*c2c66affSColin Finck 
166*c2c66affSColin Finck     RtlInitUnicodeString(&Name, KeyName);
167*c2c66affSColin Finck 
168*c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
169*c2c66affSColin Finck                                &Name,
170*c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
171*c2c66affSColin Finck                                ParentKeyHandle,
172*c2c66affSColin Finck                                NULL);
173*c2c66affSColin Finck 
174*c2c66affSColin Finck     return NtOpenKey(KeyHandle,
175*c2c66affSColin Finck                      DesiredAccess,
176*c2c66affSColin Finck                      &ObjectAttributes);
177*c2c66affSColin Finck }
178*c2c66affSColin Finck 
179*c2c66affSColin Finck 
180*c2c66affSColin Finck NTSTATUS
SampRegQueryKeyInfo(IN HANDLE KeyHandle,OUT PULONG SubKeyCount,OUT PULONG ValueCount)181*c2c66affSColin Finck SampRegQueryKeyInfo(IN HANDLE KeyHandle,
182*c2c66affSColin Finck                     OUT PULONG SubKeyCount,
183*c2c66affSColin Finck                     OUT PULONG ValueCount)
184*c2c66affSColin Finck {
185*c2c66affSColin Finck     KEY_FULL_INFORMATION FullInfoBuffer;
186*c2c66affSColin Finck     ULONG Length;
187*c2c66affSColin Finck     NTSTATUS Status;
188*c2c66affSColin Finck 
189*c2c66affSColin Finck     FullInfoBuffer.ClassLength = 0;
190*c2c66affSColin Finck     FullInfoBuffer.ClassOffset = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
191*c2c66affSColin Finck 
192*c2c66affSColin Finck     Status = NtQueryKey(KeyHandle,
193*c2c66affSColin Finck                         KeyFullInformation,
194*c2c66affSColin Finck                         &FullInfoBuffer,
195*c2c66affSColin Finck                         sizeof(KEY_FULL_INFORMATION),
196*c2c66affSColin Finck                         &Length);
197*c2c66affSColin Finck     TRACE("NtQueryKey() returned status 0x%08lX\n", Status);
198*c2c66affSColin Finck     if (!NT_SUCCESS(Status))
199*c2c66affSColin Finck         return Status;
200*c2c66affSColin Finck 
201*c2c66affSColin Finck     if (SubKeyCount != NULL)
202*c2c66affSColin Finck         *SubKeyCount = FullInfoBuffer.SubKeys;
203*c2c66affSColin Finck 
204*c2c66affSColin Finck     if (ValueCount != NULL)
205*c2c66affSColin Finck         *ValueCount = FullInfoBuffer.Values;
206*c2c66affSColin Finck 
207*c2c66affSColin Finck     return Status;
208*c2c66affSColin Finck }
209*c2c66affSColin Finck 
210*c2c66affSColin Finck 
211*c2c66affSColin Finck NTSTATUS
SampRegDeleteValue(IN HANDLE KeyHandle,IN LPCWSTR ValueName)212*c2c66affSColin Finck SampRegDeleteValue(IN HANDLE KeyHandle,
213*c2c66affSColin Finck                    IN LPCWSTR ValueName)
214*c2c66affSColin Finck {
215*c2c66affSColin Finck     UNICODE_STRING Name;
216*c2c66affSColin Finck 
217*c2c66affSColin Finck     RtlInitUnicodeString(&Name,
218*c2c66affSColin Finck                          ValueName);
219*c2c66affSColin Finck 
220*c2c66affSColin Finck     return NtDeleteValueKey(KeyHandle,
221*c2c66affSColin Finck                             &Name);
222*c2c66affSColin Finck }
223*c2c66affSColin Finck 
224*c2c66affSColin Finck 
225*c2c66affSColin Finck 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)226*c2c66affSColin Finck SampRegEnumerateValue(IN HANDLE KeyHandle,
227*c2c66affSColin Finck                       IN ULONG Index,
228*c2c66affSColin Finck                       OUT LPWSTR Name,
229*c2c66affSColin Finck                       IN OUT PULONG NameLength,
230*c2c66affSColin Finck                       OUT PULONG Type OPTIONAL,
231*c2c66affSColin Finck                       OUT PVOID Data OPTIONAL,
232*c2c66affSColin Finck                       IN OUT PULONG DataLength OPTIONAL)
233*c2c66affSColin Finck {
234*c2c66affSColin Finck     PKEY_VALUE_FULL_INFORMATION ValueInfo = NULL;
235*c2c66affSColin Finck     ULONG BufferLength = 0;
236*c2c66affSColin Finck     ULONG ReturnedLength;
237*c2c66affSColin Finck     NTSTATUS Status;
238*c2c66affSColin Finck 
239*c2c66affSColin Finck     TRACE("Index: %lu\n", Index);
240*c2c66affSColin Finck 
241*c2c66affSColin Finck     /* Calculate the required buffer length */
242*c2c66affSColin Finck     BufferLength = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name);
243*c2c66affSColin Finck     BufferLength += (MAX_PATH + 1) * sizeof(WCHAR);
244*c2c66affSColin Finck     if (Data != NULL)
245*c2c66affSColin Finck         BufferLength += *DataLength;
246*c2c66affSColin Finck 
247*c2c66affSColin Finck     /* Allocate the value buffer */
248*c2c66affSColin Finck     ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
249*c2c66affSColin Finck     if (ValueInfo == NULL)
250*c2c66affSColin Finck         return STATUS_NO_MEMORY;
251*c2c66affSColin Finck 
252*c2c66affSColin Finck     /* Enumerate the value*/
253*c2c66affSColin Finck     Status = ZwEnumerateValueKey(KeyHandle,
254*c2c66affSColin Finck                                  Index,
255*c2c66affSColin Finck                                  KeyValueFullInformation,
256*c2c66affSColin Finck                                  ValueInfo,
257*c2c66affSColin Finck                                  BufferLength,
258*c2c66affSColin Finck                                  &ReturnedLength);
259*c2c66affSColin Finck     if (NT_SUCCESS(Status))
260*c2c66affSColin Finck     {
261*c2c66affSColin Finck         if (Name != NULL)
262*c2c66affSColin Finck         {
263*c2c66affSColin Finck             /* Check if the name fits */
264*c2c66affSColin Finck             if (ValueInfo->NameLength < (*NameLength * sizeof(WCHAR)))
265*c2c66affSColin Finck             {
266*c2c66affSColin Finck                 /* Copy it */
267*c2c66affSColin Finck                 RtlMoveMemory(Name,
268*c2c66affSColin Finck                               ValueInfo->Name,
269*c2c66affSColin Finck                               ValueInfo->NameLength);
270*c2c66affSColin Finck 
271*c2c66affSColin Finck                 /* Terminate the string */
272*c2c66affSColin Finck                 Name[ValueInfo->NameLength / sizeof(WCHAR)] = 0;
273*c2c66affSColin Finck             }
274*c2c66affSColin Finck             else
275*c2c66affSColin Finck             {
276*c2c66affSColin Finck                 /* Otherwise, we ran out of buffer space */
277*c2c66affSColin Finck                 Status = STATUS_BUFFER_OVERFLOW;
278*c2c66affSColin Finck                 goto done;
279*c2c66affSColin Finck             }
280*c2c66affSColin Finck         }
281*c2c66affSColin Finck 
282*c2c66affSColin Finck         if (Data != NULL)
283*c2c66affSColin Finck         {
284*c2c66affSColin Finck             /* Check if the data fits */
285*c2c66affSColin Finck             if (ValueInfo->DataLength <= *DataLength)
286*c2c66affSColin Finck             {
287*c2c66affSColin Finck                 /* Copy it */
288*c2c66affSColin Finck                 RtlMoveMemory(Data,
289*c2c66affSColin Finck                               (PVOID)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset),
290*c2c66affSColin Finck                               ValueInfo->DataLength);
291*c2c66affSColin Finck 
292*c2c66affSColin Finck                 /* if the type is REG_SZ and data is not 0-terminated
293*c2c66affSColin Finck                  * and there is enough space in the buffer NT appends a \0 */
294*c2c66affSColin Finck                 if (IsStringType(ValueInfo->Type) &&
295*c2c66affSColin Finck                     ValueInfo->DataLength <= *DataLength - sizeof(WCHAR))
296*c2c66affSColin Finck                 {
297*c2c66affSColin Finck                     WCHAR *ptr = (WCHAR *)((ULONG_PTR)Data + ValueInfo->DataLength);
298*c2c66affSColin Finck                     if ((ptr > (WCHAR *)Data) && ptr[-1])
299*c2c66affSColin Finck                         *ptr = 0;
300*c2c66affSColin Finck                 }
301*c2c66affSColin Finck             }
302*c2c66affSColin Finck             else
303*c2c66affSColin Finck             {
304*c2c66affSColin Finck                 Status = STATUS_BUFFER_OVERFLOW;
305*c2c66affSColin Finck                 goto done;
306*c2c66affSColin Finck             }
307*c2c66affSColin Finck         }
308*c2c66affSColin Finck     }
309*c2c66affSColin Finck 
310*c2c66affSColin Finck done:
311*c2c66affSColin Finck     if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
312*c2c66affSColin Finck     {
313*c2c66affSColin Finck         if (Type != NULL)
314*c2c66affSColin Finck             *Type = ValueInfo->Type;
315*c2c66affSColin Finck 
316*c2c66affSColin Finck         if (NameLength != NULL)
317*c2c66affSColin Finck             *NameLength = ValueInfo->NameLength;
318*c2c66affSColin Finck 
319*c2c66affSColin Finck         if (DataLength != NULL)
320*c2c66affSColin Finck             *DataLength = ValueInfo->DataLength;
321*c2c66affSColin Finck     }
322*c2c66affSColin Finck 
323*c2c66affSColin Finck     /* Free the buffer and return status */
324*c2c66affSColin Finck     if (ValueInfo)
325*c2c66affSColin Finck         RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
326*c2c66affSColin Finck 
327*c2c66affSColin Finck     return Status;
328*c2c66affSColin Finck }
329*c2c66affSColin Finck 
330*c2c66affSColin Finck 
331*c2c66affSColin Finck NTSTATUS
SampRegQueryValue(IN HANDLE KeyHandle,IN LPCWSTR ValueName,OUT PULONG Type OPTIONAL,OUT PVOID Data OPTIONAL,IN OUT PULONG DataLength OPTIONAL)332*c2c66affSColin Finck SampRegQueryValue(IN HANDLE KeyHandle,
333*c2c66affSColin Finck                   IN LPCWSTR ValueName,
334*c2c66affSColin Finck                   OUT PULONG Type OPTIONAL,
335*c2c66affSColin Finck                   OUT PVOID Data OPTIONAL,
336*c2c66affSColin Finck                   IN OUT PULONG DataLength OPTIONAL)
337*c2c66affSColin Finck {
338*c2c66affSColin Finck     PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
339*c2c66affSColin Finck     UNICODE_STRING Name;
340*c2c66affSColin Finck     ULONG BufferLength = 0;
341*c2c66affSColin Finck     NTSTATUS Status;
342*c2c66affSColin Finck 
343*c2c66affSColin Finck     RtlInitUnicodeString(&Name,
344*c2c66affSColin Finck                          ValueName);
345*c2c66affSColin Finck 
346*c2c66affSColin Finck     if (DataLength != NULL)
347*c2c66affSColin Finck         BufferLength = *DataLength;
348*c2c66affSColin Finck 
349*c2c66affSColin Finck     BufferLength += FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
350*c2c66affSColin Finck 
351*c2c66affSColin Finck     /* Allocate memory for the value */
352*c2c66affSColin Finck     ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
353*c2c66affSColin Finck     if (ValueInfo == NULL)
354*c2c66affSColin Finck         return STATUS_NO_MEMORY;
355*c2c66affSColin Finck 
356*c2c66affSColin Finck     /* Query the value */
357*c2c66affSColin Finck     Status = ZwQueryValueKey(KeyHandle,
358*c2c66affSColin Finck                              &Name,
359*c2c66affSColin Finck                              KeyValuePartialInformation,
360*c2c66affSColin Finck                              ValueInfo,
361*c2c66affSColin Finck                              BufferLength,
362*c2c66affSColin Finck                              &BufferLength);
363*c2c66affSColin Finck     if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
364*c2c66affSColin Finck     {
365*c2c66affSColin Finck         if (Type != NULL)
366*c2c66affSColin Finck             *Type = ValueInfo->Type;
367*c2c66affSColin Finck 
368*c2c66affSColin Finck         if (DataLength != NULL)
369*c2c66affSColin Finck             *DataLength = ValueInfo->DataLength;
370*c2c66affSColin Finck     }
371*c2c66affSColin Finck 
372*c2c66affSColin Finck     /* Check if the caller wanted data back, and we got it */
373*c2c66affSColin Finck     if ((NT_SUCCESS(Status)) && (Data != NULL))
374*c2c66affSColin Finck     {
375*c2c66affSColin Finck         /* Copy it */
376*c2c66affSColin Finck         RtlMoveMemory(Data,
377*c2c66affSColin Finck                       ValueInfo->Data,
378*c2c66affSColin Finck                       ValueInfo->DataLength);
379*c2c66affSColin Finck 
380*c2c66affSColin Finck         /* if the type is REG_SZ and data is not 0-terminated
381*c2c66affSColin Finck          * and there is enough space in the buffer NT appends a \0 */
382*c2c66affSColin Finck         if (IsStringType(ValueInfo->Type) &&
383*c2c66affSColin Finck             ValueInfo->DataLength <= *DataLength - sizeof(WCHAR))
384*c2c66affSColin Finck         {
385*c2c66affSColin Finck             WCHAR *ptr = (WCHAR *)((ULONG_PTR)Data + ValueInfo->DataLength);
386*c2c66affSColin Finck             if ((ptr > (WCHAR *)Data) && ptr[-1])
387*c2c66affSColin Finck                 *ptr = 0;
388*c2c66affSColin Finck         }
389*c2c66affSColin Finck     }
390*c2c66affSColin Finck 
391*c2c66affSColin Finck     /* Free the memory and return status */
392*c2c66affSColin Finck     RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
393*c2c66affSColin Finck 
394*c2c66affSColin Finck     if ((Data == NULL) && (Status == STATUS_BUFFER_OVERFLOW))
395*c2c66affSColin Finck         Status = STATUS_SUCCESS;
396*c2c66affSColin Finck 
397*c2c66affSColin Finck     return Status;
398*c2c66affSColin Finck }
399*c2c66affSColin Finck 
400*c2c66affSColin Finck 
401*c2c66affSColin Finck NTSTATUS
SampRegSetValue(HANDLE KeyHandle,LPCWSTR ValueName,ULONG Type,LPVOID Data,ULONG DataLength)402*c2c66affSColin Finck SampRegSetValue(HANDLE KeyHandle,
403*c2c66affSColin Finck                 LPCWSTR ValueName,
404*c2c66affSColin Finck                 ULONG Type,
405*c2c66affSColin Finck                 LPVOID Data,
406*c2c66affSColin Finck                 ULONG DataLength)
407*c2c66affSColin Finck {
408*c2c66affSColin Finck     UNICODE_STRING Name;
409*c2c66affSColin Finck 
410*c2c66affSColin Finck     RtlInitUnicodeString(&Name,
411*c2c66affSColin Finck                          ValueName);
412*c2c66affSColin Finck 
413*c2c66affSColin Finck     return ZwSetValueKey(KeyHandle,
414*c2c66affSColin Finck                          &Name,
415*c2c66affSColin Finck                          0,
416*c2c66affSColin Finck                          Type,
417*c2c66affSColin Finck                          Data,
418*c2c66affSColin Finck                          DataLength);
419*c2c66affSColin Finck }
420