xref: /reactos/dll/win32/advapi32/reg/reg.c (revision aff16663)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT:       See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT:         ReactOS system libraries
4c2c66affSColin Finck  * FILE:            lib/advapi32/reg/reg.c
5c2c66affSColin Finck  * PURPOSE:         Registry functions
6c2c66affSColin Finck  * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
7c2c66affSColin Finck  *                  Thomas Weidenmueller <w3seek@reactos.com>
8c2c66affSColin Finck  * UPDATE HISTORY:
9c2c66affSColin Finck  *                  Created 01/11/98
10c2c66affSColin Finck  *                  19990309 EA Stubs
11c2c66affSColin Finck  *                  20050502 Fireball imported some stuff from WINE
12c2c66affSColin Finck  */
13c2c66affSColin Finck 
14c2c66affSColin Finck /* INCLUDES *****************************************************************/
15c2c66affSColin Finck 
16c2c66affSColin Finck #include <advapi32.h>
17c2c66affSColin Finck 
18c2c66affSColin Finck #include <ndk/cmfuncs.h>
19c2c66affSColin Finck #include <pseh/pseh2.h>
20c2c66affSColin Finck 
21c2c66affSColin Finck #include "reg.h"
22c2c66affSColin Finck 
23c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(reg);
24c2c66affSColin Finck 
25c2c66affSColin Finck /* DEFINES ******************************************************************/
26c2c66affSColin Finck 
27c2c66affSColin Finck #define MAX_DEFAULT_HANDLES   6
28c2c66affSColin Finck #define REG_MAX_NAME_SIZE     256
29c2c66affSColin Finck #define REG_MAX_DATA_SIZE     2048
30c2c66affSColin Finck 
31c2c66affSColin Finck /* GLOBALS ******************************************************************/
32c2c66affSColin Finck 
33c2c66affSColin Finck static RTL_CRITICAL_SECTION HandleTableCS;
34c2c66affSColin Finck static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES];
35c2c66affSColin Finck static HANDLE ProcessHeap;
36c2c66affSColin Finck static BOOLEAN DefaultHandlesDisabled = FALSE;
37c2c66affSColin Finck static BOOLEAN DefaultHandleHKUDisabled = FALSE;
38c2c66affSColin Finck static BOOLEAN DllInitialized = FALSE; /* HACK */
39c2c66affSColin Finck 
40c2c66affSColin Finck /* PROTOTYPES ***************************************************************/
41c2c66affSColin Finck 
42c2c66affSColin Finck static NTSTATUS MapDefaultKey (PHANDLE ParentKey, HKEY Key);
43c2c66affSColin Finck static VOID CloseDefaultKeys(VOID);
44c2c66affSColin Finck #define ClosePredefKey(Handle)                                                 \
45c2c66affSColin Finck     if ((ULONG_PTR)Handle & 0x1) {                                             \
46c2c66affSColin Finck         NtClose(Handle);                                                       \
47c2c66affSColin Finck     }
48c2c66affSColin Finck #define IsPredefKey(HKey)                                                      \
49c2c66affSColin Finck     (((ULONG_PTR)(HKey) & 0xF0000000) == 0x80000000)
50c2c66affSColin Finck #define GetPredefKeyIndex(HKey)                                                \
51c2c66affSColin Finck     ((ULONG_PTR)(HKey) & 0x0FFFFFFF)
52c2c66affSColin Finck 
53c2c66affSColin Finck static NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle);
54c2c66affSColin Finck static NTSTATUS OpenLocalMachineKey (PHANDLE KeyHandle);
55c2c66affSColin Finck static NTSTATUS OpenUsersKey (PHANDLE KeyHandle);
56c2c66affSColin Finck static NTSTATUS OpenCurrentConfigKey(PHANDLE KeyHandle);
57c2c66affSColin Finck 
58c2c66affSColin Finck 
59c2c66affSColin Finck /* FUNCTIONS ****************************************************************/
60c2c66affSColin Finck /* check if value type needs string conversion (Ansi<->Unicode) */
61c2c66affSColin Finck __inline static int is_string( DWORD type )
62c2c66affSColin Finck {
63c2c66affSColin Finck     return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
64c2c66affSColin Finck }
65c2c66affSColin Finck 
66c2c66affSColin Finck /************************************************************************
67c2c66affSColin Finck  *  RegInitDefaultHandles
68c2c66affSColin Finck  */
69c2c66affSColin Finck BOOL
70c2c66affSColin Finck RegInitialize(VOID)
71c2c66affSColin Finck {
72c2c66affSColin Finck     TRACE("RegInitialize()\n");
73c2c66affSColin Finck 
74c2c66affSColin Finck     /* Lazy init hack */
75c2c66affSColin Finck     if (!DllInitialized)
76c2c66affSColin Finck     {
77c2c66affSColin Finck         ProcessHeap = RtlGetProcessHeap();
78c2c66affSColin Finck         RtlZeroMemory(DefaultHandleTable,
79c2c66affSColin Finck                       MAX_DEFAULT_HANDLES * sizeof(HANDLE));
80c2c66affSColin Finck         RtlInitializeCriticalSection(&HandleTableCS);
81c2c66affSColin Finck 
82c2c66affSColin Finck         DllInitialized = TRUE;
83c2c66affSColin Finck     }
84c2c66affSColin Finck 
85c2c66affSColin Finck     return TRUE;
86c2c66affSColin Finck }
87c2c66affSColin Finck 
88c2c66affSColin Finck 
89c2c66affSColin Finck /************************************************************************
90c2c66affSColin Finck  *  RegInit
91c2c66affSColin Finck  */
92c2c66affSColin Finck BOOL
93c2c66affSColin Finck RegCleanup(VOID)
94c2c66affSColin Finck {
95c2c66affSColin Finck     TRACE("RegCleanup()\n");
96c2c66affSColin Finck 
97c2c66affSColin Finck     CloseDefaultKeys();
98c2c66affSColin Finck     RtlDeleteCriticalSection(&HandleTableCS);
99c2c66affSColin Finck 
100c2c66affSColin Finck     return TRUE;
101c2c66affSColin Finck }
102c2c66affSColin Finck 
103c2c66affSColin Finck 
104c2c66affSColin Finck static NTSTATUS
105c2c66affSColin Finck OpenPredefinedKey(IN ULONG Index,
106c2c66affSColin Finck                   OUT HANDLE Handle)
107c2c66affSColin Finck {
108c2c66affSColin Finck     NTSTATUS Status;
109c2c66affSColin Finck 
110c2c66affSColin Finck     switch (Index)
111c2c66affSColin Finck     {
112c2c66affSColin Finck         case 0: /* HKEY_CLASSES_ROOT */
113c2c66affSColin Finck             Status = OpenClassesRootKey (Handle);
114c2c66affSColin Finck             break;
115c2c66affSColin Finck 
116c2c66affSColin Finck         case 1: /* HKEY_CURRENT_USER */
117c2c66affSColin Finck             Status = RtlOpenCurrentUser (MAXIMUM_ALLOWED,
118c2c66affSColin Finck                                          Handle);
119c2c66affSColin Finck             break;
120c2c66affSColin Finck 
121c2c66affSColin Finck         case 2: /* HKEY_LOCAL_MACHINE */
122c2c66affSColin Finck             Status = OpenLocalMachineKey (Handle);
123c2c66affSColin Finck             break;
124c2c66affSColin Finck 
125c2c66affSColin Finck         case 3: /* HKEY_USERS */
126c2c66affSColin Finck             Status = OpenUsersKey (Handle);
127c2c66affSColin Finck             break;
128c2c66affSColin Finck #if 0
129c2c66affSColin Finck         case 4: /* HKEY_PERFORMANCE_DATA */
130c2c66affSColin Finck             Status = OpenPerformanceDataKey (Handle);
131c2c66affSColin Finck             break;
132c2c66affSColin Finck #endif
133c2c66affSColin Finck 
134c2c66affSColin Finck         case 5: /* HKEY_CURRENT_CONFIG */
135c2c66affSColin Finck             Status = OpenCurrentConfigKey (Handle);
136c2c66affSColin Finck             break;
137c2c66affSColin Finck 
138c2c66affSColin Finck         case 6: /* HKEY_DYN_DATA */
139c2c66affSColin Finck             Status = STATUS_NOT_IMPLEMENTED;
140c2c66affSColin Finck             break;
141c2c66affSColin Finck 
142c2c66affSColin Finck         default:
143c2c66affSColin Finck             WARN("MapDefaultHandle() no handle creator\n");
144c2c66affSColin Finck             Status = STATUS_INVALID_PARAMETER;
145c2c66affSColin Finck             break;
146c2c66affSColin Finck     }
147c2c66affSColin Finck 
148c2c66affSColin Finck     return Status;
149c2c66affSColin Finck }
150c2c66affSColin Finck 
151c2c66affSColin Finck 
152c2c66affSColin Finck static NTSTATUS
153c2c66affSColin Finck MapDefaultKey(OUT PHANDLE RealKey,
154c2c66affSColin Finck               IN HKEY Key)
155c2c66affSColin Finck {
156c2c66affSColin Finck     PHANDLE Handle;
157c2c66affSColin Finck     ULONG Index;
158c2c66affSColin Finck     BOOLEAN DoOpen, DefDisabled;
159c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
160c2c66affSColin Finck 
161c2c66affSColin Finck     TRACE("MapDefaultKey (Key %x)\n", Key);
162c2c66affSColin Finck 
163c2c66affSColin Finck     if (!IsPredefKey(Key))
164c2c66affSColin Finck     {
165c2c66affSColin Finck         *RealKey = (HANDLE)((ULONG_PTR)Key & ~0x1);
166c2c66affSColin Finck         return STATUS_SUCCESS;
167c2c66affSColin Finck     }
168c2c66affSColin Finck 
169c2c66affSColin Finck     /* Handle special cases here */
170c2c66affSColin Finck     Index = GetPredefKeyIndex(Key);
171c2c66affSColin Finck     if (Index >= MAX_DEFAULT_HANDLES)
172c2c66affSColin Finck     {
173c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
174c2c66affSColin Finck     }
175c2c66affSColin Finck     RegInitialize(); /* HACK until delay-loading is implemented */
176c2c66affSColin Finck     RtlEnterCriticalSection (&HandleTableCS);
177c2c66affSColin Finck 
178c2c66affSColin Finck     if (Key == HKEY_CURRENT_USER)
179c2c66affSColin Finck         DefDisabled = DefaultHandleHKUDisabled;
180c2c66affSColin Finck     else
181c2c66affSColin Finck         DefDisabled = DefaultHandlesDisabled;
182c2c66affSColin Finck 
183c2c66affSColin Finck     if (!DefDisabled)
184c2c66affSColin Finck     {
185c2c66affSColin Finck         Handle = &DefaultHandleTable[Index];
186c2c66affSColin Finck         DoOpen = (*Handle == NULL);
187c2c66affSColin Finck     }
188c2c66affSColin Finck     else
189c2c66affSColin Finck     {
190c2c66affSColin Finck         Handle = RealKey;
191c2c66affSColin Finck         DoOpen = TRUE;
192c2c66affSColin Finck     }
193c2c66affSColin Finck 
194c2c66affSColin Finck     if (DoOpen)
195c2c66affSColin Finck     {
196c2c66affSColin Finck         /* create/open the default handle */
197c2c66affSColin Finck         Status = OpenPredefinedKey(Index,
198c2c66affSColin Finck                                    Handle);
199c2c66affSColin Finck     }
200c2c66affSColin Finck 
201c2c66affSColin Finck     if (NT_SUCCESS(Status))
202c2c66affSColin Finck     {
203c2c66affSColin Finck         if (!DefDisabled)
204c2c66affSColin Finck             *RealKey = *Handle;
205c2c66affSColin Finck         else
206c2c66affSColin Finck             *(PULONG_PTR)Handle |= 0x1;
207c2c66affSColin Finck     }
208c2c66affSColin Finck 
209c2c66affSColin Finck     RtlLeaveCriticalSection (&HandleTableCS);
210c2c66affSColin Finck 
211c2c66affSColin Finck     return Status;
212c2c66affSColin Finck }
213c2c66affSColin Finck 
214c2c66affSColin Finck 
215c2c66affSColin Finck static VOID
216c2c66affSColin Finck CloseDefaultKeys(VOID)
217c2c66affSColin Finck {
218c2c66affSColin Finck     ULONG i;
219c2c66affSColin Finck     RegInitialize(); /* HACK until delay-loading is implemented */
220c2c66affSColin Finck     RtlEnterCriticalSection(&HandleTableCS);
221c2c66affSColin Finck 
222c2c66affSColin Finck     for (i = 0; i < MAX_DEFAULT_HANDLES; i++)
223c2c66affSColin Finck     {
224c2c66affSColin Finck         if (DefaultHandleTable[i] != NULL)
225c2c66affSColin Finck         {
226c2c66affSColin Finck             NtClose(DefaultHandleTable[i]);
227c2c66affSColin Finck             DefaultHandleTable[i] = NULL;
228c2c66affSColin Finck         }
229c2c66affSColin Finck     }
230c2c66affSColin Finck 
231c2c66affSColin Finck     RtlLeaveCriticalSection(&HandleTableCS);
232c2c66affSColin Finck }
233c2c66affSColin Finck 
234c2c66affSColin Finck 
235c2c66affSColin Finck static NTSTATUS
236c2c66affSColin Finck OpenClassesRootKey(_Out_ PHANDLE KeyHandle)
237c2c66affSColin Finck {
238c2c66affSColin Finck     OBJECT_ATTRIBUTES Attributes;
239c2c66affSColin Finck     UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\CLASSES");
240c2c66affSColin Finck     NTSTATUS Status;
241c2c66affSColin Finck 
242c2c66affSColin Finck     TRACE("OpenClassesRootKey()\n");
243c2c66affSColin Finck 
244c2c66affSColin Finck     InitializeObjectAttributes(&Attributes,
245c2c66affSColin Finck                                &KeyName,
246c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
247c2c66affSColin Finck                                NULL,
248c2c66affSColin Finck                                NULL);
249c2c66affSColin Finck     Status = NtOpenKey(KeyHandle,
250c2c66affSColin Finck                        MAXIMUM_ALLOWED,
251c2c66affSColin Finck                        &Attributes);
252c2c66affSColin Finck 
253c2c66affSColin Finck     if (!NT_SUCCESS(Status))
254c2c66affSColin Finck         return Status;
255c2c66affSColin Finck 
256c2c66affSColin Finck     /* Mark it as HKCR */
257c2c66affSColin Finck     MakeHKCRKey((HKEY*)KeyHandle);
258c2c66affSColin Finck 
259c2c66affSColin Finck     return Status;
260c2c66affSColin Finck }
261c2c66affSColin Finck 
262c2c66affSColin Finck 
263c2c66affSColin Finck static NTSTATUS
264c2c66affSColin Finck OpenLocalMachineKey(PHANDLE KeyHandle)
265c2c66affSColin Finck {
266c2c66affSColin Finck     OBJECT_ATTRIBUTES Attributes;
267c2c66affSColin Finck     UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine");
268c2c66affSColin Finck     NTSTATUS Status;
269c2c66affSColin Finck 
270c2c66affSColin Finck     TRACE("OpenLocalMachineKey()\n");
271c2c66affSColin Finck 
272c2c66affSColin Finck     InitializeObjectAttributes(&Attributes,
273c2c66affSColin Finck                                &KeyName,
274c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
275c2c66affSColin Finck                                NULL,
276c2c66affSColin Finck                                NULL);
277c2c66affSColin Finck     Status = NtOpenKey(KeyHandle,
278c2c66affSColin Finck                        MAXIMUM_ALLOWED,
279c2c66affSColin Finck                        &Attributes);
280c2c66affSColin Finck 
281c2c66affSColin Finck     TRACE("NtOpenKey(%wZ) => %08x\n", &KeyName, Status);
282c2c66affSColin Finck 
283c2c66affSColin Finck     return Status;
284c2c66affSColin Finck }
285c2c66affSColin Finck 
286c2c66affSColin Finck 
287c2c66affSColin Finck static NTSTATUS
288c2c66affSColin Finck OpenUsersKey(PHANDLE KeyHandle)
289c2c66affSColin Finck {
290c2c66affSColin Finck     OBJECT_ATTRIBUTES Attributes;
291c2c66affSColin Finck     UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\User");
292c2c66affSColin Finck 
293c2c66affSColin Finck     TRACE("OpenUsersKey()\n");
294c2c66affSColin Finck 
295c2c66affSColin Finck     InitializeObjectAttributes(&Attributes,
296c2c66affSColin Finck                                &KeyName,
297c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
298c2c66affSColin Finck                                NULL,
299c2c66affSColin Finck                                NULL);
300c2c66affSColin Finck     return NtOpenKey(KeyHandle,
301c2c66affSColin Finck                      MAXIMUM_ALLOWED,
302c2c66affSColin Finck                      &Attributes);
303c2c66affSColin Finck }
304c2c66affSColin Finck 
305c2c66affSColin Finck 
306c2c66affSColin Finck static NTSTATUS
307c2c66affSColin Finck OpenCurrentConfigKey (PHANDLE KeyHandle)
308c2c66affSColin Finck {
309c2c66affSColin Finck     OBJECT_ATTRIBUTES Attributes;
310c2c66affSColin Finck     UNICODE_STRING KeyName =
311c2c66affSColin Finck         RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
312c2c66affSColin Finck 
313c2c66affSColin Finck     TRACE("OpenCurrentConfigKey()\n");
314c2c66affSColin Finck 
315c2c66affSColin Finck     InitializeObjectAttributes(&Attributes,
316c2c66affSColin Finck                                &KeyName,
317c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
318c2c66affSColin Finck                                NULL,
319c2c66affSColin Finck                                NULL);
320c2c66affSColin Finck     return NtOpenKey(KeyHandle,
321c2c66affSColin Finck                      MAXIMUM_ALLOWED,
322c2c66affSColin Finck                      &Attributes);
323c2c66affSColin Finck }
324c2c66affSColin Finck 
325c2c66affSColin Finck 
326c2c66affSColin Finck /************************************************************************
327c2c66affSColin Finck  *  RegDisablePredefinedCache
328c2c66affSColin Finck  *
329c2c66affSColin Finck  * @implemented
330c2c66affSColin Finck  */
331c2c66affSColin Finck LONG WINAPI
332c2c66affSColin Finck RegDisablePredefinedCache(VOID)
333c2c66affSColin Finck {
334c2c66affSColin Finck     RegInitialize(); /* HACK until delay-loading is implemented */
335c2c66affSColin Finck     RtlEnterCriticalSection(&HandleTableCS);
336c2c66affSColin Finck     DefaultHandleHKUDisabled = TRUE;
337c2c66affSColin Finck     RtlLeaveCriticalSection(&HandleTableCS);
338c2c66affSColin Finck     return ERROR_SUCCESS;
339c2c66affSColin Finck }
340c2c66affSColin Finck 
341c2c66affSColin Finck 
342c2c66affSColin Finck /************************************************************************
343c2c66affSColin Finck  *  RegDisablePredefinedCacheEx
344c2c66affSColin Finck  *
345c2c66affSColin Finck  * @implemented
346c2c66affSColin Finck  */
347c2c66affSColin Finck LONG WINAPI
348c2c66affSColin Finck RegDisablePredefinedCacheEx(VOID)
349c2c66affSColin Finck {
350c2c66affSColin Finck     RegInitialize(); /* HACK until delay-loading is implemented */
351c2c66affSColin Finck     RtlEnterCriticalSection(&HandleTableCS);
352c2c66affSColin Finck     DefaultHandlesDisabled = TRUE;
353c2c66affSColin Finck     DefaultHandleHKUDisabled = TRUE;
354c2c66affSColin Finck     RtlLeaveCriticalSection(&HandleTableCS);
355c2c66affSColin Finck     return ERROR_SUCCESS;
356c2c66affSColin Finck }
357c2c66affSColin Finck 
358c2c66affSColin Finck 
359c2c66affSColin Finck /************************************************************************
360c2c66affSColin Finck  *  RegOverridePredefKey
361c2c66affSColin Finck  *
362c2c66affSColin Finck  * @implemented
363c2c66affSColin Finck  */
364c2c66affSColin Finck LONG WINAPI
365c2c66affSColin Finck RegOverridePredefKey(IN HKEY hKey,
366c2c66affSColin Finck                      IN HKEY hNewHKey  OPTIONAL)
367c2c66affSColin Finck {
368c2c66affSColin Finck     LONG ErrorCode = ERROR_SUCCESS;
369c2c66affSColin Finck 
370c2c66affSColin Finck     if ((hKey == HKEY_CLASSES_ROOT ||
371c2c66affSColin Finck          hKey == HKEY_CURRENT_CONFIG ||
372c2c66affSColin Finck          hKey == HKEY_CURRENT_USER ||
373c2c66affSColin Finck          hKey == HKEY_LOCAL_MACHINE ||
374c2c66affSColin Finck          hKey == HKEY_PERFORMANCE_DATA ||
375c2c66affSColin Finck          hKey == HKEY_USERS) &&
376c2c66affSColin Finck         !IsPredefKey(hNewHKey))
377c2c66affSColin Finck     {
378c2c66affSColin Finck         PHANDLE Handle;
379c2c66affSColin Finck         ULONG Index;
380c2c66affSColin Finck 
381c2c66affSColin Finck         Index = GetPredefKeyIndex(hKey);
382c2c66affSColin Finck         Handle = &DefaultHandleTable[Index];
383c2c66affSColin Finck 
384c2c66affSColin Finck         if (hNewHKey == NULL)
385c2c66affSColin Finck         {
386c2c66affSColin Finck             /* restore the default mapping */
387c2c66affSColin Finck             NTSTATUS Status = OpenPredefinedKey(Index,
388c2c66affSColin Finck                                                 &hNewHKey);
389c2c66affSColin Finck             if (!NT_SUCCESS(Status))
390c2c66affSColin Finck             {
391c2c66affSColin Finck                 return RtlNtStatusToDosError(Status);
392c2c66affSColin Finck             }
393c2c66affSColin Finck 
394c2c66affSColin Finck             ASSERT(hNewHKey != NULL);
395c2c66affSColin Finck         }
396c2c66affSColin Finck         RegInitialize(); /* HACK until delay-loading is implemented */
397c2c66affSColin Finck         RtlEnterCriticalSection(&HandleTableCS);
398c2c66affSColin Finck 
399c2c66affSColin Finck         /* close the currently mapped handle if existing */
400c2c66affSColin Finck         if (*Handle != NULL)
401c2c66affSColin Finck         {
402c2c66affSColin Finck             NtClose(*Handle);
403c2c66affSColin Finck         }
404c2c66affSColin Finck 
405c2c66affSColin Finck         /* update the mapping */
406c2c66affSColin Finck         *Handle = hNewHKey;
407c2c66affSColin Finck 
408c2c66affSColin Finck         RtlLeaveCriticalSection(&HandleTableCS);
409c2c66affSColin Finck     }
410c2c66affSColin Finck     else
411c2c66affSColin Finck         ErrorCode = ERROR_INVALID_HANDLE;
412c2c66affSColin Finck 
413c2c66affSColin Finck     return ErrorCode;
414c2c66affSColin Finck }
415c2c66affSColin Finck 
416c2c66affSColin Finck 
417c2c66affSColin Finck /************************************************************************
418c2c66affSColin Finck  *  RegCloseKey
419c2c66affSColin Finck  *
420c2c66affSColin Finck  * @implemented
421c2c66affSColin Finck  */
422c2c66affSColin Finck LONG WINAPI
423c2c66affSColin Finck RegCloseKey(HKEY hKey)
424c2c66affSColin Finck {
425c2c66affSColin Finck     NTSTATUS Status;
426c2c66affSColin Finck 
427c2c66affSColin Finck     /* don't close null handle or a pseudo handle */
428c2c66affSColin Finck     if (!hKey)
429c2c66affSColin Finck     {
430c2c66affSColin Finck         return ERROR_INVALID_HANDLE;
431c2c66affSColin Finck     }
432c2c66affSColin Finck 
433c2c66affSColin Finck     if (((ULONG_PTR)hKey & 0xF0000000) == 0x80000000)
434c2c66affSColin Finck     {
435c2c66affSColin Finck         return ERROR_SUCCESS;
436c2c66affSColin Finck     }
437c2c66affSColin Finck 
438c2c66affSColin Finck     Status = NtClose(hKey);
439c2c66affSColin Finck     if (!NT_SUCCESS(Status))
440c2c66affSColin Finck     {
441c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
442c2c66affSColin Finck     }
443c2c66affSColin Finck 
444c2c66affSColin Finck   return ERROR_SUCCESS;
445c2c66affSColin Finck }
446c2c66affSColin Finck 
447c2c66affSColin Finck 
448c2c66affSColin Finck static NTSTATUS
449c2c66affSColin Finck RegpCopyTree(IN HKEY hKeySrc,
450c2c66affSColin Finck              IN HKEY hKeyDest)
451c2c66affSColin Finck {
452c2c66affSColin Finck     typedef struct
453c2c66affSColin Finck     {
454c2c66affSColin Finck         LIST_ENTRY ListEntry;
455c2c66affSColin Finck         HANDLE hKeySrc;
456c2c66affSColin Finck         HANDLE hKeyDest;
457c2c66affSColin Finck     } REGP_COPY_KEYS, *PREGP_COPY_KEYS;
458c2c66affSColin Finck 
459c2c66affSColin Finck     LIST_ENTRY copyQueueHead;
460c2c66affSColin Finck     PREGP_COPY_KEYS copyKeys, newCopyKeys;
461c2c66affSColin Finck     union
462c2c66affSColin Finck     {
463c2c66affSColin Finck         KEY_VALUE_FULL_INFORMATION *KeyValue;
464c2c66affSColin Finck         KEY_NODE_INFORMATION *KeyNode;
465c2c66affSColin Finck         PVOID Buffer;
466c2c66affSColin Finck     } Info;
467c2c66affSColin Finck     ULONG Index, BufferSizeRequired, BufferSize = 0x200;
468c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
469c2c66affSColin Finck     NTSTATUS Status2 = STATUS_SUCCESS;
470c2c66affSColin Finck 
471c2c66affSColin Finck     InitializeListHead(&copyQueueHead);
472c2c66affSColin Finck 
473c2c66affSColin Finck     Info.Buffer = RtlAllocateHeap(ProcessHeap,
474c2c66affSColin Finck                                   0,
475c2c66affSColin Finck                                   BufferSize);
476c2c66affSColin Finck     if (Info.Buffer == NULL)
477c2c66affSColin Finck     {
478c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
479c2c66affSColin Finck     }
480c2c66affSColin Finck 
481c2c66affSColin Finck     copyKeys = RtlAllocateHeap(ProcessHeap,
482c2c66affSColin Finck                                0,
483c2c66affSColin Finck                                sizeof(REGP_COPY_KEYS));
484c2c66affSColin Finck     if (copyKeys != NULL)
485c2c66affSColin Finck     {
486c2c66affSColin Finck         copyKeys->hKeySrc = hKeySrc;
487c2c66affSColin Finck         copyKeys->hKeyDest = hKeyDest;
488c2c66affSColin Finck         InsertHeadList(&copyQueueHead,
489c2c66affSColin Finck                        &copyKeys->ListEntry);
490c2c66affSColin Finck 
491c2c66affSColin Finck         /* FIXME - copy security from hKeySrc to hKeyDest or just for the subkeys? */
492c2c66affSColin Finck 
493c2c66affSColin Finck         do
494c2c66affSColin Finck         {
495c2c66affSColin Finck             copyKeys = CONTAINING_RECORD(copyQueueHead.Flink,
496c2c66affSColin Finck                                          REGP_COPY_KEYS,
497c2c66affSColin Finck                                          ListEntry);
498c2c66affSColin Finck 
499c2c66affSColin Finck             /* enumerate all values and copy them */
500c2c66affSColin Finck             Index = 0;
501c2c66affSColin Finck             for (;;)
502c2c66affSColin Finck             {
503c2c66affSColin Finck                 Status2 = NtEnumerateValueKey(copyKeys->hKeySrc,
504c2c66affSColin Finck                                               Index,
505c2c66affSColin Finck                                               KeyValueFullInformation,
506c2c66affSColin Finck                                               Info.KeyValue,
507c2c66affSColin Finck                                               BufferSize,
508c2c66affSColin Finck                                               &BufferSizeRequired);
509c2c66affSColin Finck                 if (NT_SUCCESS(Status2))
510c2c66affSColin Finck                 {
511c2c66affSColin Finck                     UNICODE_STRING ValueName;
512c2c66affSColin Finck                     PVOID Data;
513c2c66affSColin Finck 
514c2c66affSColin Finck                     /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
515c2c66affSColin Finck                     ValueName.Length = Info.KeyValue->NameLength;
516c2c66affSColin Finck                     ValueName.MaximumLength = ValueName.Length;
517c2c66affSColin Finck                     ValueName.Buffer = Info.KeyValue->Name;
518c2c66affSColin Finck 
519c2c66affSColin Finck                     Data = (PVOID)((ULONG_PTR)Info.KeyValue + Info.KeyValue->DataOffset);
520c2c66affSColin Finck 
521c2c66affSColin Finck                     Status2 = NtSetValueKey(copyKeys->hKeyDest,
522c2c66affSColin Finck                                             &ValueName,
523c2c66affSColin Finck                                             Info.KeyValue->TitleIndex,
524c2c66affSColin Finck                                             Info.KeyValue->Type,
525c2c66affSColin Finck                                             Data,
526c2c66affSColin Finck                                             Info.KeyValue->DataLength);
527c2c66affSColin Finck 
528c2c66affSColin Finck                     /* don't break, let's try to copy as many values as possible */
529c2c66affSColin Finck                     if (!NT_SUCCESS(Status2) && NT_SUCCESS(Status))
530c2c66affSColin Finck                     {
531c2c66affSColin Finck                         Status = Status2;
532c2c66affSColin Finck                     }
533c2c66affSColin Finck 
534c2c66affSColin Finck                     Index++;
535c2c66affSColin Finck                 }
536c2c66affSColin Finck                 else if (Status2 == STATUS_BUFFER_OVERFLOW)
537c2c66affSColin Finck                 {
538c2c66affSColin Finck                     PVOID Buffer;
539c2c66affSColin Finck 
540c2c66affSColin Finck                     ASSERT(BufferSize < BufferSizeRequired);
541c2c66affSColin Finck 
542c2c66affSColin Finck                     Buffer = RtlReAllocateHeap(ProcessHeap,
543c2c66affSColin Finck                                                0,
544c2c66affSColin Finck                                                Info.Buffer,
545c2c66affSColin Finck                                                BufferSizeRequired);
546c2c66affSColin Finck                     if (Buffer != NULL)
547c2c66affSColin Finck                     {
548c2c66affSColin Finck                         Info.Buffer = Buffer;
549c2c66affSColin Finck                         /* try again */
550c2c66affSColin Finck                     }
551c2c66affSColin Finck                     else
552c2c66affSColin Finck                     {
553c2c66affSColin Finck                         /* don't break, let's try to copy as many values as possible */
554c2c66affSColin Finck                         Status2 = STATUS_INSUFFICIENT_RESOURCES;
555c2c66affSColin Finck                         Index++;
556c2c66affSColin Finck 
557c2c66affSColin Finck                         if (NT_SUCCESS(Status))
558c2c66affSColin Finck                         {
559c2c66affSColin Finck                             Status = Status2;
560c2c66affSColin Finck                         }
561c2c66affSColin Finck                     }
562c2c66affSColin Finck                 }
563c2c66affSColin Finck                 else
564c2c66affSColin Finck                 {
565c2c66affSColin Finck                     /* break to avoid an infinite loop in case of denied access or
566c2c66affSColin Finck                        other errors! */
567c2c66affSColin Finck                     if (Status2 != STATUS_NO_MORE_ENTRIES && NT_SUCCESS(Status))
568c2c66affSColin Finck                     {
569c2c66affSColin Finck                         Status = Status2;
570c2c66affSColin Finck                     }
571c2c66affSColin Finck 
572c2c66affSColin Finck                     break;
573c2c66affSColin Finck                 }
574c2c66affSColin Finck             }
575c2c66affSColin Finck 
576c2c66affSColin Finck             /* enumerate all subkeys and open and enqueue them */
577c2c66affSColin Finck             Index = 0;
578c2c66affSColin Finck             for (;;)
579c2c66affSColin Finck             {
580c2c66affSColin Finck                 Status2 = NtEnumerateKey(copyKeys->hKeySrc,
581c2c66affSColin Finck                                          Index,
582c2c66affSColin Finck                                          KeyNodeInformation,
583c2c66affSColin Finck                                          Info.KeyNode,
584c2c66affSColin Finck                                          BufferSize,
585c2c66affSColin Finck                                          &BufferSizeRequired);
586c2c66affSColin Finck                 if (NT_SUCCESS(Status2))
587c2c66affSColin Finck                 {
588c2c66affSColin Finck                     HANDLE KeyHandle, NewKeyHandle;
589c2c66affSColin Finck                     OBJECT_ATTRIBUTES ObjectAttributes;
590c2c66affSColin Finck                     UNICODE_STRING SubKeyName, ClassName;
591c2c66affSColin Finck 
592c2c66affSColin Finck                     /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
593c2c66affSColin Finck                     SubKeyName.Length = Info.KeyNode->NameLength;
594c2c66affSColin Finck                     SubKeyName.MaximumLength = SubKeyName.Length;
595c2c66affSColin Finck                     SubKeyName.Buffer = Info.KeyNode->Name;
596c2c66affSColin Finck                     ClassName.Length = Info.KeyNode->ClassLength;
597c2c66affSColin Finck                     ClassName.MaximumLength = ClassName.Length;
598c2c66affSColin Finck                     ClassName.Buffer = (PWSTR)((ULONG_PTR)Info.KeyNode + Info.KeyNode->ClassOffset);
599c2c66affSColin Finck 
600c2c66affSColin Finck                     /* open the subkey with sufficient rights */
601c2c66affSColin Finck 
602c2c66affSColin Finck                     InitializeObjectAttributes(&ObjectAttributes,
603c2c66affSColin Finck                                                &SubKeyName,
604c2c66affSColin Finck                                                OBJ_CASE_INSENSITIVE,
605c2c66affSColin Finck                                                copyKeys->hKeySrc,
606c2c66affSColin Finck                                                NULL);
607c2c66affSColin Finck 
608c2c66affSColin Finck                     Status2 = NtOpenKey(&KeyHandle,
609c2c66affSColin Finck                                         KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
610c2c66affSColin Finck                                         &ObjectAttributes);
611c2c66affSColin Finck                     if (NT_SUCCESS(Status2))
612c2c66affSColin Finck                     {
613c2c66affSColin Finck                         /* FIXME - attempt to query the security information */
614c2c66affSColin Finck 
615c2c66affSColin Finck                         InitializeObjectAttributes(&ObjectAttributes,
616c2c66affSColin Finck                                                &SubKeyName,
617c2c66affSColin Finck                                                OBJ_CASE_INSENSITIVE,
618c2c66affSColin Finck                                                copyKeys->hKeyDest,
619c2c66affSColin Finck                                                NULL);
620c2c66affSColin Finck 
621c2c66affSColin Finck                         Status2 = NtCreateKey(&NewKeyHandle,
622c2c66affSColin Finck                                               KEY_ALL_ACCESS,
623c2c66affSColin Finck                                               &ObjectAttributes,
624c2c66affSColin Finck                                               Info.KeyNode->TitleIndex,
625c2c66affSColin Finck                                               &ClassName,
626c2c66affSColin Finck                                               0,
627c2c66affSColin Finck                                               NULL);
628c2c66affSColin Finck                         if (NT_SUCCESS(Status2))
629c2c66affSColin Finck                         {
630c2c66affSColin Finck                             newCopyKeys = RtlAllocateHeap(ProcessHeap,
631c2c66affSColin Finck                                                           0,
632c2c66affSColin Finck                                                           sizeof(REGP_COPY_KEYS));
633c2c66affSColin Finck                             if (newCopyKeys != NULL)
634c2c66affSColin Finck                             {
635c2c66affSColin Finck                                 /* save the handles and enqueue the subkey */
636c2c66affSColin Finck                                 newCopyKeys->hKeySrc = KeyHandle;
637c2c66affSColin Finck                                 newCopyKeys->hKeyDest = NewKeyHandle;
638c2c66affSColin Finck                                 InsertTailList(&copyQueueHead,
639c2c66affSColin Finck                                                &newCopyKeys->ListEntry);
640c2c66affSColin Finck                             }
641c2c66affSColin Finck                             else
642c2c66affSColin Finck                             {
643c2c66affSColin Finck                                 NtClose(KeyHandle);
644c2c66affSColin Finck                                 NtClose(NewKeyHandle);
645c2c66affSColin Finck 
646c2c66affSColin Finck                                 Status2 = STATUS_INSUFFICIENT_RESOURCES;
647c2c66affSColin Finck                             }
648c2c66affSColin Finck                         }
649c2c66affSColin Finck                         else
650c2c66affSColin Finck                         {
651c2c66affSColin Finck                             NtClose(KeyHandle);
652c2c66affSColin Finck                         }
653c2c66affSColin Finck                     }
654c2c66affSColin Finck 
655c2c66affSColin Finck                     if (!NT_SUCCESS(Status2) && NT_SUCCESS(Status))
656c2c66affSColin Finck                     {
657c2c66affSColin Finck                         Status = Status2;
658c2c66affSColin Finck                     }
659c2c66affSColin Finck 
660c2c66affSColin Finck                     Index++;
661c2c66affSColin Finck                 }
662c2c66affSColin Finck                 else if (Status2 == STATUS_BUFFER_OVERFLOW)
663c2c66affSColin Finck                 {
664c2c66affSColin Finck                     PVOID Buffer;
665c2c66affSColin Finck 
666c2c66affSColin Finck                     ASSERT(BufferSize < BufferSizeRequired);
667c2c66affSColin Finck 
668c2c66affSColin Finck                     Buffer = RtlReAllocateHeap(ProcessHeap,
669c2c66affSColin Finck                                                0,
670c2c66affSColin Finck                                                Info.Buffer,
671c2c66affSColin Finck                                                BufferSizeRequired);
672c2c66affSColin Finck                     if (Buffer != NULL)
673c2c66affSColin Finck                     {
674c2c66affSColin Finck                         Info.Buffer = Buffer;
675c2c66affSColin Finck                         /* try again */
676c2c66affSColin Finck                     }
677c2c66affSColin Finck                     else
678c2c66affSColin Finck                     {
679c2c66affSColin Finck                         /* don't break, let's try to copy as many keys as possible */
680c2c66affSColin Finck                         Status2 = STATUS_INSUFFICIENT_RESOURCES;
681c2c66affSColin Finck                         Index++;
682c2c66affSColin Finck 
683c2c66affSColin Finck                         if (NT_SUCCESS(Status))
684c2c66affSColin Finck                         {
685c2c66affSColin Finck                             Status = Status2;
686c2c66affSColin Finck                         }
687c2c66affSColin Finck                     }
688c2c66affSColin Finck                 }
689c2c66affSColin Finck                 else
690c2c66affSColin Finck                 {
691c2c66affSColin Finck                     /* break to avoid an infinite loop in case of denied access or
692c2c66affSColin Finck                        other errors! */
693c2c66affSColin Finck                     if (Status2 != STATUS_NO_MORE_ENTRIES && NT_SUCCESS(Status))
694c2c66affSColin Finck                     {
695c2c66affSColin Finck                         Status = Status2;
696c2c66affSColin Finck                     }
697c2c66affSColin Finck 
698c2c66affSColin Finck                     break;
699c2c66affSColin Finck                 }
700c2c66affSColin Finck             }
701c2c66affSColin Finck 
702c2c66affSColin Finck             /* close the handles and remove the entry from the list */
703c2c66affSColin Finck             if (copyKeys->hKeySrc != hKeySrc)
704c2c66affSColin Finck             {
705c2c66affSColin Finck                 NtClose(copyKeys->hKeySrc);
706c2c66affSColin Finck             }
707c2c66affSColin Finck             if (copyKeys->hKeyDest != hKeyDest)
708c2c66affSColin Finck             {
709c2c66affSColin Finck                 NtClose(copyKeys->hKeyDest);
710c2c66affSColin Finck             }
711c2c66affSColin Finck 
712c2c66affSColin Finck             RemoveEntryList(&copyKeys->ListEntry);
713c2c66affSColin Finck 
714c2c66affSColin Finck             RtlFreeHeap(ProcessHeap,
715c2c66affSColin Finck                         0,
716c2c66affSColin Finck                         copyKeys);
717c2c66affSColin Finck         } while (!IsListEmpty(&copyQueueHead));
718c2c66affSColin Finck     }
719c2c66affSColin Finck     else
720c2c66affSColin Finck         Status = STATUS_INSUFFICIENT_RESOURCES;
721c2c66affSColin Finck 
722c2c66affSColin Finck     RtlFreeHeap(ProcessHeap,
723c2c66affSColin Finck                 0,
724c2c66affSColin Finck                 Info.Buffer);
725c2c66affSColin Finck 
726c2c66affSColin Finck     return Status;
727c2c66affSColin Finck }
728c2c66affSColin Finck 
729c2c66affSColin Finck 
730c2c66affSColin Finck /************************************************************************
731c2c66affSColin Finck  *  RegCopyTreeW
732c2c66affSColin Finck  *
733c2c66affSColin Finck  * @implemented
734c2c66affSColin Finck  */
735c2c66affSColin Finck LONG WINAPI
736c2c66affSColin Finck RegCopyTreeW(IN HKEY hKeySrc,
737c2c66affSColin Finck              IN LPCWSTR lpSubKey  OPTIONAL,
738c2c66affSColin Finck              IN HKEY hKeyDest)
739c2c66affSColin Finck {
740c2c66affSColin Finck     HANDLE DestKeyHandle, KeyHandle, CurKey, SubKeyHandle = NULL;
741c2c66affSColin Finck     NTSTATUS Status;
742c2c66affSColin Finck 
743c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
744c2c66affSColin Finck                            hKeySrc);
745c2c66affSColin Finck     if (!NT_SUCCESS(Status))
746c2c66affSColin Finck     {
747c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
748c2c66affSColin Finck     }
749c2c66affSColin Finck 
750c2c66affSColin Finck     Status = MapDefaultKey(&DestKeyHandle,
751c2c66affSColin Finck                            hKeyDest);
752c2c66affSColin Finck     if (!NT_SUCCESS(Status))
753c2c66affSColin Finck     {
754c2c66affSColin Finck         goto Cleanup2;
755c2c66affSColin Finck     }
756c2c66affSColin Finck 
757c2c66affSColin Finck     if (lpSubKey != NULL)
758c2c66affSColin Finck     {
759c2c66affSColin Finck         OBJECT_ATTRIBUTES ObjectAttributes;
760c2c66affSColin Finck         UNICODE_STRING SubKeyName;
761c2c66affSColin Finck 
76246259092SSerge Gautherie         RtlInitUnicodeString(&SubKeyName, lpSubKey);
763c2c66affSColin Finck 
764c2c66affSColin Finck         InitializeObjectAttributes(&ObjectAttributes,
765c2c66affSColin Finck                                    &SubKeyName,
766c2c66affSColin Finck                                    OBJ_CASE_INSENSITIVE,
767c2c66affSColin Finck                                    KeyHandle,
768c2c66affSColin Finck                                    NULL);
769c2c66affSColin Finck 
770c2c66affSColin Finck         Status = NtOpenKey(&SubKeyHandle,
771c2c66affSColin Finck                            KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
772c2c66affSColin Finck                            &ObjectAttributes);
773c2c66affSColin Finck         if (!NT_SUCCESS(Status))
774c2c66affSColin Finck         {
775c2c66affSColin Finck             goto Cleanup;
776c2c66affSColin Finck         }
777c2c66affSColin Finck 
778c2c66affSColin Finck         CurKey = SubKeyHandle;
779c2c66affSColin Finck     }
780c2c66affSColin Finck     else
781c2c66affSColin Finck         CurKey = KeyHandle;
782c2c66affSColin Finck 
783c2c66affSColin Finck     Status = RegpCopyTree(CurKey,
784c2c66affSColin Finck                           hKeyDest);
785c2c66affSColin Finck 
786c2c66affSColin Finck     if (SubKeyHandle != NULL)
787c2c66affSColin Finck     {
788c2c66affSColin Finck         NtClose(SubKeyHandle);
789c2c66affSColin Finck     }
790c2c66affSColin Finck 
791c2c66affSColin Finck Cleanup:
792c2c66affSColin Finck     ClosePredefKey(DestKeyHandle);
793c2c66affSColin Finck Cleanup2:
794c2c66affSColin Finck     ClosePredefKey(KeyHandle);
795c2c66affSColin Finck 
796c2c66affSColin Finck     if (!NT_SUCCESS(Status))
797c2c66affSColin Finck     {
798c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
799c2c66affSColin Finck     }
800c2c66affSColin Finck 
801c2c66affSColin Finck     return ERROR_SUCCESS;
802c2c66affSColin Finck }
803c2c66affSColin Finck 
804c2c66affSColin Finck 
805c2c66affSColin Finck /************************************************************************
806c2c66affSColin Finck  *  RegCopyTreeA
807c2c66affSColin Finck  *
808c2c66affSColin Finck  * @implemented
809c2c66affSColin Finck  */
810c2c66affSColin Finck LONG WINAPI
811c2c66affSColin Finck RegCopyTreeA(IN HKEY hKeySrc,
812c2c66affSColin Finck              IN LPCSTR lpSubKey  OPTIONAL,
813c2c66affSColin Finck              IN HKEY hKeyDest)
814c2c66affSColin Finck {
815c2c66affSColin Finck     UNICODE_STRING SubKeyName = { 0, 0, NULL };
816c2c66affSColin Finck     LONG Ret;
817c2c66affSColin Finck 
818c2c66affSColin Finck     if (lpSubKey != NULL &&
81946259092SSerge Gautherie         !RtlCreateUnicodeStringFromAsciiz(&SubKeyName, lpSubKey))
820c2c66affSColin Finck     {
821c2c66affSColin Finck         return ERROR_NOT_ENOUGH_MEMORY;
822c2c66affSColin Finck     }
823c2c66affSColin Finck 
824c2c66affSColin Finck     Ret = RegCopyTreeW(hKeySrc,
825c2c66affSColin Finck                        SubKeyName.Buffer,
826c2c66affSColin Finck                        hKeyDest);
827c2c66affSColin Finck 
828c2c66affSColin Finck     RtlFreeUnicodeString(&SubKeyName);
829c2c66affSColin Finck 
830c2c66affSColin Finck     return Ret;
831c2c66affSColin Finck }
832c2c66affSColin Finck 
833c2c66affSColin Finck 
834c2c66affSColin Finck /************************************************************************
835c2c66affSColin Finck  *  RegConnectRegistryA
836c2c66affSColin Finck  *
837c2c66affSColin Finck  * @implemented
838c2c66affSColin Finck  */
839c2c66affSColin Finck LONG WINAPI
840c2c66affSColin Finck RegConnectRegistryA(IN LPCSTR lpMachineName,
841c2c66affSColin Finck                     IN HKEY hKey,
842c2c66affSColin Finck                     OUT PHKEY phkResult)
843c2c66affSColin Finck {
844c2c66affSColin Finck     UNICODE_STRING MachineName = { 0, 0, NULL };
845c2c66affSColin Finck     LONG Ret;
846c2c66affSColin Finck 
847c2c66affSColin Finck     if (lpMachineName != NULL &&
84846259092SSerge Gautherie         !RtlCreateUnicodeStringFromAsciiz(&MachineName, lpMachineName))
849c2c66affSColin Finck     {
850c2c66affSColin Finck         return ERROR_NOT_ENOUGH_MEMORY;
851c2c66affSColin Finck     }
852c2c66affSColin Finck 
853c2c66affSColin Finck     Ret = RegConnectRegistryW(MachineName.Buffer,
854c2c66affSColin Finck                               hKey,
855c2c66affSColin Finck                               phkResult);
856c2c66affSColin Finck 
857c2c66affSColin Finck     RtlFreeUnicodeString(&MachineName);
858c2c66affSColin Finck 
859c2c66affSColin Finck     return Ret;
860c2c66affSColin Finck }
861c2c66affSColin Finck 
862c2c66affSColin Finck 
863c2c66affSColin Finck /************************************************************************
864c2c66affSColin Finck  *  RegConnectRegistryW
865c2c66affSColin Finck  *
866c2c66affSColin Finck  * @unimplemented
867c2c66affSColin Finck  */
868c2c66affSColin Finck LONG WINAPI
869c2c66affSColin Finck RegConnectRegistryW(LPCWSTR lpMachineName,
870c2c66affSColin Finck                     HKEY hKey,
871c2c66affSColin Finck                     PHKEY phkResult)
872c2c66affSColin Finck {
873c2c66affSColin Finck     LONG ret;
874c2c66affSColin Finck 
875c2c66affSColin Finck     TRACE("(%s,%p,%p): stub\n",debugstr_w(lpMachineName),hKey,phkResult);
876c2c66affSColin Finck 
877c2c66affSColin Finck     if (!lpMachineName || !*lpMachineName)
878c2c66affSColin Finck     {
879c2c66affSColin Finck         /* Use the local machine name */
880c2c66affSColin Finck         ret = RegOpenKeyW( hKey, NULL, phkResult );
881c2c66affSColin Finck     }
882c2c66affSColin Finck     else
883c2c66affSColin Finck     {
884c2c66affSColin Finck         WCHAR compName[MAX_COMPUTERNAME_LENGTH + 1];
885c2c66affSColin Finck         DWORD len = sizeof(compName) / sizeof(WCHAR);
886c2c66affSColin Finck 
887c2c66affSColin Finck         /* MSDN says lpMachineName must start with \\ : not so */
888c2c66affSColin Finck         if( lpMachineName[0] == '\\' &&  lpMachineName[1] == '\\')
889c2c66affSColin Finck             lpMachineName += 2;
890c2c66affSColin Finck 
891c2c66affSColin Finck         if (GetComputerNameW(compName, &len))
892c2c66affSColin Finck         {
893c2c66affSColin Finck             if (!_wcsicmp(lpMachineName, compName))
894c2c66affSColin Finck                 ret = RegOpenKeyW(hKey, NULL, phkResult);
895c2c66affSColin Finck             else
896c2c66affSColin Finck             {
897c2c66affSColin Finck                 FIXME("Connect to %s is not supported.\n",debugstr_w(lpMachineName));
898c2c66affSColin Finck                 ret = ERROR_BAD_NETPATH;
899c2c66affSColin Finck             }
900c2c66affSColin Finck         }
901c2c66affSColin Finck         else
902c2c66affSColin Finck             ret = GetLastError();
903c2c66affSColin Finck     }
904c2c66affSColin Finck 
905c2c66affSColin Finck     return ret;
906c2c66affSColin Finck }
907c2c66affSColin Finck 
908c2c66affSColin Finck 
909c2c66affSColin Finck /************************************************************************
910c2c66affSColin Finck  *  CreateNestedKey
911c2c66affSColin Finck  *
912c2c66affSColin Finck  *  Create key and all necessary intermediate keys
913c2c66affSColin Finck  */
914c2c66affSColin Finck static NTSTATUS
915c2c66affSColin Finck CreateNestedKey(PHKEY KeyHandle,
916c2c66affSColin Finck                 POBJECT_ATTRIBUTES ObjectAttributes,
917c2c66affSColin Finck                 PUNICODE_STRING ClassString,
918c2c66affSColin Finck                 DWORD dwOptions,
919c2c66affSColin Finck                 REGSAM samDesired,
920c2c66affSColin Finck                 DWORD *lpdwDisposition)
921c2c66affSColin Finck {
922c2c66affSColin Finck     OBJECT_ATTRIBUTES LocalObjectAttributes;
923c2c66affSColin Finck     UNICODE_STRING LocalKeyName;
924c2c66affSColin Finck     ULONG Disposition;
925c2c66affSColin Finck     NTSTATUS Status;
926c2c66affSColin Finck     ULONG FullNameLength;
927c2c66affSColin Finck     ULONG Length;
928c2c66affSColin Finck     PWCHAR Ptr;
929c2c66affSColin Finck     HANDLE LocalKeyHandle;
930c2c66affSColin Finck 
931c2c66affSColin Finck     Status = NtCreateKey((PHANDLE) KeyHandle,
932c2c66affSColin Finck                          samDesired,
933c2c66affSColin Finck                          ObjectAttributes,
934c2c66affSColin Finck                          0,
935c2c66affSColin Finck                          ClassString,
936c2c66affSColin Finck                          dwOptions,
937c2c66affSColin Finck                          (PULONG)lpdwDisposition);
938c2c66affSColin Finck     TRACE("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes->ObjectName, Status);
939c2c66affSColin Finck     if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
940c2c66affSColin Finck         return Status;
941c2c66affSColin Finck 
942c2c66affSColin Finck     /* Copy object attributes */
943c2c66affSColin Finck     RtlCopyMemory(&LocalObjectAttributes,
944c2c66affSColin Finck                   ObjectAttributes,
945c2c66affSColin Finck                   sizeof(OBJECT_ATTRIBUTES));
946c2c66affSColin Finck     RtlCreateUnicodeString(&LocalKeyName,
947c2c66affSColin Finck                            ObjectAttributes->ObjectName->Buffer);
948c2c66affSColin Finck     LocalObjectAttributes.ObjectName = &LocalKeyName;
949c2c66affSColin Finck     FullNameLength = LocalKeyName.Length / sizeof(WCHAR);
950c2c66affSColin Finck 
951c2c66affSColin Finck     LocalKeyHandle = NULL;
952c2c66affSColin Finck 
953c2c66affSColin Finck     /* Remove the last part of the key name and try to create the key again. */
954c2c66affSColin Finck     while (Status == STATUS_OBJECT_NAME_NOT_FOUND)
955c2c66affSColin Finck     {
956c2c66affSColin Finck         Ptr = wcsrchr(LocalKeyName.Buffer, '\\');
957c2c66affSColin Finck         if (Ptr == NULL || Ptr == LocalKeyName.Buffer)
958c2c66affSColin Finck         {
959c2c66affSColin Finck             Status = STATUS_UNSUCCESSFUL;
960c2c66affSColin Finck             break;
961c2c66affSColin Finck         }
962c2c66affSColin Finck 
963c2c66affSColin Finck         *Ptr = (WCHAR)0;
9645d8e8348STimo Kreuzer         LocalKeyName.Length = (USHORT)wcslen(LocalKeyName.Buffer) * sizeof(WCHAR);
965c2c66affSColin Finck 
966c2c66affSColin Finck         Status = NtCreateKey(&LocalKeyHandle,
967c2c66affSColin Finck                              KEY_CREATE_SUB_KEY,
968c2c66affSColin Finck                              &LocalObjectAttributes,
969c2c66affSColin Finck                              0,
970c2c66affSColin Finck                              NULL,
971c2c66affSColin Finck                              0,
972c2c66affSColin Finck                              &Disposition);
973c2c66affSColin Finck         TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
974c2c66affSColin Finck     }
975c2c66affSColin Finck 
976c2c66affSColin Finck     if (!NT_SUCCESS(Status))
977c2c66affSColin Finck     {
978c2c66affSColin Finck         RtlFreeUnicodeString(&LocalKeyName);
979c2c66affSColin Finck         return Status;
980c2c66affSColin Finck     }
981c2c66affSColin Finck 
982c2c66affSColin Finck     /* Add removed parts of the key name and create them too. */
983c2c66affSColin Finck     Length = wcslen(LocalKeyName.Buffer);
984c2c66affSColin Finck     while (TRUE)
985c2c66affSColin Finck     {
986c2c66affSColin Finck         if (LocalKeyHandle)
987c2c66affSColin Finck             NtClose (LocalKeyHandle);
988c2c66affSColin Finck 
989c2c66affSColin Finck         LocalKeyName.Buffer[Length] = L'\\';
990c2c66affSColin Finck         Length = wcslen (LocalKeyName.Buffer);
991c2c66affSColin Finck         LocalKeyName.Length = Length * sizeof(WCHAR);
992c2c66affSColin Finck 
993c2c66affSColin Finck         if (Length == FullNameLength)
994c2c66affSColin Finck         {
995c2c66affSColin Finck             Status = NtCreateKey((PHANDLE) KeyHandle,
996c2c66affSColin Finck                                  samDesired,
997c2c66affSColin Finck                                  ObjectAttributes,
998c2c66affSColin Finck                                  0,
999c2c66affSColin Finck                                  ClassString,
1000c2c66affSColin Finck                                  dwOptions,
1001c2c66affSColin Finck                                  (PULONG)lpdwDisposition);
1002c2c66affSColin Finck             break;
1003c2c66affSColin Finck         }
1004c2c66affSColin Finck 
1005c2c66affSColin Finck         Status = NtCreateKey(&LocalKeyHandle,
1006c2c66affSColin Finck                              KEY_CREATE_SUB_KEY,
1007c2c66affSColin Finck                              &LocalObjectAttributes,
1008c2c66affSColin Finck                              0,
1009c2c66affSColin Finck                              NULL,
1010c2c66affSColin Finck                              0,
1011c2c66affSColin Finck                              &Disposition);
1012c2c66affSColin Finck         TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
1013c2c66affSColin Finck         if (!NT_SUCCESS(Status))
1014c2c66affSColin Finck             break;
1015c2c66affSColin Finck     }
1016c2c66affSColin Finck 
1017c2c66affSColin Finck     RtlFreeUnicodeString(&LocalKeyName);
1018c2c66affSColin Finck 
1019c2c66affSColin Finck     return Status;
1020c2c66affSColin Finck }
1021c2c66affSColin Finck 
1022c2c66affSColin Finck 
1023c2c66affSColin Finck /************************************************************************
1024c2c66affSColin Finck  *  RegCreateKeyExA
1025c2c66affSColin Finck  *
1026c2c66affSColin Finck  * @implemented
1027c2c66affSColin Finck  */
1028c2c66affSColin Finck LONG WINAPI
1029c2c66affSColin Finck RegCreateKeyExA(
1030c2c66affSColin Finck     _In_ HKEY hKey,
1031c2c66affSColin Finck     _In_ LPCSTR lpSubKey,
1032c2c66affSColin Finck     _In_ DWORD Reserved,
1033c2c66affSColin Finck     _In_ LPSTR lpClass,
1034c2c66affSColin Finck     _In_ DWORD dwOptions,
1035c2c66affSColin Finck     _In_ REGSAM samDesired,
1036c2c66affSColin Finck     _In_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1037c2c66affSColin Finck     _Out_ PHKEY phkResult,
1038c2c66affSColin Finck     _Out_ LPDWORD lpdwDisposition)
1039c2c66affSColin Finck {
1040c2c66affSColin Finck     UNICODE_STRING SubKeyString;
1041c2c66affSColin Finck     UNICODE_STRING ClassString;
1042c2c66affSColin Finck     DWORD ErrorCode;
1043c2c66affSColin Finck 
1044c2c66affSColin Finck     RtlInitEmptyUnicodeString(&ClassString, NULL, 0);
1045c2c66affSColin Finck     RtlInitEmptyUnicodeString(&SubKeyString, NULL, 0);
1046c2c66affSColin Finck 
1047c2c66affSColin Finck     if (lpClass)
1048c2c66affSColin Finck     {
1049c2c66affSColin Finck         if (!RtlCreateUnicodeStringFromAsciiz(&ClassString, lpClass))
1050c2c66affSColin Finck         {
1051c2c66affSColin Finck             ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1052c2c66affSColin Finck             goto Exit;
1053c2c66affSColin Finck         }
1054c2c66affSColin Finck     }
1055c2c66affSColin Finck 
1056c2c66affSColin Finck     if (lpSubKey)
1057c2c66affSColin Finck     {
1058c2c66affSColin Finck         if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyString, lpSubKey))
1059c2c66affSColin Finck         {
1060c2c66affSColin Finck             ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1061c2c66affSColin Finck             goto Exit;
1062c2c66affSColin Finck         }
1063c2c66affSColin Finck     }
1064c2c66affSColin Finck 
1065c2c66affSColin Finck     ErrorCode = RegCreateKeyExW(
1066c2c66affSColin Finck         hKey,
1067c2c66affSColin Finck         SubKeyString.Buffer,
1068c2c66affSColin Finck         Reserved,
1069c2c66affSColin Finck         ClassString.Buffer,
1070c2c66affSColin Finck         dwOptions,
1071c2c66affSColin Finck         samDesired,
1072c2c66affSColin Finck         lpSecurityAttributes,
1073c2c66affSColin Finck         phkResult,
1074c2c66affSColin Finck         lpdwDisposition);
1075c2c66affSColin Finck 
1076c2c66affSColin Finck Exit:
1077c2c66affSColin Finck     RtlFreeUnicodeString(&SubKeyString);
1078c2c66affSColin Finck     RtlFreeUnicodeString(&ClassString);
1079c2c66affSColin Finck 
1080c2c66affSColin Finck     return ErrorCode;
1081c2c66affSColin Finck }
1082c2c66affSColin Finck 
1083c2c66affSColin Finck 
1084c2c66affSColin Finck /************************************************************************
1085c2c66affSColin Finck  *  RegCreateKeyExW
1086c2c66affSColin Finck  *
1087c2c66affSColin Finck  * @implemented
1088c2c66affSColin Finck  */
1089c2c66affSColin Finck LONG
1090c2c66affSColin Finck WINAPI
1091c2c66affSColin Finck RegCreateKeyExW(
1092c2c66affSColin Finck     _In_ HKEY hKey,
1093c2c66affSColin Finck     _In_ LPCWSTR lpSubKey,
1094c2c66affSColin Finck     _In_ DWORD Reserved,
1095c2c66affSColin Finck     _In_opt_ LPWSTR lpClass,
1096c2c66affSColin Finck     _In_ DWORD dwOptions,
1097c2c66affSColin Finck     _In_ REGSAM samDesired,
1098c2c66affSColin Finck     _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1099c2c66affSColin Finck     _Out_ PHKEY phkResult,
1100c2c66affSColin Finck     _Out_opt_ LPDWORD lpdwDisposition)
1101c2c66affSColin Finck {
1102c2c66affSColin Finck     UNICODE_STRING SubKeyString;
1103c2c66affSColin Finck     UNICODE_STRING ClassString;
1104c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
1105c2c66affSColin Finck     HANDLE ParentKey;
1106c2c66affSColin Finck     ULONG Attributes = OBJ_CASE_INSENSITIVE;
1107c2c66affSColin Finck     NTSTATUS Status;
1108c2c66affSColin Finck 
1109c2c66affSColin Finck     TRACE("RegCreateKeyExW() called\n");
1110c2c66affSColin Finck 
1111c2c66affSColin Finck     /* get the real parent key */
1112c2c66affSColin Finck     Status = MapDefaultKey(&ParentKey,
1113c2c66affSColin Finck                            hKey);
1114c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1115c2c66affSColin Finck     {
1116c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
1117c2c66affSColin Finck     }
1118c2c66affSColin Finck 
1119c2c66affSColin Finck     TRACE("ParentKey %p\n", ParentKey);
1120c2c66affSColin Finck 
1121c2c66affSColin Finck     if (IsHKCRKey(ParentKey))
1122c2c66affSColin Finck     {
1123c2c66affSColin Finck         LONG ErrorCode = CreateHKCRKey(
1124c2c66affSColin Finck             ParentKey,
1125c2c66affSColin Finck             lpSubKey,
1126c2c66affSColin Finck             Reserved,
1127c2c66affSColin Finck             lpClass,
1128c2c66affSColin Finck             dwOptions,
1129c2c66affSColin Finck             samDesired,
1130c2c66affSColin Finck             lpSecurityAttributes,
1131c2c66affSColin Finck             phkResult,
1132c2c66affSColin Finck             lpdwDisposition);
1133c2c66affSColin Finck         ClosePredefKey(ParentKey);
1134c2c66affSColin Finck         return ErrorCode;
1135c2c66affSColin Finck     }
1136c2c66affSColin Finck 
1137c2c66affSColin Finck     if (dwOptions & REG_OPTION_OPEN_LINK)
1138c2c66affSColin Finck         Attributes |= OBJ_OPENLINK;
1139c2c66affSColin Finck 
1140c2c66affSColin Finck     RtlInitUnicodeString(&ClassString,
1141c2c66affSColin Finck                          lpClass);
1142c2c66affSColin Finck     RtlInitUnicodeString(&SubKeyString,
1143c2c66affSColin Finck                          lpSubKey);
1144c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
1145c2c66affSColin Finck                                &SubKeyString,
1146c2c66affSColin Finck                                Attributes,
1147c2c66affSColin Finck                                (HANDLE)ParentKey,
1148c2c66affSColin Finck                                lpSecurityAttributes ? (PSECURITY_DESCRIPTOR)lpSecurityAttributes->lpSecurityDescriptor : NULL);
1149c2c66affSColin Finck     Status = CreateNestedKey(phkResult,
1150c2c66affSColin Finck                              &ObjectAttributes,
1151c2c66affSColin Finck                              (lpClass == NULL)? NULL : &ClassString,
1152c2c66affSColin Finck                              dwOptions,
1153c2c66affSColin Finck                              samDesired,
1154c2c66affSColin Finck                              lpdwDisposition);
1155c2c66affSColin Finck 
1156c2c66affSColin Finck     ClosePredefKey(ParentKey);
1157c2c66affSColin Finck 
1158c2c66affSColin Finck     TRACE("Status %x\n", Status);
1159c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1160c2c66affSColin Finck     {
1161c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
1162c2c66affSColin Finck     }
1163c2c66affSColin Finck 
1164c2c66affSColin Finck     return ERROR_SUCCESS;
1165c2c66affSColin Finck }
1166c2c66affSColin Finck 
1167c2c66affSColin Finck 
1168c2c66affSColin Finck /************************************************************************
1169c2c66affSColin Finck  *  RegCreateKeyA
1170c2c66affSColin Finck  *
1171c2c66affSColin Finck  * @implemented
1172c2c66affSColin Finck  */
1173c2c66affSColin Finck LONG WINAPI
1174c2c66affSColin Finck RegCreateKeyA(HKEY hKey,
1175c2c66affSColin Finck               LPCSTR lpSubKey,
1176c2c66affSColin Finck               PHKEY phkResult)
1177c2c66affSColin Finck {
1178c2c66affSColin Finck     return RegCreateKeyExA(hKey,
1179c2c66affSColin Finck                            lpSubKey,
1180c2c66affSColin Finck                            0,
1181c2c66affSColin Finck                            NULL,
1182c2c66affSColin Finck                            0,
1183c2c66affSColin Finck                            MAXIMUM_ALLOWED,
1184c2c66affSColin Finck                            NULL,
1185c2c66affSColin Finck                            phkResult,
1186c2c66affSColin Finck                            NULL);
1187c2c66affSColin Finck }
1188c2c66affSColin Finck 
1189c2c66affSColin Finck 
1190c2c66affSColin Finck /************************************************************************
1191c2c66affSColin Finck  *  RegCreateKeyW
1192c2c66affSColin Finck  *
1193c2c66affSColin Finck  * @implemented
1194c2c66affSColin Finck  */
1195c2c66affSColin Finck LONG WINAPI
1196c2c66affSColin Finck RegCreateKeyW(HKEY hKey,
1197c2c66affSColin Finck               LPCWSTR lpSubKey,
1198c2c66affSColin Finck               PHKEY phkResult)
1199c2c66affSColin Finck {
1200c2c66affSColin Finck     return RegCreateKeyExW(hKey,
1201c2c66affSColin Finck                            lpSubKey,
1202c2c66affSColin Finck                            0,
1203c2c66affSColin Finck                            NULL,
1204c2c66affSColin Finck                            0,
1205c2c66affSColin Finck                            MAXIMUM_ALLOWED,
1206c2c66affSColin Finck                            NULL,
1207c2c66affSColin Finck                            phkResult,
1208c2c66affSColin Finck                            NULL);
1209c2c66affSColin Finck }
1210c2c66affSColin Finck 
1211c2c66affSColin Finck 
1212c2c66affSColin Finck /************************************************************************
1213c2c66affSColin Finck  *  RegDeleteKeyA
1214c2c66affSColin Finck  *
1215c2c66affSColin Finck  * @implemented
1216c2c66affSColin Finck  */
1217c2c66affSColin Finck LONG
1218c2c66affSColin Finck WINAPI
1219c2c66affSColin Finck RegDeleteKeyA(
1220c2c66affSColin Finck     _In_ HKEY hKey,
1221c2c66affSColin Finck     _In_ LPCSTR lpSubKey)
1222c2c66affSColin Finck {
1223c2c66affSColin Finck     return RegDeleteKeyExA(hKey, lpSubKey, 0, 0);
1224c2c66affSColin Finck }
1225c2c66affSColin Finck 
1226c2c66affSColin Finck 
1227c2c66affSColin Finck /************************************************************************
1228c2c66affSColin Finck  *  RegDeleteKeyW
1229c2c66affSColin Finck  *
1230c2c66affSColin Finck  * @implemented
1231c2c66affSColin Finck  */
1232c2c66affSColin Finck LONG
1233c2c66affSColin Finck WINAPI
1234c2c66affSColin Finck RegDeleteKeyW(
1235c2c66affSColin Finck     _In_ HKEY hKey,
1236c2c66affSColin Finck     _In_ LPCWSTR lpSubKey)
1237c2c66affSColin Finck {
1238c2c66affSColin Finck     return RegDeleteKeyExW(hKey, lpSubKey, 0, 0);
1239c2c66affSColin Finck }
1240c2c66affSColin Finck 
1241c2c66affSColin Finck 
1242c2c66affSColin Finck /************************************************************************
1243c2c66affSColin Finck  *  RegDeleteKeyExA
1244c2c66affSColin Finck  *
1245c2c66affSColin Finck  * @implemented
1246c2c66affSColin Finck  */
1247c2c66affSColin Finck LONG
1248c2c66affSColin Finck WINAPI
1249c2c66affSColin Finck RegDeleteKeyExA(
1250c2c66affSColin Finck     _In_ HKEY hKey,
1251c2c66affSColin Finck     _In_ LPCSTR lpSubKey,
1252c2c66affSColin Finck     _In_ REGSAM samDesired,
1253c2c66affSColin Finck     _In_ DWORD Reserved)
1254c2c66affSColin Finck {
1255c2c66affSColin Finck     LONG ErrorCode;
1256c2c66affSColin Finck     UNICODE_STRING SubKeyName;
1257c2c66affSColin Finck 
1258c2c66affSColin Finck     if (lpSubKey)
1259c2c66affSColin Finck     {
1260c2c66affSColin Finck         if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName, lpSubKey))
1261c2c66affSColin Finck             return ERROR_NOT_ENOUGH_MEMORY;
1262c2c66affSColin Finck     }
1263c2c66affSColin Finck     else
1264c2c66affSColin Finck         RtlInitEmptyUnicodeString(&SubKeyName, NULL, 0);
1265c2c66affSColin Finck 
1266c2c66affSColin Finck     ErrorCode = RegDeleteKeyExW(hKey, SubKeyName.Buffer, samDesired, Reserved);
1267c2c66affSColin Finck 
1268c2c66affSColin Finck     RtlFreeUnicodeString(&SubKeyName);
1269c2c66affSColin Finck 
1270c2c66affSColin Finck     return ErrorCode;
1271c2c66affSColin Finck }
1272c2c66affSColin Finck 
1273c2c66affSColin Finck 
1274c2c66affSColin Finck /************************************************************************
1275c2c66affSColin Finck  *  RegDeleteKeyExW
1276c2c66affSColin Finck  *
1277c2c66affSColin Finck  * @implemented
1278c2c66affSColin Finck  */
1279c2c66affSColin Finck LONG
1280c2c66affSColin Finck WINAPI
1281c2c66affSColin Finck RegDeleteKeyExW(
1282c2c66affSColin Finck     _In_ HKEY hKey,
1283c2c66affSColin Finck     _In_ LPCWSTR lpSubKey,
1284c2c66affSColin Finck     _In_ REGSAM samDesired,
1285c2c66affSColin Finck     _In_ DWORD Reserved)
1286c2c66affSColin Finck {
1287c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
1288c2c66affSColin Finck     UNICODE_STRING SubKeyName;
1289c2c66affSColin Finck     HANDLE ParentKey;
1290c2c66affSColin Finck     HANDLE TargetKey;
1291c2c66affSColin Finck     NTSTATUS Status;
1292c2c66affSColin Finck 
1293c2c66affSColin Finck     /* Make sure we got a subkey */
1294c2c66affSColin Finck     if (!lpSubKey)
1295c2c66affSColin Finck     {
1296c2c66affSColin Finck         /* Fail */
1297c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
1298c2c66affSColin Finck     }
1299c2c66affSColin Finck 
1300c2c66affSColin Finck     Status = MapDefaultKey(&ParentKey,
1301c2c66affSColin Finck                            hKey);
1302c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1303c2c66affSColin Finck     {
1304c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
1305c2c66affSColin Finck     }
1306c2c66affSColin Finck 
1307c2c66affSColin Finck     if (IsHKCRKey(ParentKey))
1308c2c66affSColin Finck     {
1309c2c66affSColin Finck         LONG ErrorCode = DeleteHKCRKey(ParentKey, lpSubKey, samDesired, Reserved);
1310c2c66affSColin Finck         ClosePredefKey(ParentKey);
1311c2c66affSColin Finck         return ErrorCode;
1312c2c66affSColin Finck     }
1313c2c66affSColin Finck 
1314c2c66affSColin Finck     if (samDesired & KEY_WOW64_32KEY)
1315c2c66affSColin Finck         ERR("Wow64 not yet supported!\n");
1316c2c66affSColin Finck 
1317c2c66affSColin Finck     if (samDesired & KEY_WOW64_64KEY)
1318c2c66affSColin Finck         ERR("Wow64 not yet supported!\n");
1319c2c66affSColin Finck 
1320c2c66affSColin Finck 
132146259092SSerge Gautherie     RtlInitUnicodeString(&SubKeyName, lpSubKey);
1322c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
1323c2c66affSColin Finck                                &SubKeyName,
1324c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
1325c2c66affSColin Finck                                ParentKey,
1326c2c66affSColin Finck                                NULL);
1327c2c66affSColin Finck     Status = NtOpenKey(&TargetKey,
1328c2c66affSColin Finck                        DELETE,
1329c2c66affSColin Finck                        &ObjectAttributes);
1330c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1331c2c66affSColin Finck     {
1332c2c66affSColin Finck         goto Cleanup;
1333c2c66affSColin Finck     }
1334c2c66affSColin Finck 
1335c2c66affSColin Finck     Status = NtDeleteKey(TargetKey);
1336c2c66affSColin Finck     NtClose(TargetKey);
1337c2c66affSColin Finck 
1338c2c66affSColin Finck Cleanup:
1339c2c66affSColin Finck     ClosePredefKey(ParentKey);
1340c2c66affSColin Finck 
1341c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1342c2c66affSColin Finck     {
1343c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
1344c2c66affSColin Finck     }
1345c2c66affSColin Finck 
1346c2c66affSColin Finck     return ERROR_SUCCESS;
1347c2c66affSColin Finck }
1348c2c66affSColin Finck 
1349c2c66affSColin Finck 
1350c2c66affSColin Finck /************************************************************************
1351c2c66affSColin Finck  *  RegDeleteKeyValueW
1352c2c66affSColin Finck  *
1353c2c66affSColin Finck  * @implemented
1354c2c66affSColin Finck  */
1355c2c66affSColin Finck LONG WINAPI
1356c2c66affSColin Finck RegDeleteKeyValueW(IN HKEY hKey,
1357c2c66affSColin Finck                    IN LPCWSTR lpSubKey  OPTIONAL,
1358c2c66affSColin Finck                    IN LPCWSTR lpValueName  OPTIONAL)
1359c2c66affSColin Finck {
1360c2c66affSColin Finck     UNICODE_STRING ValueName;
1361c2c66affSColin Finck     HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
1362c2c66affSColin Finck     NTSTATUS Status;
1363c2c66affSColin Finck 
1364c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
1365c2c66affSColin Finck                            hKey);
1366c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1367c2c66affSColin Finck     {
1368c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
1369c2c66affSColin Finck     }
1370c2c66affSColin Finck 
1371c2c66affSColin Finck     if (lpSubKey != NULL)
1372c2c66affSColin Finck     {
1373c2c66affSColin Finck         OBJECT_ATTRIBUTES ObjectAttributes;
1374c2c66affSColin Finck         UNICODE_STRING SubKeyName;
1375c2c66affSColin Finck 
137646259092SSerge Gautherie         RtlInitUnicodeString(&SubKeyName, lpSubKey);
1377c2c66affSColin Finck 
1378c2c66affSColin Finck         InitializeObjectAttributes(&ObjectAttributes,
1379c2c66affSColin Finck                                    &SubKeyName,
1380c2c66affSColin Finck                                    OBJ_CASE_INSENSITIVE,
1381c2c66affSColin Finck                                    KeyHandle,
1382c2c66affSColin Finck                                    NULL);
1383c2c66affSColin Finck 
1384c2c66affSColin Finck         Status = NtOpenKey(&SubKeyHandle,
1385c2c66affSColin Finck                            KEY_SET_VALUE,
1386c2c66affSColin Finck                            &ObjectAttributes);
1387c2c66affSColin Finck         if (!NT_SUCCESS(Status))
1388c2c66affSColin Finck         {
1389c2c66affSColin Finck             goto Cleanup;
1390c2c66affSColin Finck         }
1391c2c66affSColin Finck 
1392c2c66affSColin Finck         CurKey = SubKeyHandle;
1393c2c66affSColin Finck     }
1394c2c66affSColin Finck     else
1395c2c66affSColin Finck         CurKey = KeyHandle;
1396c2c66affSColin Finck 
139746259092SSerge Gautherie     RtlInitUnicodeString(&ValueName, lpValueName);
1398c2c66affSColin Finck 
1399c2c66affSColin Finck     Status = NtDeleteValueKey(CurKey,
1400c2c66affSColin Finck                               &ValueName);
1401c2c66affSColin Finck 
1402c2c66affSColin Finck     if (SubKeyHandle != NULL)
1403c2c66affSColin Finck     {
1404c2c66affSColin Finck         NtClose(SubKeyHandle);
1405c2c66affSColin Finck     }
1406c2c66affSColin Finck 
1407c2c66affSColin Finck Cleanup:
1408c2c66affSColin Finck     ClosePredefKey(KeyHandle);
1409c2c66affSColin Finck 
1410c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1411c2c66affSColin Finck     {
1412c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
1413c2c66affSColin Finck     }
1414c2c66affSColin Finck 
1415c2c66affSColin Finck     return ERROR_SUCCESS;
1416c2c66affSColin Finck }
1417c2c66affSColin Finck 
1418c2c66affSColin Finck 
1419c2c66affSColin Finck /************************************************************************
1420c2c66affSColin Finck  *  RegDeleteKeyValueA
1421c2c66affSColin Finck  *
1422c2c66affSColin Finck  * @implemented
1423c2c66affSColin Finck  */
1424c2c66affSColin Finck LONG WINAPI
1425c2c66affSColin Finck RegDeleteKeyValueA(IN HKEY hKey,
1426c2c66affSColin Finck                    IN LPCSTR lpSubKey  OPTIONAL,
1427c2c66affSColin Finck                    IN LPCSTR lpValueName  OPTIONAL)
1428c2c66affSColin Finck {
1429c2c66affSColin Finck     UNICODE_STRING SubKey = { 0, 0, NULL }, ValueName = { 0, 0, NULL };
1430c2c66affSColin Finck     LONG Ret;
1431c2c66affSColin Finck 
1432c2c66affSColin Finck     if (lpSubKey != NULL &&
143346259092SSerge Gautherie         !RtlCreateUnicodeStringFromAsciiz(&SubKey, lpSubKey))
1434c2c66affSColin Finck     {
1435c2c66affSColin Finck         return ERROR_NOT_ENOUGH_MEMORY;
1436c2c66affSColin Finck     }
1437c2c66affSColin Finck 
1438c2c66affSColin Finck     if (lpValueName != NULL &&
143946259092SSerge Gautherie         !RtlCreateUnicodeStringFromAsciiz(&ValueName, lpValueName))
1440c2c66affSColin Finck     {
1441c2c66affSColin Finck         RtlFreeUnicodeString(&SubKey);
1442c2c66affSColin Finck         return ERROR_NOT_ENOUGH_MEMORY;
1443c2c66affSColin Finck     }
1444c2c66affSColin Finck 
1445c2c66affSColin Finck     Ret = RegDeleteKeyValueW(hKey,
1446c2c66affSColin Finck                              SubKey.Buffer,
1447c2c66affSColin Finck                              SubKey.Buffer);
1448c2c66affSColin Finck 
1449c2c66affSColin Finck     RtlFreeUnicodeString(&SubKey);
1450c2c66affSColin Finck     RtlFreeUnicodeString(&ValueName);
1451c2c66affSColin Finck 
1452c2c66affSColin Finck     return Ret;
1453c2c66affSColin Finck }
1454c2c66affSColin Finck 
1455c2c66affSColin Finck #if 0
1456c2c66affSColin Finck // Non-recursive RegDeleteTreeW implementation by Thomas, however it needs bugfixing
1457c2c66affSColin Finck static NTSTATUS
1458c2c66affSColin Finck RegpDeleteTree(IN HKEY hKey)
1459c2c66affSColin Finck {
1460c2c66affSColin Finck     typedef struct
1461c2c66affSColin Finck     {
1462c2c66affSColin Finck         LIST_ENTRY ListEntry;
1463c2c66affSColin Finck         HANDLE KeyHandle;
1464c2c66affSColin Finck     } REGP_DEL_KEYS, *PREG_DEL_KEYS;
1465c2c66affSColin Finck 
1466c2c66affSColin Finck     LIST_ENTRY delQueueHead;
1467c2c66affSColin Finck     PREG_DEL_KEYS delKeys, newDelKeys;
1468c2c66affSColin Finck     HANDLE ProcessHeap;
1469c2c66affSColin Finck     ULONG BufferSize;
1470c2c66affSColin Finck     PKEY_BASIC_INFORMATION BasicInfo;
1471c2c66affSColin Finck     PREG_DEL_KEYS KeyDelRoot;
1472c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
1473c2c66affSColin Finck     NTSTATUS Status2 = STATUS_SUCCESS;
1474c2c66affSColin Finck 
1475c2c66affSColin Finck     InitializeListHead(&delQueueHead);
1476c2c66affSColin Finck 
1477c2c66affSColin Finck     ProcessHeap = RtlGetProcessHeap();
1478c2c66affSColin Finck 
1479c2c66affSColin Finck     /* NOTE: no need to allocate enough memory for an additional KEY_BASIC_INFORMATION
1480c2c66affSColin Finck              structure for the root key, we only do that for subkeys as we need to
1481c2c66affSColin Finck              allocate REGP_DEL_KEYS structures anyway! */
1482c2c66affSColin Finck     KeyDelRoot = RtlAllocateHeap(ProcessHeap,
1483c2c66affSColin Finck                                  0,
1484c2c66affSColin Finck                                  sizeof(REGP_DEL_KEYS));
1485c2c66affSColin Finck     if (KeyDelRoot != NULL)
1486c2c66affSColin Finck     {
1487c2c66affSColin Finck         KeyDelRoot->KeyHandle = hKey;
1488c2c66affSColin Finck         InsertTailList(&delQueueHead,
1489c2c66affSColin Finck                        &KeyDelRoot->ListEntry);
1490c2c66affSColin Finck 
1491c2c66affSColin Finck         do
1492c2c66affSColin Finck         {
1493c2c66affSColin Finck             delKeys = CONTAINING_RECORD(delQueueHead.Flink,
1494c2c66affSColin Finck                                         REGP_DEL_KEYS,
1495c2c66affSColin Finck                                         ListEntry);
1496c2c66affSColin Finck 
1497c2c66affSColin Finck             BufferSize = 0;
1498c2c66affSColin Finck             BasicInfo = NULL;
1499c2c66affSColin Finck             newDelKeys = NULL;
1500c2c66affSColin Finck 
1501c2c66affSColin Finck ReadFirstSubKey:
1502c2c66affSColin Finck             /* check if this key contains subkeys and delete them first by queuing
1503c2c66affSColin Finck                them at the head of the list */
1504c2c66affSColin Finck             Status2 = NtEnumerateKey(delKeys->KeyHandle,
1505c2c66affSColin Finck                                      0,
1506c2c66affSColin Finck                                      KeyBasicInformation,
1507c2c66affSColin Finck                                      BasicInfo,
1508c2c66affSColin Finck                                      BufferSize,
1509c2c66affSColin Finck                                      &BufferSize);
1510c2c66affSColin Finck 
1511c2c66affSColin Finck             if (NT_SUCCESS(Status2))
1512c2c66affSColin Finck             {
1513c2c66affSColin Finck                 OBJECT_ATTRIBUTES ObjectAttributes;
1514c2c66affSColin Finck                 UNICODE_STRING SubKeyName;
1515c2c66affSColin Finck 
1516c2c66affSColin Finck                 ASSERT(newDelKeys != NULL);
1517c2c66affSColin Finck                 ASSERT(BasicInfo != NULL);
1518c2c66affSColin Finck 
1519c2c66affSColin Finck                 /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
1520c2c66affSColin Finck                 SubKeyName.Length = BasicInfo->NameLength;
1521c2c66affSColin Finck                 SubKeyName.MaximumLength = BasicInfo->NameLength;
1522c2c66affSColin Finck                 SubKeyName.Buffer = BasicInfo->Name;
1523c2c66affSColin Finck 
1524c2c66affSColin Finck                 InitializeObjectAttributes(&ObjectAttributes,
1525c2c66affSColin Finck                                            &SubKeyName,
1526c2c66affSColin Finck                                            OBJ_CASE_INSENSITIVE,
1527c2c66affSColin Finck                                            delKeys->KeyHandle,
1528c2c66affSColin Finck                                            NULL);
1529c2c66affSColin Finck 
1530c2c66affSColin Finck                 /* open the subkey */
1531c2c66affSColin Finck                 Status2 = NtOpenKey(&newDelKeys->KeyHandle,
1532c2c66affSColin Finck                                     DELETE | KEY_ENUMERATE_SUB_KEYS,
1533c2c66affSColin Finck                                     &ObjectAttributes);
1534c2c66affSColin Finck                 if (!NT_SUCCESS(Status2))
1535c2c66affSColin Finck                 {
1536c2c66affSColin Finck                     goto SubKeyFailure;
1537c2c66affSColin Finck                 }
1538c2c66affSColin Finck 
1539c2c66affSColin Finck                 /* enqueue this key to the head of the deletion queue */
1540c2c66affSColin Finck                 InsertHeadList(&delQueueHead,
1541c2c66affSColin Finck                                &newDelKeys->ListEntry);
1542c2c66affSColin Finck 
1543c2c66affSColin Finck                 /* try again from the head of the list */
1544c2c66affSColin Finck                 continue;
1545c2c66affSColin Finck             }
1546c2c66affSColin Finck             else
1547c2c66affSColin Finck             {
1548c2c66affSColin Finck                 if (Status2 == STATUS_BUFFER_TOO_SMALL)
1549c2c66affSColin Finck                 {
1550c2c66affSColin Finck                     newDelKeys = RtlAllocateHeap(ProcessHeap,
1551c2c66affSColin Finck                                                  0,
1552c2c66affSColin Finck                                                  BufferSize + sizeof(REGP_DEL_KEYS));
1553c2c66affSColin Finck                     if (newDelKeys != NULL)
1554c2c66affSColin Finck                     {
1555c2c66affSColin Finck                         BasicInfo = (PKEY_BASIC_INFORMATION)(newDelKeys + 1);
1556c2c66affSColin Finck 
1557c2c66affSColin Finck                         /* try again */
1558c2c66affSColin Finck                         goto ReadFirstSubKey;
1559c2c66affSColin Finck                     }
1560c2c66affSColin Finck                     else
1561c2c66affSColin Finck                     {
1562c2c66affSColin Finck                         /* don't break, let's try to delete as many keys as possible */
1563c2c66affSColin Finck                         Status2 = STATUS_INSUFFICIENT_RESOURCES;
1564c2c66affSColin Finck                         goto SubKeyFailureNoFree;
1565c2c66affSColin Finck                     }
1566c2c66affSColin Finck                 }
1567c2c66affSColin Finck                 else if (Status2 == STATUS_BUFFER_OVERFLOW)
1568c2c66affSColin Finck                 {
1569c2c66affSColin Finck                     PREG_DEL_KEYS newDelKeys2;
1570c2c66affSColin Finck 
1571c2c66affSColin Finck                     ASSERT(newDelKeys != NULL);
1572c2c66affSColin Finck 
1573c2c66affSColin Finck                     /* we need more memory to query the key name */
1574c2c66affSColin Finck                     newDelKeys2 = RtlReAllocateHeap(ProcessHeap,
1575c2c66affSColin Finck                                                     0,
1576c2c66affSColin Finck                                                     newDelKeys,
1577c2c66affSColin Finck                                                     BufferSize + sizeof(REGP_DEL_KEYS));
1578c2c66affSColin Finck                     if (newDelKeys2 != NULL)
1579c2c66affSColin Finck                     {
1580c2c66affSColin Finck                         newDelKeys = newDelKeys2;
1581c2c66affSColin Finck                         BasicInfo = (PKEY_BASIC_INFORMATION)(newDelKeys + 1);
1582c2c66affSColin Finck 
1583c2c66affSColin Finck                         /* try again */
1584c2c66affSColin Finck                         goto ReadFirstSubKey;
1585c2c66affSColin Finck                     }
1586c2c66affSColin Finck                     else
1587c2c66affSColin Finck                     {
1588c2c66affSColin Finck                         /* don't break, let's try to delete as many keys as possible */
1589c2c66affSColin Finck                         Status2 = STATUS_INSUFFICIENT_RESOURCES;
1590c2c66affSColin Finck                     }
1591c2c66affSColin Finck                 }
1592c2c66affSColin Finck                 else if (Status2 == STATUS_NO_MORE_ENTRIES)
1593c2c66affSColin Finck                 {
1594c2c66affSColin Finck                     /* in some race conditions where another thread would delete
1595c2c66affSColin Finck                        the same tree at the same time, newDelKeys could actually
1596c2c66affSColin Finck                        be != NULL! */
1597c2c66affSColin Finck                     if (newDelKeys != NULL)
1598c2c66affSColin Finck                     {
1599c2c66affSColin Finck                         RtlFreeHeap(ProcessHeap,
1600c2c66affSColin Finck                                     0,
1601c2c66affSColin Finck                                     newDelKeys);
1602c2c66affSColin Finck                     }
1603c2c66affSColin Finck                     break;
1604c2c66affSColin Finck                 }
1605c2c66affSColin Finck 
1606c2c66affSColin Finck SubKeyFailure:
1607c2c66affSColin Finck                 /* newDelKeys can be NULL here when NtEnumerateKey returned an
1608c2c66affSColin Finck                    error other than STATUS_BUFFER_TOO_SMALL or STATUS_BUFFER_OVERFLOW! */
1609c2c66affSColin Finck                 if (newDelKeys != NULL)
1610c2c66affSColin Finck                 {
1611c2c66affSColin Finck                     RtlFreeHeap(ProcessHeap,
1612c2c66affSColin Finck                                 0,
1613c2c66affSColin Finck                                 newDelKeys);
1614c2c66affSColin Finck                 }
1615c2c66affSColin Finck 
1616c2c66affSColin Finck SubKeyFailureNoFree:
1617c2c66affSColin Finck                 /* don't break, let's try to delete as many keys as possible */
1618c2c66affSColin Finck                 if (NT_SUCCESS(Status))
1619c2c66affSColin Finck                 {
1620c2c66affSColin Finck                     Status = Status2;
1621c2c66affSColin Finck                 }
1622c2c66affSColin Finck             }
1623c2c66affSColin Finck 
1624c2c66affSColin Finck             Status2 = NtDeleteKey(delKeys->KeyHandle);
1625c2c66affSColin Finck 
1626c2c66affSColin Finck             /* NOTE: do NOT close the handle anymore, it's invalid already! */
1627c2c66affSColin Finck 
1628c2c66affSColin Finck             if (!NT_SUCCESS(Status2))
1629c2c66affSColin Finck             {
1630c2c66affSColin Finck                 /* close the key handle so we don't leak handles for keys we were
1631c2c66affSColin Finck                    unable to delete. But only do this for handles not supplied
1632c2c66affSColin Finck                    by the caller! */
1633c2c66affSColin Finck 
1634c2c66affSColin Finck                 if (delKeys->KeyHandle != hKey)
1635c2c66affSColin Finck                 {
1636c2c66affSColin Finck                     NtClose(delKeys->KeyHandle);
1637c2c66affSColin Finck                 }
1638c2c66affSColin Finck 
1639c2c66affSColin Finck                 if (NT_SUCCESS(Status))
1640c2c66affSColin Finck                 {
1641c2c66affSColin Finck                     /* don't break, let's try to delete as many keys as possible */
1642c2c66affSColin Finck                     Status = Status2;
1643c2c66affSColin Finck                 }
1644c2c66affSColin Finck             }
1645c2c66affSColin Finck 
1646c2c66affSColin Finck             /* remove the entry from the list */
1647c2c66affSColin Finck             RemoveEntryList(&delKeys->ListEntry);
1648c2c66affSColin Finck 
1649c2c66affSColin Finck             RtlFreeHeap(ProcessHeap,
1650c2c66affSColin Finck                         0,
1651c2c66affSColin Finck                         delKeys);
1652c2c66affSColin Finck         } while (!IsListEmpty(&delQueueHead));
1653c2c66affSColin Finck     }
1654c2c66affSColin Finck     else
1655c2c66affSColin Finck         Status = STATUS_INSUFFICIENT_RESOURCES;
1656c2c66affSColin Finck 
1657c2c66affSColin Finck     return Status;
1658c2c66affSColin Finck }
1659c2c66affSColin Finck 
1660c2c66affSColin Finck 
1661c2c66affSColin Finck /************************************************************************
1662c2c66affSColin Finck  *  RegDeleteTreeW
1663c2c66affSColin Finck  *
1664c2c66affSColin Finck  * @implemented
1665c2c66affSColin Finck  */
1666c2c66affSColin Finck LONG WINAPI
1667c2c66affSColin Finck RegDeleteTreeW(IN HKEY hKey,
1668c2c66affSColin Finck                IN LPCWSTR lpSubKey  OPTIONAL)
1669c2c66affSColin Finck {
1670c2c66affSColin Finck     HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
1671c2c66affSColin Finck     NTSTATUS Status;
1672c2c66affSColin Finck 
1673c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
1674c2c66affSColin Finck                            hKey);
1675c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1676c2c66affSColin Finck     {
1677c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
1678c2c66affSColin Finck     }
1679c2c66affSColin Finck 
1680c2c66affSColin Finck     if (lpSubKey != NULL)
1681c2c66affSColin Finck     {
1682c2c66affSColin Finck         OBJECT_ATTRIBUTES ObjectAttributes;
1683c2c66affSColin Finck         UNICODE_STRING SubKeyName;
1684c2c66affSColin Finck 
168546259092SSerge Gautherie         RtlInitUnicodeString(&SubKeyName, lpSubKey);
1686c2c66affSColin Finck 
1687c2c66affSColin Finck         InitializeObjectAttributes(&ObjectAttributes,
1688c2c66affSColin Finck                                    &SubKeyName,
1689c2c66affSColin Finck                                    OBJ_CASE_INSENSITIVE,
1690c2c66affSColin Finck                                    KeyHandle,
1691c2c66affSColin Finck                                    NULL);
1692c2c66affSColin Finck 
1693c2c66affSColin Finck         Status = NtOpenKey(&SubKeyHandle,
1694c2c66affSColin Finck                            DELETE | KEY_ENUMERATE_SUB_KEYS,
1695c2c66affSColin Finck                            &ObjectAttributes);
1696c2c66affSColin Finck         if (!NT_SUCCESS(Status))
1697c2c66affSColin Finck         {
1698c2c66affSColin Finck             goto Cleanup;
1699c2c66affSColin Finck         }
1700c2c66affSColin Finck 
1701c2c66affSColin Finck         CurKey = SubKeyHandle;
1702c2c66affSColin Finck     }
1703c2c66affSColin Finck     else
1704c2c66affSColin Finck         CurKey = KeyHandle;
1705c2c66affSColin Finck 
1706c2c66affSColin Finck     Status = RegpDeleteTree(CurKey);
1707c2c66affSColin Finck 
1708c2c66affSColin Finck     if (NT_SUCCESS(Status))
1709c2c66affSColin Finck     {
1710c2c66affSColin Finck         /* make sure we only close hKey (KeyHandle) when the caller specified a
1711c2c66affSColin Finck            subkey, because the handle would be invalid already! */
1712c2c66affSColin Finck         if (CurKey != KeyHandle)
1713c2c66affSColin Finck         {
1714c2c66affSColin Finck             ClosePredefKey(KeyHandle);
1715c2c66affSColin Finck         }
1716c2c66affSColin Finck 
1717c2c66affSColin Finck         return ERROR_SUCCESS;
1718c2c66affSColin Finck     }
1719c2c66affSColin Finck     else
1720c2c66affSColin Finck     {
1721c2c66affSColin Finck         /* make sure we close all handles we created! */
1722c2c66affSColin Finck         if (SubKeyHandle != NULL)
1723c2c66affSColin Finck         {
1724c2c66affSColin Finck             NtClose(SubKeyHandle);
1725c2c66affSColin Finck         }
1726c2c66affSColin Finck 
1727c2c66affSColin Finck Cleanup:
1728c2c66affSColin Finck         ClosePredefKey(KeyHandle);
1729c2c66affSColin Finck 
1730c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
1731c2c66affSColin Finck     }
1732c2c66affSColin Finck }
1733c2c66affSColin Finck #endif
1734c2c66affSColin Finck 
1735c2c66affSColin Finck 
1736c2c66affSColin Finck /************************************************************************
1737c2c66affSColin Finck  *  RegDeleteTreeW
1738c2c66affSColin Finck  *
1739c2c66affSColin Finck  * @implemented
1740c2c66affSColin Finck  */
1741c2c66affSColin Finck LSTATUS
1742c2c66affSColin Finck WINAPI
1743c2c66affSColin Finck RegDeleteTreeW(HKEY hKey,
1744c2c66affSColin Finck                LPCWSTR lpszSubKey)
1745c2c66affSColin Finck {
1746c2c66affSColin Finck     LONG ret;
1747c2c66affSColin Finck     DWORD dwMaxSubkeyLen, dwMaxValueLen;
1748c2c66affSColin Finck     DWORD dwMaxLen, dwSize;
1749c2c66affSColin Finck     NTSTATUS Status;
1750c2c66affSColin Finck     HANDLE KeyHandle;
1751c2c66affSColin Finck     HKEY hSubKey;
1752c2c66affSColin Finck     WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1753c2c66affSColin Finck 
1754c2c66affSColin Finck     TRACE("(hkey=%p,%p %s)\n", hKey, lpszSubKey, debugstr_w(lpszSubKey));
1755c2c66affSColin Finck 
1756c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
1757c2c66affSColin Finck                            hKey);
1758c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1759c2c66affSColin Finck     {
1760c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
1761c2c66affSColin Finck     }
1762c2c66affSColin Finck 
1763c2c66affSColin Finck     hSubKey = KeyHandle;
1764c2c66affSColin Finck 
1765c2c66affSColin Finck     if(lpszSubKey)
1766c2c66affSColin Finck     {
1767c2c66affSColin Finck         ret = RegOpenKeyExW(KeyHandle, lpszSubKey, 0, KEY_READ, &hSubKey);
1768c2c66affSColin Finck         if (ret)
1769c2c66affSColin Finck         {
1770c2c66affSColin Finck             ClosePredefKey(KeyHandle);
1771c2c66affSColin Finck             return ret;
1772c2c66affSColin Finck         }
1773c2c66affSColin Finck     }
1774c2c66affSColin Finck 
1775c2c66affSColin Finck     /* Get highest length for keys, values */
1776c2c66affSColin Finck     ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
1777c2c66affSColin Finck             &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
1778c2c66affSColin Finck     if (ret) goto cleanup;
1779c2c66affSColin Finck 
1780c2c66affSColin Finck     dwMaxSubkeyLen++;
1781c2c66affSColin Finck     dwMaxValueLen++;
1782c2c66affSColin Finck     dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
1783c2c66affSColin Finck     if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
1784c2c66affSColin Finck     {
1785c2c66affSColin Finck         /* Name too big: alloc a buffer for it */
1786c2c66affSColin Finck         if (!(lpszName = RtlAllocateHeap( RtlGetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
1787c2c66affSColin Finck         {
1788c2c66affSColin Finck             ret = ERROR_NOT_ENOUGH_MEMORY;
1789c2c66affSColin Finck             goto cleanup;
1790c2c66affSColin Finck         }
1791c2c66affSColin Finck     }
1792c2c66affSColin Finck 
1793c2c66affSColin Finck 
1794c2c66affSColin Finck     /* Recursively delete all the subkeys */
1795c2c66affSColin Finck     while (TRUE)
1796c2c66affSColin Finck     {
1797c2c66affSColin Finck         dwSize = dwMaxLen;
1798c2c66affSColin Finck         if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
1799c2c66affSColin Finck                           NULL, NULL, NULL)) break;
1800c2c66affSColin Finck 
1801c2c66affSColin Finck         ret = RegDeleteTreeW(hSubKey, lpszName);
1802c2c66affSColin Finck         if (ret) goto cleanup;
1803c2c66affSColin Finck     }
1804c2c66affSColin Finck 
1805c2c66affSColin Finck     if (lpszSubKey)
1806c2c66affSColin Finck         ret = RegDeleteKeyW(KeyHandle, lpszSubKey);
1807c2c66affSColin Finck     else
1808c2c66affSColin Finck         while (TRUE)
1809c2c66affSColin Finck         {
1810c2c66affSColin Finck             dwSize = dwMaxLen;
1811c2c66affSColin Finck             if (RegEnumValueW(KeyHandle, 0, lpszName, &dwSize,
1812c2c66affSColin Finck                   NULL, NULL, NULL, NULL)) break;
1813c2c66affSColin Finck 
1814c2c66affSColin Finck             ret = RegDeleteValueW(KeyHandle, lpszName);
1815c2c66affSColin Finck             if (ret) goto cleanup;
1816c2c66affSColin Finck         }
1817c2c66affSColin Finck 
1818c2c66affSColin Finck cleanup:
1819c2c66affSColin Finck     /* Free buffer if allocated */
1820c2c66affSColin Finck     if (lpszName != szNameBuf)
1821c2c66affSColin Finck         RtlFreeHeap( RtlGetProcessHeap(), 0, lpszName);
1822c2c66affSColin Finck     if(lpszSubKey)
1823c2c66affSColin Finck         RegCloseKey(hSubKey);
1824c2c66affSColin Finck 
1825c2c66affSColin Finck     ClosePredefKey(KeyHandle);
1826c2c66affSColin Finck 
1827c2c66affSColin Finck     return ret;
1828c2c66affSColin Finck }
1829c2c66affSColin Finck 
1830c2c66affSColin Finck 
1831c2c66affSColin Finck /************************************************************************
1832c2c66affSColin Finck  *  RegDeleteTreeA
1833c2c66affSColin Finck  *
1834c2c66affSColin Finck  * @implemented
1835c2c66affSColin Finck  */
1836c2c66affSColin Finck LONG WINAPI
1837c2c66affSColin Finck RegDeleteTreeA(IN HKEY hKey,
1838c2c66affSColin Finck                IN LPCSTR lpSubKey  OPTIONAL)
1839c2c66affSColin Finck {
1840c2c66affSColin Finck     UNICODE_STRING SubKeyName = { 0, 0, NULL };
1841c2c66affSColin Finck     LONG Ret;
1842c2c66affSColin Finck 
1843c2c66affSColin Finck     if (lpSubKey != NULL &&
184446259092SSerge Gautherie         !RtlCreateUnicodeStringFromAsciiz(&SubKeyName, lpSubKey))
1845c2c66affSColin Finck     {
1846c2c66affSColin Finck         return ERROR_NOT_ENOUGH_MEMORY;
1847c2c66affSColin Finck     }
1848c2c66affSColin Finck 
1849c2c66affSColin Finck     Ret = RegDeleteTreeW(hKey,
1850c2c66affSColin Finck                          SubKeyName.Buffer);
1851c2c66affSColin Finck 
1852c2c66affSColin Finck     RtlFreeUnicodeString(&SubKeyName);
1853c2c66affSColin Finck 
1854c2c66affSColin Finck     return Ret;
1855c2c66affSColin Finck }
1856c2c66affSColin Finck 
1857c2c66affSColin Finck 
1858c2c66affSColin Finck /************************************************************************
1859c2c66affSColin Finck  *  RegDisableReflectionKey
1860c2c66affSColin Finck  *
1861c2c66affSColin Finck  * @unimplemented
1862c2c66affSColin Finck  */
1863c2c66affSColin Finck LONG WINAPI
1864c2c66affSColin Finck RegDisableReflectionKey(IN HKEY hBase)
1865c2c66affSColin Finck {
1866c2c66affSColin Finck     FIXME("RegDisableReflectionKey(0x%p) UNIMPLEMENTED!\n", hBase);
1867c2c66affSColin Finck     return ERROR_CALL_NOT_IMPLEMENTED;
1868c2c66affSColin Finck }
1869c2c66affSColin Finck 
1870c2c66affSColin Finck 
1871c2c66affSColin Finck /************************************************************************
1872c2c66affSColin Finck  *  RegEnableReflectionKey
1873c2c66affSColin Finck  *
1874c2c66affSColin Finck  * @unimplemented
1875c2c66affSColin Finck  */
1876c2c66affSColin Finck LONG WINAPI
1877c2c66affSColin Finck RegEnableReflectionKey(IN HKEY hBase)
1878c2c66affSColin Finck {
1879c2c66affSColin Finck     FIXME("RegEnableReflectionKey(0x%p) UNIMPLEMENTED!\n", hBase);
1880c2c66affSColin Finck     return ERROR_CALL_NOT_IMPLEMENTED;
1881c2c66affSColin Finck }
1882c2c66affSColin Finck 
1883c2c66affSColin Finck 
1884c2c66affSColin Finck /******************************************************************************
1885c2c66affSColin Finck  * RegpApplyRestrictions   [internal]
1886c2c66affSColin Finck  *
1887c2c66affSColin Finck  * Helper function for RegGetValueA/W.
1888c2c66affSColin Finck  */
1889c2c66affSColin Finck static VOID
1890c2c66affSColin Finck RegpApplyRestrictions(DWORD dwFlags,
1891c2c66affSColin Finck                       DWORD dwType,
1892c2c66affSColin Finck                       DWORD cbData,
1893c2c66affSColin Finck                       PLONG ret)
1894c2c66affSColin Finck {
1895c2c66affSColin Finck     /* Check if the type is restricted by the passed flags */
1896c2c66affSColin Finck     if (*ret == ERROR_SUCCESS || *ret == ERROR_MORE_DATA)
1897c2c66affSColin Finck     {
1898c2c66affSColin Finck         DWORD dwMask = 0;
1899c2c66affSColin Finck 
1900c2c66affSColin Finck         switch (dwType)
1901c2c66affSColin Finck         {
1902c2c66affSColin Finck         case REG_NONE: dwMask = RRF_RT_REG_NONE; break;
1903c2c66affSColin Finck         case REG_SZ: dwMask = RRF_RT_REG_SZ; break;
1904c2c66affSColin Finck         case REG_EXPAND_SZ: dwMask = RRF_RT_REG_EXPAND_SZ; break;
1905c2c66affSColin Finck         case REG_MULTI_SZ: dwMask = RRF_RT_REG_MULTI_SZ; break;
1906c2c66affSColin Finck         case REG_BINARY: dwMask = RRF_RT_REG_BINARY; break;
1907c2c66affSColin Finck         case REG_DWORD: dwMask = RRF_RT_REG_DWORD; break;
1908c2c66affSColin Finck         case REG_QWORD: dwMask = RRF_RT_REG_QWORD; break;
1909c2c66affSColin Finck         }
1910c2c66affSColin Finck 
1911c2c66affSColin Finck         if (dwFlags & dwMask)
1912c2c66affSColin Finck         {
1913c2c66affSColin Finck             /* Type is not restricted, check for size mismatch */
1914c2c66affSColin Finck             if (dwType == REG_BINARY)
1915c2c66affSColin Finck             {
1916c2c66affSColin Finck                 DWORD cbExpect = 0;
1917c2c66affSColin Finck 
1918c2c66affSColin Finck                 if ((dwFlags & RRF_RT_ANY) == RRF_RT_DWORD)
1919c2c66affSColin Finck                     cbExpect = 4;
1920c2c66affSColin Finck                 else if ((dwFlags & RRF_RT_ANY) == RRF_RT_QWORD)
1921c2c66affSColin Finck                     cbExpect = 8;
1922c2c66affSColin Finck 
1923c2c66affSColin Finck                 if (cbExpect && cbData != cbExpect)
1924c2c66affSColin Finck                     *ret = ERROR_DATATYPE_MISMATCH;
1925c2c66affSColin Finck             }
1926c2c66affSColin Finck         }
1927c2c66affSColin Finck         else *ret = ERROR_UNSUPPORTED_TYPE;
1928c2c66affSColin Finck     }
1929c2c66affSColin Finck }
1930c2c66affSColin Finck 
1931c2c66affSColin Finck 
1932c2c66affSColin Finck /******************************************************************************
1933c2c66affSColin Finck  * RegGetValueW   [ADVAPI32.@]
1934c2c66affSColin Finck  *
1935c2c66affSColin Finck  * Retrieves the type and data for a value name associated with a key,
1936c2c66affSColin Finck  * optionally expanding its content and restricting its type.
1937c2c66affSColin Finck  *
1938c2c66affSColin Finck  * PARAMS
1939c2c66affSColin Finck  *  hKey      [I] Handle to an open key.
1940c2c66affSColin Finck  *  pszSubKey [I] Name of the subkey of hKey.
1941c2c66affSColin Finck  *  pszValue  [I] Name of value under hKey/szSubKey to query.
1942c2c66affSColin Finck  *  dwFlags   [I] Flags restricting the value type to retrieve.
1943c2c66affSColin Finck  *  pdwType   [O] Destination for the values type, may be NULL.
1944c2c66affSColin Finck  *  pvData    [O] Destination for the values content, may be NULL.
1945c2c66affSColin Finck  *  pcbData   [I/O] Size of pvData, updated with the size in bytes required to
1946c2c66affSColin Finck  *                  retrieve the whole content, including the trailing '\0'
1947c2c66affSColin Finck  *                  for strings.
1948c2c66affSColin Finck  *
1949c2c66affSColin Finck  * RETURNS
1950c2c66affSColin Finck  *  Success: ERROR_SUCCESS
1951c2c66affSColin Finck  *  Failure: nonzero error code from Winerror.h
1952c2c66affSColin Finck  *
1953c2c66affSColin Finck  * NOTES
1954c2c66affSColin Finck  *  - Unless RRF_NOEXPAND is specified, REG_EXPAND_SZ values are automatically
1955c2c66affSColin Finck  *    expanded and pdwType is set to REG_SZ instead.
1956c2c66affSColin Finck  *  - Restrictions are applied after expanding, using RRF_RT_REG_EXPAND_SZ
1957c2c66affSColin Finck  *    without RRF_NOEXPAND is thus not allowed.
1958c2c66affSColin Finck  *    An exception is the case where RRF_RT_ANY is specified, because then
1959c2c66affSColin Finck  *    RRF_NOEXPAND is allowed.
1960c2c66affSColin Finck  */
1961c2c66affSColin Finck LSTATUS WINAPI
1962c2c66affSColin Finck RegGetValueW(HKEY hKey,
1963c2c66affSColin Finck              LPCWSTR pszSubKey,
1964c2c66affSColin Finck              LPCWSTR pszValue,
1965c2c66affSColin Finck              DWORD dwFlags,
1966c2c66affSColin Finck              LPDWORD pdwType,
1967c2c66affSColin Finck              PVOID pvData,
1968c2c66affSColin Finck              LPDWORD pcbData)
1969c2c66affSColin Finck {
1970c2c66affSColin Finck     DWORD dwType, cbData = pcbData ? *pcbData : 0;
1971c2c66affSColin Finck     PVOID pvBuf = NULL;
1972c2c66affSColin Finck     LONG ret;
1973c2c66affSColin Finck 
1974c2c66affSColin Finck     TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
1975c2c66affSColin Finck           hKey, debugstr_w(pszSubKey), debugstr_w(pszValue), dwFlags, pdwType,
1976c2c66affSColin Finck           pvData, pcbData, cbData);
1977c2c66affSColin Finck 
1978c2c66affSColin Finck     if (pvData && !pcbData)
1979c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
1980c2c66affSColin Finck     if ((dwFlags & RRF_RT_REG_EXPAND_SZ) && !(dwFlags & RRF_NOEXPAND) &&
1981c2c66affSColin Finck             ((dwFlags & RRF_RT_ANY) != RRF_RT_ANY))
1982c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
1983c2c66affSColin Finck 
1984c2c66affSColin Finck     if (pszSubKey && pszSubKey[0])
1985c2c66affSColin Finck     {
1986c2c66affSColin Finck         ret = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey);
1987c2c66affSColin Finck         if (ret != ERROR_SUCCESS) return ret;
1988c2c66affSColin Finck     }
1989c2c66affSColin Finck 
1990c2c66affSColin Finck     ret = RegQueryValueExW(hKey, pszValue, NULL, &dwType, pvData, &cbData);
1991c2c66affSColin Finck 
1992c2c66affSColin Finck     /* If we are going to expand we need to read in the whole the value even
1993c2c66affSColin Finck      * if the passed buffer was too small as the expanded string might be
1994c2c66affSColin Finck      * smaller than the unexpanded one and could fit into cbData bytes. */
1995c2c66affSColin Finck     if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) &&
1996c2c66affSColin Finck         dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND))
1997c2c66affSColin Finck     {
1998c2c66affSColin Finck         do
1999c2c66affSColin Finck         {
2000c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, pvBuf);
2001c2c66affSColin Finck 
2002c2c66affSColin Finck             pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData);
2003c2c66affSColin Finck             if (!pvBuf)
2004c2c66affSColin Finck             {
2005c2c66affSColin Finck                 ret = ERROR_NOT_ENOUGH_MEMORY;
2006c2c66affSColin Finck                 break;
2007c2c66affSColin Finck             }
2008c2c66affSColin Finck 
2009c2c66affSColin Finck             if (ret == ERROR_MORE_DATA || !pvData)
2010c2c66affSColin Finck                 ret = RegQueryValueExW(hKey, pszValue, NULL,
2011c2c66affSColin Finck                                        &dwType, pvBuf, &cbData);
2012c2c66affSColin Finck             else
2013c2c66affSColin Finck             {
2014c2c66affSColin Finck                 /* Even if cbData was large enough we have to copy the
2015c2c66affSColin Finck                  * string since ExpandEnvironmentStrings can't handle
2016c2c66affSColin Finck                  * overlapping buffers. */
2017c2c66affSColin Finck                 CopyMemory(pvBuf, pvData, cbData);
2018c2c66affSColin Finck             }
2019c2c66affSColin Finck 
2020c2c66affSColin Finck             /* Both the type or the value itself could have been modified in
2021c2c66affSColin Finck              * between so we have to keep retrying until the buffer is large
2022c2c66affSColin Finck              * enough or we no longer have to expand the value. */
2023c2c66affSColin Finck         }
2024c2c66affSColin Finck         while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA);
2025c2c66affSColin Finck 
2026c2c66affSColin Finck         if (ret == ERROR_SUCCESS)
2027c2c66affSColin Finck         {
2028c2c66affSColin Finck             /* Recheck dwType in case it changed since the first call */
2029c2c66affSColin Finck             if (dwType == REG_EXPAND_SZ)
2030c2c66affSColin Finck             {
2031c2c66affSColin Finck                 cbData = ExpandEnvironmentStringsW(pvBuf, pvData,
2032c2c66affSColin Finck                                                    pcbData ? *pcbData : 0) * sizeof(WCHAR);
2033c2c66affSColin Finck                 dwType = REG_SZ;
2034c2c66affSColin Finck                 if (pvData && pcbData && cbData > *pcbData)
2035c2c66affSColin Finck                     ret = ERROR_MORE_DATA;
2036c2c66affSColin Finck             }
2037c2c66affSColin Finck             else if (pvData)
2038c2c66affSColin Finck                 CopyMemory(pvData, pvBuf, *pcbData);
2039c2c66affSColin Finck         }
2040c2c66affSColin Finck 
2041c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, pvBuf);
2042c2c66affSColin Finck     }
2043c2c66affSColin Finck 
2044c2c66affSColin Finck     if (pszSubKey && pszSubKey[0])
2045c2c66affSColin Finck         RegCloseKey(hKey);
2046c2c66affSColin Finck 
2047c2c66affSColin Finck     RegpApplyRestrictions(dwFlags, dwType, cbData, &ret);
2048c2c66affSColin Finck 
2049c2c66affSColin Finck     if (pvData && ret != ERROR_SUCCESS && (dwFlags & RRF_ZEROONFAILURE))
2050c2c66affSColin Finck         ZeroMemory(pvData, *pcbData);
2051c2c66affSColin Finck 
2052c2c66affSColin Finck     if (pdwType)
2053c2c66affSColin Finck         *pdwType = dwType;
2054c2c66affSColin Finck 
2055c2c66affSColin Finck     if (pcbData)
2056c2c66affSColin Finck         *pcbData = cbData;
2057c2c66affSColin Finck 
2058c2c66affSColin Finck     return ret;
2059c2c66affSColin Finck }
2060c2c66affSColin Finck 
2061c2c66affSColin Finck 
2062c2c66affSColin Finck /******************************************************************************
2063c2c66affSColin Finck  * RegGetValueA   [ADVAPI32.@]
2064c2c66affSColin Finck  *
2065c2c66affSColin Finck  * See RegGetValueW.
2066c2c66affSColin Finck  */
2067c2c66affSColin Finck LSTATUS WINAPI
2068c2c66affSColin Finck RegGetValueA(HKEY hKey,
2069c2c66affSColin Finck              LPCSTR pszSubKey,
2070c2c66affSColin Finck              LPCSTR pszValue,
2071c2c66affSColin Finck              DWORD dwFlags,
2072c2c66affSColin Finck              LPDWORD pdwType,
2073c2c66affSColin Finck              PVOID pvData,
2074c2c66affSColin Finck              LPDWORD pcbData)
2075c2c66affSColin Finck {
2076c2c66affSColin Finck     DWORD dwType, cbData = pcbData ? *pcbData : 0;
2077c2c66affSColin Finck     PVOID pvBuf = NULL;
2078c2c66affSColin Finck     LONG ret;
2079c2c66affSColin Finck 
2080c2c66affSColin Finck     TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
2081c2c66affSColin Finck           hKey, pszSubKey, pszValue, dwFlags, pdwType, pvData, pcbData,
2082c2c66affSColin Finck           cbData);
2083c2c66affSColin Finck 
2084c2c66affSColin Finck     if (pvData && !pcbData)
2085c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
2086c2c66affSColin Finck     if ((dwFlags & RRF_RT_REG_EXPAND_SZ) && !(dwFlags & RRF_NOEXPAND) &&
2087c2c66affSColin Finck             ((dwFlags & RRF_RT_ANY) != RRF_RT_ANY))
2088c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
2089c2c66affSColin Finck 
2090c2c66affSColin Finck     if (pszSubKey && pszSubKey[0])
2091c2c66affSColin Finck     {
2092c2c66affSColin Finck         ret = RegOpenKeyExA(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey);
2093c2c66affSColin Finck         if (ret != ERROR_SUCCESS) return ret;
2094c2c66affSColin Finck     }
2095c2c66affSColin Finck 
2096c2c66affSColin Finck     ret = RegQueryValueExA(hKey, pszValue, NULL, &dwType, pvData, &cbData);
2097c2c66affSColin Finck 
2098c2c66affSColin Finck     /* If we are going to expand we need to read in the whole the value even
2099c2c66affSColin Finck      * if the passed buffer was too small as the expanded string might be
2100c2c66affSColin Finck      * smaller than the unexpanded one and could fit into cbData bytes. */
2101c2c66affSColin Finck     if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) &&
2102c2c66affSColin Finck         (dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND)))
2103c2c66affSColin Finck     {
2104c2c66affSColin Finck         do {
2105c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, pvBuf);
2106c2c66affSColin Finck 
2107c2c66affSColin Finck             pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData);
2108c2c66affSColin Finck             if (!pvBuf)
2109c2c66affSColin Finck             {
2110c2c66affSColin Finck                 ret = ERROR_NOT_ENOUGH_MEMORY;
2111c2c66affSColin Finck                 break;
2112c2c66affSColin Finck             }
2113c2c66affSColin Finck 
2114c2c66affSColin Finck             if (ret == ERROR_MORE_DATA || !pvData)
2115c2c66affSColin Finck                 ret = RegQueryValueExA(hKey, pszValue, NULL,
2116c2c66affSColin Finck                                        &dwType, pvBuf, &cbData);
2117c2c66affSColin Finck             else
2118c2c66affSColin Finck             {
2119c2c66affSColin Finck                 /* Even if cbData was large enough we have to copy the
2120c2c66affSColin Finck                  * string since ExpandEnvironmentStrings can't handle
2121c2c66affSColin Finck                  * overlapping buffers. */
2122c2c66affSColin Finck                 CopyMemory(pvBuf, pvData, cbData);
2123c2c66affSColin Finck             }
2124c2c66affSColin Finck 
2125c2c66affSColin Finck             /* Both the type or the value itself could have been modified in
2126c2c66affSColin Finck              * between so we have to keep retrying until the buffer is large
2127c2c66affSColin Finck              * enough or we no longer have to expand the value. */
2128c2c66affSColin Finck         } while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA);
2129c2c66affSColin Finck 
2130c2c66affSColin Finck         if (ret == ERROR_SUCCESS)
2131c2c66affSColin Finck         {
2132c2c66affSColin Finck             /* Recheck dwType in case it changed since the first call */
2133c2c66affSColin Finck             if (dwType == REG_EXPAND_SZ)
2134c2c66affSColin Finck             {
2135c2c66affSColin Finck                 cbData = ExpandEnvironmentStringsA(pvBuf, pvData,
2136c2c66affSColin Finck                                                    pcbData ? *pcbData : 0);
2137c2c66affSColin Finck                 dwType = REG_SZ;
2138c2c66affSColin Finck                 if(pvData && pcbData && cbData > *pcbData)
2139c2c66affSColin Finck                     ret = ERROR_MORE_DATA;
2140c2c66affSColin Finck             }
2141c2c66affSColin Finck             else if (pvData)
2142c2c66affSColin Finck                 CopyMemory(pvData, pvBuf, *pcbData);
2143c2c66affSColin Finck         }
2144c2c66affSColin Finck 
2145c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, pvBuf);
2146c2c66affSColin Finck     }
2147c2c66affSColin Finck 
2148c2c66affSColin Finck     if (pszSubKey && pszSubKey[0])
2149c2c66affSColin Finck         RegCloseKey(hKey);
2150c2c66affSColin Finck 
2151c2c66affSColin Finck     RegpApplyRestrictions(dwFlags, dwType, cbData, &ret);
2152c2c66affSColin Finck 
2153c2c66affSColin Finck     if (pvData && ret != ERROR_SUCCESS && (dwFlags & RRF_ZEROONFAILURE))
2154c2c66affSColin Finck         ZeroMemory(pvData, *pcbData);
2155c2c66affSColin Finck 
2156c2c66affSColin Finck     if (pdwType) *pdwType = dwType;
2157c2c66affSColin Finck     if (pcbData) *pcbData = cbData;
2158c2c66affSColin Finck 
2159c2c66affSColin Finck     return ret;
2160c2c66affSColin Finck }
2161c2c66affSColin Finck 
2162c2c66affSColin Finck 
2163c2c66affSColin Finck /************************************************************************
2164c2c66affSColin Finck  *  RegSetKeyValueW
2165c2c66affSColin Finck  *
2166c2c66affSColin Finck  * @implemented
2167c2c66affSColin Finck  */
2168c2c66affSColin Finck LONG WINAPI
2169c2c66affSColin Finck RegSetKeyValueW(IN HKEY hKey,
2170c2c66affSColin Finck                 IN LPCWSTR lpSubKey  OPTIONAL,
2171c2c66affSColin Finck                 IN LPCWSTR lpValueName  OPTIONAL,
2172c2c66affSColin Finck                 IN DWORD dwType,
2173c2c66affSColin Finck                 IN LPCVOID lpData  OPTIONAL,
2174c2c66affSColin Finck                 IN DWORD cbData)
2175c2c66affSColin Finck {
2176c2c66affSColin Finck     HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
2177c2c66affSColin Finck     NTSTATUS Status;
2178c2c66affSColin Finck     LONG Ret;
2179c2c66affSColin Finck 
2180c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
2181c2c66affSColin Finck                            hKey);
2182c2c66affSColin Finck     if (!NT_SUCCESS(Status))
2183c2c66affSColin Finck     {
2184c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
2185c2c66affSColin Finck     }
2186c2c66affSColin Finck 
2187c2c66affSColin Finck     if (lpSubKey != NULL)
2188c2c66affSColin Finck     {
2189c2c66affSColin Finck         OBJECT_ATTRIBUTES ObjectAttributes;
2190c2c66affSColin Finck         UNICODE_STRING SubKeyName;
2191c2c66affSColin Finck 
219246259092SSerge Gautherie         RtlInitUnicodeString(&SubKeyName, lpSubKey);
2193c2c66affSColin Finck 
2194c2c66affSColin Finck         InitializeObjectAttributes(&ObjectAttributes,
2195c2c66affSColin Finck                                    &SubKeyName,
2196c2c66affSColin Finck                                    OBJ_CASE_INSENSITIVE,
2197c2c66affSColin Finck                                    KeyHandle,
2198c2c66affSColin Finck                                    NULL);
2199c2c66affSColin Finck 
2200c2c66affSColin Finck         Status = NtOpenKey(&SubKeyHandle,
2201c2c66affSColin Finck                            KEY_SET_VALUE,
2202c2c66affSColin Finck                            &ObjectAttributes);
2203c2c66affSColin Finck         if (!NT_SUCCESS(Status))
2204c2c66affSColin Finck         {
2205c2c66affSColin Finck             Ret = RtlNtStatusToDosError(Status);
2206c2c66affSColin Finck             goto Cleanup;
2207c2c66affSColin Finck         }
2208c2c66affSColin Finck 
2209c2c66affSColin Finck         CurKey = SubKeyHandle;
2210c2c66affSColin Finck     }
2211c2c66affSColin Finck     else
2212c2c66affSColin Finck         CurKey = KeyHandle;
2213c2c66affSColin Finck 
2214c2c66affSColin Finck     Ret = RegSetValueExW(CurKey,
2215c2c66affSColin Finck                          lpValueName,
2216c2c66affSColin Finck                          0,
2217c2c66affSColin Finck                          dwType,
2218c2c66affSColin Finck                          lpData,
2219c2c66affSColin Finck                          cbData);
2220c2c66affSColin Finck 
2221c2c66affSColin Finck     if (SubKeyHandle != NULL)
2222c2c66affSColin Finck     {
2223c2c66affSColin Finck         NtClose(SubKeyHandle);
2224c2c66affSColin Finck     }
2225c2c66affSColin Finck 
2226c2c66affSColin Finck Cleanup:
2227c2c66affSColin Finck     ClosePredefKey(KeyHandle);
2228c2c66affSColin Finck 
2229c2c66affSColin Finck     return Ret;
2230c2c66affSColin Finck }
2231c2c66affSColin Finck 
2232c2c66affSColin Finck 
2233c2c66affSColin Finck /************************************************************************
2234c2c66affSColin Finck  *  RegSetKeyValueA
2235c2c66affSColin Finck  *
2236c2c66affSColin Finck  * @implemented
2237c2c66affSColin Finck  */
2238c2c66affSColin Finck LONG WINAPI
2239c2c66affSColin Finck RegSetKeyValueA(IN HKEY hKey,
2240c2c66affSColin Finck                 IN LPCSTR lpSubKey  OPTIONAL,
2241c2c66affSColin Finck                 IN LPCSTR lpValueName  OPTIONAL,
2242c2c66affSColin Finck                 IN DWORD dwType,
2243c2c66affSColin Finck                 IN LPCVOID lpData  OPTIONAL,
2244c2c66affSColin Finck                 IN DWORD cbData)
2245c2c66affSColin Finck {
2246c2c66affSColin Finck     HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
2247c2c66affSColin Finck     NTSTATUS Status;
2248c2c66affSColin Finck     LONG Ret;
2249c2c66affSColin Finck 
2250c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
2251c2c66affSColin Finck                            hKey);
2252c2c66affSColin Finck     if (!NT_SUCCESS(Status))
2253c2c66affSColin Finck     {
2254c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
2255c2c66affSColin Finck     }
2256c2c66affSColin Finck 
2257c2c66affSColin Finck     if (lpSubKey != NULL)
2258c2c66affSColin Finck     {
2259c2c66affSColin Finck         OBJECT_ATTRIBUTES ObjectAttributes;
2260c2c66affSColin Finck         UNICODE_STRING SubKeyName;
2261c2c66affSColin Finck 
226246259092SSerge Gautherie         if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName, lpSubKey))
2263c2c66affSColin Finck         {
2264c2c66affSColin Finck             Ret = ERROR_NOT_ENOUGH_MEMORY;
2265c2c66affSColin Finck             goto Cleanup;
2266c2c66affSColin Finck         }
2267c2c66affSColin Finck 
2268c2c66affSColin Finck         InitializeObjectAttributes(&ObjectAttributes,
2269c2c66affSColin Finck                                    &SubKeyName,
2270c2c66affSColin Finck                                    OBJ_CASE_INSENSITIVE,
2271c2c66affSColin Finck                                    KeyHandle,
2272c2c66affSColin Finck                                    NULL);
2273c2c66affSColin Finck 
2274c2c66affSColin Finck         Status = NtOpenKey(&SubKeyHandle,
2275c2c66affSColin Finck                            KEY_SET_VALUE,
2276c2c66affSColin Finck                            &ObjectAttributes);
2277c2c66affSColin Finck 
2278c2c66affSColin Finck         RtlFreeUnicodeString(&SubKeyName);
2279c2c66affSColin Finck 
2280c2c66affSColin Finck         if (!NT_SUCCESS(Status))
2281c2c66affSColin Finck         {
2282c2c66affSColin Finck             Ret = RtlNtStatusToDosError(Status);
2283c2c66affSColin Finck             goto Cleanup;
2284c2c66affSColin Finck         }
2285c2c66affSColin Finck 
2286c2c66affSColin Finck         CurKey = SubKeyHandle;
2287c2c66affSColin Finck     }
2288c2c66affSColin Finck     else
2289c2c66affSColin Finck         CurKey = KeyHandle;
2290c2c66affSColin Finck 
2291c2c66affSColin Finck     Ret = RegSetValueExA(CurKey,
2292c2c66affSColin Finck                          lpValueName,
2293c2c66affSColin Finck                          0,
2294c2c66affSColin Finck                          dwType,
2295c2c66affSColin Finck                          lpData,
2296c2c66affSColin Finck                          cbData);
2297c2c66affSColin Finck 
2298c2c66affSColin Finck     if (SubKeyHandle != NULL)
2299c2c66affSColin Finck     {
2300c2c66affSColin Finck         NtClose(SubKeyHandle);
2301c2c66affSColin Finck     }
2302c2c66affSColin Finck 
2303c2c66affSColin Finck Cleanup:
2304c2c66affSColin Finck     ClosePredefKey(KeyHandle);
2305c2c66affSColin Finck 
2306c2c66affSColin Finck     return Ret;
2307c2c66affSColin Finck }
2308c2c66affSColin Finck 
2309c2c66affSColin Finck 
2310c2c66affSColin Finck /************************************************************************
2311c2c66affSColin Finck  *  RegDeleteValueA
2312c2c66affSColin Finck  *
2313c2c66affSColin Finck  * @implemented
2314c2c66affSColin Finck  */
2315c2c66affSColin Finck LONG WINAPI
2316c2c66affSColin Finck RegDeleteValueA(HKEY hKey,
2317c2c66affSColin Finck                 LPCSTR lpValueName)
2318c2c66affSColin Finck {
2319c2c66affSColin Finck     UNICODE_STRING ValueName;
2320c2c66affSColin Finck     HANDLE KeyHandle;
2321c2c66affSColin Finck     NTSTATUS Status;
2322c2c66affSColin Finck 
2323c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
2324c2c66affSColin Finck                            hKey);
2325c2c66affSColin Finck     if (!NT_SUCCESS(Status))
2326c2c66affSColin Finck     {
2327c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
2328c2c66affSColin Finck     }
2329c2c66affSColin Finck 
233046259092SSerge Gautherie     RtlCreateUnicodeStringFromAsciiz(&ValueName, lpValueName);
2331c2c66affSColin Finck     Status = NtDeleteValueKey(KeyHandle,
2332c2c66affSColin Finck                               &ValueName);
2333c2c66affSColin Finck     RtlFreeUnicodeString (&ValueName);
2334c2c66affSColin Finck 
2335c2c66affSColin Finck     ClosePredefKey(KeyHandle);
2336c2c66affSColin Finck 
2337c2c66affSColin Finck     if (!NT_SUCCESS(Status))
2338c2c66affSColin Finck     {
2339c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
2340c2c66affSColin Finck     }
2341c2c66affSColin Finck 
2342c2c66affSColin Finck     return ERROR_SUCCESS;
2343c2c66affSColin Finck }
2344c2c66affSColin Finck 
2345c2c66affSColin Finck 
2346c2c66affSColin Finck /************************************************************************
2347c2c66affSColin Finck  *  RegDeleteValueW
2348c2c66affSColin Finck  *
2349c2c66affSColin Finck  * @implemented
2350c2c66affSColin Finck  */
2351c2c66affSColin Finck LONG WINAPI
2352c2c66affSColin Finck RegDeleteValueW(HKEY hKey,
2353c2c66affSColin Finck                 LPCWSTR lpValueName)
2354c2c66affSColin Finck {
2355c2c66affSColin Finck     UNICODE_STRING ValueName;
2356c2c66affSColin Finck     NTSTATUS Status;
2357c2c66affSColin Finck     HANDLE KeyHandle;
2358c2c66affSColin Finck 
2359c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
2360c2c66affSColin Finck                            hKey);
2361c2c66affSColin Finck     if (!NT_SUCCESS(Status))
2362c2c66affSColin Finck     {
2363c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
2364c2c66affSColin Finck     }
2365c2c66affSColin Finck 
236646259092SSerge Gautherie     RtlInitUnicodeString(&ValueName, lpValueName);
2367c2c66affSColin Finck 
2368c2c66affSColin Finck     Status = NtDeleteValueKey(KeyHandle,
2369c2c66affSColin Finck                               &ValueName);
2370c2c66affSColin Finck 
2371c2c66affSColin Finck     ClosePredefKey(KeyHandle);
2372c2c66affSColin Finck 
2373c2c66affSColin Finck     if (!NT_SUCCESS(Status))
2374c2c66affSColin Finck     {
2375c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
2376c2c66affSColin Finck     }
2377c2c66affSColin Finck 
2378c2c66affSColin Finck     return ERROR_SUCCESS;
2379c2c66affSColin Finck }
2380c2c66affSColin Finck 
2381c2c66affSColin Finck 
2382c2c66affSColin Finck /************************************************************************
2383c2c66affSColin Finck  *  RegEnumKeyA
2384c2c66affSColin Finck  *
2385c2c66affSColin Finck  * @implemented
2386c2c66affSColin Finck  */
2387c2c66affSColin Finck LONG WINAPI
2388c2c66affSColin Finck RegEnumKeyA(HKEY hKey,
2389c2c66affSColin Finck             DWORD dwIndex,
2390c2c66affSColin Finck             LPSTR lpName,
2391c2c66affSColin Finck             DWORD cbName)
2392c2c66affSColin Finck {
2393c2c66affSColin Finck     DWORD dwLength;
2394c2c66affSColin Finck 
2395c2c66affSColin Finck     dwLength = cbName;
2396c2c66affSColin Finck     return RegEnumKeyExA(hKey,
2397c2c66affSColin Finck                          dwIndex,
2398c2c66affSColin Finck                          lpName,
2399c2c66affSColin Finck                          &dwLength,
2400c2c66affSColin Finck                          NULL,
2401c2c66affSColin Finck                          NULL,
2402c2c66affSColin Finck                          NULL,
2403c2c66affSColin Finck                          NULL);
2404c2c66affSColin Finck }
2405c2c66affSColin Finck 
2406c2c66affSColin Finck 
2407c2c66affSColin Finck /************************************************************************
2408c2c66affSColin Finck  *  RegEnumKeyW
2409c2c66affSColin Finck  *
2410c2c66affSColin Finck  * @implemented
2411c2c66affSColin Finck  */
2412c2c66affSColin Finck LONG WINAPI
2413c2c66affSColin Finck RegEnumKeyW(HKEY hKey,
2414c2c66affSColin Finck             DWORD dwIndex,
2415c2c66affSColin Finck             LPWSTR lpName,
2416c2c66affSColin Finck             DWORD cbName)
2417c2c66affSColin Finck {
2418c2c66affSColin Finck     DWORD dwLength;
2419c2c66affSColin Finck 
2420c2c66affSColin Finck     dwLength = cbName;
2421c2c66affSColin Finck     return RegEnumKeyExW(hKey,
2422c2c66affSColin Finck                          dwIndex,
2423c2c66affSColin Finck                          lpName,
2424c2c66affSColin Finck                          &dwLength,
2425c2c66affSColin Finck                          NULL,
2426c2c66affSColin Finck                          NULL,
2427c2c66affSColin Finck                          NULL,
2428c2c66affSColin Finck                          NULL);
2429c2c66affSColin Finck }
2430c2c66affSColin Finck 
2431c2c66affSColin Finck 
2432c2c66affSColin Finck /************************************************************************
2433c2c66affSColin Finck  *  RegEnumKeyExA
2434c2c66affSColin Finck  *
2435c2c66affSColin Finck  * @implemented
2436c2c66affSColin Finck  */
2437c2c66affSColin Finck LONG
2438c2c66affSColin Finck WINAPI
2439c2c66affSColin Finck RegEnumKeyExA(
2440c2c66affSColin Finck     _In_ HKEY hKey,
2441c2c66affSColin Finck     _In_ DWORD dwIndex,
2442c2c66affSColin Finck     _Out_ LPSTR lpName,
2443c2c66affSColin Finck     _Inout_ LPDWORD lpcbName,
2444c2c66affSColin Finck     _Reserved_ LPDWORD lpReserved,
2445c2c66affSColin Finck     _Out_opt_ LPSTR lpClass,
2446c2c66affSColin Finck     _Inout_opt_ LPDWORD lpcbClass,
2447c2c66affSColin Finck     _Out_opt_ PFILETIME lpftLastWriteTime)
2448c2c66affSColin Finck {
2449c2c66affSColin Finck     WCHAR* NameBuffer = NULL;
2450c2c66affSColin Finck     WCHAR* ClassBuffer = NULL;
2451c2c66affSColin Finck     DWORD NameLength, ClassLength;
2452c2c66affSColin Finck     LONG ErrorCode;
2453c2c66affSColin Finck 
2454c2c66affSColin Finck     /* Allocate our buffers */
2455c2c66affSColin Finck     if (*lpcbName > 0)
2456c2c66affSColin Finck     {
2457c2c66affSColin Finck         NameLength = *lpcbName;
2458c2c66affSColin Finck         NameBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *lpcbName * sizeof(WCHAR));
2459c2c66affSColin Finck         if (NameBuffer == NULL)
2460c2c66affSColin Finck         {
2461c2c66affSColin Finck             ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2462c2c66affSColin Finck             goto Exit;
2463c2c66affSColin Finck         }
2464c2c66affSColin Finck     }
2465c2c66affSColin Finck 
2466c2c66affSColin Finck     if (lpClass)
2467c2c66affSColin Finck     {
2468c2c66affSColin Finck         if (*lpcbClass > 0)
2469c2c66affSColin Finck         {
2470c2c66affSColin Finck             ClassLength = *lpcbClass;
2471c2c66affSColin Finck             ClassBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *lpcbClass * sizeof(WCHAR));
2472c2c66affSColin Finck             if (ClassBuffer == NULL)
2473c2c66affSColin Finck             {
2474c2c66affSColin Finck                 ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2475c2c66affSColin Finck                 goto Exit;
2476c2c66affSColin Finck             }
2477c2c66affSColin Finck         }
2478c2c66affSColin Finck     }
2479c2c66affSColin Finck 
2480c2c66affSColin Finck     /* Do the actual call */
2481c2c66affSColin Finck     ErrorCode = RegEnumKeyExW(
2482c2c66affSColin Finck         hKey,
2483c2c66affSColin Finck         dwIndex,
2484c2c66affSColin Finck         NameBuffer,
2485c2c66affSColin Finck         lpcbName,
2486c2c66affSColin Finck         lpReserved,
2487c2c66affSColin Finck         ClassBuffer,
2488c2c66affSColin Finck         lpcbClass,
2489c2c66affSColin Finck         lpftLastWriteTime);
2490c2c66affSColin Finck 
2491c2c66affSColin Finck     if (ErrorCode != ERROR_SUCCESS)
2492c2c66affSColin Finck         goto Exit;
2493c2c66affSColin Finck 
2494c2c66affSColin Finck     /* Convert the strings */
2495c2c66affSColin Finck     RtlUnicodeToMultiByteN(lpName, *lpcbName, 0, NameBuffer, *lpcbName * sizeof(WCHAR));
2496c2c66affSColin Finck     /* NULL terminate if we can */
2497c2c66affSColin Finck     if (NameLength > *lpcbName)
2498c2c66affSColin Finck         lpName[*lpcbName] = '\0';
2499c2c66affSColin Finck 
2500c2c66affSColin Finck     if (lpClass)
2501c2c66affSColin Finck     {
2502c2c66affSColin Finck         RtlUnicodeToMultiByteN(lpClass, *lpcbClass, 0, NameBuffer, *lpcbClass * sizeof(WCHAR));
2503c2c66affSColin Finck         if (ClassLength > *lpcbClass)
2504c2c66affSColin Finck             lpClass[*lpcbClass] = '\0';
2505c2c66affSColin Finck     }
2506c2c66affSColin Finck 
2507c2c66affSColin Finck Exit:
2508c2c66affSColin Finck     if (NameBuffer)
2509c2c66affSColin Finck         RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer);
2510c2c66affSColin Finck     if (ClassBuffer)
2511c2c66affSColin Finck         RtlFreeHeap(RtlGetProcessHeap(), 0, ClassBuffer);
2512c2c66affSColin Finck 
2513c2c66affSColin Finck     return ErrorCode;
2514c2c66affSColin Finck }
2515c2c66affSColin Finck 
2516c2c66affSColin Finck 
2517c2c66affSColin Finck /************************************************************************
2518c2c66affSColin Finck  *  RegEnumKeyExW
2519c2c66affSColin Finck  *
2520c2c66affSColin Finck  * @implemented
2521c2c66affSColin Finck  */
2522c2c66affSColin Finck LONG
2523c2c66affSColin Finck WINAPI
2524c2c66affSColin Finck RegEnumKeyExW(
2525c2c66affSColin Finck     _In_ HKEY hKey,
2526c2c66affSColin Finck     _In_ DWORD dwIndex,
2527c2c66affSColin Finck     _Out_ LPWSTR lpName,
2528c2c66affSColin Finck     _Inout_ LPDWORD lpcbName,
2529c2c66affSColin Finck     _Reserved_ LPDWORD lpReserved,
2530c2c66affSColin Finck     _Out_opt_ LPWSTR lpClass,
2531c2c66affSColin Finck     _Inout_opt_ LPDWORD lpcbClass,
2532c2c66affSColin Finck     _Out_opt_ PFILETIME lpftLastWriteTime)
2533c2c66affSColin Finck {
2534c2c66affSColin Finck     union
2535c2c66affSColin Finck     {
2536c2c66affSColin Finck         KEY_NODE_INFORMATION Node;
2537c2c66affSColin Finck         KEY_BASIC_INFORMATION Basic;
2538c2c66affSColin Finck     } *KeyInfo;
2539c2c66affSColin Finck 
2540c2c66affSColin Finck     ULONG BufferSize;
2541c2c66affSColin Finck     ULONG ResultSize;
2542c2c66affSColin Finck     ULONG NameLength;
2543c2c66affSColin Finck     ULONG ClassLength = 0;
2544c2c66affSColin Finck     HANDLE KeyHandle;
2545c2c66affSColin Finck     LONG ErrorCode = ERROR_SUCCESS;
2546c2c66affSColin Finck     NTSTATUS Status;
2547c2c66affSColin Finck 
2548c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
2549c2c66affSColin Finck                            hKey);
2550c2c66affSColin Finck     if (!NT_SUCCESS(Status))
2551c2c66affSColin Finck     {
2552c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
2553c2c66affSColin Finck     }
2554c2c66affSColin Finck 
2555c2c66affSColin Finck     if (IsHKCRKey(KeyHandle))
2556c2c66affSColin Finck     {
2557c2c66affSColin Finck         ErrorCode = EnumHKCRKey(
2558c2c66affSColin Finck             KeyHandle,
2559c2c66affSColin Finck             dwIndex,
2560c2c66affSColin Finck             lpName,
2561c2c66affSColin Finck             lpcbName,
2562c2c66affSColin Finck             lpReserved,
2563c2c66affSColin Finck             lpClass,
2564c2c66affSColin Finck             lpcbClass,
2565c2c66affSColin Finck             lpftLastWriteTime);
2566c2c66affSColin Finck         ClosePredefKey(KeyHandle);
2567c2c66affSColin Finck         return ErrorCode;
2568c2c66affSColin Finck     }
2569c2c66affSColin Finck 
2570c2c66affSColin Finck     if (*lpcbName > 0)
2571c2c66affSColin Finck     {
2572c2c66affSColin Finck         NameLength = min (*lpcbName - 1, REG_MAX_NAME_SIZE) * sizeof (WCHAR);
2573c2c66affSColin Finck     }
2574c2c66affSColin Finck     else
2575c2c66affSColin Finck     {
2576c2c66affSColin Finck         NameLength = 0;
2577c2c66affSColin Finck     }
2578c2c66affSColin Finck 
2579c2c66affSColin Finck     if (lpClass)
2580c2c66affSColin Finck     {
2581c2c66affSColin Finck         if (*lpcbClass > 0)
2582c2c66affSColin Finck         {
2583c2c66affSColin Finck             ClassLength = min (*lpcbClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
2584c2c66affSColin Finck         }
2585c2c66affSColin Finck         else
2586c2c66affSColin Finck         {
2587c2c66affSColin Finck             ClassLength = 0;
2588c2c66affSColin Finck         }
2589c2c66affSColin Finck 
2590c2c66affSColin Finck         BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength + 3) & ~3) + ClassLength;
2591c2c66affSColin Finck     }
2592c2c66affSColin Finck     else
2593c2c66affSColin Finck     {
2594c2c66affSColin Finck         BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength;
2595c2c66affSColin Finck     }
2596c2c66affSColin Finck 
2597c2c66affSColin Finck     KeyInfo = RtlAllocateHeap(ProcessHeap,
2598c2c66affSColin Finck                               0,
2599c2c66affSColin Finck                               BufferSize);
2600c2c66affSColin Finck     if (KeyInfo == NULL)
2601c2c66affSColin Finck     {
2602c2c66affSColin Finck         ErrorCode = ERROR_OUTOFMEMORY;
2603c2c66affSColin Finck         goto Cleanup;
2604c2c66affSColin Finck     }
2605c2c66affSColin Finck 
2606c2c66affSColin Finck     Status = NtEnumerateKey(KeyHandle,
2607c2c66affSColin Finck                             (ULONG)dwIndex,
2608c2c66affSColin Finck                             lpClass ? KeyNodeInformation : KeyBasicInformation,
2609c2c66affSColin Finck                             KeyInfo,
2610c2c66affSColin Finck                             BufferSize,
2611c2c66affSColin Finck                             &ResultSize);
2612c2c66affSColin Finck     TRACE("NtEnumerateKey() returned status 0x%X\n", Status);
2613c2c66affSColin Finck     if (!NT_SUCCESS(Status))
2614c2c66affSColin Finck     {
2615c2c66affSColin Finck         ErrorCode = RtlNtStatusToDosError (Status);
2616c2c66affSColin Finck     }
2617c2c66affSColin Finck     else
2618c2c66affSColin Finck     {
2619c2c66affSColin Finck         if (lpClass == NULL)
2620c2c66affSColin Finck         {
2621c2c66affSColin Finck             if (KeyInfo->Basic.NameLength > NameLength)
2622c2c66affSColin Finck             {
2623c2c66affSColin Finck                 ErrorCode = ERROR_MORE_DATA;
2624c2c66affSColin Finck             }
2625c2c66affSColin Finck             else
2626c2c66affSColin Finck             {
2627c2c66affSColin Finck                 RtlCopyMemory(lpName,
2628c2c66affSColin Finck                               KeyInfo->Basic.Name,
2629c2c66affSColin Finck                               KeyInfo->Basic.NameLength);
2630c2c66affSColin Finck                 *lpcbName = (DWORD)(KeyInfo->Basic.NameLength / sizeof(WCHAR));
2631c2c66affSColin Finck                 lpName[*lpcbName] = 0;
2632c2c66affSColin Finck             }
2633c2c66affSColin Finck         }
2634c2c66affSColin Finck         else
2635c2c66affSColin Finck         {
2636c2c66affSColin Finck             if (KeyInfo->Node.NameLength > NameLength ||
2637c2c66affSColin Finck                 KeyInfo->Node.ClassLength > ClassLength)
2638c2c66affSColin Finck             {
2639c2c66affSColin Finck                 ErrorCode = ERROR_MORE_DATA;
2640c2c66affSColin Finck             }
2641c2c66affSColin Finck             else
2642c2c66affSColin Finck             {
2643c2c66affSColin Finck                 RtlCopyMemory(lpName,
2644c2c66affSColin Finck                               KeyInfo->Node.Name,
2645c2c66affSColin Finck                               KeyInfo->Node.NameLength);
2646c2c66affSColin Finck                 *lpcbName = KeyInfo->Node.NameLength / sizeof(WCHAR);
2647c2c66affSColin Finck                 lpName[*lpcbName] = 0;
2648c2c66affSColin Finck                 RtlCopyMemory(lpClass,
2649c2c66affSColin Finck                               (PVOID)((ULONG_PTR)KeyInfo->Node.Name + KeyInfo->Node.ClassOffset),
2650c2c66affSColin Finck                               KeyInfo->Node.ClassLength);
2651c2c66affSColin Finck                 *lpcbClass = (DWORD)(KeyInfo->Node.ClassLength / sizeof(WCHAR));
2652c2c66affSColin Finck                 lpClass[*lpcbClass] = 0;
2653c2c66affSColin Finck             }
2654c2c66affSColin Finck         }
2655c2c66affSColin Finck 
2656c2c66affSColin Finck         if (ErrorCode == ERROR_SUCCESS && lpftLastWriteTime != NULL)
2657c2c66affSColin Finck         {
2658c2c66affSColin Finck             if (lpClass == NULL)
2659c2c66affSColin Finck             {
2660c2c66affSColin Finck                 lpftLastWriteTime->dwLowDateTime = KeyInfo->Basic.LastWriteTime.u.LowPart;
2661c2c66affSColin Finck                 lpftLastWriteTime->dwHighDateTime = KeyInfo->Basic.LastWriteTime.u.HighPart;
2662c2c66affSColin Finck             }
2663c2c66affSColin Finck             else
2664c2c66affSColin Finck             {
2665c2c66affSColin Finck                 lpftLastWriteTime->dwLowDateTime = KeyInfo->Node.LastWriteTime.u.LowPart;
2666c2c66affSColin Finck                 lpftLastWriteTime->dwHighDateTime = KeyInfo->Node.LastWriteTime.u.HighPart;
2667c2c66affSColin Finck             }
2668c2c66affSColin Finck         }
2669c2c66affSColin Finck     }
2670c2c66affSColin Finck 
2671c2c66affSColin Finck     RtlFreeHeap(ProcessHeap,
2672c2c66affSColin Finck                 0,
2673c2c66affSColin Finck                 KeyInfo);
2674c2c66affSColin Finck 
2675c2c66affSColin Finck Cleanup:
2676c2c66affSColin Finck     ClosePredefKey(KeyHandle);
2677c2c66affSColin Finck 
2678c2c66affSColin Finck     return ErrorCode;
2679c2c66affSColin Finck }
2680c2c66affSColin Finck 
2681c2c66affSColin Finck 
2682c2c66affSColin Finck /************************************************************************
2683c2c66affSColin Finck  *  RegEnumValueA
2684c2c66affSColin Finck  *
2685c2c66affSColin Finck  * @implemented
2686c2c66affSColin Finck  */
2687c2c66affSColin Finck LONG WINAPI
2688c2c66affSColin Finck RegEnumValueA(
2689c2c66affSColin Finck     _In_ HKEY hKey,
2690c2c66affSColin Finck     _In_ DWORD dwIndex,
2691c2c66affSColin Finck     _Out_ LPSTR lpName,
2692c2c66affSColin Finck     _Inout_ LPDWORD lpcbName,
2693c2c66affSColin Finck     _Reserved_ LPDWORD lpdwReserved,
2694c2c66affSColin Finck     _Out_opt_ LPDWORD lpdwType,
2695c2c66affSColin Finck     _Out_opt_ LPBYTE lpData,
2696c2c66affSColin Finck     _Inout_opt_ LPDWORD lpcbData)
2697c2c66affSColin Finck {
2698c2c66affSColin Finck     WCHAR* NameBuffer;
2699c2c66affSColin Finck     DWORD NameBufferSize, NameLength;
2700c2c66affSColin Finck     LONG ErrorCode;
2701c2c66affSColin Finck     DWORD LocalType = REG_NONE;
2702c2c66affSColin Finck     BOOL NameOverflow = FALSE;
2703c2c66affSColin Finck 
2704c2c66affSColin Finck     /* Do parameter checks now, once and for all. */
2705c2c66affSColin Finck     if (!lpName || !lpcbName)
2706c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
2707c2c66affSColin Finck 
2708c2c66affSColin Finck     if ((lpData && !lpcbData) || lpdwReserved)
2709c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
2710c2c66affSColin Finck 
2711c2c66affSColin Finck     /* Get the size of the buffer we must use for the first call to RegEnumValueW */
2712c2c66affSColin Finck     ErrorCode = RegQueryInfoKeyW(
2713c2c66affSColin Finck         hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &NameBufferSize, NULL, NULL, NULL);
2714c2c66affSColin Finck     if (ErrorCode != ERROR_SUCCESS)
2715c2c66affSColin Finck         return ErrorCode;
2716c2c66affSColin Finck 
2717c2c66affSColin Finck     /* Add space for the null terminator */
2718c2c66affSColin Finck     NameBufferSize++;
2719c2c66affSColin Finck 
2720c2c66affSColin Finck     /* Allocate the buffer for the unicode name */
2721c2c66affSColin Finck     NameBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, NameBufferSize * sizeof(WCHAR));
2722c2c66affSColin Finck     if (NameBuffer == NULL)
2723c2c66affSColin Finck     {
2724c2c66affSColin Finck         return ERROR_NOT_ENOUGH_MEMORY;
2725c2c66affSColin Finck     }
2726c2c66affSColin Finck 
2727c2c66affSColin Finck     /*
2728c2c66affSColin Finck      * This code calls RegEnumValueW twice, because we need to know the type of the enumerated value.
2729c2c66affSColin Finck      * So for the first call, we check if we overflow on the name, as we have no way of knowing if this
2730c2c66affSColin Finck      * is an overflow on the data or on the name during the the second call. So the first time, we make the
2731c2c66affSColin Finck      * call with the supplied value. This is merdique, but this is how it is.
2732c2c66affSColin Finck      */
2733c2c66affSColin Finck     NameLength = *lpcbName;
2734c2c66affSColin Finck     ErrorCode = RegEnumValueW(
2735c2c66affSColin Finck         hKey,
2736c2c66affSColin Finck         dwIndex,
2737c2c66affSColin Finck         NameBuffer,
2738c2c66affSColin Finck         &NameLength,
2739c2c66affSColin Finck         NULL,
2740c2c66affSColin Finck         &LocalType,
2741c2c66affSColin Finck         NULL,
2742c2c66affSColin Finck         NULL);
2743c2c66affSColin Finck     if (ErrorCode != ERROR_SUCCESS)
2744c2c66affSColin Finck     {
2745c2c66affSColin Finck         if (ErrorCode == ERROR_MORE_DATA)
2746c2c66affSColin Finck             NameOverflow = TRUE;
2747c2c66affSColin Finck         else
2748c2c66affSColin Finck             goto Exit;
2749c2c66affSColin Finck     }
2750c2c66affSColin Finck 
2751c2c66affSColin Finck     if (is_string(LocalType) && lpcbData)
2752c2c66affSColin Finck     {
2753c2c66affSColin Finck         /* We must allocate a buffer to get the unicode data */
2754c2c66affSColin Finck         DWORD DataBufferSize = *lpcbData * sizeof(WCHAR);
2755c2c66affSColin Finck         WCHAR* DataBuffer = NULL;
2756c2c66affSColin Finck         DWORD DataLength = *lpcbData;
2757c2c66affSColin Finck         LPSTR DataStr = (LPSTR)lpData;
2758c2c66affSColin Finck 
2759c2c66affSColin Finck         if (lpData)
2760c2c66affSColin Finck             DataBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *lpcbData * sizeof(WCHAR));
2761c2c66affSColin Finck 
2762c2c66affSColin Finck         /* Do the real call */
2763c2c66affSColin Finck         ErrorCode = RegEnumValueW(
2764c2c66affSColin Finck             hKey,
2765c2c66affSColin Finck             dwIndex,
2766c2c66affSColin Finck             NameBuffer,
2767c2c66affSColin Finck             &NameBufferSize,
2768c2c66affSColin Finck             lpdwReserved,
2769c2c66affSColin Finck             lpdwType,
2770c2c66affSColin Finck             (LPBYTE)DataBuffer,
2771c2c66affSColin Finck             &DataBufferSize);
2772c2c66affSColin Finck 
2773c2c66affSColin Finck         *lpcbData = DataBufferSize / sizeof(WCHAR);
2774c2c66affSColin Finck 
2775c2c66affSColin Finck         if (ErrorCode != ERROR_SUCCESS)
2776c2c66affSColin Finck         {
2777c2c66affSColin Finck             RtlFreeHeap(RtlGetProcessHeap(), 0, DataBuffer);
2778c2c66affSColin Finck             goto Exit;
2779c2c66affSColin Finck         }
2780c2c66affSColin Finck 
2781c2c66affSColin Finck         /* Copy the data whatever the error code is */
2782c2c66affSColin Finck         if (lpData)
2783c2c66affSColin Finck         {
2784c2c66affSColin Finck             /* Do the data conversion */
2785c2c66affSColin Finck             RtlUnicodeToMultiByteN(DataStr, DataLength, 0, DataBuffer, DataBufferSize);
2786c2c66affSColin Finck             /* NULL-terminate if there is enough room */
2787c2c66affSColin Finck             if ((DataLength > *lpcbData) && (DataStr[*lpcbData - 1] != '\0'))
2788c2c66affSColin Finck                 DataStr[*lpcbData] = '\0';
2789c2c66affSColin Finck         }
2790c2c66affSColin Finck 
2791c2c66affSColin Finck         RtlFreeHeap(RtlGetProcessHeap(), 0, DataBuffer);
2792c2c66affSColin Finck     }
2793c2c66affSColin Finck     else
2794c2c66affSColin Finck     {
2795c2c66affSColin Finck         /* No data conversion needed. Do the call with provided buffers */
2796c2c66affSColin Finck         ErrorCode = RegEnumValueW(
2797c2c66affSColin Finck             hKey,
2798c2c66affSColin Finck             dwIndex,
2799c2c66affSColin Finck             NameBuffer,
2800c2c66affSColin Finck             &NameBufferSize,
2801c2c66affSColin Finck             lpdwReserved,
2802c2c66affSColin Finck             lpdwType,
2803c2c66affSColin Finck             lpData,
2804c2c66affSColin Finck             lpcbData);
2805c2c66affSColin Finck 
2806c2c66affSColin Finck         if (ErrorCode != ERROR_SUCCESS)
2807c2c66affSColin Finck         {
2808c2c66affSColin Finck             goto Exit;
2809c2c66affSColin Finck         }
2810c2c66affSColin Finck     }
2811c2c66affSColin Finck 
2812c2c66affSColin Finck     if (NameOverflow)
2813c2c66affSColin Finck     {
2814c2c66affSColin Finck         ErrorCode = ERROR_MORE_DATA;
2815c2c66affSColin Finck         goto Exit;
2816c2c66affSColin Finck     }
2817c2c66affSColin Finck 
2818c2c66affSColin Finck     /* Convert the name string */
2819c2c66affSColin Finck     RtlUnicodeToMultiByteN(lpName, *lpcbName, lpcbName, NameBuffer, NameBufferSize * sizeof(WCHAR));
282046259092SSerge Gautherie     lpName[*lpcbName] = ANSI_NULL;
2821c2c66affSColin Finck 
2822c2c66affSColin Finck Exit:
2823c2c66affSColin Finck     if (NameBuffer)
2824c2c66affSColin Finck         RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer);
2825c2c66affSColin Finck 
2826c2c66affSColin Finck     return ErrorCode;
2827c2c66affSColin Finck }
2828c2c66affSColin Finck 
2829c2c66affSColin Finck 
2830c2c66affSColin Finck /******************************************************************************
2831c2c66affSColin Finck  * RegEnumValueW   [ADVAPI32.@]
2832c2c66affSColin Finck  * @implemented
2833c2c66affSColin Finck  *
2834c2c66affSColin Finck  * PARAMS
2835c2c66affSColin Finck  *  hkey       [I] Handle to key to query
2836c2c66affSColin Finck  *  index      [I] Index of value to query
2837c2c66affSColin Finck  *  value      [O] Value string
2838c2c66affSColin Finck  *  val_count  [I/O] Size of value buffer (in wchars)
2839c2c66affSColin Finck  *  reserved   [I] Reserved
2840c2c66affSColin Finck  *  type       [O] Type code
2841c2c66affSColin Finck  *  data       [O] Value data
2842c2c66affSColin Finck  *  count      [I/O] Size of data buffer (in bytes)
2843c2c66affSColin Finck  *
2844c2c66affSColin Finck  * RETURNS
2845c2c66affSColin Finck  *  Success: ERROR_SUCCESS
2846c2c66affSColin Finck  *  Failure: nonzero error code from Winerror.h
2847c2c66affSColin Finck  */
2848c2c66affSColin Finck LONG
2849c2c66affSColin Finck WINAPI
2850c2c66affSColin Finck RegEnumValueW(
2851c2c66affSColin Finck     _In_ HKEY hKey,
2852c2c66affSColin Finck     _In_ DWORD index,
2853c2c66affSColin Finck     _Out_ LPWSTR value,
2854c2c66affSColin Finck     _Inout_ PDWORD val_count,
2855c2c66affSColin Finck     _Reserved_ PDWORD reserved,
2856c2c66affSColin Finck     _Out_opt_ PDWORD type,
2857c2c66affSColin Finck     _Out_opt_ LPBYTE data,
2858c2c66affSColin Finck     _Inout_opt_ PDWORD count)
2859c2c66affSColin Finck {
2860c2c66affSColin Finck     HANDLE KeyHandle;
2861c2c66affSColin Finck     NTSTATUS status;
2862c2c66affSColin Finck     ULONG total_size;
2863c2c66affSColin Finck     char buffer[256], *buf_ptr = buffer;
2864c2c66affSColin Finck     KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
2865c2c66affSColin Finck     static const int info_size = FIELD_OFFSET( KEY_VALUE_FULL_INFORMATION, Name );
2866c2c66affSColin Finck 
2867c2c66affSColin Finck     TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
2868c2c66affSColin Finck           hKey, index, value, val_count, reserved, type, data, count );
2869c2c66affSColin Finck 
2870c2c66affSColin Finck     if (!value || !val_count)
2871c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
2872c2c66affSColin Finck 
2873c2c66affSColin Finck     if ((data && !count) || reserved)
2874c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
2875c2c66affSColin Finck 
2876c2c66affSColin Finck     status = MapDefaultKey(&KeyHandle, hKey);
2877c2c66affSColin Finck     if (!NT_SUCCESS(status))
2878c2c66affSColin Finck     {
2879c2c66affSColin Finck         return RtlNtStatusToDosError(status);
2880c2c66affSColin Finck     }
2881c2c66affSColin Finck 
2882c2c66affSColin Finck     if (IsHKCRKey(KeyHandle))
2883c2c66affSColin Finck     {
2884c2c66affSColin Finck         LONG ErrorCode = EnumHKCRValue(
2885c2c66affSColin Finck             KeyHandle,
2886c2c66affSColin Finck             index,
2887c2c66affSColin Finck             value,
2888c2c66affSColin Finck             val_count,
2889c2c66affSColin Finck             reserved,
2890c2c66affSColin Finck             type,
2891c2c66affSColin Finck             data,
2892c2c66affSColin Finck             count);
2893c2c66affSColin Finck         ClosePredefKey(KeyHandle);
2894c2c66affSColin Finck         return ErrorCode;
2895c2c66affSColin Finck     }
2896c2c66affSColin Finck 
2897c2c66affSColin Finck     total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
2898c2c66affSColin Finck     if (data) total_size += *count;
2899c2c66affSColin Finck     total_size = min( sizeof(buffer), total_size );
2900c2c66affSColin Finck 
2901c2c66affSColin Finck     status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
2902c2c66affSColin Finck                                   buffer, total_size, &total_size );
2903c2c66affSColin Finck     if (status && (status != STATUS_BUFFER_OVERFLOW) && (status != STATUS_BUFFER_TOO_SMALL)) goto done;
2904c2c66affSColin Finck 
2905c2c66affSColin Finck     if (value || data)
2906c2c66affSColin Finck     {
2907c2c66affSColin Finck         /* retry with a dynamically allocated buffer */
2908c2c66affSColin Finck         while ((status == STATUS_BUFFER_OVERFLOW) || (status == STATUS_BUFFER_TOO_SMALL))
2909c2c66affSColin Finck         {
2910c2c66affSColin Finck             if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
2911c2c66affSColin Finck             if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
2912c2c66affSColin Finck             {
2913c2c66affSColin Finck                 status = ERROR_NOT_ENOUGH_MEMORY;
2914c2c66affSColin Finck                 goto done;
2915c2c66affSColin Finck             }
2916c2c66affSColin Finck             info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
2917c2c66affSColin Finck             status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
2918c2c66affSColin Finck                                           buf_ptr, total_size, &total_size );
2919c2c66affSColin Finck         }
2920c2c66affSColin Finck 
2921c2c66affSColin Finck         if (status) goto done;
2922c2c66affSColin Finck 
2923c2c66affSColin Finck         if (value)
2924c2c66affSColin Finck         {
2925c2c66affSColin Finck             if (info->NameLength/sizeof(WCHAR) >= *val_count)
2926c2c66affSColin Finck             {
2927c2c66affSColin Finck                 status = STATUS_BUFFER_OVERFLOW;
2928c2c66affSColin Finck                 goto overflow;
2929c2c66affSColin Finck             }
2930c2c66affSColin Finck             memcpy( value, info->Name, info->NameLength );
2931c2c66affSColin Finck             *val_count = info->NameLength / sizeof(WCHAR);
2932c2c66affSColin Finck             value[*val_count] = 0;
2933c2c66affSColin Finck         }
2934c2c66affSColin Finck 
2935c2c66affSColin Finck         if (data)
2936c2c66affSColin Finck         {
2937c2c66affSColin Finck             if (info->DataLength > *count)
2938c2c66affSColin Finck             {
2939c2c66affSColin Finck                 status = STATUS_BUFFER_OVERFLOW;
2940c2c66affSColin Finck                 goto overflow;
2941c2c66affSColin Finck             }
2942c2c66affSColin Finck             memcpy( data, buf_ptr + info->DataOffset, info->DataLength );
2943c2c66affSColin Finck             if (is_string(info->Type) && info->DataLength <= *count - sizeof(WCHAR))
2944c2c66affSColin Finck             {
2945c2c66affSColin Finck                 /* if the type is REG_SZ and data is not 0-terminated
2946c2c66affSColin Finck                  * and there is enough space in the buffer NT appends a \0 */
2947c2c66affSColin Finck                 WCHAR *ptr = (WCHAR *)(data + info->DataLength);
2948c2c66affSColin Finck                 if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
2949c2c66affSColin Finck             }
2950c2c66affSColin Finck         }
2951c2c66affSColin Finck     }
2952c2c66affSColin Finck     else status = STATUS_SUCCESS;
2953c2c66affSColin Finck 
2954c2c66affSColin Finck  overflow:
2955c2c66affSColin Finck     if (type) *type = info->Type;
2956c2c66affSColin Finck     if (count) *count = info->DataLength;
2957c2c66affSColin Finck 
2958c2c66affSColin Finck  done:
2959c2c66affSColin Finck     if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
2960c2c66affSColin Finck     ClosePredefKey(KeyHandle);
2961c2c66affSColin Finck     return RtlNtStatusToDosError(status);
2962c2c66affSColin Finck }
2963c2c66affSColin Finck 
2964c2c66affSColin Finck 
2965c2c66affSColin Finck /************************************************************************
2966c2c66affSColin Finck  *  RegFlushKey
2967c2c66affSColin Finck  *
2968c2c66affSColin Finck  * @implemented
2969c2c66affSColin Finck  */
2970c2c66affSColin Finck LONG WINAPI
2971c2c66affSColin Finck RegFlushKey(HKEY hKey)
2972c2c66affSColin Finck {
2973c2c66affSColin Finck     HANDLE KeyHandle;
2974c2c66affSColin Finck     NTSTATUS Status;
2975c2c66affSColin Finck 
2976c2c66affSColin Finck     if (hKey == HKEY_PERFORMANCE_DATA)
2977c2c66affSColin Finck     {
2978c2c66affSColin Finck         return ERROR_SUCCESS;
2979c2c66affSColin Finck     }
2980c2c66affSColin Finck 
2981c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
2982c2c66affSColin Finck                            hKey);
2983c2c66affSColin Finck     if (!NT_SUCCESS(Status))
2984c2c66affSColin Finck     {
2985c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
2986c2c66affSColin Finck     }
2987c2c66affSColin Finck 
2988c2c66affSColin Finck     Status = NtFlushKey(KeyHandle);
2989c2c66affSColin Finck 
2990c2c66affSColin Finck     ClosePredefKey(KeyHandle);
2991c2c66affSColin Finck 
2992c2c66affSColin Finck     if (!NT_SUCCESS(Status))
2993c2c66affSColin Finck     {
2994c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
2995c2c66affSColin Finck     }
2996c2c66affSColin Finck 
2997c2c66affSColin Finck     return ERROR_SUCCESS;
2998c2c66affSColin Finck }
2999c2c66affSColin Finck 
3000c2c66affSColin Finck 
3001c2c66affSColin Finck /************************************************************************
3002c2c66affSColin Finck  *  RegGetKeySecurity
3003c2c66affSColin Finck  *
3004c2c66affSColin Finck  * @implemented
3005c2c66affSColin Finck  */
3006c2c66affSColin Finck LONG WINAPI
3007c2c66affSColin Finck RegGetKeySecurity(HKEY hKey,
3008c2c66affSColin Finck                   SECURITY_INFORMATION SecurityInformation,
3009c2c66affSColin Finck                   PSECURITY_DESCRIPTOR pSecurityDescriptor,
3010c2c66affSColin Finck                   LPDWORD lpcbSecurityDescriptor)
3011c2c66affSColin Finck {
3012c2c66affSColin Finck     HANDLE KeyHandle;
3013c2c66affSColin Finck     NTSTATUS Status;
3014c2c66affSColin Finck 
3015c2c66affSColin Finck     if (hKey == HKEY_PERFORMANCE_DATA)
3016c2c66affSColin Finck     {
3017c2c66affSColin Finck         return ERROR_INVALID_HANDLE;
3018c2c66affSColin Finck     }
3019c2c66affSColin Finck 
3020c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
3021c2c66affSColin Finck                            hKey);
3022c2c66affSColin Finck     if (!NT_SUCCESS(Status))
3023c2c66affSColin Finck     {
3024c2c66affSColin Finck         TRACE("MapDefaultKey() failed (Status %lx)\n", Status);
3025c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
3026c2c66affSColin Finck     }
3027c2c66affSColin Finck 
3028c2c66affSColin Finck     Status = NtQuerySecurityObject(KeyHandle,
3029c2c66affSColin Finck                                    SecurityInformation,
3030c2c66affSColin Finck                                    pSecurityDescriptor,
3031c2c66affSColin Finck                                    *lpcbSecurityDescriptor,
3032c2c66affSColin Finck                                    lpcbSecurityDescriptor);
3033c2c66affSColin Finck 
3034c2c66affSColin Finck     ClosePredefKey(KeyHandle);
3035c2c66affSColin Finck 
3036c2c66affSColin Finck     if (!NT_SUCCESS(Status))
3037c2c66affSColin Finck     {
3038c2c66affSColin Finck          WARN("NtQuerySecurityObject() failed (Status %lx)\n", Status);
3039c2c66affSColin Finck          return RtlNtStatusToDosError(Status);
3040c2c66affSColin Finck     }
3041c2c66affSColin Finck 
3042c2c66affSColin Finck     return ERROR_SUCCESS;
3043c2c66affSColin Finck }
3044c2c66affSColin Finck 
3045c2c66affSColin Finck 
3046c2c66affSColin Finck /************************************************************************
3047c2c66affSColin Finck  *  RegLoadKeyA
3048c2c66affSColin Finck  *
3049c2c66affSColin Finck  * @implemented
3050c2c66affSColin Finck  */
3051c2c66affSColin Finck LONG WINAPI
3052c2c66affSColin Finck RegLoadKeyA(HKEY hKey,
3053c2c66affSColin Finck             LPCSTR lpSubKey,
3054c2c66affSColin Finck             LPCSTR lpFile)
3055c2c66affSColin Finck {
3056c2c66affSColin Finck     UNICODE_STRING FileName;
3057c2c66affSColin Finck     UNICODE_STRING KeyName;
3058c2c66affSColin Finck     LONG ErrorCode;
3059c2c66affSColin Finck 
3060c2c66affSColin Finck     RtlInitEmptyUnicodeString(&KeyName, NULL, 0);
3061c2c66affSColin Finck     RtlInitEmptyUnicodeString(&FileName, NULL, 0);
3062c2c66affSColin Finck 
3063c2c66affSColin Finck     if (lpSubKey)
3064c2c66affSColin Finck     {
3065c2c66affSColin Finck         if (!RtlCreateUnicodeStringFromAsciiz(&KeyName, lpSubKey))
3066c2c66affSColin Finck         {
3067c2c66affSColin Finck             ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
3068c2c66affSColin Finck             goto Exit;
3069c2c66affSColin Finck         }
3070c2c66affSColin Finck     }
3071c2c66affSColin Finck 
3072c2c66affSColin Finck     if (lpFile)
3073c2c66affSColin Finck     {
3074c2c66affSColin Finck         if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFile))
3075c2c66affSColin Finck         {
3076c2c66affSColin Finck             ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
3077c2c66affSColin Finck             goto Exit;
3078c2c66affSColin Finck         }
3079c2c66affSColin Finck     }
3080c2c66affSColin Finck 
3081c2c66affSColin Finck     ErrorCode = RegLoadKeyW(hKey,
3082c2c66affSColin Finck                             KeyName.Buffer,
3083c2c66affSColin Finck                             FileName.Buffer);
3084c2c66affSColin Finck 
3085c2c66affSColin Finck Exit:
3086c2c66affSColin Finck     RtlFreeUnicodeString(&FileName);
3087c2c66affSColin Finck     RtlFreeUnicodeString(&KeyName);
3088c2c66affSColin Finck 
3089c2c66affSColin Finck     return ErrorCode;
3090c2c66affSColin Finck }
3091c2c66affSColin Finck 
3092c2c66affSColin Finck 
3093c2c66affSColin Finck /************************************************************************
3094c2c66affSColin Finck  *  RegLoadKeyW
3095c2c66affSColin Finck  *
3096c2c66affSColin Finck  * @implemented
3097c2c66affSColin Finck  */
3098c2c66affSColin Finck LONG WINAPI
3099c2c66affSColin Finck RegLoadKeyW(HKEY hKey,
3100c2c66affSColin Finck             LPCWSTR lpSubKey,
3101c2c66affSColin Finck             LPCWSTR lpFile)
3102c2c66affSColin Finck {
3103c2c66affSColin Finck     OBJECT_ATTRIBUTES FileObjectAttributes;
3104c2c66affSColin Finck     OBJECT_ATTRIBUTES KeyObjectAttributes;
3105c2c66affSColin Finck     UNICODE_STRING FileName;
3106c2c66affSColin Finck     UNICODE_STRING KeyName;
3107c2c66affSColin Finck     HANDLE KeyHandle;
3108c2c66affSColin Finck     NTSTATUS Status;
3109c2c66affSColin Finck     LONG ErrorCode = ERROR_SUCCESS;
3110c2c66affSColin Finck 
3111c2c66affSColin Finck     if (hKey == HKEY_PERFORMANCE_DATA)
3112c2c66affSColin Finck     {
3113c2c66affSColin Finck         return ERROR_INVALID_HANDLE;
3114c2c66affSColin Finck     }
3115c2c66affSColin Finck 
3116c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
3117c2c66affSColin Finck                            hKey);
3118c2c66affSColin Finck     if (!NT_SUCCESS(Status))
3119c2c66affSColin Finck     {
3120c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
3121c2c66affSColin Finck     }
3122c2c66affSColin Finck 
3123c2c66affSColin Finck     if (!RtlDosPathNameToNtPathName_U(lpFile,
3124c2c66affSColin Finck                                       &FileName,
3125c2c66affSColin Finck                                       NULL,
3126c2c66affSColin Finck                                       NULL))
3127c2c66affSColin Finck     {
3128c2c66affSColin Finck       ErrorCode = ERROR_BAD_PATHNAME;
3129c2c66affSColin Finck       goto Cleanup;
3130c2c66affSColin Finck     }
3131c2c66affSColin Finck 
3132c2c66affSColin Finck     InitializeObjectAttributes(&FileObjectAttributes,
3133c2c66affSColin Finck                                &FileName,
3134c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
3135c2c66affSColin Finck                                NULL,
3136c2c66affSColin Finck                                NULL);
3137c2c66affSColin Finck 
313846259092SSerge Gautherie     RtlInitUnicodeString(&KeyName, lpSubKey);
3139c2c66affSColin Finck 
3140c2c66affSColin Finck     InitializeObjectAttributes(&KeyObjectAttributes,
3141c2c66affSColin Finck                                &KeyName,
3142c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
3143c2c66affSColin Finck                                KeyHandle,
3144c2c66affSColin Finck                                NULL);
3145c2c66affSColin Finck 
3146c2c66affSColin Finck     Status = NtLoadKey(&KeyObjectAttributes,
3147c2c66affSColin Finck                        &FileObjectAttributes);
3148c2c66affSColin Finck 
3149c2c66affSColin Finck     RtlFreeHeap(RtlGetProcessHeap(),
3150c2c66affSColin Finck                 0,
3151c2c66affSColin Finck                 FileName.Buffer);
3152c2c66affSColin Finck 
3153c2c66affSColin Finck     if (!NT_SUCCESS(Status))
3154c2c66affSColin Finck     {
3155c2c66affSColin Finck         ErrorCode = RtlNtStatusToDosError(Status);
3156c2c66affSColin Finck         goto Cleanup;
3157c2c66affSColin Finck     }
3158c2c66affSColin Finck 
3159c2c66affSColin Finck Cleanup:
3160c2c66affSColin Finck     ClosePredefKey(KeyHandle);
3161c2c66affSColin Finck 
3162c2c66affSColin Finck     return ErrorCode;
3163c2c66affSColin Finck }
3164c2c66affSColin Finck 
3165c2c66affSColin Finck 
3166c2c66affSColin Finck /************************************************************************
3167c2c66affSColin Finck  *  RegNotifyChangeKeyValue
3168c2c66affSColin Finck  *
3169c2c66affSColin Finck  * @unimplemented
3170c2c66affSColin Finck  */
3171c2c66affSColin Finck LONG WINAPI
3172c2c66affSColin Finck RegNotifyChangeKeyValue(HKEY hKey,
3173c2c66affSColin Finck                         BOOL bWatchSubtree,
3174c2c66affSColin Finck                         DWORD dwNotifyFilter,
3175c2c66affSColin Finck                         HANDLE hEvent,
3176c2c66affSColin Finck                         BOOL fAsynchronous)
3177c2c66affSColin Finck {
3178c2c66affSColin Finck     IO_STATUS_BLOCK IoStatusBlock;
3179c2c66affSColin Finck     HANDLE KeyHandle;
3180c2c66affSColin Finck     NTSTATUS Status;
3181c2c66affSColin Finck     LONG ErrorCode = ERROR_SUCCESS;
3182c2c66affSColin Finck 
3183c2c66affSColin Finck     if (hKey == HKEY_PERFORMANCE_DATA)
3184c2c66affSColin Finck     {
3185c2c66affSColin Finck         return ERROR_INVALID_HANDLE;
3186c2c66affSColin Finck     }
3187c2c66affSColin Finck 
3188c2c66affSColin Finck     if ((fAsynchronous != FALSE) && (hEvent == NULL))
3189c2c66affSColin Finck     {
3190c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
3191c2c66affSColin Finck     }
3192c2c66affSColin Finck 
3193c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
3194c2c66affSColin Finck                            hKey);
3195c2c66affSColin Finck     if (!NT_SUCCESS(Status))
3196c2c66affSColin Finck     {
3197c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
3198c2c66affSColin Finck     }
3199c2c66affSColin Finck 
3200c2c66affSColin Finck     /* FIXME: Remote key handles must fail */
3201c2c66affSColin Finck 
3202c2c66affSColin Finck     Status = NtNotifyChangeKey(KeyHandle,
3203c2c66affSColin Finck                                hEvent,
3204c2c66affSColin Finck                                0,
3205c2c66affSColin Finck                                0,
3206c2c66affSColin Finck                                &IoStatusBlock,
3207c2c66affSColin Finck                                dwNotifyFilter,
3208c2c66affSColin Finck                                bWatchSubtree,
3209c2c66affSColin Finck                                0,
3210c2c66affSColin Finck                                0,
3211c2c66affSColin Finck                                fAsynchronous);
3212c2c66affSColin Finck     if (!NT_SUCCESS(Status) && Status != STATUS_TIMEOUT)
3213c2c66affSColin Finck     {
3214c2c66affSColin Finck         ErrorCode = RtlNtStatusToDosError(Status);
3215c2c66affSColin Finck     }
3216c2c66affSColin Finck 
3217c2c66affSColin Finck     ClosePredefKey(KeyHandle);
3218c2c66affSColin Finck 
3219c2c66affSColin Finck     return ErrorCode;
3220c2c66affSColin Finck }
3221c2c66affSColin Finck 
3222c2c66affSColin Finck 
3223c2c66affSColin Finck /************************************************************************
3224c2c66affSColin Finck  *  RegOpenCurrentUser
3225c2c66affSColin Finck  *
3226c2c66affSColin Finck  * @implemented
3227c2c66affSColin Finck  */
3228c2c66affSColin Finck LONG WINAPI
3229c2c66affSColin Finck RegOpenCurrentUser(IN REGSAM samDesired,
3230c2c66affSColin Finck                    OUT PHKEY phkResult)
3231c2c66affSColin Finck {
3232c2c66affSColin Finck     NTSTATUS Status;
3233c2c66affSColin Finck 
3234c2c66affSColin Finck     Status = RtlOpenCurrentUser((ACCESS_MASK)samDesired,
3235c2c66affSColin Finck                                 (PHANDLE)phkResult);
3236c2c66affSColin Finck     if (!NT_SUCCESS(Status))
3237c2c66affSColin Finck     {
3238c2c66affSColin Finck         /* NOTE - don't set the last error code! just return the error! */
3239c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
3240c2c66affSColin Finck     }
3241c2c66affSColin Finck 
3242c2c66affSColin Finck     return ERROR_SUCCESS;
3243c2c66affSColin Finck }
3244c2c66affSColin Finck 
3245c2c66affSColin Finck 
3246c2c66affSColin Finck /************************************************************************
3247c2c66affSColin Finck  *  RegOpenKeyA
3248c2c66affSColin Finck  *
3249c2c66affSColin Finck  *  20050503 Fireball - imported from WINE
3250c2c66affSColin Finck  *
3251c2c66affSColin Finck  * @implemented
3252c2c66affSColin Finck  */
3253c2c66affSColin Finck LONG WINAPI
3254c2c66affSColin Finck RegOpenKeyA(HKEY hKey,
3255c2c66affSColin Finck             LPCSTR lpSubKey,
3256c2c66affSColin Finck             PHKEY phkResult)
3257c2c66affSColin Finck {
3258c2c66affSColin Finck     TRACE("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n",
3259c2c66affSColin Finck           hKey, lpSubKey, phkResult);
3260c2c66affSColin Finck 
3261c2c66affSColin Finck     if (!phkResult)
3262c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
3263c2c66affSColin Finck 
32641ade494aSEric Kohl     if (!hKey && !lpSubKey)
3265c2c66affSColin Finck     {
3266c2c66affSColin Finck         *phkResult = hKey;
3267c2c66affSColin Finck         return ERROR_SUCCESS;
3268c2c66affSColin Finck     }
3269c2c66affSColin Finck 
3270c2c66affSColin Finck     return RegOpenKeyExA(hKey,
3271c2c66affSColin Finck                          lpSubKey,
3272c2c66affSColin Finck                          0,
3273c2c66affSColin Finck                          MAXIMUM_ALLOWED,
3274c2c66affSColin Finck                          phkResult);
3275c2c66affSColin Finck }
3276c2c66affSColin Finck 
3277c2c66affSColin Finck 
3278c2c66affSColin Finck /************************************************************************
3279c2c66affSColin Finck  *  RegOpenKeyW
3280c2c66affSColin Finck  *
3281c2c66affSColin Finck  *  19981101 Ariadne
3282c2c66affSColin Finck  *  19990525 EA
3283c2c66affSColin Finck  *  20050503 Fireball - imported from WINE
3284c2c66affSColin Finck  *
3285c2c66affSColin Finck  * @implemented
3286c2c66affSColin Finck  */
3287c2c66affSColin Finck LONG WINAPI
3288c2c66affSColin Finck RegOpenKeyW(HKEY hKey,
3289c2c66affSColin Finck             LPCWSTR lpSubKey,
3290c2c66affSColin Finck             PHKEY phkResult)
3291c2c66affSColin Finck {
3292c2c66affSColin Finck     TRACE("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n",
3293c2c66affSColin Finck           hKey, lpSubKey, phkResult);
3294c2c66affSColin Finck 
3295c2c66affSColin Finck     if (!phkResult)
3296c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
3297c2c66affSColin Finck 
32981ade494aSEric Kohl     if (!hKey && !lpSubKey)
3299c2c66affSColin Finck     {
3300c2c66affSColin Finck         *phkResult = hKey;
3301c2c66affSColin Finck         return ERROR_SUCCESS;
3302c2c66affSColin Finck     }
3303c2c66affSColin Finck 
3304c2c66affSColin Finck     return RegOpenKeyExW(hKey,
3305c2c66affSColin Finck                          lpSubKey,
3306c2c66affSColin Finck                          0,
3307c2c66affSColin Finck                          MAXIMUM_ALLOWED,
3308c2c66affSColin Finck                          phkResult);
3309c2c66affSColin Finck }
3310c2c66affSColin Finck 
3311c2c66affSColin Finck 
3312c2c66affSColin Finck /************************************************************************
3313c2c66affSColin Finck  *  RegOpenKeyExA
3314c2c66affSColin Finck  *
3315c2c66affSColin Finck  * @implemented
3316c2c66affSColin Finck  */
3317c2c66affSColin Finck LONG WINAPI
3318c2c66affSColin Finck RegOpenKeyExA(
3319c2c66affSColin Finck     _In_ HKEY hKey,
3320c2c66affSColin Finck     _In_ LPCSTR lpSubKey,
3321c2c66affSColin Finck     _In_ DWORD ulOptions,
3322c2c66affSColin Finck     _In_ REGSAM samDesired,
3323c2c66affSColin Finck     _Out_ PHKEY phkResult)
3324c2c66affSColin Finck {
3325c2c66affSColin Finck     UNICODE_STRING SubKeyString;
3326c2c66affSColin Finck     LONG ErrorCode;
3327c2c66affSColin Finck 
3328c2c66affSColin Finck     TRACE("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
3329c2c66affSColin Finck           hKey, lpSubKey, ulOptions, samDesired, phkResult);
3330c2c66affSColin Finck 
3331c2c66affSColin Finck     if (lpSubKey)
3332c2c66affSColin Finck     {
3333c2c66affSColin Finck         if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyString, lpSubKey))
3334c2c66affSColin Finck             return ERROR_NOT_ENOUGH_MEMORY;
3335c2c66affSColin Finck     }
3336c2c66affSColin Finck     else
3337c2c66affSColin Finck         RtlInitEmptyUnicodeString(&SubKeyString, NULL, 0);
3338c2c66affSColin Finck 
3339c2c66affSColin Finck     ErrorCode = RegOpenKeyExW(hKey, SubKeyString.Buffer, ulOptions, samDesired, phkResult);
3340c2c66affSColin Finck 
3341c2c66affSColin Finck     RtlFreeUnicodeString(&SubKeyString);
3342c2c66affSColin Finck 
3343c2c66affSColin Finck     return ErrorCode;
3344c2c66affSColin Finck }
3345c2c66affSColin Finck 
3346c2c66affSColin Finck 
3347c2c66affSColin Finck /************************************************************************
3348c2c66affSColin Finck  *  RegOpenKeyExW
3349c2c66affSColin Finck  *
3350c2c66affSColin Finck  * @implemented
3351c2c66affSColin Finck  */
3352c2c66affSColin Finck LONG WINAPI
3353c2c66affSColin Finck RegOpenKeyExW(HKEY hKey,
3354c2c66affSColin Finck               LPCWSTR lpSubKey,
3355c2c66affSColin Finck               DWORD ulOptions,
3356c2c66affSColin Finck               REGSAM samDesired,
3357c2c66affSColin Finck               PHKEY phkResult)
3358c2c66affSColin Finck {
3359c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
3360c2c66affSColin Finck     UNICODE_STRING SubKeyString;
3361c2c66affSColin Finck     HANDLE KeyHandle;
3362c2c66affSColin Finck     NTSTATUS Status;
3363c2c66affSColin Finck     ULONG Attributes = OBJ_CASE_INSENSITIVE;
3364c2c66affSColin Finck     LONG ErrorCode = ERROR_SUCCESS;
3365*aff16663STimo Kreuzer     BOOLEAN SubKeyStringAllocated = FALSE;
3366c2c66affSColin Finck 
3367c2c66affSColin Finck     TRACE("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
3368c2c66affSColin Finck           hKey, lpSubKey, ulOptions, samDesired, phkResult);
3369c2c66affSColin Finck     if (!phkResult)
3370c2c66affSColin Finck     {
3371c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
3372c2c66affSColin Finck     }
3373c2c66affSColin Finck 
33741ade494aSEric Kohl     if (!hKey && lpSubKey && phkResult)
33751ade494aSEric Kohl     {
33761ade494aSEric Kohl         return ERROR_INVALID_HANDLE;
33771ade494aSEric Kohl     }
33781ade494aSEric Kohl 
33791ade494aSEric Kohl     if (IsPredefKey(hKey) && (!lpSubKey || !*lpSubKey))
33801ade494aSEric Kohl     {
33811ade494aSEric Kohl         *phkResult = hKey;
33821ade494aSEric Kohl         return ERROR_SUCCESS;
33831ade494aSEric Kohl     }
33841ade494aSEric Kohl 
3385c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle, hKey);
3386c2c66affSColin Finck     if (!NT_SUCCESS(Status))
3387c2c66affSColin Finck     {
3388c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
3389c2c66affSColin Finck     }
3390c2c66affSColin Finck 
3391c2c66affSColin Finck     if (IsHKCRKey(KeyHandle))
3392c2c66affSColin Finck     {
3393c2c66affSColin Finck         ErrorCode = OpenHKCRKey(KeyHandle, lpSubKey, ulOptions, samDesired, phkResult);
3394c2c66affSColin Finck         ClosePredefKey(KeyHandle);
3395c2c66affSColin Finck         return ErrorCode;
3396c2c66affSColin Finck     }
3397c2c66affSColin Finck 
3398c2c66affSColin Finck     if (ulOptions & REG_OPTION_OPEN_LINK)
3399c2c66affSColin Finck         Attributes |= OBJ_OPENLINK;
3400c2c66affSColin Finck 
34011ade494aSEric Kohl     if (lpSubKey == NULL || wcscmp(lpSubKey, L"\\") == 0)
3402*aff16663STimo Kreuzer     {
34031ade494aSEric Kohl         RtlInitUnicodeString(&SubKeyString, L"");
3404*aff16663STimo Kreuzer     }
34051ade494aSEric Kohl     else
3406*aff16663STimo Kreuzer     {
34071ade494aSEric Kohl         RtlInitUnicodeString(&SubKeyString, lpSubKey);
3408c2c66affSColin Finck 
3409*aff16663STimo Kreuzer         /* Handle unaligned lpSubKey */
3410*aff16663STimo Kreuzer         if ((ULONG_PTR)lpSubKey & 1)
3411*aff16663STimo Kreuzer         {
3412*aff16663STimo Kreuzer             UNICODE_STRING AlignedString;
3413*aff16663STimo Kreuzer 
3414*aff16663STimo Kreuzer             Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
3415*aff16663STimo Kreuzer                                                &SubKeyString,
3416*aff16663STimo Kreuzer                                                &AlignedString);
3417*aff16663STimo Kreuzer             if (!NT_SUCCESS(Status))
3418*aff16663STimo Kreuzer             {
3419*aff16663STimo Kreuzer                 goto Exit;
3420*aff16663STimo Kreuzer             }
3421*aff16663STimo Kreuzer 
3422*aff16663STimo Kreuzer             SubKeyString = AlignedString;
3423*aff16663STimo Kreuzer             SubKeyStringAllocated = TRUE;
3424*aff16663STimo Kreuzer         }
3425*aff16663STimo Kreuzer     }
3426*aff16663STimo Kreuzer 
3427c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
3428c2c66affSColin Finck                                &SubKeyString,
3429c2c66affSColin Finck                                Attributes,
3430c2c66affSColin Finck                                KeyHandle,
3431c2c66affSColin Finck                                NULL);
3432c2c66affSColin Finck 
3433c2c66affSColin Finck     Status = NtOpenKey((PHANDLE)phkResult,
3434c2c66affSColin Finck                        samDesired,
3435c2c66affSColin Finck                        &ObjectAttributes);
3436c2c66affSColin Finck 
3437*aff16663STimo Kreuzer Exit:
3438*aff16663STimo Kreuzer 
3439*aff16663STimo Kreuzer     if (SubKeyStringAllocated)
3440c2c66affSColin Finck     {
3441*aff16663STimo Kreuzer         RtlFreeUnicodeString(&SubKeyString);
3442c2c66affSColin Finck     }
3443c2c66affSColin Finck 
3444c2c66affSColin Finck     if (!NT_SUCCESS(Status))
3445c2c66affSColin Finck     {
3446c2c66affSColin Finck         ErrorCode = RtlNtStatusToDosError(Status);
3447c2c66affSColin Finck     }
3448c2c66affSColin Finck 
3449c2c66affSColin Finck     ClosePredefKey(KeyHandle);
3450c2c66affSColin Finck 
3451c2c66affSColin Finck     return ErrorCode;
3452c2c66affSColin Finck }
3453c2c66affSColin Finck 
3454c2c66affSColin Finck 
3455c2c66affSColin Finck /************************************************************************
3456c2c66affSColin Finck  *  RegOpenUserClassesRoot
3457c2c66affSColin Finck  *
3458c2c66affSColin Finck  * @implemented
3459c2c66affSColin Finck  */
3460c2c66affSColin Finck LONG WINAPI
3461c2c66affSColin Finck RegOpenUserClassesRoot(IN HANDLE hToken,
3462c2c66affSColin Finck                        IN DWORD dwOptions,
3463c2c66affSColin Finck                        IN REGSAM samDesired,
3464c2c66affSColin Finck                        OUT PHKEY phkResult)
3465c2c66affSColin Finck {
3466c2c66affSColin Finck     const WCHAR UserClassesKeyPrefix[] = L"\\Registry\\User\\";
3467c2c66affSColin Finck     const WCHAR UserClassesKeySuffix[] = L"_Classes";
3468c2c66affSColin Finck     PTOKEN_USER TokenUserData;
3469c2c66affSColin Finck     ULONG RequiredLength;
3470c2c66affSColin Finck     UNICODE_STRING UserSidString, UserClassesKeyRoot;
3471c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
3472c2c66affSColin Finck     NTSTATUS Status;
3473c2c66affSColin Finck 
3474c2c66affSColin Finck     /* check parameters */
3475c2c66affSColin Finck     if (hToken == NULL || dwOptions != 0 || phkResult == NULL)
3476c2c66affSColin Finck     {
3477c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
3478c2c66affSColin Finck     }
3479c2c66affSColin Finck 
3480c2c66affSColin Finck     /*
3481c2c66affSColin Finck      * Get the user sid from the token
3482c2c66affSColin Finck      */
3483c2c66affSColin Finck 
3484c2c66affSColin Finck ReadTokenSid:
3485c2c66affSColin Finck     /* determine how much memory we need */
3486c2c66affSColin Finck     Status = NtQueryInformationToken(hToken,
3487c2c66affSColin Finck                                      TokenUser,
3488c2c66affSColin Finck                                      NULL,
3489c2c66affSColin Finck                                      0,
3490c2c66affSColin Finck                                      &RequiredLength);
3491c2c66affSColin Finck     if (!NT_SUCCESS(Status) && (Status != STATUS_BUFFER_TOO_SMALL))
3492c2c66affSColin Finck     {
3493c2c66affSColin Finck         /* NOTE - as opposed to all other registry functions windows does indeed
3494c2c66affSColin Finck                   change the last error code in case the caller supplied a invalid
3495c2c66affSColin Finck                   handle for example! */
3496c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
3497c2c66affSColin Finck     }
3498c2c66affSColin Finck     RegInitialize(); /* HACK until delay-loading is implemented */
3499c2c66affSColin Finck     TokenUserData = RtlAllocateHeap(ProcessHeap,
3500c2c66affSColin Finck                                     0,
3501c2c66affSColin Finck                                     RequiredLength);
3502c2c66affSColin Finck     if (TokenUserData == NULL)
3503c2c66affSColin Finck     {
3504c2c66affSColin Finck         return ERROR_NOT_ENOUGH_MEMORY;
3505c2c66affSColin Finck     }
3506c2c66affSColin Finck 
3507c2c66affSColin Finck     /* attempt to read the information */
3508c2c66affSColin Finck     Status = NtQueryInformationToken(hToken,
3509c2c66affSColin Finck                                      TokenUser,
3510c2c66affSColin Finck                                      TokenUserData,
3511c2c66affSColin Finck                                      RequiredLength,
3512c2c66affSColin Finck                                      &RequiredLength);
3513c2c66affSColin Finck     if (!NT_SUCCESS(Status))
3514c2c66affSColin Finck     {
3515c2c66affSColin Finck         RtlFreeHeap(ProcessHeap,
3516c2c66affSColin Finck                     0,
3517c2c66affSColin Finck                     TokenUserData);
3518c2c66affSColin Finck         if (Status == STATUS_BUFFER_TOO_SMALL)
3519c2c66affSColin Finck         {
3520c2c66affSColin Finck             /* the information appears to have changed?! try again */
3521c2c66affSColin Finck             goto ReadTokenSid;
3522c2c66affSColin Finck         }
3523c2c66affSColin Finck 
3524c2c66affSColin Finck         /* NOTE - as opposed to all other registry functions windows does indeed
3525c2c66affSColin Finck                   change the last error code in case the caller supplied a invalid
3526c2c66affSColin Finck                   handle for example! */
3527c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
3528c2c66affSColin Finck     }
3529c2c66affSColin Finck 
3530c2c66affSColin Finck     /*
3531c2c66affSColin Finck      * Build the absolute path for the user's registry in the form
3532c2c66affSColin Finck      * "\Registry\User\<SID>_Classes"
3533c2c66affSColin Finck      */
3534c2c66affSColin Finck     Status = RtlConvertSidToUnicodeString(&UserSidString,
3535c2c66affSColin Finck                                           TokenUserData->User.Sid,
3536c2c66affSColin Finck                                           TRUE);
3537c2c66affSColin Finck 
3538c2c66affSColin Finck     /* we don't need the user data anymore, free it */
3539c2c66affSColin Finck     RtlFreeHeap(ProcessHeap,
3540c2c66affSColin Finck                 0,
3541c2c66affSColin Finck                 TokenUserData);
3542c2c66affSColin Finck 
3543c2c66affSColin Finck     if (!NT_SUCCESS(Status))
3544c2c66affSColin Finck     {
3545c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
3546c2c66affSColin Finck     }
3547c2c66affSColin Finck 
3548c2c66affSColin Finck     /* allocate enough memory for the entire key string */
3549c2c66affSColin Finck     UserClassesKeyRoot.Length = 0;
3550c2c66affSColin Finck     UserClassesKeyRoot.MaximumLength = UserSidString.Length +
3551c2c66affSColin Finck                                        sizeof(UserClassesKeyPrefix) +
3552c2c66affSColin Finck                                        sizeof(UserClassesKeySuffix);
3553c2c66affSColin Finck     UserClassesKeyRoot.Buffer = RtlAllocateHeap(ProcessHeap,
3554c2c66affSColin Finck                                                 0,
3555c2c66affSColin Finck                                                 UserClassesKeyRoot.MaximumLength);
3556c2c66affSColin Finck     if (UserClassesKeyRoot.Buffer == NULL)
3557c2c66affSColin Finck     {
3558c2c66affSColin Finck         RtlFreeUnicodeString(&UserSidString);
3559c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
3560c2c66affSColin Finck     }
3561c2c66affSColin Finck 
3562c2c66affSColin Finck     /* build the string */
3563c2c66affSColin Finck     RtlAppendUnicodeToString(&UserClassesKeyRoot,
3564c2c66affSColin Finck                              UserClassesKeyPrefix);
3565c2c66affSColin Finck     RtlAppendUnicodeStringToString(&UserClassesKeyRoot,
3566c2c66affSColin Finck                                    &UserSidString);
3567c2c66affSColin Finck     RtlAppendUnicodeToString(&UserClassesKeyRoot,
3568c2c66affSColin Finck                              UserClassesKeySuffix);
3569c2c66affSColin Finck 
3570c2c66affSColin Finck     TRACE("RegOpenUserClassesRoot: Absolute path: %wZ\n", &UserClassesKeyRoot);
3571c2c66affSColin Finck 
3572c2c66affSColin Finck     /*
3573c2c66affSColin Finck      * Open the key
3574c2c66affSColin Finck      */
3575c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
3576c2c66affSColin Finck                                &UserClassesKeyRoot,
3577c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
3578c2c66affSColin Finck                                NULL,
3579c2c66affSColin Finck                                NULL);
3580c2c66affSColin Finck 
3581c2c66affSColin Finck     Status = NtOpenKey((PHANDLE)phkResult,
3582c2c66affSColin Finck                        samDesired,
3583c2c66affSColin Finck                        &ObjectAttributes);
3584c2c66affSColin Finck 
3585c2c66affSColin Finck     RtlFreeUnicodeString(&UserSidString);
3586c2c66affSColin Finck     RtlFreeUnicodeString(&UserClassesKeyRoot);
3587c2c66affSColin Finck 
3588c2c66affSColin Finck     if (!NT_SUCCESS(Status))
3589c2c66affSColin Finck     {
3590c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
3591c2c66affSColin Finck     }
3592c2c66affSColin Finck 
3593c2c66affSColin Finck     return ERROR_SUCCESS;
3594c2c66affSColin Finck }
3595c2c66affSColin Finck 
3596c2c66affSColin Finck 
3597c2c66affSColin Finck /************************************************************************
3598c2c66affSColin Finck  *  RegQueryInfoKeyA
3599c2c66affSColin Finck  *
3600c2c66affSColin Finck  * @implemented
3601c2c66affSColin Finck  */
3602c2c66affSColin Finck LONG WINAPI
3603c2c66affSColin Finck RegQueryInfoKeyA(HKEY hKey,
3604c2c66affSColin Finck                  LPSTR lpClass,
3605c2c66affSColin Finck                  LPDWORD lpcClass,
3606c2c66affSColin Finck                  LPDWORD lpReserved,
3607c2c66affSColin Finck                  LPDWORD lpcSubKeys,
3608c2c66affSColin Finck                  LPDWORD lpcMaxSubKeyLen,
3609c2c66affSColin Finck                  LPDWORD lpcMaxClassLen,
3610c2c66affSColin Finck                  LPDWORD lpcValues,
3611c2c66affSColin Finck                  LPDWORD lpcMaxValueNameLen,
3612c2c66affSColin Finck                  LPDWORD lpcMaxValueLen,
3613c2c66affSColin Finck                  LPDWORD lpcbSecurityDescriptor,
3614c2c66affSColin Finck                  PFILETIME lpftLastWriteTime)
3615c2c66affSColin Finck {
3616c2c66affSColin Finck     WCHAR ClassName[MAX_PATH];
3617c2c66affSColin Finck     UNICODE_STRING UnicodeString;
3618c2c66affSColin Finck     ANSI_STRING AnsiString;
3619c2c66affSColin Finck     LONG ErrorCode;
3620c2c66affSColin Finck     NTSTATUS Status;
3621c2c66affSColin Finck     DWORD cClass = 0;
3622c2c66affSColin Finck 
3623c2c66affSColin Finck     if ((lpClass) && (!lpcClass))
3624c2c66affSColin Finck     {
3625c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
3626c2c66affSColin Finck     }
3627c2c66affSColin Finck 
3628c2c66affSColin Finck     RtlInitUnicodeString(&UnicodeString,
3629c2c66affSColin Finck                          NULL);
3630c2c66affSColin Finck     if (lpClass != NULL)
3631c2c66affSColin Finck     {
3632c2c66affSColin Finck         RtlInitEmptyUnicodeString(&UnicodeString,
3633c2c66affSColin Finck                                   ClassName,
3634c2c66affSColin Finck                                   sizeof(ClassName));
3635c2c66affSColin Finck         cClass = sizeof(ClassName) / sizeof(WCHAR);
3636c2c66affSColin Finck     }
3637c2c66affSColin Finck 
3638c2c66affSColin Finck     ErrorCode = RegQueryInfoKeyW(hKey,
3639c2c66affSColin Finck                                  UnicodeString.Buffer,
3640c2c66affSColin Finck                                  &cClass,
3641c2c66affSColin Finck                                  lpReserved,
3642c2c66affSColin Finck                                  lpcSubKeys,
3643c2c66affSColin Finck                                  lpcMaxSubKeyLen,
3644c2c66affSColin Finck                                  lpcMaxClassLen,
3645c2c66affSColin Finck                                  lpcValues,
3646c2c66affSColin Finck                                  lpcMaxValueNameLen,
3647c2c66affSColin Finck                                  lpcMaxValueLen,
3648c2c66affSColin Finck                                  lpcbSecurityDescriptor,
3649c2c66affSColin Finck                                  lpftLastWriteTime);
3650c2c66affSColin Finck     if ((ErrorCode == ERROR_SUCCESS) && (lpClass != NULL))
3651c2c66affSColin Finck     {
3652c2c66affSColin Finck         if (*lpcClass == 0)
3653c2c66affSColin Finck         {
3654c2c66affSColin Finck             return ErrorCode;
3655c2c66affSColin Finck         }
3656c2c66affSColin Finck 
3657c2c66affSColin Finck         RtlInitEmptyAnsiString(&AnsiString, lpClass, *lpcClass);
3658c2c66affSColin Finck         UnicodeString.Length = cClass * sizeof(WCHAR);
3659c2c66affSColin Finck         Status = RtlUnicodeStringToAnsiString(&AnsiString,
3660c2c66affSColin Finck                                               &UnicodeString,
3661c2c66affSColin Finck                                               FALSE);
3662c2c66affSColin Finck         ErrorCode = RtlNtStatusToDosError(Status);
3663c2c66affSColin Finck         cClass = AnsiString.Length;
3664c2c66affSColin Finck         lpClass[cClass] = ANSI_NULL;
3665c2c66affSColin Finck     }
3666c2c66affSColin Finck 
3667c2c66affSColin Finck     if (lpcClass != NULL)
3668c2c66affSColin Finck     {
3669c2c66affSColin Finck         *lpcClass = cClass;
3670c2c66affSColin Finck     }
3671c2c66affSColin Finck 
3672c2c66affSColin Finck     return ErrorCode;
3673c2c66affSColin Finck }
3674c2c66affSColin Finck 
3675c2c66affSColin Finck 
3676c2c66affSColin Finck /************************************************************************
3677c2c66affSColin Finck  *  RegQueryInfoKeyW
3678c2c66affSColin Finck  *
3679c2c66affSColin Finck  * @implemented
3680c2c66affSColin Finck  */
3681c2c66affSColin Finck LONG WINAPI
3682c2c66affSColin Finck RegQueryInfoKeyW(HKEY hKey,
3683c2c66affSColin Finck                  LPWSTR lpClass,
3684c2c66affSColin Finck                  LPDWORD lpcClass,
3685c2c66affSColin Finck                  LPDWORD lpReserved,
3686c2c66affSColin Finck                  LPDWORD lpcSubKeys,
3687c2c66affSColin Finck                  LPDWORD lpcMaxSubKeyLen,
3688c2c66affSColin Finck                  LPDWORD lpcMaxClassLen,
3689c2c66affSColin Finck                  LPDWORD lpcValues,
3690c2c66affSColin Finck                  LPDWORD lpcMaxValueNameLen,
3691c2c66affSColin Finck                  LPDWORD lpcMaxValueLen,
3692c2c66affSColin Finck                  LPDWORD lpcbSecurityDescriptor,
3693c2c66affSColin Finck                  PFILETIME lpftLastWriteTime)
3694c2c66affSColin Finck {
3695c2c66affSColin Finck     KEY_FULL_INFORMATION FullInfoBuffer;
3696c2c66affSColin Finck     PKEY_FULL_INFORMATION FullInfo;
3697c2c66affSColin Finck     ULONG FullInfoSize;
3698c2c66affSColin Finck     ULONG ClassLength = 0;
3699c2c66affSColin Finck     HANDLE KeyHandle;
3700c2c66affSColin Finck     NTSTATUS Status;
3701c2c66affSColin Finck     ULONG Length;
3702c2c66affSColin Finck     LONG ErrorCode = ERROR_SUCCESS;
3703c2c66affSColin Finck 
3704c2c66affSColin Finck     if ((lpClass) && (!lpcClass))
3705c2c66affSColin Finck     {
3706c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
3707c2c66affSColin Finck     }
3708c2c66affSColin Finck 
3709c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
3710c2c66affSColin Finck                            hKey);
3711c2c66affSColin Finck     if (!NT_SUCCESS(Status))
3712c2c66affSColin Finck     {
3713c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
3714c2c66affSColin Finck     }
3715c2c66affSColin Finck 
3716413b5a08SWhindmar Saksit     if (IsHKCRKey(KeyHandle))
3717413b5a08SWhindmar Saksit     {
3718413b5a08SWhindmar Saksit         ErrorCode = QueryInfoHKCRKey(KeyHandle, lpClass, lpcClass, lpReserved,
3719413b5a08SWhindmar Saksit                                      lpcSubKeys, lpcMaxSubKeyLen, lpcMaxClassLen,
3720413b5a08SWhindmar Saksit                                      lpcValues, lpcMaxValueNameLen, lpcMaxValueLen,
3721413b5a08SWhindmar Saksit                                      lpcbSecurityDescriptor, lpftLastWriteTime);
3722413b5a08SWhindmar Saksit         ClosePredefKey(KeyHandle);
3723413b5a08SWhindmar Saksit         return ErrorCode;
3724413b5a08SWhindmar Saksit     }
3725413b5a08SWhindmar Saksit 
3726c2c66affSColin Finck     if (lpClass != NULL)
3727c2c66affSColin Finck     {
3728c2c66affSColin Finck         if (*lpcClass > 0)
3729c2c66affSColin Finck         {
3730c2c66affSColin Finck             ClassLength = min(*lpcClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
3731c2c66affSColin Finck         }
3732c2c66affSColin Finck         else
3733c2c66affSColin Finck         {
3734c2c66affSColin Finck             ClassLength = 0;
3735c2c66affSColin Finck         }
3736c2c66affSColin Finck 
3737c2c66affSColin Finck         FullInfoSize = sizeof(KEY_FULL_INFORMATION) + ((ClassLength + 3) & ~3);
3738c2c66affSColin Finck         FullInfo = RtlAllocateHeap(ProcessHeap,
3739c2c66affSColin Finck                                    0,
3740c2c66affSColin Finck                                    FullInfoSize);
3741c2c66affSColin Finck         if (FullInfo == NULL)
3742c2c66affSColin Finck         {
3743c2c66affSColin Finck             ErrorCode = ERROR_OUTOFMEMORY;
3744c2c66affSColin Finck             goto Cleanup;
3745c2c66affSColin Finck         }
3746c2c66affSColin Finck     }
3747c2c66affSColin Finck     else
3748c2c66affSColin Finck     {
3749c2c66affSColin Finck         FullInfoSize = sizeof(KEY_FULL_INFORMATION);
3750c2c66affSColin Finck         FullInfo = &FullInfoBuffer;
3751c2c66affSColin Finck     }
3752c2c66affSColin Finck 
3753c2c66affSColin Finck     if (lpcbSecurityDescriptor != NULL)
3754c2c66affSColin Finck         *lpcbSecurityDescriptor = 0;
3755c2c66affSColin Finck 
3756c2c66affSColin Finck     Status = NtQueryKey(KeyHandle,
3757c2c66affSColin Finck                         KeyFullInformation,
3758c2c66affSColin Finck                         FullInfo,
3759c2c66affSColin Finck                         FullInfoSize,
3760c2c66affSColin Finck                         &Length);
3761c2c66affSColin Finck     TRACE("NtQueryKey() returned status 0x%X\n", Status);
3762c2c66affSColin Finck     if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
3763c2c66affSColin Finck     {
3764c2c66affSColin Finck         ErrorCode = RtlNtStatusToDosError(Status);
3765c2c66affSColin Finck         goto Cleanup;
3766c2c66affSColin Finck     }
3767c2c66affSColin Finck 
3768c2c66affSColin Finck     TRACE("SubKeys %d\n", FullInfo->SubKeys);
3769c2c66affSColin Finck     if (lpcSubKeys != NULL)
3770c2c66affSColin Finck     {
3771c2c66affSColin Finck         *lpcSubKeys = FullInfo->SubKeys;
3772c2c66affSColin Finck     }
3773c2c66affSColin Finck 
3774c2c66affSColin Finck     TRACE("MaxNameLen %lu\n", FullInfo->MaxNameLen);
3775c2c66affSColin Finck     if (lpcMaxSubKeyLen != NULL)
3776c2c66affSColin Finck     {
3777c2c66affSColin Finck         *lpcMaxSubKeyLen = FullInfo->MaxNameLen / sizeof(WCHAR);
3778c2c66affSColin Finck     }
3779c2c66affSColin Finck 
3780c2c66affSColin Finck     TRACE("MaxClassLen %lu\n", FullInfo->MaxClassLen);
3781c2c66affSColin Finck     if (lpcMaxClassLen != NULL)
3782c2c66affSColin Finck     {
3783c2c66affSColin Finck         *lpcMaxClassLen = FullInfo->MaxClassLen / sizeof(WCHAR);
3784c2c66affSColin Finck     }
3785c2c66affSColin Finck 
3786c2c66affSColin Finck     TRACE("Values %lu\n", FullInfo->Values);
3787c2c66affSColin Finck     if (lpcValues != NULL)
3788c2c66affSColin Finck     {
3789c2c66affSColin Finck         *lpcValues = FullInfo->Values;
3790c2c66affSColin Finck     }
3791c2c66affSColin Finck 
3792c2c66affSColin Finck     TRACE("MaxValueNameLen %lu\n", FullInfo->MaxValueNameLen);
3793c2c66affSColin Finck     if (lpcMaxValueNameLen != NULL)
3794c2c66affSColin Finck     {
3795c2c66affSColin Finck         *lpcMaxValueNameLen = FullInfo->MaxValueNameLen / sizeof(WCHAR);
3796c2c66affSColin Finck     }
3797c2c66affSColin Finck 
3798c2c66affSColin Finck     TRACE("MaxValueDataLen %lu\n", FullInfo->MaxValueDataLen);
3799c2c66affSColin Finck     if (lpcMaxValueLen != NULL)
3800c2c66affSColin Finck     {
3801c2c66affSColin Finck         *lpcMaxValueLen = FullInfo->MaxValueDataLen;
3802c2c66affSColin Finck     }
3803c2c66affSColin Finck 
3804c2c66affSColin Finck     if (lpcbSecurityDescriptor != NULL)
3805c2c66affSColin Finck     {
3806c2c66affSColin Finck         Status = NtQuerySecurityObject(KeyHandle,
3807c2c66affSColin Finck                                        OWNER_SECURITY_INFORMATION |
3808c2c66affSColin Finck                                        GROUP_SECURITY_INFORMATION |
3809c2c66affSColin Finck                                        DACL_SECURITY_INFORMATION,
3810c2c66affSColin Finck                                        NULL,
3811c2c66affSColin Finck                                        0,
3812c2c66affSColin Finck                                        lpcbSecurityDescriptor);
3813c2c66affSColin Finck         TRACE("NtQuerySecurityObject() returned status 0x%X\n", Status);
3814c2c66affSColin Finck     }
3815c2c66affSColin Finck 
3816c2c66affSColin Finck     if (lpftLastWriteTime != NULL)
3817c2c66affSColin Finck     {
3818c2c66affSColin Finck         lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart;
3819c2c66affSColin Finck         lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart;
3820c2c66affSColin Finck     }
3821c2c66affSColin Finck 
3822c2c66affSColin Finck     if (lpClass != NULL)
3823c2c66affSColin Finck     {
3824c2c66affSColin Finck         if (*lpcClass == 0)
3825c2c66affSColin Finck         {
3826c2c66affSColin Finck             goto Cleanup;
3827c2c66affSColin Finck         }
3828c2c66affSColin Finck 
3829c2c66affSColin Finck         if (FullInfo->ClassLength > ClassLength)
3830c2c66affSColin Finck         {
3831c2c66affSColin Finck             ErrorCode = ERROR_INSUFFICIENT_BUFFER;
3832c2c66affSColin Finck         }
3833c2c66affSColin Finck         else
3834c2c66affSColin Finck         {
3835c2c66affSColin Finck             RtlCopyMemory(lpClass,
3836c2c66affSColin Finck                           FullInfo->Class,
3837c2c66affSColin Finck                           FullInfo->ClassLength);
3838c2c66affSColin Finck             lpClass[FullInfo->ClassLength / sizeof(WCHAR)] = UNICODE_NULL;
3839c2c66affSColin Finck         }
3840c2c66affSColin Finck     }
3841c2c66affSColin Finck 
3842c2c66affSColin Finck     if (lpcClass != NULL)
3843c2c66affSColin Finck     {
3844c2c66affSColin Finck         *lpcClass = FullInfo->ClassLength / sizeof(WCHAR);
3845c2c66affSColin Finck     }
3846c2c66affSColin Finck 
3847c2c66affSColin Finck Cleanup:
3848c2c66affSColin Finck     if (lpClass != NULL)
3849c2c66affSColin Finck     {
3850c2c66affSColin Finck         RtlFreeHeap(ProcessHeap,
3851c2c66affSColin Finck                     0,
3852c2c66affSColin Finck                     FullInfo);
3853c2c66affSColin Finck     }
3854c2c66affSColin Finck 
3855c2c66affSColin Finck     ClosePredefKey(KeyHandle);
3856c2c66affSColin Finck 
3857c2c66affSColin Finck     return ErrorCode;
3858c2c66affSColin Finck }
3859c2c66affSColin Finck 
3860c2c66affSColin Finck 
3861c2c66affSColin Finck /************************************************************************
3862c2c66affSColin Finck  *  RegQueryMultipleValuesA
3863c2c66affSColin Finck  *
3864c2c66affSColin Finck  * @implemented
3865c2c66affSColin Finck  */
3866c2c66affSColin Finck LONG WINAPI
3867c2c66affSColin Finck RegQueryMultipleValuesA(HKEY hKey,
3868c2c66affSColin Finck                         PVALENTA val_list,
3869c2c66affSColin Finck                         DWORD num_vals,
3870c2c66affSColin Finck                         LPSTR lpValueBuf,
3871c2c66affSColin Finck                         LPDWORD ldwTotsize)
3872c2c66affSColin Finck {
3873c2c66affSColin Finck     ULONG i;
3874c2c66affSColin Finck     DWORD maxBytes = *ldwTotsize;
387546259092SSerge Gautherie     LPSTR bufptr = lpValueBuf;
3876c2c66affSColin Finck     LONG ErrorCode;
3877c2c66affSColin Finck 
3878c2c66affSColin Finck     if (maxBytes >= (1024*1024))
3879c2c66affSColin Finck         return ERROR_MORE_DATA;
3880c2c66affSColin Finck 
3881c2c66affSColin Finck     *ldwTotsize = 0;
3882c2c66affSColin Finck 
3883c2c66affSColin Finck     TRACE("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
3884c2c66affSColin Finck           hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
3885c2c66affSColin Finck 
3886c2c66affSColin Finck     for (i = 0; i < num_vals; i++)
3887c2c66affSColin Finck     {
3888c2c66affSColin Finck         val_list[i].ve_valuelen = 0;
3889c2c66affSColin Finck         ErrorCode = RegQueryValueExA(hKey,
3890c2c66affSColin Finck                                      val_list[i].ve_valuename,
3891c2c66affSColin Finck                                      NULL,
3892c2c66affSColin Finck                                      NULL,
3893c2c66affSColin Finck                                      NULL,
3894c2c66affSColin Finck                                      &val_list[i].ve_valuelen);
3895c2c66affSColin Finck         if (ErrorCode != ERROR_SUCCESS)
3896c2c66affSColin Finck         {
3897c2c66affSColin Finck             return ErrorCode;
3898c2c66affSColin Finck         }
3899c2c66affSColin Finck 
3900c2c66affSColin Finck         if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
3901c2c66affSColin Finck         {
3902c2c66affSColin Finck             ErrorCode = RegQueryValueExA(hKey,
3903c2c66affSColin Finck                                          val_list[i].ve_valuename,
3904c2c66affSColin Finck                                          NULL,
3905c2c66affSColin Finck                                          &val_list[i].ve_type,
3906c2c66affSColin Finck                                          (LPBYTE)bufptr,
3907c2c66affSColin Finck                                          &val_list[i].ve_valuelen);
3908c2c66affSColin Finck             if (ErrorCode != ERROR_SUCCESS)
3909c2c66affSColin Finck             {
3910c2c66affSColin Finck                 return ErrorCode;
3911c2c66affSColin Finck             }
3912c2c66affSColin Finck 
3913c2c66affSColin Finck             val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
3914c2c66affSColin Finck 
3915c2c66affSColin Finck             bufptr += val_list[i].ve_valuelen;
3916c2c66affSColin Finck         }
3917c2c66affSColin Finck 
3918c2c66affSColin Finck         *ldwTotsize += val_list[i].ve_valuelen;
3919c2c66affSColin Finck     }
3920c2c66affSColin Finck 
3921c2c66affSColin Finck     return (lpValueBuf != NULL && *ldwTotsize <= maxBytes) ? ERROR_SUCCESS : ERROR_MORE_DATA;
3922c2c66affSColin Finck }
3923c2c66affSColin Finck 
3924c2c66affSColin Finck 
3925c2c66affSColin Finck /************************************************************************
3926c2c66affSColin Finck  *  RegQueryMultipleValuesW
3927c2c66affSColin Finck  *
3928c2c66affSColin Finck  * @implemented
3929c2c66affSColin Finck  */
3930c2c66affSColin Finck LONG WINAPI
3931c2c66affSColin Finck RegQueryMultipleValuesW(HKEY hKey,
3932c2c66affSColin Finck                         PVALENTW val_list,
3933c2c66affSColin Finck                         DWORD num_vals,
3934c2c66affSColin Finck                         LPWSTR lpValueBuf,
3935c2c66affSColin Finck                         LPDWORD ldwTotsize)
3936c2c66affSColin Finck {
3937c2c66affSColin Finck     ULONG i;
3938c2c66affSColin Finck     DWORD maxBytes = *ldwTotsize;
3939c2c66affSColin Finck     LPSTR bufptr = (LPSTR)lpValueBuf;
3940c2c66affSColin Finck     LONG ErrorCode;
3941c2c66affSColin Finck 
3942c2c66affSColin Finck     if (maxBytes >= (1024*1024))
3943c2c66affSColin Finck         return ERROR_MORE_DATA;
3944c2c66affSColin Finck 
3945c2c66affSColin Finck     *ldwTotsize = 0;
3946c2c66affSColin Finck 
3947c2c66affSColin Finck     TRACE("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
3948c2c66affSColin Finck           hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
3949c2c66affSColin Finck 
3950c2c66affSColin Finck     for (i = 0; i < num_vals; i++)
3951c2c66affSColin Finck     {
3952c2c66affSColin Finck         val_list[i].ve_valuelen = 0;
3953c2c66affSColin Finck         ErrorCode = RegQueryValueExW(hKey,
3954c2c66affSColin Finck                                      val_list[i].ve_valuename,
3955c2c66affSColin Finck                                      NULL,
3956c2c66affSColin Finck                                      NULL,
3957c2c66affSColin Finck                                      NULL,
3958c2c66affSColin Finck                                      &val_list[i].ve_valuelen);
3959c2c66affSColin Finck         if (ErrorCode != ERROR_SUCCESS)
3960c2c66affSColin Finck         {
3961c2c66affSColin Finck             return ErrorCode;
3962c2c66affSColin Finck          }
3963c2c66affSColin Finck 
3964c2c66affSColin Finck         if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
3965c2c66affSColin Finck         {
3966c2c66affSColin Finck             ErrorCode = RegQueryValueExW(hKey,
3967c2c66affSColin Finck                                          val_list[i].ve_valuename,
3968c2c66affSColin Finck                                          NULL,
3969c2c66affSColin Finck                                          &val_list[i].ve_type,
3970c2c66affSColin Finck                                          (LPBYTE)bufptr,
3971c2c66affSColin Finck                                          &val_list[i].ve_valuelen);
3972c2c66affSColin Finck             if (ErrorCode != ERROR_SUCCESS)
3973c2c66affSColin Finck             {
3974c2c66affSColin Finck                 return ErrorCode;
3975c2c66affSColin Finck             }
3976c2c66affSColin Finck 
3977c2c66affSColin Finck             val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
3978c2c66affSColin Finck 
3979c2c66affSColin Finck             bufptr += val_list[i].ve_valuelen;
3980c2c66affSColin Finck         }
3981c2c66affSColin Finck 
3982c2c66affSColin Finck         *ldwTotsize += val_list[i].ve_valuelen;
3983c2c66affSColin Finck     }
3984c2c66affSColin Finck 
3985c2c66affSColin Finck     return (lpValueBuf != NULL && *ldwTotsize <= maxBytes) ? ERROR_SUCCESS : ERROR_MORE_DATA;
3986c2c66affSColin Finck }
3987c2c66affSColin Finck 
3988c2c66affSColin Finck 
3989c2c66affSColin Finck /************************************************************************
3990c2c66affSColin Finck  *  RegQueryReflectionKey
3991c2c66affSColin Finck  *
3992c2c66affSColin Finck  * @unimplemented
3993c2c66affSColin Finck  */
3994c2c66affSColin Finck LONG WINAPI
3995c2c66affSColin Finck RegQueryReflectionKey(IN HKEY hBase,
3996c2c66affSColin Finck                       OUT BOOL* bIsReflectionDisabled)
3997c2c66affSColin Finck {
3998c2c66affSColin Finck     FIXME("RegQueryReflectionKey(0x%p, 0x%p) UNIMPLEMENTED!\n",
3999c2c66affSColin Finck           hBase, bIsReflectionDisabled);
4000c2c66affSColin Finck     return ERROR_CALL_NOT_IMPLEMENTED;
4001c2c66affSColin Finck }
4002c2c66affSColin Finck 
4003c2c66affSColin Finck 
4004c2c66affSColin Finck /******************************************************************************
4005c2c66affSColin Finck  * RegQueryValueExA   [ADVAPI32.@]
4006c2c66affSColin Finck  *
4007c2c66affSColin Finck  * Get the type and contents of a specified value under with a key.
4008c2c66affSColin Finck  *
4009c2c66affSColin Finck  * PARAMS
4010c2c66affSColin Finck  *  hkey      [I]   Handle of the key to query
4011c2c66affSColin Finck  *  name      [I]   Name of value under hkey to query
4012c2c66affSColin Finck  *  reserved  [I]   Reserved - must be NULL
4013c2c66affSColin Finck  *  type      [O]   Destination for the value type, or NULL if not required
4014c2c66affSColin Finck  *  data      [O]   Destination for the values contents, or NULL if not required
4015c2c66affSColin Finck  *  count     [I/O] Size of data, updated with the number of bytes returned
4016c2c66affSColin Finck  *
4017c2c66affSColin Finck  * RETURNS
4018c2c66affSColin Finck  *  Success: ERROR_SUCCESS. *count is updated with the number of bytes copied to data.
4019c2c66affSColin Finck  *  Failure: ERROR_INVALID_HANDLE, if hkey is invalid.
4020c2c66affSColin Finck  *           ERROR_INVALID_PARAMETER, if any other parameter is invalid.
4021c2c66affSColin Finck  *           ERROR_MORE_DATA, if on input *count is too small to hold the contents.
4022c2c66affSColin Finck  *
4023c2c66affSColin Finck  * NOTES
4024c2c66affSColin Finck  *   MSDN states that if data is too small it is partially filled. In reality
4025c2c66affSColin Finck  *   it remains untouched.
4026c2c66affSColin Finck  */
4027c2c66affSColin Finck LONG
4028c2c66affSColin Finck WINAPI
4029c2c66affSColin Finck RegQueryValueExA(
4030c2c66affSColin Finck     _In_ HKEY hkeyorg,
4031c2c66affSColin Finck     _In_ LPCSTR name,
4032c2c66affSColin Finck     _In_ LPDWORD reserved,
4033c2c66affSColin Finck     _Out_opt_ LPDWORD type,
4034c2c66affSColin Finck     _Out_opt_ LPBYTE data,
4035c2c66affSColin Finck     _Inout_opt_ LPDWORD count)
4036c2c66affSColin Finck {
4037c2c66affSColin Finck     UNICODE_STRING nameW;
4038c2c66affSColin Finck     DWORD DataLength;
4039c2c66affSColin Finck     DWORD ErrorCode;
4040c2c66affSColin Finck     DWORD BufferSize = 0;
4041c2c66affSColin Finck     WCHAR* Buffer;
4042c2c66affSColin Finck     CHAR* DataStr = (CHAR*)data;
4043c2c66affSColin Finck     DWORD LocalType;
4044c2c66affSColin Finck 
4045c2c66affSColin Finck     /* Validate those parameters, the rest will be done with the first RegQueryValueExW call */
4046c2c66affSColin Finck     if ((data && !count) || reserved)
4047c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
4048c2c66affSColin Finck 
4049c2c66affSColin Finck     if (name)
4050c2c66affSColin Finck     {
4051c2c66affSColin Finck         if (!RtlCreateUnicodeStringFromAsciiz(&nameW, name))
4052c2c66affSColin Finck             return ERROR_NOT_ENOUGH_MEMORY;
4053c2c66affSColin Finck     }
4054c2c66affSColin Finck     else
4055c2c66affSColin Finck         RtlInitEmptyUnicodeString(&nameW, NULL, 0);
4056c2c66affSColin Finck 
4057c2c66affSColin Finck     ErrorCode = RegQueryValueExW(hkeyorg, nameW.Buffer, NULL, &LocalType, NULL, &BufferSize);
4058c2c66affSColin Finck     if (ErrorCode != ERROR_SUCCESS)
4059c2c66affSColin Finck     {
4060c2c66affSColin Finck         if ((!data) && count)
4061c2c66affSColin Finck             *count = 0;
4062c2c66affSColin Finck         RtlFreeUnicodeString(&nameW);
4063c2c66affSColin Finck         return ErrorCode;
4064c2c66affSColin Finck     }
4065c2c66affSColin Finck 
4066c2c66affSColin Finck     /* See if we can directly handle the call without caring for conversion */
4067c2c66affSColin Finck     if (!is_string(LocalType) || !count)
4068c2c66affSColin Finck     {
4069c2c66affSColin Finck         ErrorCode = RegQueryValueExW(hkeyorg, nameW.Buffer, reserved, type, data, count);
4070c2c66affSColin Finck         RtlFreeUnicodeString(&nameW);
4071c2c66affSColin Finck         return ErrorCode;
4072c2c66affSColin Finck     }
4073c2c66affSColin Finck 
4074c2c66affSColin Finck     /* Allocate a unicode string to get the data */
4075c2c66affSColin Finck     Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
4076c2c66affSColin Finck     if (!Buffer)
4077c2c66affSColin Finck     {
4078c2c66affSColin Finck         RtlFreeUnicodeString(&nameW);
4079c2c66affSColin Finck         return ERROR_NOT_ENOUGH_MEMORY;
4080c2c66affSColin Finck     }
4081c2c66affSColin Finck 
4082c2c66affSColin Finck     ErrorCode = RegQueryValueExW(hkeyorg, nameW.Buffer, reserved, type, (LPBYTE)Buffer, &BufferSize);
4083c2c66affSColin Finck     if (ErrorCode != ERROR_SUCCESS)
4084c2c66affSColin Finck     {
4085c2c66affSColin Finck         RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
4086c2c66affSColin Finck         RtlFreeUnicodeString(&nameW);
4087c2c66affSColin Finck         return ErrorCode;
4088c2c66affSColin Finck     }
4089c2c66affSColin Finck 
4090c2c66affSColin Finck     /* We don't need this anymore */
4091c2c66affSColin Finck     RtlFreeUnicodeString(&nameW);
4092c2c66affSColin Finck 
4093c5158963STimo Kreuzer     /* Get the length for the multi-byte string (without the terminating NULL!) */
4094c2c66affSColin Finck     DataLength = *count;
4095c2c66affSColin Finck     RtlUnicodeToMultiByteSize(count, Buffer, BufferSize);
4096c2c66affSColin Finck 
4097c2c66affSColin Finck     if ((!data) || (DataLength < *count))
4098c2c66affSColin Finck     {
4099c2c66affSColin Finck         RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
4100c2c66affSColin Finck         return  data ? ERROR_MORE_DATA : ERROR_SUCCESS;
4101c2c66affSColin Finck     }
4102c2c66affSColin Finck 
4103c2c66affSColin Finck     /* We can finally do the conversion */
4104c2c66affSColin Finck     RtlUnicodeToMultiByteN(DataStr, DataLength, NULL, Buffer, BufferSize);
4105c2c66affSColin Finck 
4106c2c66affSColin Finck     /* NULL-terminate if there is enough room */
4107c5158963STimo Kreuzer     if (DataLength > *count)
4108c2c66affSColin Finck         DataStr[*count] = '\0';
4109c2c66affSColin Finck 
4110c2c66affSColin Finck     RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
4111c2c66affSColin Finck 
4112c2c66affSColin Finck     return ERROR_SUCCESS;
4113c2c66affSColin Finck }
4114c2c66affSColin Finck 
4115c2c66affSColin Finck 
4116c2c66affSColin Finck /************************************************************************
4117c2c66affSColin Finck  *  RegQueryValueExW
4118c2c66affSColin Finck  *
4119c2c66affSColin Finck  * @implemented
4120c2c66affSColin Finck  */
4121c2c66affSColin Finck LONG
4122c2c66affSColin Finck WINAPI
4123c2c66affSColin Finck RegQueryValueExW(
4124c2c66affSColin Finck     _In_ HKEY hkeyorg,
4125c2c66affSColin Finck     _In_ LPCWSTR name,
4126c2c66affSColin Finck     _In_ LPDWORD reserved,
4127c2c66affSColin Finck     _In_ LPDWORD type,
4128c2c66affSColin Finck     _In_ LPBYTE data,
4129c2c66affSColin Finck     _In_ LPDWORD count)
4130c2c66affSColin Finck {
4131c2c66affSColin Finck     HANDLE hkey;
4132c2c66affSColin Finck     NTSTATUS status;
4133c2c66affSColin Finck     UNICODE_STRING name_str;
4134c2c66affSColin Finck     DWORD total_size;
4135c2c66affSColin Finck     char buffer[256], *buf_ptr = buffer;
4136c2c66affSColin Finck     KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
4137c2c66affSColin Finck     static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data );
4138c2c66affSColin Finck 
4139c2c66affSColin Finck     TRACE("(%p,%s,%p,%p,%p,%p=%d)\n",
4140c2c66affSColin Finck           hkeyorg, debugstr_w(name), reserved, type, data, count,
4141c2c66affSColin Finck           (count && data) ? *count : 0 );
4142c2c66affSColin Finck 
4143c2c66affSColin Finck     if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
4144c2c66affSColin Finck 
4145c2c66affSColin Finck     status = MapDefaultKey(&hkey, hkeyorg);
4146c2c66affSColin Finck     if (!NT_SUCCESS(status))
4147c2c66affSColin Finck     {
4148c2c66affSColin Finck         return RtlNtStatusToDosError(status);
4149c2c66affSColin Finck     }
4150c2c66affSColin Finck 
4151c2c66affSColin Finck     if (IsHKCRKey(hkey))
4152c2c66affSColin Finck     {
4153c2c66affSColin Finck         LONG ErrorCode = QueryHKCRValue(hkey, name, reserved, type, data, count);
4154c2c66affSColin Finck         ClosePredefKey(hkey);
4155c2c66affSColin Finck         return ErrorCode;
4156c2c66affSColin Finck     }
4157c2c66affSColin Finck 
4158c2c66affSColin Finck     RtlInitUnicodeString( &name_str, name );
4159c2c66affSColin Finck 
4160c2c66affSColin Finck     if (data)
4161c2c66affSColin Finck         total_size = min( sizeof(buffer), *count + info_size );
4162c2c66affSColin Finck     else
4163c2c66affSColin Finck         total_size = info_size;
4164c2c66affSColin Finck 
4165c2c66affSColin Finck 
4166c2c66affSColin Finck     status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
4167c2c66affSColin Finck                               buffer, total_size, &total_size );
4168c2c66affSColin Finck 
4169c2c66affSColin Finck     if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW)
4170c2c66affSColin Finck     {
4171c2c66affSColin Finck         // NT: Valid handles with inexistant/null values or invalid (but not NULL) handles sets type to REG_NONE
4172c2c66affSColin Finck         // On windows these conditions are likely to be side effects of the implementation...
4173c2c66affSColin Finck         if (status == STATUS_INVALID_HANDLE && hkey)
4174c2c66affSColin Finck         {
4175c2c66affSColin Finck             if (type) *type = REG_NONE;
4176c2c66affSColin Finck             if (count) *count = 0;
4177c2c66affSColin Finck         }
4178c2c66affSColin Finck         else if (status == STATUS_OBJECT_NAME_NOT_FOUND)
4179c2c66affSColin Finck         {
4180c2c66affSColin Finck             if (type) *type = REG_NONE;
4181c2c66affSColin Finck             if (data == NULL && count) *count = 0;
4182c2c66affSColin Finck         }
4183c2c66affSColin Finck         goto done;
4184c2c66affSColin Finck     }
4185c2c66affSColin Finck 
4186c2c66affSColin Finck     if (data)
4187c2c66affSColin Finck     {
4188c2c66affSColin Finck         /* retry with a dynamically allocated buffer */
4189c2c66affSColin Finck         while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count)
4190c2c66affSColin Finck         {
4191c2c66affSColin Finck             if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
4192c2c66affSColin Finck             if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
4193c2c66affSColin Finck             {
4194c2c66affSColin Finck                 ClosePredefKey(hkey);
4195c2c66affSColin Finck                 return ERROR_NOT_ENOUGH_MEMORY;
4196c2c66affSColin Finck             }
4197c2c66affSColin Finck             info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr;
4198c2c66affSColin Finck             status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
4199c2c66affSColin Finck                                       buf_ptr, total_size, &total_size );
4200c2c66affSColin Finck         }
4201c2c66affSColin Finck 
4202c2c66affSColin Finck         if (NT_SUCCESS(status))
4203c2c66affSColin Finck         {
4204c2c66affSColin Finck             memcpy( data, buf_ptr + info_size, total_size - info_size );
4205c2c66affSColin Finck             /* if the type is REG_SZ and data is not 0-terminated
4206c2c66affSColin Finck              * and there is enough space in the buffer NT appends a \0 */
4207c2c66affSColin Finck             if (is_string(info->Type) && total_size - info_size <= *count-sizeof(WCHAR))
4208c2c66affSColin Finck             {
4209c2c66affSColin Finck                 WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
4210c2c66affSColin Finck                 if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
4211c2c66affSColin Finck             }
4212c2c66affSColin Finck         }
4213c2c66affSColin Finck         else if (status != STATUS_BUFFER_OVERFLOW) goto done;
4214c2c66affSColin Finck     }
4215c2c66affSColin Finck     else status = STATUS_SUCCESS;
4216c2c66affSColin Finck 
4217c2c66affSColin Finck     if (type) *type = info->Type;
4218c2c66affSColin Finck     if (count) *count = total_size - info_size;
4219c2c66affSColin Finck 
4220c2c66affSColin Finck  done:
4221c2c66affSColin Finck     if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
4222c2c66affSColin Finck     ClosePredefKey(hkey);
4223c2c66affSColin Finck     return RtlNtStatusToDosError(status);
4224c2c66affSColin Finck }
4225c2c66affSColin Finck 
4226c2c66affSColin Finck 
4227c2c66affSColin Finck /************************************************************************
4228c2c66affSColin Finck  *  RegQueryValueA
4229c2c66affSColin Finck  *
4230c2c66affSColin Finck  * @implemented
4231c2c66affSColin Finck  */
4232c2c66affSColin Finck LSTATUS WINAPI RegQueryValueA( HKEY hkey, LPCSTR name, LPSTR data, LPLONG count )
4233c2c66affSColin Finck {
4234c2c66affSColin Finck     DWORD ret;
4235c2c66affSColin Finck     HKEY subkey = hkey;
4236c2c66affSColin Finck 
4237c2c66affSColin Finck     TRACE("(%p,%s,%p,%d)\n", hkey, debugstr_a(name), data, count ? *count : 0 );
4238c2c66affSColin Finck 
4239c2c66affSColin Finck     if (name && name[0])
4240c2c66affSColin Finck     {
4241c2c66affSColin Finck     if ((ret = RegOpenKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
4242c2c66affSColin Finck     }
4243c2c66affSColin Finck     ret = RegQueryValueExA( subkey, NULL, NULL, NULL, (LPBYTE)data, (LPDWORD)count );
4244c2c66affSColin Finck     if (subkey != hkey) RegCloseKey( subkey );
4245c2c66affSColin Finck     if (ret == ERROR_FILE_NOT_FOUND)
4246c2c66affSColin Finck     {
4247c2c66affSColin Finck     /* return empty string if default value not found */
4248c2c66affSColin Finck     if (data) *data = 0;
4249c2c66affSColin Finck     if (count) *count = 1;
4250c2c66affSColin Finck     ret = ERROR_SUCCESS;
4251c2c66affSColin Finck     }
4252c2c66affSColin Finck     return ret;
4253c2c66affSColin Finck }
4254c2c66affSColin Finck 
4255c2c66affSColin Finck 
4256c2c66affSColin Finck /************************************************************************
4257c2c66affSColin Finck  *  RegQueryValueW
4258c2c66affSColin Finck  *
4259c2c66affSColin Finck  * @implemented
4260c2c66affSColin Finck  */
4261c2c66affSColin Finck LSTATUS WINAPI RegQueryValueW( HKEY hkey, LPCWSTR name, LPWSTR data, LPLONG count )
4262c2c66affSColin Finck {
4263c2c66affSColin Finck     DWORD ret;
4264c2c66affSColin Finck     HKEY subkey = hkey;
4265c2c66affSColin Finck 
4266c2c66affSColin Finck     TRACE("(%p,%s,%p,%d)\n", hkey, debugstr_w(name), data, count ? *count : 0 );
4267c2c66affSColin Finck     if (hkey == NULL)
4268c2c66affSColin Finck     {
4269c2c66affSColin Finck        return ERROR_INVALID_HANDLE;
4270c2c66affSColin Finck     }
4271c2c66affSColin Finck     if (name && name[0])
4272c2c66affSColin Finck     {
4273c2c66affSColin Finck         ret = RegOpenKeyW( hkey, name, &subkey);
4274c2c66affSColin Finck         if (ret != ERROR_SUCCESS)
4275c2c66affSColin Finck         {
4276c2c66affSColin Finck             return ret;
4277c2c66affSColin Finck         }
4278c2c66affSColin Finck     }
4279c2c66affSColin Finck 
4280c2c66affSColin Finck     ret = RegQueryValueExW( subkey, NULL, NULL, NULL, (LPBYTE)data, (LPDWORD)count );
4281c2c66affSColin Finck 
4282c2c66affSColin Finck     if (subkey != hkey)
4283c2c66affSColin Finck     {
4284c2c66affSColin Finck         RegCloseKey( subkey );
4285c2c66affSColin Finck     }
4286c2c66affSColin Finck 
4287c2c66affSColin Finck     if (ret == ERROR_FILE_NOT_FOUND)
4288c2c66affSColin Finck     {
4289c2c66affSColin Finck         /* return empty string if default value not found */
4290c2c66affSColin Finck         if (data)
4291c2c66affSColin Finck             *data = 0;
4292c2c66affSColin Finck         if (count)
4293c2c66affSColin Finck             *count = sizeof(WCHAR);
4294c2c66affSColin Finck         ret = ERROR_SUCCESS;
4295c2c66affSColin Finck     }
4296c2c66affSColin Finck     return ret;
4297c2c66affSColin Finck }
4298c2c66affSColin Finck 
4299c2c66affSColin Finck 
4300c2c66affSColin Finck /************************************************************************
4301c2c66affSColin Finck  *  RegReplaceKeyA
4302c2c66affSColin Finck  *
4303c2c66affSColin Finck  * @implemented
4304c2c66affSColin Finck  */
4305c2c66affSColin Finck LONG WINAPI
4306c2c66affSColin Finck RegReplaceKeyA(HKEY hKey,
4307c2c66affSColin Finck                LPCSTR lpSubKey,
4308c2c66affSColin Finck                LPCSTR lpNewFile,
4309c2c66affSColin Finck                LPCSTR lpOldFile)
4310c2c66affSColin Finck {
4311c2c66affSColin Finck     UNICODE_STRING SubKey;
4312c2c66affSColin Finck     UNICODE_STRING NewFile;
4313c2c66affSColin Finck     UNICODE_STRING OldFile;
4314c2c66affSColin Finck     LONG ErrorCode;
4315c2c66affSColin Finck 
4316c2c66affSColin Finck     RtlInitEmptyUnicodeString(&SubKey, NULL, 0);
4317c2c66affSColin Finck     RtlInitEmptyUnicodeString(&OldFile, NULL, 0);
4318c2c66affSColin Finck     RtlInitEmptyUnicodeString(&NewFile, NULL, 0);
4319c2c66affSColin Finck 
4320c2c66affSColin Finck     if (lpSubKey)
4321c2c66affSColin Finck     {
4322c2c66affSColin Finck         if (!RtlCreateUnicodeStringFromAsciiz(&SubKey, lpSubKey))
4323c2c66affSColin Finck         {
4324c2c66affSColin Finck             ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
4325c2c66affSColin Finck             goto Exit;
4326c2c66affSColin Finck         }
4327c2c66affSColin Finck     }
4328c2c66affSColin Finck 
4329c2c66affSColin Finck     if (lpOldFile)
4330c2c66affSColin Finck     {
4331c2c66affSColin Finck         if (!RtlCreateUnicodeStringFromAsciiz(&OldFile, lpOldFile))
4332c2c66affSColin Finck         {
4333c2c66affSColin Finck             ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
4334c2c66affSColin Finck             goto Exit;
4335c2c66affSColin Finck         }
4336c2c66affSColin Finck     }
4337c2c66affSColin Finck 
4338c2c66affSColin Finck     if (lpNewFile)
4339c2c66affSColin Finck     {
4340c2c66affSColin Finck         if (!RtlCreateUnicodeStringFromAsciiz(&NewFile, lpNewFile))
4341c2c66affSColin Finck         {
4342c2c66affSColin Finck             ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
4343c2c66affSColin Finck             goto Exit;
4344c2c66affSColin Finck         }
4345c2c66affSColin Finck     }
4346c2c66affSColin Finck 
4347c2c66affSColin Finck     ErrorCode = RegReplaceKeyW(hKey,
4348c2c66affSColin Finck                                SubKey.Buffer,
4349c2c66affSColin Finck                                NewFile.Buffer,
4350c2c66affSColin Finck                                OldFile.Buffer);
4351c2c66affSColin Finck 
4352c2c66affSColin Finck Exit:
4353c2c66affSColin Finck     RtlFreeUnicodeString(&OldFile);
4354c2c66affSColin Finck     RtlFreeUnicodeString(&NewFile);
4355c2c66affSColin Finck     RtlFreeUnicodeString(&SubKey);
4356c2c66affSColin Finck 
4357c2c66affSColin Finck     return ErrorCode;
4358c2c66affSColin Finck }
4359c2c66affSColin Finck 
4360c2c66affSColin Finck 
4361c2c66affSColin Finck /************************************************************************
4362c2c66affSColin Finck  *  RegReplaceKeyW
4363c2c66affSColin Finck  *
4364c2c66affSColin Finck  * @unimplemented
4365c2c66affSColin Finck  */
4366c2c66affSColin Finck LONG WINAPI
4367c2c66affSColin Finck RegReplaceKeyW(HKEY hKey,
4368c2c66affSColin Finck                LPCWSTR lpSubKey,
4369c2c66affSColin Finck                LPCWSTR lpNewFile,
4370c2c66affSColin Finck                LPCWSTR lpOldFile)
4371c2c66affSColin Finck {
4372c2c66affSColin Finck     OBJECT_ATTRIBUTES KeyObjectAttributes;
4373c2c66affSColin Finck     OBJECT_ATTRIBUTES NewObjectAttributes;
4374c2c66affSColin Finck     OBJECT_ATTRIBUTES OldObjectAttributes;
4375c2c66affSColin Finck     UNICODE_STRING SubKeyName;
4376c2c66affSColin Finck     UNICODE_STRING NewFileName;
4377c2c66affSColin Finck     UNICODE_STRING OldFileName;
4378c2c66affSColin Finck     BOOLEAN CloseRealKey;
4379c2c66affSColin Finck     HANDLE RealKeyHandle;
4380c2c66affSColin Finck     HANDLE KeyHandle;
4381c2c66affSColin Finck     NTSTATUS Status;
4382c2c66affSColin Finck     LONG ErrorCode = ERROR_SUCCESS;
4383c2c66affSColin Finck 
4384c2c66affSColin Finck     if (hKey == HKEY_PERFORMANCE_DATA)
4385c2c66affSColin Finck     {
4386c2c66affSColin Finck         return ERROR_INVALID_HANDLE;
4387c2c66affSColin Finck     }
4388c2c66affSColin Finck 
4389c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
4390c2c66affSColin Finck                            hKey);
4391c2c66affSColin Finck     if (!NT_SUCCESS(Status))
4392c2c66affSColin Finck     {
4393c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
4394c2c66affSColin Finck     }
4395c2c66affSColin Finck 
4396c2c66affSColin Finck     /* Open the real key */
4397c2c66affSColin Finck     if (lpSubKey != NULL && *lpSubKey != (WCHAR)0)
4398c2c66affSColin Finck     {
439946259092SSerge Gautherie         RtlInitUnicodeString(&SubKeyName, lpSubKey);
4400c2c66affSColin Finck         InitializeObjectAttributes(&KeyObjectAttributes,
4401c2c66affSColin Finck                                    &SubKeyName,
4402c2c66affSColin Finck                                    OBJ_CASE_INSENSITIVE,
4403c2c66affSColin Finck                                    KeyHandle,
4404c2c66affSColin Finck                                    NULL);
4405c2c66affSColin Finck         Status = NtOpenKey(&RealKeyHandle,
4406c2c66affSColin Finck                            MAXIMUM_ALLOWED,
4407c2c66affSColin Finck                            &KeyObjectAttributes);
4408c2c66affSColin Finck         if (!NT_SUCCESS(Status))
4409c2c66affSColin Finck         {
4410c2c66affSColin Finck             ErrorCode = RtlNtStatusToDosError(Status);
4411c2c66affSColin Finck             goto Cleanup;
4412c2c66affSColin Finck         }
4413c2c66affSColin Finck 
4414c2c66affSColin Finck         CloseRealKey = TRUE;
4415c2c66affSColin Finck     }
4416c2c66affSColin Finck     else
4417c2c66affSColin Finck     {
4418c2c66affSColin Finck         RealKeyHandle = KeyHandle;
4419c2c66affSColin Finck         CloseRealKey = FALSE;
4420c2c66affSColin Finck     }
4421c2c66affSColin Finck 
4422c2c66affSColin Finck     /* Convert new file name */
4423c2c66affSColin Finck     if (!RtlDosPathNameToNtPathName_U(lpNewFile,
4424c2c66affSColin Finck                                       &NewFileName,
4425c2c66affSColin Finck                                       NULL,
4426c2c66affSColin Finck                                       NULL))
4427c2c66affSColin Finck     {
4428c2c66affSColin Finck         if (CloseRealKey)
4429c2c66affSColin Finck         {
4430c2c66affSColin Finck             NtClose(RealKeyHandle);
4431c2c66affSColin Finck         }
4432c2c66affSColin Finck 
4433c2c66affSColin Finck         ErrorCode = ERROR_INVALID_PARAMETER;
4434c2c66affSColin Finck         goto Cleanup;
4435c2c66affSColin Finck     }
4436c2c66affSColin Finck 
4437c2c66affSColin Finck     InitializeObjectAttributes(&NewObjectAttributes,
4438c2c66affSColin Finck                                &NewFileName,
4439c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
4440c2c66affSColin Finck                                NULL,
4441c2c66affSColin Finck                                NULL);
4442c2c66affSColin Finck 
4443c2c66affSColin Finck     /* Convert old file name */
4444c2c66affSColin Finck     if (!RtlDosPathNameToNtPathName_U(lpOldFile,
4445c2c66affSColin Finck                                       &OldFileName,
4446c2c66affSColin Finck                                       NULL,
4447c2c66affSColin Finck                                       NULL))
4448c2c66affSColin Finck     {
4449c2c66affSColin Finck         RtlFreeHeap(RtlGetProcessHeap (),
4450c2c66affSColin Finck                     0,
4451c2c66affSColin Finck                     NewFileName.Buffer);
4452c2c66affSColin Finck         if (CloseRealKey)
4453c2c66affSColin Finck         {
4454c2c66affSColin Finck             NtClose(RealKeyHandle);
4455c2c66affSColin Finck         }
4456c2c66affSColin Finck 
4457c2c66affSColin Finck         ErrorCode = ERROR_INVALID_PARAMETER;
4458c2c66affSColin Finck         goto Cleanup;
4459c2c66affSColin Finck     }
4460c2c66affSColin Finck 
4461c2c66affSColin Finck     InitializeObjectAttributes(&OldObjectAttributes,
4462c2c66affSColin Finck                                &OldFileName,
4463c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
4464c2c66affSColin Finck                                NULL,
4465c2c66affSColin Finck                                NULL);
4466c2c66affSColin Finck 
4467c2c66affSColin Finck     Status = NtReplaceKey(&NewObjectAttributes,
4468c2c66affSColin Finck                           RealKeyHandle,
4469c2c66affSColin Finck                           &OldObjectAttributes);
4470c2c66affSColin Finck 
4471c2c66affSColin Finck     RtlFreeHeap(RtlGetProcessHeap(),
4472c2c66affSColin Finck                 0,
4473c2c66affSColin Finck                 OldFileName.Buffer);
4474c2c66affSColin Finck     RtlFreeHeap(RtlGetProcessHeap(),
4475c2c66affSColin Finck                 0,
4476c2c66affSColin Finck                 NewFileName.Buffer);
4477c2c66affSColin Finck 
4478c2c66affSColin Finck     if (CloseRealKey)
4479c2c66affSColin Finck     {
4480c2c66affSColin Finck         NtClose(RealKeyHandle);
4481c2c66affSColin Finck     }
4482c2c66affSColin Finck 
4483c2c66affSColin Finck     if (!NT_SUCCESS(Status))
4484c2c66affSColin Finck     {
4485c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
4486c2c66affSColin Finck     }
4487c2c66affSColin Finck 
4488c2c66affSColin Finck Cleanup:
4489c2c66affSColin Finck     ClosePredefKey(KeyHandle);
4490c2c66affSColin Finck 
4491c2c66affSColin Finck     return ErrorCode;
4492c2c66affSColin Finck }
4493c2c66affSColin Finck 
4494c2c66affSColin Finck 
4495c2c66affSColin Finck /************************************************************************
4496c2c66affSColin Finck  *  RegRestoreKeyA
4497c2c66affSColin Finck  *
4498c2c66affSColin Finck  * @implemented
4499c2c66affSColin Finck  */
4500c2c66affSColin Finck LONG WINAPI
4501c2c66affSColin Finck RegRestoreKeyA(HKEY hKey,
4502c2c66affSColin Finck                LPCSTR lpFile,
4503c2c66affSColin Finck                DWORD dwFlags)
4504c2c66affSColin Finck {
4505c2c66affSColin Finck     UNICODE_STRING FileName;
4506c2c66affSColin Finck     LONG ErrorCode;
4507c2c66affSColin Finck 
4508c2c66affSColin Finck     if (lpFile)
4509c2c66affSColin Finck     {
4510c2c66affSColin Finck         if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFile))
4511c2c66affSColin Finck             return ERROR_NOT_ENOUGH_MEMORY;
4512c2c66affSColin Finck     }
4513c2c66affSColin Finck     else
4514c2c66affSColin Finck         RtlInitEmptyUnicodeString(&FileName, NULL, 0);
4515c2c66affSColin Finck 
4516c2c66affSColin Finck     ErrorCode = RegRestoreKeyW(hKey,
4517c2c66affSColin Finck                                FileName.Buffer,
4518c2c66affSColin Finck                                dwFlags);
4519c2c66affSColin Finck 
4520c2c66affSColin Finck     RtlFreeUnicodeString(&FileName);
4521c2c66affSColin Finck 
4522c2c66affSColin Finck     return ErrorCode;
4523c2c66affSColin Finck }
4524c2c66affSColin Finck 
4525c2c66affSColin Finck 
4526c2c66affSColin Finck /************************************************************************
4527c2c66affSColin Finck  *  RegRestoreKeyW
4528c2c66affSColin Finck  *
4529c2c66affSColin Finck  * @implemented
4530c2c66affSColin Finck  */
4531c2c66affSColin Finck LONG WINAPI
4532c2c66affSColin Finck RegRestoreKeyW(HKEY hKey,
4533c2c66affSColin Finck                LPCWSTR lpFile,
4534c2c66affSColin Finck                DWORD dwFlags)
4535c2c66affSColin Finck {
4536c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
4537c2c66affSColin Finck     IO_STATUS_BLOCK IoStatusBlock;
4538c2c66affSColin Finck     UNICODE_STRING FileName;
4539c2c66affSColin Finck     HANDLE FileHandle;
4540c2c66affSColin Finck     HANDLE KeyHandle;
4541c2c66affSColin Finck     NTSTATUS Status;
4542c2c66affSColin Finck 
4543c2c66affSColin Finck     if (hKey == HKEY_PERFORMANCE_DATA)
4544c2c66affSColin Finck     {
4545c2c66affSColin Finck         return ERROR_INVALID_HANDLE;
4546c2c66affSColin Finck     }
4547c2c66affSColin Finck 
4548c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
4549c2c66affSColin Finck                            hKey);
4550c2c66affSColin Finck     if (!NT_SUCCESS(Status))
4551c2c66affSColin Finck     {
4552c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
4553c2c66affSColin Finck     }
4554c2c66affSColin Finck 
4555c2c66affSColin Finck     if (!RtlDosPathNameToNtPathName_U(lpFile,
4556c2c66affSColin Finck                                       &FileName,
4557c2c66affSColin Finck                                       NULL,
4558c2c66affSColin Finck                                       NULL))
4559c2c66affSColin Finck     {
4560c2c66affSColin Finck         Status = STATUS_INVALID_PARAMETER;
4561c2c66affSColin Finck         goto Cleanup;
4562c2c66affSColin Finck     }
4563c2c66affSColin Finck 
4564c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
4565c2c66affSColin Finck                                &FileName,
4566c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
4567c2c66affSColin Finck                                NULL,
4568c2c66affSColin Finck                                NULL);
4569c2c66affSColin Finck 
4570c2c66affSColin Finck     Status = NtOpenFile(&FileHandle,
4571c2c66affSColin Finck                         FILE_GENERIC_READ,
4572c2c66affSColin Finck                         &ObjectAttributes,
4573c2c66affSColin Finck                         &IoStatusBlock,
4574c2c66affSColin Finck                         FILE_SHARE_READ,
4575c2c66affSColin Finck                         FILE_SYNCHRONOUS_IO_NONALERT);
4576c2c66affSColin Finck     RtlFreeHeap(RtlGetProcessHeap(),
4577c2c66affSColin Finck                 0,
4578c2c66affSColin Finck                 FileName.Buffer);
4579c2c66affSColin Finck     if (!NT_SUCCESS(Status))
4580c2c66affSColin Finck     {
4581c2c66affSColin Finck         goto Cleanup;
4582c2c66affSColin Finck     }
4583c2c66affSColin Finck 
4584c2c66affSColin Finck     Status = NtRestoreKey(KeyHandle,
4585c2c66affSColin Finck                           FileHandle,
4586c2c66affSColin Finck                           (ULONG)dwFlags);
4587c2c66affSColin Finck     NtClose (FileHandle);
4588c2c66affSColin Finck 
4589c2c66affSColin Finck Cleanup:
4590c2c66affSColin Finck     ClosePredefKey(KeyHandle);
4591c2c66affSColin Finck 
4592c2c66affSColin Finck     if (!NT_SUCCESS(Status))
4593c2c66affSColin Finck     {
4594c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
4595c2c66affSColin Finck     }
4596c2c66affSColin Finck 
4597c2c66affSColin Finck     return ERROR_SUCCESS;
4598c2c66affSColin Finck }
4599c2c66affSColin Finck 
4600c2c66affSColin Finck 
4601c2c66affSColin Finck /************************************************************************
4602c2c66affSColin Finck  *  RegSaveKeyA
4603c2c66affSColin Finck  *
4604c2c66affSColin Finck  * @implemented
4605c2c66affSColin Finck  */
4606c2c66affSColin Finck LONG WINAPI
4607c2c66affSColin Finck RegSaveKeyA(HKEY hKey,
4608c2c66affSColin Finck             LPCSTR lpFile,
4609c2c66affSColin Finck             LPSECURITY_ATTRIBUTES lpSecurityAttributes)
4610c2c66affSColin Finck {
4611c2c66affSColin Finck     UNICODE_STRING FileName;
4612c2c66affSColin Finck     LONG ErrorCode;
4613c2c66affSColin Finck 
4614c2c66affSColin Finck     if (lpFile)
4615c2c66affSColin Finck     {
4616c2c66affSColin Finck         if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFile))
4617c2c66affSColin Finck             return ERROR_NOT_ENOUGH_MEMORY;
4618c2c66affSColin Finck     }
4619c2c66affSColin Finck     else
4620c2c66affSColin Finck         RtlInitEmptyUnicodeString(&FileName, NULL, 0);
4621c2c66affSColin Finck 
4622c2c66affSColin Finck     ErrorCode = RegSaveKeyW(hKey,
4623c2c66affSColin Finck                             FileName.Buffer,
4624c2c66affSColin Finck                             lpSecurityAttributes);
4625c2c66affSColin Finck     RtlFreeUnicodeString(&FileName);
4626c2c66affSColin Finck 
4627c2c66affSColin Finck     return ErrorCode;
4628c2c66affSColin Finck }
4629c2c66affSColin Finck 
4630c2c66affSColin Finck 
4631c2c66affSColin Finck /************************************************************************
4632c2c66affSColin Finck  *  RegSaveKeyW
4633c2c66affSColin Finck  *
4634c2c66affSColin Finck  * @implemented
4635c2c66affSColin Finck  */
4636c2c66affSColin Finck LONG WINAPI
4637c2c66affSColin Finck RegSaveKeyW(HKEY hKey,
4638c2c66affSColin Finck             LPCWSTR lpFile,
4639c2c66affSColin Finck             LPSECURITY_ATTRIBUTES lpSecurityAttributes)
4640c2c66affSColin Finck {
4641c2c66affSColin Finck     PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
4642c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
4643c2c66affSColin Finck     UNICODE_STRING FileName;
4644c2c66affSColin Finck     IO_STATUS_BLOCK IoStatusBlock;
4645c2c66affSColin Finck     HANDLE FileHandle;
4646c2c66affSColin Finck     HANDLE KeyHandle;
4647c2c66affSColin Finck     NTSTATUS Status;
4648c2c66affSColin Finck 
4649c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
4650c2c66affSColin Finck                            hKey);
4651c2c66affSColin Finck     if (!NT_SUCCESS(Status))
4652c2c66affSColin Finck     {
4653c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
4654c2c66affSColin Finck     }
4655c2c66affSColin Finck 
4656c2c66affSColin Finck     if (!RtlDosPathNameToNtPathName_U(lpFile,
4657c2c66affSColin Finck                                       &FileName,
4658c2c66affSColin Finck                                       NULL,
4659c2c66affSColin Finck                                       NULL))
4660c2c66affSColin Finck     {
4661c2c66affSColin Finck         Status = STATUS_INVALID_PARAMETER;
4662c2c66affSColin Finck         goto Cleanup;
4663c2c66affSColin Finck     }
4664c2c66affSColin Finck 
4665c2c66affSColin Finck     if (lpSecurityAttributes != NULL)
4666c2c66affSColin Finck     {
4667c2c66affSColin Finck         SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
4668c2c66affSColin Finck     }
4669c2c66affSColin Finck 
4670c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
4671c2c66affSColin Finck                                &FileName,
4672c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
4673c2c66affSColin Finck                                NULL,
4674c2c66affSColin Finck                                SecurityDescriptor);
4675c2c66affSColin Finck     Status = NtCreateFile(&FileHandle,
4676c2c66affSColin Finck                           GENERIC_WRITE | SYNCHRONIZE,
4677c2c66affSColin Finck                           &ObjectAttributes,
4678c2c66affSColin Finck                           &IoStatusBlock,
4679c2c66affSColin Finck                           NULL,
4680c2c66affSColin Finck                           FILE_ATTRIBUTE_NORMAL,
4681c2c66affSColin Finck                           FILE_SHARE_READ,
4682c2c66affSColin Finck                           FILE_CREATE,
4683c2c66affSColin Finck                           FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
4684c2c66affSColin Finck                           NULL,
4685c2c66affSColin Finck                           0);
4686c2c66affSColin Finck     RtlFreeHeap(RtlGetProcessHeap(),
4687c2c66affSColin Finck                 0,
4688c2c66affSColin Finck                 FileName.Buffer);
4689c2c66affSColin Finck     if (!NT_SUCCESS(Status))
4690c2c66affSColin Finck     {
4691c2c66affSColin Finck         goto Cleanup;
4692c2c66affSColin Finck     }
4693c2c66affSColin Finck 
4694c2c66affSColin Finck     Status = NtSaveKey(KeyHandle,
4695c2c66affSColin Finck                        FileHandle);
4696c2c66affSColin Finck     NtClose (FileHandle);
4697c2c66affSColin Finck 
4698c2c66affSColin Finck Cleanup:
4699c2c66affSColin Finck     ClosePredefKey(KeyHandle);
4700c2c66affSColin Finck 
4701c2c66affSColin Finck     if (!NT_SUCCESS(Status))
4702c2c66affSColin Finck     {
4703c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
4704c2c66affSColin Finck     }
4705c2c66affSColin Finck 
4706c2c66affSColin Finck     return ERROR_SUCCESS;
4707c2c66affSColin Finck }
4708c2c66affSColin Finck 
4709c2c66affSColin Finck 
4710c2c66affSColin Finck /************************************************************************
4711c2c66affSColin Finck  *  RegSaveKeyExA
4712c2c66affSColin Finck  *
4713c2c66affSColin Finck  * @implemented
4714c2c66affSColin Finck  */
4715c2c66affSColin Finck LONG
4716c2c66affSColin Finck WINAPI
4717c2c66affSColin Finck RegSaveKeyExA(HKEY hKey,
4718c2c66affSColin Finck               LPCSTR lpFile,
4719c2c66affSColin Finck               LPSECURITY_ATTRIBUTES lpSecurityAttributes,
4720c2c66affSColin Finck               DWORD Flags)
4721c2c66affSColin Finck {
4722c2c66affSColin Finck     UNICODE_STRING FileName;
4723c2c66affSColin Finck     LONG ErrorCode;
4724c2c66affSColin Finck 
4725c2c66affSColin Finck     if (lpFile)
4726c2c66affSColin Finck     {
4727c2c66affSColin Finck         if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFile))
4728c2c66affSColin Finck             return ERROR_NOT_ENOUGH_MEMORY;
4729c2c66affSColin Finck     }
4730c2c66affSColin Finck     else
4731c2c66affSColin Finck         RtlInitEmptyUnicodeString(&FileName, NULL, 0);
4732c2c66affSColin Finck 
4733c2c66affSColin Finck     ErrorCode = RegSaveKeyExW(hKey,
4734c2c66affSColin Finck                               FileName.Buffer,
4735c2c66affSColin Finck                               lpSecurityAttributes,
4736c2c66affSColin Finck                               Flags);
4737c2c66affSColin Finck     RtlFreeUnicodeString(&FileName);
4738c2c66affSColin Finck 
4739c2c66affSColin Finck     return ErrorCode;
4740c2c66affSColin Finck }
4741c2c66affSColin Finck 
4742c2c66affSColin Finck 
4743c2c66affSColin Finck /************************************************************************
4744c2c66affSColin Finck  *  RegSaveKeyExW
4745c2c66affSColin Finck  *
4746c2c66affSColin Finck  * @unimplemented
4747c2c66affSColin Finck  */
4748c2c66affSColin Finck LONG
4749c2c66affSColin Finck WINAPI
4750c2c66affSColin Finck RegSaveKeyExW(HKEY hKey,
4751c2c66affSColin Finck               LPCWSTR lpFile,
4752c2c66affSColin Finck               LPSECURITY_ATTRIBUTES lpSecurityAttributes,
4753c2c66affSColin Finck               DWORD Flags)
4754c2c66affSColin Finck {
4755c2c66affSColin Finck     switch (Flags)
4756c2c66affSColin Finck     {
4757c2c66affSColin Finck         case REG_STANDARD_FORMAT:
4758c2c66affSColin Finck         case REG_LATEST_FORMAT:
4759c2c66affSColin Finck         case REG_NO_COMPRESSION:
4760c2c66affSColin Finck             break;
4761c2c66affSColin Finck         default:
4762c2c66affSColin Finck             return ERROR_INVALID_PARAMETER;
4763c2c66affSColin Finck     }
4764c2c66affSColin Finck 
4765c2c66affSColin Finck     FIXME("RegSaveKeyExW(): Flags ignored!\n");
4766c2c66affSColin Finck 
4767c2c66affSColin Finck     return RegSaveKeyW(hKey,
4768c2c66affSColin Finck                        lpFile,
4769c2c66affSColin Finck                        lpSecurityAttributes);
4770c2c66affSColin Finck }
4771c2c66affSColin Finck 
4772c2c66affSColin Finck 
4773c2c66affSColin Finck /************************************************************************
4774c2c66affSColin Finck  *  RegSetKeySecurity
4775c2c66affSColin Finck  *
4776c2c66affSColin Finck  * @implemented
4777c2c66affSColin Finck  */
4778c2c66affSColin Finck LONG WINAPI
4779c2c66affSColin Finck RegSetKeySecurity(HKEY hKey,
4780c2c66affSColin Finck                   SECURITY_INFORMATION SecurityInformation,
4781c2c66affSColin Finck                   PSECURITY_DESCRIPTOR pSecurityDescriptor)
4782c2c66affSColin Finck {
4783c2c66affSColin Finck     HANDLE KeyHandle;
4784c2c66affSColin Finck     NTSTATUS Status;
4785c2c66affSColin Finck 
4786c2c66affSColin Finck     if (hKey == HKEY_PERFORMANCE_DATA)
4787c2c66affSColin Finck     {
4788c2c66affSColin Finck         return ERROR_INVALID_HANDLE;
4789c2c66affSColin Finck     }
4790c2c66affSColin Finck 
4791c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
4792c2c66affSColin Finck                            hKey);
4793c2c66affSColin Finck     if (!NT_SUCCESS(Status))
4794c2c66affSColin Finck     {
4795c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
4796c2c66affSColin Finck     }
4797c2c66affSColin Finck 
4798c2c66affSColin Finck     Status = NtSetSecurityObject(KeyHandle,
4799c2c66affSColin Finck                                  SecurityInformation,
4800c2c66affSColin Finck                                  pSecurityDescriptor);
4801c2c66affSColin Finck 
4802c2c66affSColin Finck     ClosePredefKey(KeyHandle);
4803c2c66affSColin Finck 
4804c2c66affSColin Finck     if (!NT_SUCCESS(Status))
4805c2c66affSColin Finck     {
4806c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
4807c2c66affSColin Finck     }
4808c2c66affSColin Finck 
4809c2c66affSColin Finck     return ERROR_SUCCESS;
4810c2c66affSColin Finck }
4811c2c66affSColin Finck 
4812c2c66affSColin Finck 
4813c2c66affSColin Finck /************************************************************************
4814c2c66affSColin Finck  *  RegSetValueExA
4815c2c66affSColin Finck  *
4816c2c66affSColin Finck  * @implemented
4817c2c66affSColin Finck  */
4818c2c66affSColin Finck LONG WINAPI
4819c2c66affSColin Finck RegSetValueExA(HKEY hKey,
4820c2c66affSColin Finck                LPCSTR lpValueName,
4821c2c66affSColin Finck                DWORD Reserved,
4822c2c66affSColin Finck                DWORD dwType,
4823c2c66affSColin Finck                CONST BYTE* lpData,
4824c2c66affSColin Finck                DWORD cbData)
4825c2c66affSColin Finck {
4826c2c66affSColin Finck     UNICODE_STRING ValueName;
4827c2c66affSColin Finck     LPWSTR pValueName;
4828c2c66affSColin Finck     ANSI_STRING AnsiString;
4829c2c66affSColin Finck     UNICODE_STRING Data;
4830c2c66affSColin Finck     LONG ErrorCode;
4831c2c66affSColin Finck     LPBYTE pData;
4832c2c66affSColin Finck     DWORD DataSize;
4833c2c66affSColin Finck     NTSTATUS Status;
4834c2c66affSColin Finck 
4835c2c66affSColin Finck     /* Convert SubKey name to Unicode */
4836c2c66affSColin Finck     if (lpValueName != NULL && lpValueName[0] != '\0')
4837c2c66affSColin Finck     {
483846259092SSerge Gautherie         if (!RtlCreateUnicodeStringFromAsciiz(&ValueName, lpValueName))
4839c2c66affSColin Finck             return ERROR_NOT_ENOUGH_MEMORY;
4840c2c66affSColin Finck     }
4841c2c66affSColin Finck     else
4842c2c66affSColin Finck     {
4843c2c66affSColin Finck         ValueName.Buffer = NULL;
4844c2c66affSColin Finck     }
4845c2c66affSColin Finck 
4846c2c66affSColin Finck     pValueName = (LPWSTR)ValueName.Buffer;
4847c2c66affSColin Finck 
4848c2c66affSColin Finck 
4849c2c66affSColin Finck     if (is_string(dwType) && (cbData != 0))
4850c2c66affSColin Finck     {
4851c2c66affSColin Finck         /* Convert ANSI string Data to Unicode */
4852c2c66affSColin Finck         /* If last character NOT zero then increment length */
4853c2c66affSColin Finck         LONG bNoNulledStr = ((lpData[cbData-1] != '\0') ? 1 : 0);
4854c2c66affSColin Finck         AnsiString.Buffer = (PSTR)lpData;
4855c2c66affSColin Finck         AnsiString.Length = cbData + bNoNulledStr;
4856c2c66affSColin Finck         AnsiString.MaximumLength = cbData + bNoNulledStr;
4857c2c66affSColin Finck         Status = RtlAnsiStringToUnicodeString(&Data,
4858c2c66affSColin Finck                                      &AnsiString,
4859c2c66affSColin Finck                                      TRUE);
4860c2c66affSColin Finck 
4861c2c66affSColin Finck         if (!NT_SUCCESS(Status))
4862c2c66affSColin Finck         {
4863c2c66affSColin Finck             if (pValueName != NULL)
4864c2c66affSColin Finck                 RtlFreeUnicodeString(&ValueName);
4865c2c66affSColin Finck 
4866c2c66affSColin Finck             return RtlNtStatusToDosError(Status);
4867c2c66affSColin Finck         }
4868c2c66affSColin Finck         pData = (LPBYTE)Data.Buffer;
4869c2c66affSColin Finck         DataSize = cbData * sizeof(WCHAR);
4870c2c66affSColin Finck     }
4871c2c66affSColin Finck     else
4872c2c66affSColin Finck     {
4873c2c66affSColin Finck         Data.Buffer = NULL;
4874c2c66affSColin Finck         pData = (LPBYTE)lpData;
4875c2c66affSColin Finck         DataSize = cbData;
4876c2c66affSColin Finck     }
4877c2c66affSColin Finck 
4878c2c66affSColin Finck     ErrorCode = RegSetValueExW(hKey,
4879c2c66affSColin Finck                                pValueName,
4880c2c66affSColin Finck                                Reserved,
4881c2c66affSColin Finck                                dwType,
4882c2c66affSColin Finck                                pData,
4883c2c66affSColin Finck                                DataSize);
4884c2c66affSColin Finck 
4885c2c66affSColin Finck     if (pValueName != NULL)
4886c2c66affSColin Finck         RtlFreeUnicodeString(&ValueName);
4887c2c66affSColin Finck 
4888c2c66affSColin Finck     if (Data.Buffer != NULL)
4889c2c66affSColin Finck         RtlFreeUnicodeString(&Data);
4890c2c66affSColin Finck 
4891c2c66affSColin Finck     return ErrorCode;
4892c2c66affSColin Finck }
4893c2c66affSColin Finck 
4894c2c66affSColin Finck 
4895c2c66affSColin Finck /************************************************************************
4896c2c66affSColin Finck  *  RegSetValueExW
4897c2c66affSColin Finck  *
4898c2c66affSColin Finck  * @implemented
4899c2c66affSColin Finck  */
4900c2c66affSColin Finck LONG
4901c2c66affSColin Finck WINAPI
4902c2c66affSColin Finck RegSetValueExW(
4903c2c66affSColin Finck     _In_ HKEY hKey,
4904c2c66affSColin Finck     _In_ LPCWSTR lpValueName,
4905c2c66affSColin Finck     _In_ DWORD Reserved,
4906c2c66affSColin Finck     _In_ DWORD dwType,
4907c2c66affSColin Finck     _In_ CONST BYTE* lpData,
4908c2c66affSColin Finck     _In_ DWORD cbData)
4909c2c66affSColin Finck {
4910c2c66affSColin Finck     UNICODE_STRING ValueName;
4911c2c66affSColin Finck     HANDLE KeyHandle;
4912c2c66affSColin Finck     NTSTATUS Status;
4913c2c66affSColin Finck 
4914c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle,
4915c2c66affSColin Finck                            hKey);
4916c2c66affSColin Finck     if (!NT_SUCCESS(Status))
4917c2c66affSColin Finck     {
4918c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
4919c2c66affSColin Finck     }
4920c2c66affSColin Finck 
4921c2c66affSColin Finck     if (IsHKCRKey(KeyHandle))
4922c2c66affSColin Finck     {
4923c2c66affSColin Finck         LONG ErrorCode = SetHKCRValue(KeyHandle, lpValueName, Reserved, dwType, lpData, cbData);
4924c2c66affSColin Finck         ClosePredefKey(KeyHandle);
4925c2c66affSColin Finck         return ErrorCode;
4926c2c66affSColin Finck     }
4927c2c66affSColin Finck 
4928c2c66affSColin Finck     if (is_string(dwType) && (cbData != 0))
4929c2c66affSColin Finck     {
4930c2c66affSColin Finck         PWSTR pwsData = (PWSTR)lpData;
4931c2c66affSColin Finck 
4932c2c66affSColin Finck         _SEH2_TRY
4933c2c66affSColin Finck         {
4934c2c66affSColin Finck             if((pwsData[cbData / sizeof(WCHAR) - 1] != L'\0') &&
4935c2c66affSColin Finck                 (pwsData[cbData / sizeof(WCHAR)] == L'\0'))
4936c2c66affSColin Finck             {
4937c2c66affSColin Finck                 /* Increment length if last character is not zero and next is zero */
4938c2c66affSColin Finck                 cbData += sizeof(WCHAR);
4939c2c66affSColin Finck             }
4940c2c66affSColin Finck         }
4941c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
4942c2c66affSColin Finck         {
494342b94e72SJérôme Gardou             /* Do not fail if we fault where we were told not to go */
4944c2c66affSColin Finck         }
4945c2c66affSColin Finck         _SEH2_END;
4946c2c66affSColin Finck     }
4947c2c66affSColin Finck 
4948c2c66affSColin Finck     RtlInitUnicodeString(&ValueName, lpValueName);
4949c2c66affSColin Finck 
4950c2c66affSColin Finck     Status = NtSetValueKey(KeyHandle,
4951c2c66affSColin Finck                            &ValueName,
4952c2c66affSColin Finck                            0,
4953c2c66affSColin Finck                            dwType,
4954c2c66affSColin Finck                            (PVOID)lpData,
4955c2c66affSColin Finck                            (ULONG)cbData);
4956c2c66affSColin Finck 
4957c2c66affSColin Finck     ClosePredefKey(KeyHandle);
4958c2c66affSColin Finck 
4959c2c66affSColin Finck     if (!NT_SUCCESS(Status))
4960c2c66affSColin Finck     {
4961c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
4962c2c66affSColin Finck     }
4963c2c66affSColin Finck 
4964c2c66affSColin Finck     return ERROR_SUCCESS;
4965c2c66affSColin Finck }
4966c2c66affSColin Finck 
4967c2c66affSColin Finck 
4968c2c66affSColin Finck /************************************************************************
4969c2c66affSColin Finck  *  RegSetValueA
4970c2c66affSColin Finck  *
4971c2c66affSColin Finck  * @implemented
4972c2c66affSColin Finck  */
4973c2c66affSColin Finck LONG WINAPI
4974c2c66affSColin Finck RegSetValueA(HKEY hKeyOriginal,
4975c2c66affSColin Finck              LPCSTR lpSubKey,
4976c2c66affSColin Finck              DWORD dwType,
4977c2c66affSColin Finck              LPCSTR lpData,
4978c2c66affSColin Finck              DWORD cbData)
4979c2c66affSColin Finck {
4980c2c66affSColin Finck     HKEY subkey;
4981c2c66affSColin Finck     HANDLE hKey;
4982c2c66affSColin Finck     DWORD ret;
4983c2c66affSColin Finck     NTSTATUS Status;
4984c2c66affSColin Finck 
4985c2c66affSColin Finck     TRACE("(%p,%s,%d,%s,%d)\n", hKeyOriginal, debugstr_a(lpSubKey), dwType, debugstr_a(lpData), cbData );
4986c2c66affSColin Finck 
4987c2c66affSColin Finck     if (dwType != REG_SZ || !lpData) return ERROR_INVALID_PARAMETER;
4988c2c66affSColin Finck 
4989c2c66affSColin Finck     Status = MapDefaultKey(&hKey, hKeyOriginal);
4990c2c66affSColin Finck     if (!NT_SUCCESS(Status))
4991c2c66affSColin Finck     {
4992c2c66affSColin Finck         return RtlNtStatusToDosError (Status);
4993c2c66affSColin Finck     }
4994c2c66affSColin Finck     subkey = hKey;
4995c2c66affSColin Finck 
4996c2c66affSColin Finck     if (lpSubKey && lpSubKey[0])  /* need to create the subkey */
4997c2c66affSColin Finck     {
4998c2c66affSColin Finck         ret = RegCreateKeyA(hKey, lpSubKey, &subkey);
4999c2c66affSColin Finck         if (ret != ERROR_SUCCESS)
5000c2c66affSColin Finck             goto Cleanup;
5001c2c66affSColin Finck     }
5002c2c66affSColin Finck 
5003c2c66affSColin Finck     ret = RegSetValueExA( subkey, NULL, 0, REG_SZ, (const BYTE*)lpData, strlen(lpData)+1 );
5004c2c66affSColin Finck     if (subkey != hKey)
5005c2c66affSColin Finck         RegCloseKey(subkey);
5006c2c66affSColin Finck 
5007c2c66affSColin Finck Cleanup:
5008c2c66affSColin Finck     ClosePredefKey(hKey);
5009c2c66affSColin Finck 
5010c2c66affSColin Finck     return ret;
5011c2c66affSColin Finck }
5012c2c66affSColin Finck 
5013c2c66affSColin Finck 
5014c2c66affSColin Finck /************************************************************************
5015c2c66affSColin Finck  *  RegSetValueW
5016c2c66affSColin Finck  *
5017c2c66affSColin Finck  * @implemented
5018c2c66affSColin Finck  */
5019c2c66affSColin Finck LONG WINAPI
5020c2c66affSColin Finck RegSetValueW(HKEY hKeyOriginal,
5021c2c66affSColin Finck              LPCWSTR lpSubKey,
5022c2c66affSColin Finck              DWORD dwType,
5023c2c66affSColin Finck              LPCWSTR lpData,
5024c2c66affSColin Finck              DWORD cbData)
5025c2c66affSColin Finck {
5026c2c66affSColin Finck     HKEY subkey;
5027c2c66affSColin Finck     HANDLE hKey;
5028c2c66affSColin Finck     DWORD ret;
5029c2c66affSColin Finck     NTSTATUS Status;
5030c2c66affSColin Finck 
5031c2c66affSColin Finck     TRACE("(%p,%s,%d,%s,%d)\n", hKeyOriginal, debugstr_w(lpSubKey), dwType, debugstr_w(lpData), cbData );
5032c2c66affSColin Finck 
5033c2c66affSColin Finck     if (dwType != REG_SZ || !lpData)
5034c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
5035c2c66affSColin Finck 
5036c2c66affSColin Finck     Status = MapDefaultKey(&hKey,
5037c2c66affSColin Finck                            hKeyOriginal);
5038c2c66affSColin Finck     if (!NT_SUCCESS(Status))
5039c2c66affSColin Finck     {
5040c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
5041c2c66affSColin Finck     }
5042c2c66affSColin Finck     subkey = hKey;
5043c2c66affSColin Finck 
5044c2c66affSColin Finck     if (lpSubKey && lpSubKey[0])  /* need to create the subkey */
5045c2c66affSColin Finck     {
5046c2c66affSColin Finck         ret = RegCreateKeyW(hKey, lpSubKey, &subkey);
5047c2c66affSColin Finck         if (ret != ERROR_SUCCESS)
5048c2c66affSColin Finck             goto Cleanup;
5049c2c66affSColin Finck     }
5050c2c66affSColin Finck 
5051c2c66affSColin Finck     ret = RegSetValueExW( subkey, NULL, 0, REG_SZ, (const BYTE*)lpData,
5052c2c66affSColin Finck                           (wcslen( lpData ) + 1) * sizeof(WCHAR) );
5053c2c66affSColin Finck     if (subkey != hKey)
5054c2c66affSColin Finck         RegCloseKey(subkey);
5055c2c66affSColin Finck 
5056c2c66affSColin Finck Cleanup:
5057c2c66affSColin Finck     ClosePredefKey(hKey);
5058c2c66affSColin Finck 
5059c2c66affSColin Finck     return ret;
5060c2c66affSColin Finck }
5061c2c66affSColin Finck 
5062c2c66affSColin Finck 
5063c2c66affSColin Finck /************************************************************************
5064c2c66affSColin Finck  *  RegUnLoadKeyA
5065c2c66affSColin Finck  *
5066c2c66affSColin Finck  * @implemented
5067c2c66affSColin Finck  */
5068c2c66affSColin Finck LONG WINAPI
5069c2c66affSColin Finck RegUnLoadKeyA(HKEY hKey,
5070c2c66affSColin Finck               LPCSTR lpSubKey)
5071c2c66affSColin Finck {
5072c2c66affSColin Finck     UNICODE_STRING KeyName;
5073c2c66affSColin Finck     DWORD ErrorCode;
5074c2c66affSColin Finck 
5075c2c66affSColin Finck     if (lpSubKey)
5076c2c66affSColin Finck     {
5077c2c66affSColin Finck         if (!RtlCreateUnicodeStringFromAsciiz(&KeyName, lpSubKey))
5078c2c66affSColin Finck             return ERROR_NOT_ENOUGH_MEMORY;
5079c2c66affSColin Finck     }
5080c2c66affSColin Finck     else
5081c2c66affSColin Finck         RtlInitEmptyUnicodeString(&KeyName, NULL, 0);
5082c2c66affSColin Finck 
5083c2c66affSColin Finck     ErrorCode = RegUnLoadKeyW(hKey,
5084c2c66affSColin Finck                               KeyName.Buffer);
5085c2c66affSColin Finck 
5086c2c66affSColin Finck     RtlFreeUnicodeString (&KeyName);
5087c2c66affSColin Finck 
5088c2c66affSColin Finck     return ErrorCode;
5089c2c66affSColin Finck }
5090c2c66affSColin Finck 
5091c2c66affSColin Finck 
5092c2c66affSColin Finck /************************************************************************
5093c2c66affSColin Finck  *  RegUnLoadKeyW
5094c2c66affSColin Finck  *
5095c2c66affSColin Finck  * @implemented
5096c2c66affSColin Finck  */
5097c2c66affSColin Finck LONG WINAPI
5098c2c66affSColin Finck RegUnLoadKeyW(HKEY hKey,
5099c2c66affSColin Finck               LPCWSTR lpSubKey)
5100c2c66affSColin Finck {
5101c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
5102c2c66affSColin Finck     UNICODE_STRING KeyName;
5103c2c66affSColin Finck     HANDLE KeyHandle;
5104c2c66affSColin Finck     NTSTATUS Status;
5105c2c66affSColin Finck 
5106c2c66affSColin Finck     if (hKey == HKEY_PERFORMANCE_DATA)
5107c2c66affSColin Finck     {
5108c2c66affSColin Finck       return ERROR_INVALID_HANDLE;
5109c2c66affSColin Finck     }
5110c2c66affSColin Finck 
5111c2c66affSColin Finck     Status = MapDefaultKey(&KeyHandle, hKey);
5112c2c66affSColin Finck     if (!NT_SUCCESS(Status))
5113c2c66affSColin Finck     {
5114c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
5115c2c66affSColin Finck     }
5116c2c66affSColin Finck 
511746259092SSerge Gautherie     RtlInitUnicodeString(&KeyName, lpSubKey);
5118c2c66affSColin Finck 
5119c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
5120c2c66affSColin Finck                                &KeyName,
5121c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
5122c2c66affSColin Finck                                KeyHandle,
5123c2c66affSColin Finck                                NULL);
5124c2c66affSColin Finck 
5125c2c66affSColin Finck     Status = NtUnloadKey(&ObjectAttributes);
5126c2c66affSColin Finck 
5127c2c66affSColin Finck     ClosePredefKey(KeyHandle);
5128c2c66affSColin Finck 
5129c2c66affSColin Finck     if (!NT_SUCCESS(Status))
5130c2c66affSColin Finck     {
5131c2c66affSColin Finck         return RtlNtStatusToDosError(Status);
5132c2c66affSColin Finck     }
5133c2c66affSColin Finck 
5134c2c66affSColin Finck     return ERROR_SUCCESS;
5135c2c66affSColin Finck }
5136c2c66affSColin Finck 
5137c2c66affSColin Finck /* EOF */
5138