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