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