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