-/* $Id: reg.c,v 1.11 2000/09/27 01:21:27 ekohl Exp $
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* UPDATE HISTORY:
* Created 01/11/98
* 19990309 EA Stubs
+ * 20050502 Fireball imported some stuff from WINE
*/
-#include <ddk/ntddk.h>
-#include <ntdll/rtl.h>
-#include <windows.h>
-#include <wchar.h>
+/* INCLUDES *****************************************************************/
+
+#include <advapi32.h>
#define NDEBUG
-#include <debug.h>
+#include <wine/debug.h>
-/* GLOBALS *******************************************************************/
+/* DEFINES ******************************************************************/
-#define MAX_DEFAULT_HANDLES 7
+#define MAX_DEFAULT_HANDLES 6
+#define REG_MAX_NAME_SIZE 256
+#define REG_MAX_DATA_SIZE 2048
-static CRITICAL_SECTION HandleTableCS;
-static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES];
+/* FIXME: should go into msvcrt.h header? */
+#define offsetof(s,m) (size_t)&(((s*)NULL)->m)
+/* GLOBALS ******************************************************************/
+
+static RTL_CRITICAL_SECTION HandleTableCS;
+static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES];
+static HANDLE ProcessHeap;
-/* PROTOTYPES ****************************************************************/
+/* PROTOTYPES ***************************************************************/
-static NTSTATUS MapDefaultKey (PHKEY ParentKey, HKEY Key);
+static NTSTATUS MapDefaultKey (PHANDLE ParentKey, HKEY Key);
static VOID CloseDefaultKeys(VOID);
+static NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle);
static NTSTATUS OpenLocalMachineKey (PHANDLE KeyHandle);
+static NTSTATUS OpenUsersKey (PHANDLE KeyHandle);
+static NTSTATUS OpenCurrentConfigKey(PHANDLE KeyHandle);
-/* FUNCTIONS *****************************************************************/
+/* FUNCTIONS ****************************************************************/
+/* check if value type needs string conversion (Ansi<->Unicode) */
+inline static int is_string( DWORD type )
+{
+ return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
+}
/************************************************************************
- * RegInitDefaultHandles
+ * RegInitDefaultHandles
*/
-
BOOL
RegInitialize (VOID)
{
- DPRINT("RegInitialize()\n");
+ TRACE("RegInitialize()\n");
- RtlZeroMemory (DefaultHandleTable,
- MAX_DEFAULT_HANDLES * sizeof(HANDLE));
+ ProcessHeap = RtlGetProcessHeap();
+ RtlZeroMemory (DefaultHandleTable,
+ MAX_DEFAULT_HANDLES * sizeof(HANDLE));
+ RtlInitializeCriticalSection (&HandleTableCS);
- RtlInitializeCriticalSection(&HandleTableCS);
- return TRUE;
+ return TRUE;
}
/************************************************************************
- * RegInit
+ * RegInit
*/
BOOL
-RegCleanup(VOID)
+RegCleanup (VOID)
{
- DPRINT("RegCleanup()\n");
+ TRACE("RegCleanup()\n");
+
+ CloseDefaultKeys ();
+ RtlDeleteCriticalSection (&HandleTableCS);
- CloseDefaultKeys();
- RtlDeleteCriticalSection(&HandleTableCS);
- return TRUE;
+ return TRUE;
}
static NTSTATUS
-MapDefaultKey (PHKEY RealKey,
- HKEY Key)
+MapDefaultKey (PHANDLE RealKey,
+ HKEY Key)
{
- PHANDLE Handle;
- ULONG Index;
- NTSTATUS Status = STATUS_SUCCESS;
-
- DPRINT("MapDefaultKey (Key %x)\n", Key);
-
- if (((ULONG)Key & 0xF0000000) != 0x80000000)
- {
- *RealKey = Key;
- return STATUS_SUCCESS;
- }
-
- /* Handle special cases here */
- Index = (ULONG)Key & 0x0FFFFFFF;
-
- if (Index >= MAX_DEFAULT_HANDLES)
- return STATUS_INVALID_PARAMETER;
-
- RtlEnterCriticalSection(&HandleTableCS);
-
- Handle = &DefaultHandleTable[Index];
- if (*Handle == NULL)
- {
- /* create/open the default handle */
- switch (Index)
- {
- case 2: /*HKEY_LOCAL_MACHINE */
- Status = OpenLocalMachineKey(Handle);
- break;
-
- default:
- DPRINT("MapDefaultHandle() no handle creator\n");
- Status = STATUS_INVALID_PARAMETER;
- }
- }
-
- RtlLeaveCriticalSection(&HandleTableCS);
+ PHANDLE Handle;
+ ULONG Index;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ TRACE("MapDefaultKey (Key %x)\n", Key);
+
+ if (((ULONG)Key & 0xF0000000) != 0x80000000)
+ {
+ *RealKey = (HANDLE)Key;
+ return STATUS_SUCCESS;
+ }
+
+ /* Handle special cases here */
+ Index = (ULONG)Key & 0x0FFFFFFF;
+ if (Index >= MAX_DEFAULT_HANDLES)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ RtlEnterCriticalSection (&HandleTableCS);
+ Handle = &DefaultHandleTable[Index];
+ if (*Handle == NULL)
+ {
+ /* create/open the default handle */
+ switch (Index)
+ {
+ case 0: /* HKEY_CLASSES_ROOT */
+ Status = OpenClassesRootKey (Handle);
+ break;
+
+ case 1: /* HKEY_CURRENT_USER */
+ Status = RtlOpenCurrentUser (MAXIMUM_ALLOWED,
+ Handle);
+ break;
+
+ case 2: /* HKEY_LOCAL_MACHINE */
+ Status = OpenLocalMachineKey (Handle);
+ break;
+
+ case 3: /* HKEY_USERS */
+ Status = OpenUsersKey (Handle);
+ break;
+#if 0
+ case 4: /* HKEY_PERFORMANCE_DATA */
+ Status = OpenPerformanceDataKey (Handle);
+ break;
+#endif
+ case 5: /* HKEY_CURRENT_CONFIG */
+ Status = OpenCurrentConfigKey (Handle);
+ break;
+
+ case 6: /* HKEY_DYN_DATA */
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ default:
+ WARN("MapDefaultHandle() no handle creator\n");
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ }
+ RtlLeaveCriticalSection (&HandleTableCS);
- if (NT_SUCCESS(Status))
- {
- *RealKey = (HKEY)*Handle;
- }
+ if (NT_SUCCESS(Status))
+ {
+ *RealKey = *Handle;
+ }
return Status;
}
-static VOID CloseDefaultKeys (VOID)
+static VOID
+CloseDefaultKeys (VOID)
{
- ULONG i;
+ ULONG i;
- RtlEnterCriticalSection(&HandleTableCS);
+ RtlEnterCriticalSection (&HandleTableCS);
+ for (i = 0; i < MAX_DEFAULT_HANDLES; i++)
+ {
+ if (DefaultHandleTable[i] != NULL)
+ {
+ NtClose (DefaultHandleTable[i]);
+ DefaultHandleTable[i] = NULL;
+ }
+ }
+ RtlLeaveCriticalSection (&HandleTableCS);
+}
- for (i = 0; i < MAX_DEFAULT_HANDLES; i++)
- {
- if (DefaultHandleTable[i] != NULL)
- {
- NtClose (DefaultHandleTable[i]);
- DefaultHandleTable[i] = NULL;
- }
- }
- RtlLeaveCriticalSection(&HandleTableCS);
+static NTSTATUS
+OpenClassesRootKey (PHANDLE KeyHandle)
+{
+ OBJECT_ATTRIBUTES Attributes;
+ UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\CLASSES");
+
+ TRACE("OpenClassesRootKey()\n");
+
+ InitializeObjectAttributes (&Attributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ return NtOpenKey (KeyHandle,
+ MAXIMUM_ALLOWED,
+ &Attributes);
}
static NTSTATUS
OpenLocalMachineKey (PHANDLE KeyHandle)
{
- OBJECT_ATTRIBUTES Attributes;
- UNICODE_STRING KeyName;
+ OBJECT_ATTRIBUTES Attributes;
+ UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine");
+ NTSTATUS Status;
+
+ TRACE("OpenLocalMachineKey()\n");
+
+ InitializeObjectAttributes (&Attributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status = NtOpenKey (KeyHandle,
+ MAXIMUM_ALLOWED,
+ &Attributes);
+
+ TRACE("NtOpenKey(%wZ) => %08x\n", &KeyName, Status);
+ return Status;
+}
- DPRINT("OpenLocalMachineKey()\n");
- RtlInitUnicodeString(&KeyName,
- L"\\Registry\\Machine");
+static NTSTATUS
+OpenUsersKey (PHANDLE KeyHandle)
+{
+ OBJECT_ATTRIBUTES Attributes;
+ UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\User");
+
+ TRACE("OpenUsersKey()\n");
+
+ InitializeObjectAttributes (&Attributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ return NtOpenKey (KeyHandle,
+ MAXIMUM_ALLOWED,
+ &Attributes);
+}
- InitializeObjectAttributes(&Attributes,
- &KeyName,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
- return (NtOpenKey (KeyHandle,
- KEY_ALL_ACCESS,
- &Attributes));
+static NTSTATUS
+OpenCurrentConfigKey (PHANDLE KeyHandle)
+{
+ OBJECT_ATTRIBUTES Attributes;
+ UNICODE_STRING KeyName =
+ RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
+
+ TRACE("OpenCurrentConfigKey()\n");
+
+ InitializeObjectAttributes (&Attributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ return NtOpenKey (KeyHandle,
+ MAXIMUM_ALLOWED,
+ &Attributes);
}
/************************************************************************
- * RegCloseKey
+ * RegCloseKey
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegCloseKey(
- HKEY hKey
- )
+LONG STDCALL
+RegCloseKey (HKEY hKey)
{
- NTSTATUS Status;
+ NTSTATUS Status;
- /* don't close null handle or a pseudo handle */
- if ((!hKey) || (((ULONG)hKey & 0xF0000000) == 0x80000000))
- return ERROR_INVALID_HANDLE;
+ /* don't close null handle or a pseudo handle */
+ if ((!hKey) || (((ULONG)hKey & 0xF0000000) == 0x80000000))
+ {
+ return ERROR_INVALID_HANDLE;
+ }
- Status = NtClose (hKey);
- if (!NT_SUCCESS(Status))
- {
- LONG ErrorCode = RtlNtStatusToDosError(Status);
-
- SetLastError (ErrorCode);
- return ErrorCode;
- }
+ Status = NtClose (hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
- return ERROR_SUCCESS;
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegConnectRegistryA
+ * RegConnectRegistryA
+ *
+ * @unimplemented
*/
-LONG
-STDCALL
-RegConnectRegistryA(
- LPSTR lpMachineName,
- HKEY hKey,
- PHKEY phkResult
- )
+LONG STDCALL
+RegConnectRegistryA (LPCSTR lpMachineName,
+ HKEY hKey,
+ PHKEY phkResult)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
- * RegConnectRegistryW
+ * RegCopyTreeW
+ *
+ * @unimplemented
*/
-LONG
-STDCALL
-RegConnectRegistryW(
- LPWSTR lpMachineName,
- HKEY hKey,
- PHKEY phkResult
- )
+LONG STDCALL
+RegCopyTreeW(IN HKEY hKeySrc,
+ IN LPCWSTR lpSubKey OPTIONAL,
+ IN HKEY hKeyDest)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ HANDLE DestKeyHandle, KeyHandle, SubKeyHandle = NULL;
+ NTSTATUS Status;
+
+ Status = MapDefaultKey(&KeyHandle,
+ hKeySrc);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+
+ Status = MapDefaultKey(&DestKeyHandle,
+ hKeyDest);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+
+ if (lpSubKey != NULL)
+ {
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING SubKeyName;
+
+ RtlInitUnicodeString(&SubKeyName,
+ (LPWSTR)lpSubKey);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &SubKeyName,
+ OBJ_CASE_INSENSITIVE,
+ KeyHandle,
+ NULL);
+
+ Status = NtOpenKey(&SubKeyHandle,
+ KEY_READ,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+ }
+
+ /* FIXME - copy all keys and values recursively */
+ Status = STATUS_NOT_IMPLEMENTED;
+
+ if (SubKeyHandle != NULL)
+ {
+ NtClose(SubKeyHandle);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegCreateKeyA
+ * RegCopyTreeA
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegCreateKeyA(
- HKEY hKey,
- LPCSTR lpSubKey,
- PHKEY phkResult
- )
-{
- return RegCreateKeyExA(hKey,
- lpSubKey,
- 0,
- NULL,
- 0,
- KEY_ALL_ACCESS,
- NULL,
- phkResult,
- NULL);
+LONG STDCALL
+RegCopyTreeA(IN HKEY hKeySrc,
+ IN LPCSTR lpSubKey OPTIONAL,
+ IN HKEY hKeyDest)
+{
+ UNICODE_STRING SubKeyName;
+ LONG Ret;
+
+ if (lpSubKey != NULL)
+ {
+ if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName,
+ (LPSTR)lpSubKey))
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+ }
+ else
+ RtlInitUnicodeString(&SubKeyName,
+ NULL);
+
+ Ret = RegCopyTreeW(hKeySrc,
+ SubKeyName.Buffer,
+ hKeyDest);
+
+ RtlFreeUnicodeString(&SubKeyName);
+
+ return Ret;
}
/************************************************************************
- * RegCreateKeyW
+ * RegConnectRegistryW
+ *
+ * @unimplemented
*/
-LONG
-STDCALL
-RegCreateKeyW(
- HKEY hKey,
- LPCWSTR lpSubKey,
- PHKEY phkResult
- )
-{
- return RegCreateKeyExW(hKey,
- lpSubKey,
- 0,
- NULL,
- 0,
- KEY_ALL_ACCESS,
- NULL,
- phkResult,
- NULL);
+LONG STDCALL
+RegConnectRegistryW (LPCWSTR lpMachineName,
+ HKEY hKey,
+ PHKEY phkResult)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
- * RegCreateKeyExA
+ * CreateNestedKey
+ *
+ * Create key and all necessary intermediate keys
*/
-LONG
-STDCALL
-RegCreateKeyExA(
- HKEY hKey,
- LPCSTR lpSubKey,
- DWORD Reserved,
- LPSTR lpClass,
- DWORD dwOptions,
- REGSAM samDesired,
- LPSECURITY_ATTRIBUTES lpSecurityAttributes,
- PHKEY phkResult,
- LPDWORD lpdwDisposition
- )
+static NTSTATUS
+CreateNestedKey(PHKEY KeyHandle,
+ POBJECT_ATTRIBUTES ObjectAttributes,
+ PUNICODE_STRING ClassString,
+ DWORD dwOptions,
+ REGSAM samDesired,
+ DWORD *lpdwDisposition)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ OBJECT_ATTRIBUTES LocalObjectAttributes;
+ UNICODE_STRING LocalKeyName;
+ ULONG Disposition;
+ NTSTATUS Status;
+ ULONG FullNameLength;
+ ULONG Length;
+ PWCHAR Ptr;
+ HANDLE LocalKeyHandle;
+
+ Status = NtCreateKey((PHANDLE) KeyHandle,
+ samDesired,
+ ObjectAttributes,
+ 0,
+ ClassString,
+ dwOptions,
+ (PULONG)lpdwDisposition);
+ TRACE("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes->ObjectName, Status);
+ if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
+ return Status;
+
+ /* Copy object attributes */
+ RtlCopyMemory (&LocalObjectAttributes,
+ ObjectAttributes,
+ sizeof(OBJECT_ATTRIBUTES));
+ RtlCreateUnicodeString (&LocalKeyName,
+ ObjectAttributes->ObjectName->Buffer);
+ LocalObjectAttributes.ObjectName = &LocalKeyName;
+ FullNameLength = LocalKeyName.Length / sizeof(WCHAR);
+
+ /* Remove the last part of the key name and try to create the key again. */
+ while (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ Ptr = wcsrchr (LocalKeyName.Buffer, '\\');
+ if (Ptr == NULL || Ptr == LocalKeyName.Buffer)
+ {
+ Status = STATUS_UNSUCCESSFUL;
+ break;
+ }
+ *Ptr = (WCHAR)0;
+ LocalKeyName.Length = wcslen (LocalKeyName.Buffer) * sizeof(WCHAR);
+
+ Status = NtCreateKey (&LocalKeyHandle,
+ KEY_ALL_ACCESS,
+ &LocalObjectAttributes,
+ 0,
+ NULL,
+ 0,
+ &Disposition);
+ TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeUnicodeString (&LocalKeyName);
+ return Status;
+ }
+
+ /* Add removed parts of the key name and create them too. */
+ Length = wcslen (LocalKeyName.Buffer);
+ while (TRUE)
+ {
+ NtClose (LocalKeyHandle);
+
+ LocalKeyName.Buffer[Length] = L'\\';
+ Length = wcslen (LocalKeyName.Buffer);
+ LocalKeyName.Length = Length * sizeof(WCHAR);
+
+ if (Length == FullNameLength)
+ {
+ Status = NtCreateKey((PHANDLE) KeyHandle,
+ samDesired,
+ ObjectAttributes,
+ 0,
+ ClassString,
+ dwOptions,
+ (PULONG)lpdwDisposition);
+ break;
+ }
+ Status = NtCreateKey (&LocalKeyHandle,
+ KEY_CREATE_SUB_KEY,
+ &LocalObjectAttributes,
+ 0,
+ NULL,
+ 0,
+ &Disposition);
+ TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
+ if (!NT_SUCCESS(Status))
+ break;
+ }
+
+ RtlFreeUnicodeString (&LocalKeyName);
+
+ return Status;
}
/************************************************************************
- * RegCreateKeyExW
+ * RegCreateKeyExA
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegCreateKeyExW(
- HKEY hKey,
- LPCWSTR lpSubKey,
- DWORD Reserved,
- LPWSTR lpClass,
- DWORD dwOptions,
- REGSAM samDesired,
- LPSECURITY_ATTRIBUTES lpSecurityAttributes,
- PHKEY phkResult,
- LPDWORD lpdwDisposition
- )
+LONG STDCALL
+RegCreateKeyExA (HKEY hKey,
+ LPCSTR lpSubKey,
+ DWORD Reserved,
+ LPSTR lpClass,
+ DWORD dwOptions,
+ REGSAM samDesired,
+ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+ PHKEY phkResult,
+ LPDWORD lpdwDisposition)
{
- UNICODE_STRING SubKeyString;
- UNICODE_STRING ClassString;
- OBJECT_ATTRIBUTES Attributes;
- NTSTATUS Status;
- HKEY ParentKey;
-
- DPRINT("RegCreateKeyExW() called\n");
-
- /* get the real parent key */
- Status = MapDefaultKey (&ParentKey, hKey);
- if (!NT_SUCCESS(Status))
- {
- LONG ErrorCode = RtlNtStatusToDosError(Status);
-
- SetLastError (ErrorCode);
- return ErrorCode;
- }
-
- DPRINT("ParentKey %x\n", (ULONG)ParentKey);
-
- RtlInitUnicodeString (&ClassString, lpClass);
- RtlInitUnicodeString (&SubKeyString, lpSubKey);
-
- InitializeObjectAttributes (&Attributes,
- &SubKeyString,
- OBJ_CASE_INSENSITIVE,
- (HANDLE)ParentKey,
- (PSECURITY_DESCRIPTOR)lpSecurityAttributes);
-
- Status = NtCreateKey (phkResult,
- samDesired,
- &Attributes,
- 0,
- (lpClass == NULL)? NULL : &ClassString,
- dwOptions,
- (PULONG)lpdwDisposition);
- DPRINT("Status %x\n", Status);
- if (!NT_SUCCESS(Status))
- {
- LONG ErrorCode = RtlNtStatusToDosError(Status);
-
- SetLastError (ErrorCode);
- return ErrorCode;
- }
-
- return ERROR_SUCCESS;
+ UNICODE_STRING SubKeyString;
+ UNICODE_STRING ClassString;
+ OBJECT_ATTRIBUTES Attributes;
+ HANDLE ParentKey;
+ NTSTATUS Status;
+
+ TRACE("RegCreateKeyExA() called\n");
+
+ /* get the real parent key */
+ Status = MapDefaultKey (&ParentKey,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+ TRACE("ParentKey %x\n", (ULONG)ParentKey);
+
+ if (lpClass != NULL)
+ {
+ RtlCreateUnicodeStringFromAsciiz (&ClassString,
+ lpClass);
+ }
+
+ RtlCreateUnicodeStringFromAsciiz(&SubKeyString,
+ (LPSTR)lpSubKey);
+ InitializeObjectAttributes (&Attributes,
+ &SubKeyString,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)ParentKey,
+ (PSECURITY_DESCRIPTOR)lpSecurityAttributes);
+ Status = CreateNestedKey(phkResult,
+ &Attributes,
+ (lpClass == NULL)? NULL : &ClassString,
+ dwOptions,
+ samDesired,
+ lpdwDisposition);
+ RtlFreeUnicodeString (&SubKeyString);
+ if (lpClass != NULL)
+ {
+ RtlFreeUnicodeString (&ClassString);
+ }
+
+ TRACE("Status %x\n", Status);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegDeleteKeyA
+ * RegCreateKeyExW
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegDeleteKeyA(
- HKEY hKey,
- LPCSTR lpSubKey
- )
+LONG STDCALL
+RegCreateKeyExW (HKEY hKey,
+ LPCWSTR lpSubKey,
+ DWORD Reserved,
+ LPWSTR lpClass,
+ DWORD dwOptions,
+ REGSAM samDesired,
+ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+ PHKEY phkResult,
+ LPDWORD lpdwDisposition)
{
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING SubKeyStringW;
- ANSI_STRING SubKeyStringA;
- HANDLE ParentKey;
- HANDLE TargetKey;
- NTSTATUS Status;
- LONG ErrorCode;
-
- Status = MapDefaultKey(&ParentKey,
- hKey);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError(Status);
-
- SetLastError (ErrorCode);
- return ErrorCode;
- }
-
- RtlInitAnsiString(&SubKeyStringA,
- (LPSTR)lpSubKey);
- RtlAnsiStringToUnicodeString(&SubKeyStringW,
- &SubKeyStringA,
- TRUE);
-
- InitializeObjectAttributes (&ObjectAttributes,
- &SubKeyStringW,
- OBJ_CASE_INSENSITIVE,
- (HANDLE)ParentKey,
- NULL);
-
- Status = NtOpenKey (&TargetKey,
- DELETE,
- &ObjectAttributes);
-
- RtlFreeUnicodeString (&SubKeyStringW);
-
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError(Status);
-
- SetLastError (ErrorCode);
- return ErrorCode;
- }
-
- Status = NtDeleteKey(TargetKey);
-
- NtClose(TargetKey);
-
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError(Status);
-
- SetLastError (ErrorCode);
- return ErrorCode;
- }
- return ERROR_SUCCESS;
+ UNICODE_STRING SubKeyString;
+ UNICODE_STRING ClassString;
+ OBJECT_ATTRIBUTES Attributes;
+ HANDLE ParentKey;
+ NTSTATUS Status;
+
+ TRACE("RegCreateKeyExW() called\n");
+
+ /* get the real parent key */
+ Status = MapDefaultKey (&ParentKey,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+ TRACE("ParentKey %x\n", (ULONG)ParentKey);
+
+ RtlInitUnicodeString (&ClassString,
+ lpClass);
+ RtlInitUnicodeString (&SubKeyString,
+ lpSubKey);
+ InitializeObjectAttributes (&Attributes,
+ &SubKeyString,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)ParentKey,
+ (PSECURITY_DESCRIPTOR)lpSecurityAttributes);
+ Status = CreateNestedKey(phkResult,
+ &Attributes,
+ (lpClass == NULL)? NULL : &ClassString,
+ dwOptions,
+ samDesired,
+ lpdwDisposition);
+ TRACE("Status %x\n", Status);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegDeleteKeyW
+ * RegCreateKeyA
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegDeleteKeyW(
- HKEY hKey,
- LPCWSTR lpSubKey
- )
+LONG STDCALL
+RegCreateKeyA (HKEY hKey,
+ LPCSTR lpSubKey,
+ PHKEY phkResult)
{
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING SubKeyString;
- HANDLE ParentKey;
- HANDLE TargetKey;
- NTSTATUS Status;
- LONG ErrorCode;
-
- Status = MapDefaultKey(&ParentKey,
- hKey);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError(Status);
-
- SetLastError (ErrorCode);
- return ErrorCode;
- }
-
- RtlInitUnicodeString(&SubKeyString,
- (LPWSTR)lpSubKey);
-
- InitializeObjectAttributes (&ObjectAttributes,
- &SubKeyString,
- OBJ_CASE_INSENSITIVE,
- (HANDLE)ParentKey,
- NULL);
-
- Status = NtOpenKey (&TargetKey,
- DELETE,
- &ObjectAttributes);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError(Status);
+ return RegCreateKeyExA (hKey,
+ lpSubKey,
+ 0,
+ NULL,
+ 0,
+ MAXIMUM_ALLOWED,
+ NULL,
+ phkResult,
+ NULL);
+}
- SetLastError (ErrorCode);
- return ErrorCode;
- }
- Status = NtDeleteKey(TargetKey);
+/************************************************************************
+ * RegCreateKeyW
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegCreateKeyW (HKEY hKey,
+ LPCWSTR lpSubKey,
+ PHKEY phkResult)
+{
+ return RegCreateKeyExW (hKey,
+ lpSubKey,
+ 0,
+ NULL,
+ 0,
+ MAXIMUM_ALLOWED,
+ NULL,
+ phkResult,
+ NULL);
+}
- NtClose(TargetKey);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError(Status);
+/************************************************************************
+ * RegDeleteKeyA
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegDeleteKeyA (HKEY hKey,
+ LPCSTR lpSubKey)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING SubKeyName;
+ HANDLE ParentKey;
+ HANDLE TargetKey;
+ NTSTATUS Status;
+
+ Status = MapDefaultKey (&ParentKey,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ RtlCreateUnicodeStringFromAsciiz (&SubKeyName,
+ (LPSTR)lpSubKey);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &SubKeyName,
+ OBJ_CASE_INSENSITIVE,
+ ParentKey,
+ NULL);
- SetLastError (ErrorCode);
- return ErrorCode;
- }
- return ERROR_SUCCESS;
+ Status = NtOpenKey (&TargetKey,
+ DELETE,
+ &ObjectAttributes);
+ RtlFreeUnicodeString (&SubKeyName);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ Status = NtDeleteKey (TargetKey);
+ NtClose (TargetKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegDeleteValueA
+ * RegDeleteKeyW
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegDeleteValueA(
- HKEY hKey,
- LPCSTR lpValueName
- )
-{
- UNICODE_STRING ValueNameW;
- ANSI_STRING ValueNameA;
- NTSTATUS Status;
- LONG ErrorCode;
- HANDLE KeyHandle;
+LONG STDCALL
+RegDeleteKeyW (HKEY hKey,
+ LPCWSTR lpSubKey)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING SubKeyName;
+ HANDLE ParentKey;
+ HANDLE TargetKey;
+ NTSTATUS Status;
+
+ Status = MapDefaultKey (&ParentKey,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ RtlInitUnicodeString (&SubKeyName,
+ (LPWSTR)lpSubKey);
+ InitializeObjectAttributes (&ObjectAttributes,
+ &SubKeyName,
+ OBJ_CASE_INSENSITIVE,
+ ParentKey,
+ NULL);
+ Status = NtOpenKey (&TargetKey,
+ DELETE,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ Status = NtDeleteKey (TargetKey);
+ NtClose (TargetKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
+}
- Status = MapDefaultKey(&KeyHandle,
- hKey);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError(Status);
- SetLastError (ErrorCode);
- return ErrorCode;
- }
+/************************************************************************
+ * RegDeleteKeyValueW
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegDeleteKeyValueW(IN HKEY hKey,
+ IN LPCWSTR lpSubKey OPTIONAL,
+ IN LPCWSTR lpValueName OPTIONAL)
+{
+ UNICODE_STRING ValueName;
+ HANDLE KeyHandle, SubKeyHandle = NULL;
+ NTSTATUS Status;
+
+ Status = MapDefaultKey(&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+
+ if (lpSubKey != NULL)
+ {
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING SubKeyName;
+
+ RtlInitUnicodeString(&SubKeyName,
+ (LPWSTR)lpSubKey);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &SubKeyName,
+ OBJ_CASE_INSENSITIVE,
+ KeyHandle,
+ NULL);
+
+ Status = NtOpenKey(&SubKeyHandle,
+ KEY_SET_VALUE,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+ }
+
+ RtlInitUnicodeString(&ValueName,
+ (LPWSTR)lpValueName);
+
+ Status = NtDeleteValueKey((SubKeyHandle != NULL) ? SubKeyHandle : KeyHandle,
+ &ValueName);
+
+ if (SubKeyHandle != NULL)
+ {
+ NtClose(SubKeyHandle);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+
+ return ERROR_SUCCESS;
+}
- RtlInitAnsiString(&ValueNameA,
- (LPSTR)lpValueName);
- RtlAnsiStringToUnicodeString(&ValueNameW,
- &ValueNameA,
- TRUE);
- Status = NtDeleteValueKey(KeyHandle,
- &ValueNameW);
+/************************************************************************
+ * RegDeleteKeyValueA
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegDeleteKeyValueA(IN HKEY hKey,
+ IN LPCSTR lpSubKey OPTIONAL,
+ IN LPCSTR lpValueName OPTIONAL)
+{
+ UNICODE_STRING SubKey, ValueName;
+ LONG Ret;
+
+ if (lpSubKey != NULL)
+ {
+ if (!RtlCreateUnicodeStringFromAsciiz(&SubKey,
+ (LPSTR)lpSubKey))
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+ }
+ else
+ RtlInitUnicodeString(&SubKey,
+ NULL);
+
+ if (lpValueName != NULL)
+ {
+ if (!RtlCreateUnicodeStringFromAsciiz(&ValueName,
+ (LPSTR)lpValueName))
+ {
+ RtlFreeUnicodeString(&SubKey);
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+ }
+ else
+ RtlInitUnicodeString(&ValueName,
+ NULL);
+
+ Ret = RegDeleteKeyValueW(hKey,
+ SubKey.Buffer,
+ SubKey.Buffer);
+
+ RtlFreeUnicodeString(&SubKey);
+ RtlFreeUnicodeString(&ValueName);
+
+ return Ret;
+}
- RtlFreeUnicodeString (&ValueNameW);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError(Status);
+/************************************************************************
+ * RegDeleteTreeW
+ *
+ * @unimplemented
+ */
+LONG STDCALL
+RegDeleteTreeW(IN HKEY hKey,
+ IN LPCWSTR lpSubKey OPTIONAL)
+{
+ HANDLE KeyHandle, SubKeyHandle = NULL;
+ NTSTATUS Status;
+
+ Status = MapDefaultKey(&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+
+ if (lpSubKey != NULL)
+ {
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING SubKeyName;
+
+ RtlInitUnicodeString(&SubKeyName,
+ (LPWSTR)lpSubKey);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &SubKeyName,
+ OBJ_CASE_INSENSITIVE,
+ KeyHandle,
+ NULL);
+
+ Status = NtOpenKey(&SubKeyHandle,
+ DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+ }
+
+ /* FIXME - delete all keys recursively */
+ Status = STATUS_NOT_IMPLEMENTED;
+
+ if (SubKeyHandle != NULL)
+ {
+ NtClose(SubKeyHandle);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+
+ return ERROR_SUCCESS;
+}
- SetLastError (ErrorCode);
- return ErrorCode;
- }
- return ERROR_SUCCESS;
+/************************************************************************
+ * RegDeleteTreeA
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegDeleteTreeA(IN HKEY hKey,
+ IN LPCSTR lpSubKey OPTIONAL)
+{
+ UNICODE_STRING SubKeyName;
+ LONG Ret;
+
+ if (lpSubKey != NULL)
+ {
+ if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName,
+ (LPSTR)lpSubKey))
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+ }
+ else
+ RtlInitUnicodeString(&SubKeyName,
+ NULL);
+
+ Ret = RegDeleteTreeW(hKey,
+ SubKeyName.Buffer);
+
+ RtlFreeUnicodeString(&SubKeyName);
+
+ return Ret;
}
/************************************************************************
- * RegDeleteValueW
+ * RegSetKeyValueW
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegDeleteValueW(
- HKEY hKey,
- LPCWSTR lpValueName
- )
-{
- UNICODE_STRING ValueName;
- NTSTATUS Status;
- LONG ErrorCode;
- HANDLE KeyHandle;
+LONG STDCALL
+RegSetKeyValueW(IN HKEY hKey,
+ IN LPCWSTR lpSubKey OPTIONAL,
+ IN LPCWSTR lpValueName OPTIONAL,
+ IN DWORD dwType,
+ IN LPCVOID lpData OPTIONAL,
+ IN DWORD cbData)
+{
+ HANDLE KeyHandle, SubKeyHandle = NULL;
+ NTSTATUS Status;
+ LONG Ret;
+
+ Status = MapDefaultKey(&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+
+ if (lpSubKey != NULL)
+ {
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING SubKeyName;
+
+ RtlInitUnicodeString(&SubKeyName,
+ (LPWSTR)lpSubKey);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &SubKeyName,
+ OBJ_CASE_INSENSITIVE,
+ KeyHandle,
+ NULL);
+
+ Status = NtOpenKey(&SubKeyHandle,
+ KEY_SET_VALUE,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+ }
+
+ Ret = RegSetValueExW((SubKeyHandle != NULL) ? SubKeyHandle : KeyHandle,
+ lpValueName,
+ 0,
+ dwType,
+ lpData,
+ cbData);
+
+ if (SubKeyHandle != NULL)
+ {
+ NtClose(SubKeyHandle);
+ }
+
+ return Ret;
+}
- Status = MapDefaultKey(&KeyHandle,
- hKey);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError(Status);
- SetLastError (ErrorCode);
- return ErrorCode;
- }
+/************************************************************************
+ * RegSetKeyValueA
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegSetKeyValueA(IN HKEY hKey,
+ IN LPCSTR lpSubKey OPTIONAL,
+ IN LPCSTR lpValueName OPTIONAL,
+ IN DWORD dwType,
+ IN LPCVOID lpData OPTIONAL,
+ IN DWORD cbData)
+{
+ HANDLE KeyHandle, SubKeyHandle = NULL;
+ NTSTATUS Status;
+ LONG Ret;
+
+ Status = MapDefaultKey(&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+
+ if (lpSubKey != NULL)
+ {
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING SubKeyName;
+
+ if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName,
+ (LPSTR)lpSubKey))
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &SubKeyName,
+ OBJ_CASE_INSENSITIVE,
+ KeyHandle,
+ NULL);
+
+ Status = NtOpenKey(&SubKeyHandle,
+ KEY_SET_VALUE,
+ &ObjectAttributes);
+
+ RtlFreeUnicodeString(&SubKeyName);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+ }
+
+ Ret = RegSetValueExA((SubKeyHandle != NULL) ? SubKeyHandle : KeyHandle,
+ lpValueName,
+ 0,
+ dwType,
+ lpData,
+ cbData);
+
+ if (SubKeyHandle != NULL)
+ {
+ NtClose(SubKeyHandle);
+ }
+
+ return Ret;
+}
- RtlInitUnicodeString(&ValueName,
- (LPWSTR)lpValueName);
- Status = NtDeleteValueKey(KeyHandle,
- &ValueName);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError(Status);
+/************************************************************************
+ * RegDeleteValueA
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegDeleteValueA (HKEY hKey,
+ LPCSTR lpValueName)
+{
+ UNICODE_STRING ValueName;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+
+ Status = MapDefaultKey (&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ RtlCreateUnicodeStringFromAsciiz (&ValueName,
+ (LPSTR)lpValueName);
+ Status = NtDeleteValueKey (KeyHandle,
+ &ValueName);
+ RtlFreeUnicodeString (&ValueName);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
+}
- SetLastError (ErrorCode);
- return ErrorCode;
- }
- return ERROR_SUCCESS;
+/************************************************************************
+ * RegDeleteValueW
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegDeleteValueW (HKEY hKey,
+ LPCWSTR lpValueName)
+{
+ UNICODE_STRING ValueName;
+ NTSTATUS Status;
+ HANDLE KeyHandle;
+
+ Status = MapDefaultKey (&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ RtlInitUnicodeString (&ValueName,
+ (LPWSTR)lpValueName);
+
+ Status = NtDeleteValueKey (KeyHandle,
+ &ValueName);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegEnumKeyA
+ * RegEnumKeyA
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegEnumKeyA(
- HKEY hKey,
- DWORD dwIndex,
- LPSTR lpName,
- DWORD cbName
- )
-{
- DWORD dwLength = cbName;
-
- return RegEnumKeyExA(hKey,
- dwIndex,
- lpName,
- &dwLength,
- NULL,
- NULL,
- NULL,
- NULL);
+LONG STDCALL
+RegEnumKeyA (HKEY hKey,
+ DWORD dwIndex,
+ LPSTR lpName,
+ DWORD cbName)
+{
+ DWORD dwLength;
+
+ dwLength = cbName;
+ return RegEnumKeyExA (hKey,
+ dwIndex,
+ lpName,
+ &dwLength,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
}
/************************************************************************
- * RegEnumKeyExA
+ * RegEnumKeyW
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegEnumKeyExA(
- HKEY hKey,
- DWORD dwIndex,
- LPSTR lpName,
- LPDWORD lpcbName,
- LPDWORD lpReserved,
- LPSTR lpClass,
- LPDWORD lpcbClass,
- PFILETIME lpftLastWriteTime
- )
+LONG STDCALL
+RegEnumKeyW (HKEY hKey,
+ DWORD dwIndex,
+ LPWSTR lpName,
+ DWORD cbName)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ DWORD dwLength;
+
+ dwLength = cbName;
+ return RegEnumKeyExW (hKey,
+ dwIndex,
+ lpName,
+ &dwLength,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
}
/************************************************************************
- * RegEnumKeyExW
+ * RegEnumKeyExA
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegEnumKeyExW(
- HKEY hKey,
- DWORD dwIndex,
- LPWSTR lpName,
- LPDWORD lpcbName,
- LPDWORD lpReserved,
- LPWSTR lpClass,
- LPDWORD lpcbClass,
- PFILETIME lpftLastWriteTime
- )
-{
- PKEY_NODE_INFORMATION KeyInfo;
- NTSTATUS Status;
- DWORD dwError = ERROR_SUCCESS;
- ULONG BufferSize;
- ULONG ResultSize;
+LONG STDCALL
+RegEnumKeyExA (HKEY hKey,
+ DWORD dwIndex,
+ LPSTR lpName,
+ LPDWORD lpcbName,
+ LPDWORD lpReserved,
+ LPSTR lpClass,
+ LPDWORD lpcbClass,
+ PFILETIME lpftLastWriteTime)
+{
+ union
+ {
+ KEY_NODE_INFORMATION Node;
+ KEY_BASIC_INFORMATION Basic;
+ } *KeyInfo;
+
+ UNICODE_STRING StringU;
+ ANSI_STRING StringA;
+ LONG ErrorCode = ERROR_SUCCESS;
+ DWORD NameLength;
+ DWORD ClassLength = 0;
+ DWORD BufferSize;
+ DWORD ResultSize;
HANDLE KeyHandle;
+ NTSTATUS Status;
- Status = MapDefaultKey(&KeyHandle,
- hKey);
+ TRACE("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
+ hKey, dwIndex, lpName, *lpcbName, lpClass, lpcbClass ? *lpcbClass : 0);
+
+ if ((lpClass) && (!lpcbClass))
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ Status = MapDefaultKey(&KeyHandle, hKey);
if (!NT_SUCCESS(Status))
{
- dwError = RtlNtStatusToDosError(Status);
+ return RtlNtStatusToDosError (Status);
+ }
- SetLastError (dwError);
- return dwError;
+ if (*lpcbName > 0)
+ {
+ NameLength = min (*lpcbName - 1 , REG_MAX_NAME_SIZE) * sizeof (WCHAR);
+ }
+ else
+ {
+ NameLength = 0;
}
- BufferSize = sizeof (KEY_NODE_INFORMATION) +
- *lpcbName * sizeof(WCHAR);
if (lpClass)
- BufferSize += *lpcbClass;
- KeyInfo = RtlAllocateHeap (RtlGetProcessHeap(),
- 0,
- BufferSize);
+ {
+ if (*lpcbClass > 0)
+ {
+ ClassLength = min (*lpcbClass -1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
+ }
+ else
+ {
+ ClassLength = 0;
+ }
+
+ /* The class name should start at a dword boundary */
+ BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength + 3) & ~3) + ClassLength;
+ }
+ else
+ {
+ BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength;
+ }
+
+ KeyInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize);
if (KeyInfo == NULL)
+ {
return ERROR_OUTOFMEMORY;
+ }
Status = NtEnumerateKey (KeyHandle,
- (ULONG)dwIndex,
- KeyNodeInformation,
- KeyInfo,
- BufferSize,
- &ResultSize);
+ (ULONG)dwIndex,
+ lpClass == NULL ? KeyBasicInformation : KeyNodeInformation,
+ KeyInfo,
+ BufferSize,
+ &ResultSize);
+ TRACE("NtEnumerateKey() returned status 0x%X\n", Status);
if (!NT_SUCCESS(Status))
{
- dwError = RtlNtStatusToDosError(Status);
-
- SetLastError(dwError);
+ ErrorCode = RtlNtStatusToDosError (Status);
}
else
{
- memcpy (lpName, KeyInfo->Name, KeyInfo->NameLength);
- *lpcbName = (DWORD)(KeyInfo->NameLength / sizeof(WCHAR)) - 1;
-
- if (lpClass)
+ if (lpClass == NULL)
{
- memcpy (lpClass,
- KeyInfo->Name + KeyInfo->ClassOffset,
- KeyInfo->ClassLength);
- *lpcbClass = (DWORD)(KeyInfo->ClassLength / sizeof(WCHAR)) - 1;
+ if (KeyInfo->Basic.NameLength > NameLength)
+ {
+ ErrorCode = ERROR_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ StringU.Buffer = KeyInfo->Basic.Name;
+ StringU.Length = KeyInfo->Basic.NameLength;
+ StringU.MaximumLength = KeyInfo->Basic.NameLength;
+ }
}
-
- if (lpftLastWriteTime)
+ else
{
+ if (KeyInfo->Node.NameLength > NameLength ||
+ KeyInfo->Node.ClassLength > ClassLength)
+ {
+ ErrorCode = ERROR_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ StringA.Buffer = lpClass;
+ StringA.Length = 0;
+ StringA.MaximumLength = *lpcbClass;
+ StringU.Buffer = (PWCHAR)((ULONG_PTR)KeyInfo->Node.Name + KeyInfo->Node.ClassOffset);
+ StringU.Length = KeyInfo->Node.ClassLength;
+ StringU.MaximumLength = KeyInfo->Node.ClassLength;
+ RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE);
+ lpClass[StringA.Length] = 0;
+ *lpcbClass = StringA.Length;
+ StringU.Buffer = KeyInfo->Node.Name;
+ StringU.Length = KeyInfo->Node.NameLength;
+ StringU.MaximumLength = KeyInfo->Node.NameLength;
+ }
+ }
+ if (ErrorCode == ERROR_SUCCESS)
+ {
+ StringA.Buffer = lpName;
+ StringA.Length = 0;
+ StringA.MaximumLength = *lpcbName;
+ RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE);
+ lpName[StringA.Length] = 0;
+ *lpcbName = StringA.Length;
+ if (lpftLastWriteTime != NULL)
+ {
+ if (lpClass == NULL)
+ {
+ lpftLastWriteTime->dwLowDateTime = KeyInfo->Basic.LastWriteTime.u.LowPart;
+ lpftLastWriteTime->dwHighDateTime = KeyInfo->Basic.LastWriteTime.u.HighPart;
+ }
+ else
+ {
+ lpftLastWriteTime->dwLowDateTime = KeyInfo->Node.LastWriteTime.u.LowPart;
+ lpftLastWriteTime->dwHighDateTime = KeyInfo->Node.LastWriteTime.u.HighPart;
+ }
+ }
}
}
- RtlFreeHeap (RtlGetProcessHeap(), 0, KeyInfo);
+ TRACE("Key Namea0 Length %d\n", StringU.Length);
+ TRACE("Key Namea1 Length %d\n", NameLength);
+ TRACE("Key Namea Length %d\n", *lpcbName);
+ TRACE("Key Namea %s\n", lpName);
+
+ RtlFreeHeap (ProcessHeap,
+ 0,
+ KeyInfo);
- return dwError;
+ return ErrorCode;
}
/************************************************************************
- * RegEnumKeyW
+ * RegEnumKeyExW
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegEnumKeyW(
- HKEY hKey,
- DWORD dwIndex,
- LPWSTR lpName,
- DWORD cbName
- )
-{
- DWORD dwLength = cbName;
-
- return RegEnumKeyExW(hKey,
- dwIndex,
- lpName,
- &dwLength,
- NULL,
- NULL,
- NULL,
- NULL);
-}
+LONG STDCALL
+RegEnumKeyExW (HKEY hKey,
+ DWORD dwIndex,
+ LPWSTR lpName,
+ LPDWORD lpcbName,
+ LPDWORD lpReserved,
+ LPWSTR lpClass,
+ LPDWORD lpcbClass,
+ PFILETIME lpftLastWriteTime)
+{
+ union
+ {
+ KEY_NODE_INFORMATION Node;
+ KEY_BASIC_INFORMATION Basic;
+ } *KeyInfo;
+
+ ULONG BufferSize;
+ ULONG ResultSize;
+ ULONG NameLength;
+ ULONG ClassLength = 0;
+ HANDLE KeyHandle;
+ LONG ErrorCode = ERROR_SUCCESS;
+ NTSTATUS Status;
+
+ Status = MapDefaultKey(&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ if (*lpcbName > 0)
+ {
+ NameLength = min (*lpcbName - 1, REG_MAX_NAME_SIZE) * sizeof (WCHAR);
+ }
+ else
+ {
+ NameLength = 0;
+ }
+
+ if (lpClass)
+ {
+ if (*lpcbClass > 0)
+ {
+ ClassLength = min (*lpcbClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
+ }
+ else
+ {
+ ClassLength = 0;
+ }
+ BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength + 3) & ~3) + ClassLength;
+ }
+ else
+ {
+ BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength;
+ }
+
+ KeyInfo = RtlAllocateHeap (ProcessHeap,
+ 0,
+ BufferSize);
+ if (KeyInfo == NULL)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+
+ Status = NtEnumerateKey (KeyHandle,
+ (ULONG)dwIndex,
+ lpClass ? KeyNodeInformation : KeyBasicInformation,
+ KeyInfo,
+ BufferSize,
+ &ResultSize);
+ TRACE("NtEnumerateKey() returned status 0x%X\n", Status);
+ if (!NT_SUCCESS(Status))
+ {
+ ErrorCode = RtlNtStatusToDosError (Status);
+ }
+ else
+ {
+ if (lpClass == NULL)
+ {
+ if (KeyInfo->Basic.NameLength > NameLength)
+ {
+ ErrorCode = ERROR_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ RtlCopyMemory (lpName,
+ KeyInfo->Basic.Name,
+ KeyInfo->Basic.NameLength);
+ *lpcbName = (DWORD)(KeyInfo->Basic.NameLength / sizeof(WCHAR));
+ lpName[*lpcbName] = 0;
+ }
+ }
+ else
+ {
+ if (KeyInfo->Node.NameLength > NameLength ||
+ KeyInfo->Node.ClassLength > ClassLength)
+ {
+ ErrorCode = ERROR_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ RtlCopyMemory (lpName,
+ KeyInfo->Node.Name,
+ KeyInfo->Node.NameLength);
+ *lpcbName = KeyInfo->Node.NameLength / sizeof(WCHAR);
+ lpName[*lpcbName] = 0;
+ RtlCopyMemory (lpClass,
+ (PVOID)((ULONG_PTR)KeyInfo->Node.Name + KeyInfo->Node.ClassOffset),
+ KeyInfo->Node.ClassLength);
+ *lpcbClass = (DWORD)(KeyInfo->Node.ClassLength / sizeof(WCHAR));
+ lpClass[*lpcbClass] = 0;
+ }
+ }
+
+ if (ErrorCode == ERROR_SUCCESS && lpftLastWriteTime != NULL)
+ {
+ if (lpClass == NULL)
+ {
+ lpftLastWriteTime->dwLowDateTime = KeyInfo->Basic.LastWriteTime.u.LowPart;
+ lpftLastWriteTime->dwHighDateTime = KeyInfo->Basic.LastWriteTime.u.HighPart;
+ }
+ else
+ {
+ lpftLastWriteTime->dwLowDateTime = KeyInfo->Node.LastWriteTime.u.LowPart;
+ lpftLastWriteTime->dwHighDateTime = KeyInfo->Node.LastWriteTime.u.HighPart;
+ }
+ }
+ }
+
+ RtlFreeHeap (ProcessHeap,
+ 0,
+ KeyInfo);
+
+ return ErrorCode;
+}
/************************************************************************
- * RegEnumValueA
+ * RegEnumValueA
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegEnumValueA(
- HKEY hKey,
- DWORD dwIndex,
- LPSTR lpValueName,
- LPDWORD lpcbValueName,
- LPDWORD lpReserved,
- LPDWORD lpType,
- LPBYTE lpData,
- LPDWORD lpcbData
- )
+LONG STDCALL
+RegEnumValueA( HKEY hKey, DWORD index, LPSTR value, LPDWORD val_count,
+ LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
-}
+ HANDLE KeyHandle;
+ NTSTATUS status;
+ DWORD total_size;
+ char buffer[256], *buf_ptr = buffer;
+ KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
+ static const int info_size = offsetof( KEY_VALUE_FULL_INFORMATION, Name );
+
+ //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
+ // hkey, index, value, val_count, reserved, type, data, count );
+
+ /* NT only checks count, not val_count */
+ if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
+ status = MapDefaultKey (&KeyHandle, hKey);
+ if (!NT_SUCCESS(status))
+ {
+ return RtlNtStatusToDosError (status);
+ }
+ total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
+ if (data) total_size += *count;
+ total_size = min( sizeof(buffer), total_size );
+
+ status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
+ buffer, total_size, &total_size );
+ if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
+
+ /* we need to fetch the contents for a string type even if not requested,
+ * because we need to compute the length of the ASCII string. */
+ if (value || data || is_string(info->Type))
+ {
+ /* retry with a dynamically allocated buffer */
+ while (status == STATUS_BUFFER_OVERFLOW)
+ {
+ if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+ if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+ return ERROR_NOT_ENOUGH_MEMORY;
+ info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
+ status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
+ buf_ptr, total_size, &total_size );
+ }
+
+ if (status) goto done;
+
+ if (is_string(info->Type))
+ {
+ DWORD len;
+ RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr + info->DataOffset),
+ total_size - info->DataOffset );
+ if (data && len)
+ {
+ if (len > *count) status = STATUS_BUFFER_OVERFLOW;
+ else
+ {
+ RtlUnicodeToMultiByteN( (PCHAR)data, len, NULL, (WCHAR *)(buf_ptr + info->DataOffset),
+ total_size - info->DataOffset );
+ /* if the type is REG_SZ and data is not 0-terminated
+ * and there is enough space in the buffer NT appends a \0 */
+ if (len < *count && data[len-1]) data[len] = 0;
+ }
+ }
+ info->DataLength = len;
+ }
+ else if (data)
+ {
+ if (total_size - info->DataOffset > *count) status = STATUS_BUFFER_OVERFLOW;
+ else memcpy( data, buf_ptr + info->DataOffset, total_size - info->DataOffset );
+ }
+
+ if (value && !status)
+ {
+ DWORD len;
+
+ RtlUnicodeToMultiByteSize( &len, info->Name, info->NameLength );
+ if (len >= *val_count)
+ {
+ status = STATUS_BUFFER_OVERFLOW;
+ if (*val_count)
+ {
+ len = *val_count - 1;
+ RtlUnicodeToMultiByteN( value, len, NULL, info->Name, info->NameLength );
+ value[len] = 0;
+ }
+ }
+ else
+ {
+ RtlUnicodeToMultiByteN( value, len, NULL, info->Name, info->NameLength );
+ value[len] = 0;
+ *val_count = len;
+ }
+ }
+ }
+ else status = STATUS_SUCCESS;
+
+ if (type) *type = info->Type;
+ if (count) *count = info->DataLength;
+
+ done:
+ if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+ return RtlNtStatusToDosError(status);
+}
-/************************************************************************
- * RegEnumValueW
+/******************************************************************************
+ * RegEnumValueW [ADVAPI32.@]
+ * @implemented
+ *
+ * PARAMS
+ * hkey [I] Handle to key to query
+ * index [I] Index of value to query
+ * value [O] Value string
+ * val_count [I/O] Size of value buffer (in wchars)
+ * reserved [I] Reserved
+ * type [O] Type code
+ * data [O] Value data
+ * count [I/O] Size of data buffer (in bytes)
+ *
+ * RETURNS
+ * Success: ERROR_SUCCESS
+ * Failure: nonzero error code from Winerror.h
*/
-LONG
-STDCALL
-RegEnumValueW(
- HKEY hKey,
- DWORD dwIndex,
- LPWSTR lpValueName,
- LPDWORD lpcbValueName,
- LPDWORD lpReserved,
- LPDWORD lpType,
- LPBYTE lpData,
- LPDWORD lpcbData
- )
-{
- PKEY_VALUE_FULL_INFORMATION ValueInfo;
- NTSTATUS Status;
- DWORD dwError = ERROR_SUCCESS;
- ULONG BufferSize;
- ULONG ResultSize;
-
- BufferSize = sizeof (KEY_VALUE_FULL_INFORMATION) +
- *lpcbValueName * sizeof(WCHAR);
- if (lpcbData)
- BufferSize += *lpcbData;
- ValueInfo = RtlAllocateHeap (RtlGetProcessHeap(),
- 0,
- BufferSize);
- if (ValueInfo == NULL)
- return ERROR_OUTOFMEMORY;
+LONG STDCALL
+RegEnumValueW( HKEY hKey, DWORD index, LPWSTR value, PDWORD val_count,
+ PDWORD reserved, PDWORD type, LPBYTE data, PDWORD count )
+{
+ HANDLE KeyHandle;
+ NTSTATUS status;
+ DWORD total_size;
+ char buffer[256], *buf_ptr = buffer;
+ KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
+ static const int info_size = offsetof( KEY_VALUE_FULL_INFORMATION, Name );
- Status = NtEnumerateValueKey (hKey,
- (ULONG)dwIndex,
- KeyValueFullInformation,
- ValueInfo,
- BufferSize,
- &ResultSize);
- if (!NT_SUCCESS(Status))
- {
- dwError = RtlNtStatusToDosError(Status);
-
- SetLastError(dwError);
- }
- else
- {
- memcpy (lpValueName, ValueInfo->Name, ValueInfo->NameLength);
- *lpcbValueName = (DWORD)(ValueInfo->NameLength / sizeof(WCHAR)) - 1;
+ //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
+ // hkey, index, value, val_count, reserved, type, data, count );
- if (lpType)
- *lpType = ValueInfo->Type;
+ /* NT only checks count, not val_count */
+ if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
- if (lpData)
- {
- memcpy (lpData,
- ValueInfo->Name + ValueInfo->DataOffset,
- ValueInfo->DataLength);
- *lpcbValueName = (DWORD)ValueInfo->DataLength;
- }
+ status = MapDefaultKey (&KeyHandle, hKey);
+ if (!NT_SUCCESS(status))
+ {
+ return RtlNtStatusToDosError (status);
}
- RtlFreeHeap (RtlGetProcessHeap(), 0, ValueInfo);
+ total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
+ if (data) total_size += *count;
+ total_size = min( sizeof(buffer), total_size );
+
+ status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
+ buffer, total_size, &total_size );
+ if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
+
+ if (value || data)
+ {
+ /* retry with a dynamically allocated buffer */
+ while (status == STATUS_BUFFER_OVERFLOW)
+ {
+ if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+ if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+ return ERROR_NOT_ENOUGH_MEMORY;
+ info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
+ status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
+ buf_ptr, total_size, &total_size );
+ }
+
+ if (status) goto done;
+
+ if (value)
+ {
+ if (info->NameLength/sizeof(WCHAR) >= *val_count)
+ {
+ status = STATUS_BUFFER_OVERFLOW;
+ goto overflow;
+ }
+ memcpy( value, info->Name, info->NameLength );
+ *val_count = info->NameLength / sizeof(WCHAR);
+ value[*val_count] = 0;
+ }
+
+ if (data)
+ {
+ if (total_size - info->DataOffset > *count)
+ {
+ status = STATUS_BUFFER_OVERFLOW;
+ goto overflow;
+ }
+ memcpy( data, buf_ptr + info->DataOffset, total_size - info->DataOffset );
+ if (total_size - info->DataOffset <= *count-sizeof(WCHAR) && is_string(info->Type))
+ {
+ /* if the type is REG_SZ and data is not 0-terminated
+ * and there is enough space in the buffer NT appends a \0 */
+ WCHAR *ptr = (WCHAR *)(data + total_size - info->DataOffset);
+ if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
+ }
+ }
+ }
+ else status = STATUS_SUCCESS;
+
+ overflow:
+ if (type) *type = info->Type;
+ if (count) *count = info->DataLength;
+
+ done:
+ if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+ return RtlNtStatusToDosError(status);
+}
- return dwError;
+/************************************************************************
+ * RegFlushKey
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegFlushKey(HKEY hKey)
+{
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+
+ if (hKey == HKEY_PERFORMANCE_DATA)
+ {
+ return ERROR_SUCCESS;
+ }
+
+ Status = MapDefaultKey (&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ Status = NtFlushKey (KeyHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegFlushKey
+ * RegGetKeySecurity
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegFlushKey(
- HKEY hKey
- )
+LONG STDCALL
+RegGetKeySecurity(HKEY hKey,
+ SECURITY_INFORMATION SecurityInformation,
+ PSECURITY_DESCRIPTOR pSecurityDescriptor,
+ LPDWORD lpcbSecurityDescriptor)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+
+ if (hKey == HKEY_PERFORMANCE_DATA)
+ {
+ return ERROR_INVALID_HANDLE;
+ }
+
+ Status = MapDefaultKey(&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("MapDefaultKey() failed (Status %lx)\n", Status);
+ return RtlNtStatusToDosError (Status);
+ }
+
+ Status = NtQuerySecurityObject(KeyHandle,
+ SecurityInformation,
+ pSecurityDescriptor,
+ *lpcbSecurityDescriptor,
+ lpcbSecurityDescriptor);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN("NtQuerySecurityObject() failed (Status %lx)\n", Status);
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegGetKeySecurity
+ * RegLoadKeyA
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegGetKeySecurity (
- HKEY hKey,
- SECURITY_INFORMATION SecurityInformation, /* FIXME: ULONG ? */
- PSECURITY_DESCRIPTOR pSecurityDescriptor,
- LPDWORD lpcbSecurityDescriptor
- )
+LONG STDCALL
+RegLoadKeyA (HKEY hKey,
+ LPCSTR lpSubKey,
+ LPCSTR lpFile)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ UNICODE_STRING FileName;
+ UNICODE_STRING KeyName;
+ LONG ErrorCode;
+
+ RtlCreateUnicodeStringFromAsciiz (&KeyName,
+ (LPSTR)lpSubKey);
+ RtlCreateUnicodeStringFromAsciiz (&FileName,
+ (LPSTR)lpFile);
+
+ ErrorCode = RegLoadKeyW (hKey,
+ KeyName.Buffer,
+ FileName.Buffer);
+
+ RtlFreeUnicodeString (&FileName);
+ RtlFreeUnicodeString (&KeyName);
+
+ return ErrorCode;
}
/************************************************************************
- * RegLoadKeyA
+ * RegLoadKeyW
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegLoadKey(
- HKEY hKey,
- LPCSTR lpSubKey,
- LPCSTR lpFile
- )
+LONG STDCALL
+RegLoadKeyW (HKEY hKey,
+ LPCWSTR lpSubKey,
+ LPCWSTR lpFile)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ OBJECT_ATTRIBUTES FileObjectAttributes;
+ OBJECT_ATTRIBUTES KeyObjectAttributes;
+ UNICODE_STRING FileName;
+ UNICODE_STRING KeyName;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+
+ if (hKey == HKEY_PERFORMANCE_DATA)
+ {
+ return ERROR_INVALID_HANDLE;
+ }
+
+ Status = MapDefaultKey (&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile,
+ &FileName,
+ NULL,
+ NULL))
+ {
+ return ERROR_BAD_PATHNAME;
+ }
+
+ InitializeObjectAttributes (&FileObjectAttributes,
+ &FileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ RtlInitUnicodeString (&KeyName,
+ (LPWSTR)lpSubKey);
+
+ InitializeObjectAttributes (&KeyObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ KeyHandle,
+ NULL);
+
+ Status = NtLoadKey (&KeyObjectAttributes,
+ &FileObjectAttributes);
+
+ RtlFreeUnicodeString (&FileName);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegLoadKeyW
+ * RegNotifyChangeKeyValue
+ *
+ * @unimplemented
*/
-LONG
-STDCALL
-RegLoadKeyW(
- HKEY hKey,
- LPCWSTR lpSubKey,
- LPCWSTR lpFile
- )
+LONG STDCALL
+RegNotifyChangeKeyValue (HKEY hKey,
+ BOOL bWatchSubtree,
+ DWORD dwNotifyFilter,
+ HANDLE hEvent,
+ BOOL fAsynchronous)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+
+ if (hKey == HKEY_PERFORMANCE_DATA)
+ {
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (fAsynchronous == TRUE && hEvent == NULL)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ Status = MapDefaultKey (&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ /* FIXME: Remote key handles must fail */
+
+ Status = NtNotifyChangeKey (KeyHandle,
+ hEvent,
+ 0,
+ 0,
+ &IoStatusBlock,
+ dwNotifyFilter,
+ bWatchSubtree,
+ 0,
+ 0,
+ fAsynchronous);
+ if (!NT_SUCCESS(Status) && Status != STATUS_TIMEOUT)
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegNotifyChangeKeyValue
+ * RegOpenCurrentUser
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegNotifyChangeKeyValue(
- HKEY hKey,
- BOOL bWatchSubtree,
- DWORD dwNotifyFilter,
- HANDLE hEvent,
- BOOL fAsynchronous
- )
+LONG STDCALL
+RegOpenCurrentUser (IN REGSAM samDesired,
+ OUT PHKEY phkResult)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
-}
+ NTSTATUS Status;
+ Status = RtlOpenCurrentUser((ACCESS_MASK)samDesired,
+ (PHANDLE)phkResult);
+ if (!NT_SUCCESS(Status))
+ {
+ /* NOTE - don't set the last error code! just return the error! */
+ return RtlNtStatusToDosError(Status);
+ }
+
+ return ERROR_SUCCESS;
+}
/************************************************************************
- * RegOpenKeyA
+ * RegOpenKeyA
+ *
+ * 20050503 Fireball - imported from WINE
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegOpenKeyA(
- HKEY hKey,
- LPCSTR lpSubKey,
- PHKEY phkResult
- )
+LONG STDCALL
+RegOpenKeyA (HKEY hKey,
+ LPCSTR lpSubKey,
+ PHKEY phkResult)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ TRACE("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n", hKey, lpSubKey, phkResult);
+
+ if (!lpSubKey || !*lpSubKey)
+ {
+ *phkResult = hKey;
+ return ERROR_SUCCESS;
+ }
+
+ return RegOpenKeyExA( hKey, lpSubKey, 0, MAXIMUM_ALLOWED, phkResult);
}
/************************************************************************
- * RegOpenKeyW
+ * RegOpenKeyW
+ *
+ * 19981101 Ariadne
+ * 19990525 EA
+ * 20050503 Fireball - imported from WINE
*
- * 19981101 Ariadne
- * 19990525 EA
+ * @implemented
*/
-LONG
-STDCALL
-RegOpenKeyW (
- HKEY hKey,
- LPCWSTR lpSubKey,
- PHKEY phkResult
- )
-{
- NTSTATUS errCode;
- UNICODE_STRING SubKeyString;
- OBJECT_ATTRIBUTES ObjectAttributes;
- HANDLE KeyHandle;
- LONG ErrorCode;
-
- errCode = MapDefaultKey(&KeyHandle,
- hKey);
- if (!NT_SUCCESS(errCode))
+LONG STDCALL
+RegOpenKeyW (HKEY hKey,
+ LPCWSTR lpSubKey,
+ PHKEY phkResult)
+{
+ TRACE("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n", hKey, lpSubKey, phkResult);
+
+ if (!lpSubKey || !*lpSubKey)
{
- ErrorCode = RtlNtStatusToDosError(errCode);
+ *phkResult = hKey;
+ return ERROR_SUCCESS;
+ }
+ return RegOpenKeyExW(hKey, lpSubKey, 0, MAXIMUM_ALLOWED, phkResult);
+}
+
+
+/************************************************************************
+ * RegOpenKeyExA
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegOpenKeyExA (HKEY hKey,
+ LPCSTR lpSubKey,
+ DWORD ulOptions,
+ REGSAM samDesired,
+ PHKEY phkResult)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING SubKeyString;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+
+ TRACE("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
+ hKey, lpSubKey, ulOptions, samDesired, phkResult);
- SetLastError (ErrorCode);
- return ErrorCode;
+ Status = MapDefaultKey (&KeyHandle, hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
}
- RtlInitUnicodeString(&SubKeyString,
- (LPWSTR)lpSubKey);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &SubKeyString,
- OBJ_CASE_INSENSITIVE,
- KeyHandle,
- NULL);
-
- errCode = NtOpenKey(
- phkResult,
- KEY_ALL_ACCESS,
- & ObjectAttributes
- );
- if ( !NT_SUCCESS(errCode) )
+ RtlCreateUnicodeStringFromAsciiz (&SubKeyString, (LPSTR)lpSubKey);
+ InitializeObjectAttributes (&ObjectAttributes,
+ &SubKeyString,
+ OBJ_CASE_INSENSITIVE,
+ KeyHandle,
+ NULL);
+
+ Status = NtOpenKey ((PHANDLE)phkResult, samDesired, &ObjectAttributes);
+ RtlFreeUnicodeString (&SubKeyString);
+ if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError(errCode);
-
- SetLastError(ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
+
return ERROR_SUCCESS;
}
/************************************************************************
- * RegOpenKeyExA
+ * RegOpenKeyExW
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegOpenKeyExA(
- HKEY hKey,
- LPCSTR lpSubKey,
- DWORD ulOptions,
- REGSAM samDesired,
- PHKEY phkResult
- )
+LONG STDCALL
+RegOpenKeyExW (HKEY hKey,
+ LPCWSTR lpSubKey,
+ DWORD ulOptions,
+ REGSAM samDesired,
+ PHKEY phkResult)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
-}
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING SubKeyString;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+ TRACE("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
+ hKey, lpSubKey, ulOptions, samDesired, phkResult);
-/************************************************************************
- * RegOpenKeyExW
- */
-LONG
-STDCALL
-RegOpenKeyExW(
- HKEY hKey,
- LPCWSTR lpSubKey,
- DWORD ulOptions,
- REGSAM samDesired,
- PHKEY phkResult
- )
-{
- NTSTATUS errCode;
- UNICODE_STRING SubKeyString;
- OBJECT_ATTRIBUTES ObjectAttributes;
-
- RtlInitUnicodeString(&SubKeyString,
- (LPWSTR)lpSubKey);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &SubKeyString,
- OBJ_CASE_INSENSITIVE,
- (HANDLE)hKey,
- NULL);
-
- errCode = NtOpenKey(
- phkResult,
- samDesired,
- & ObjectAttributes
- );
- if ( !NT_SUCCESS(errCode) )
+ Status = MapDefaultKey (&KeyHandle, hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ if (lpSubKey != NULL)
+ RtlInitUnicodeString (&SubKeyString, (LPWSTR)lpSubKey);
+ else
+ RtlInitUnicodeString (&SubKeyString, (LPWSTR)L"");
+
+ InitializeObjectAttributes (&ObjectAttributes,
+ &SubKeyString,
+ OBJ_CASE_INSENSITIVE,
+ KeyHandle,
+ NULL);
+
+ Status = NtOpenKey ((PHANDLE)phkResult, samDesired, &ObjectAttributes);
+
+ if (!NT_SUCCESS(Status))
{
- LONG LastError = RtlNtStatusToDosError(errCode);
-
- SetLastError(LastError);
- return LastError;
+ return RtlNtStatusToDosError (Status);
}
+
return ERROR_SUCCESS;
}
/************************************************************************
- * RegQueryInfoKeyA
+ * RegOpenUserClassesRoot
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegQueryInfoKeyA(
- HKEY hKey,
- LPSTR lpClass,
- LPDWORD lpcbClass,
- LPDWORD lpReserved,
- LPDWORD lpcSubKeys,
- LPDWORD lpcbMaxSubKeyLen,
- LPDWORD lpcbMaxClassLen,
- LPDWORD lpcValues,
- LPDWORD lpcbMaxValueNameLen,
- LPDWORD lpcbMaxValueLen,
- LPDWORD lpcbSecurityDescriptor,
- PFILETIME lpftLastWriteTime
- )
-{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+LONG STDCALL
+RegOpenUserClassesRoot (IN HANDLE hToken,
+ IN DWORD dwOptions,
+ IN REGSAM samDesired,
+ OUT PHKEY phkResult)
+{
+ const WCHAR UserClassesKeyPrefix[] = L"\\Registry\\User\\";
+ const WCHAR UserClassesKeySuffix[] = L"_Classes";
+ PTOKEN_USER TokenUserData;
+ ULONG RequiredLength;
+ UNICODE_STRING UserSidString, UserClassesKeyRoot;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ LONG ErrorCode;
+ NTSTATUS Status;
+
+ /* check parameters */
+ if (hToken == NULL || dwOptions != 0 || phkResult == NULL)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ /*
+ * Get the user sid from the token
+ */
+
+ReadTokenSid:
+ /* determine how much memory we need */
+ Status = NtQueryInformationToken(hToken,
+ TokenUser,
+ NULL,
+ 0,
+ &RequiredLength);
+ if (!NT_SUCCESS(Status) && (Status != STATUS_BUFFER_TOO_SMALL))
+ {
+ /* NOTE - as opposed to all other registry functions windows does indeed
+ change the last error code in case the caller supplied a invalid
+ handle for example! */
+ ErrorCode = RtlNtStatusToDosError (Status);
+ return ErrorCode;
+ }
+
+ TokenUserData = RtlAllocateHeap(ProcessHeap,
+ 0,
+ RequiredLength);
+ if (TokenUserData == NULL)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ /* attempt to read the information */
+ Status = NtQueryInformationToken(hToken,
+ TokenUser,
+ TokenUserData,
+ RequiredLength,
+ &RequiredLength);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ TokenUserData);
+ if (Status == STATUS_BUFFER_TOO_SMALL)
+ {
+ /* the information appears to have changed?! try again */
+ goto ReadTokenSid;
+ }
+
+ /* NOTE - as opposed to all other registry functions windows does indeed
+ change the last error code in case the caller supplied a invalid
+ handle for example! */
+ ErrorCode = RtlNtStatusToDosError (Status);
+ return ErrorCode;
+ }
+
+ /*
+ * Build the absolute path for the user's registry in the form
+ * "\Registry\User\<SID>_Classes"
+ */
+ Status = RtlConvertSidToUnicodeString(&UserSidString,
+ TokenUserData->User.Sid,
+ TRUE);
+
+ /* we don't need the user data anymore, free it */
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ TokenUserData);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ /* allocate enough memory for the entire key string */
+ UserClassesKeyRoot.Length = 0;
+ UserClassesKeyRoot.MaximumLength = UserSidString.Length +
+ sizeof(UserClassesKeyPrefix) +
+ sizeof(UserClassesKeySuffix);
+ UserClassesKeyRoot.Buffer = RtlAllocateHeap(ProcessHeap,
+ 0,
+ UserClassesKeyRoot.MaximumLength);
+ if (UserClassesKeyRoot.Buffer == NULL)
+ {
+ RtlFreeUnicodeString(&UserSidString);
+ return RtlNtStatusToDosError (Status);
+ }
+
+ /* build the string */
+ RtlAppendUnicodeToString(&UserClassesKeyRoot,
+ UserClassesKeyPrefix);
+ RtlAppendUnicodeStringToString(&UserClassesKeyRoot,
+ &UserSidString);
+ RtlAppendUnicodeToString(&UserClassesKeyRoot,
+ UserClassesKeySuffix);
+
+ TRACE("RegOpenUserClassesRoot: Absolute path: %wZ\n", &UserClassesKeyRoot);
+
+ /*
+ * Open the key
+ */
+
+ InitializeObjectAttributes (&ObjectAttributes,
+ &UserClassesKeyRoot,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenKey((PHANDLE)phkResult,
+ samDesired,
+ &ObjectAttributes);
+
+ RtlFreeUnicodeString(&UserSidString);
+ RtlFreeUnicodeString(&UserClassesKeyRoot);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegQueryInfoKeyW
+ * RegQueryInfoKeyA
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegQueryInfoKeyW(
- HKEY hKey,
- LPWSTR lpClass,
- LPDWORD lpcbClass,
- LPDWORD lpReserved,
- LPDWORD lpcSubKeys,
- LPDWORD lpcbMaxSubKeyLen,
- LPDWORD lpcbMaxClassLen,
- LPDWORD lpcValues,
- LPDWORD lpcbMaxValueNameLen,
- LPDWORD lpcbMaxValueLen,
- LPDWORD lpcbSecurityDescriptor,
- PFILETIME lpftLastWriteTime
- )
-{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+LONG STDCALL
+RegQueryInfoKeyA (HKEY hKey,
+ LPSTR lpClass,
+ LPDWORD lpcbClass,
+ LPDWORD lpReserved,
+ LPDWORD lpcSubKeys,
+ LPDWORD lpcbMaxSubKeyLen,
+ LPDWORD lpcbMaxClassLen,
+ LPDWORD lpcValues,
+ LPDWORD lpcbMaxValueNameLen,
+ LPDWORD lpcbMaxValueLen,
+ LPDWORD lpcbSecurityDescriptor,
+ PFILETIME lpftLastWriteTime)
+{
+ WCHAR ClassName[MAX_PATH];
+ UNICODE_STRING UnicodeString;
+ ANSI_STRING AnsiString;
+ LONG ErrorCode;
+
+ RtlInitUnicodeString (&UnicodeString,
+ NULL);
+ if (lpClass != NULL)
+ {
+ UnicodeString.Buffer = &ClassName[0];
+ UnicodeString.MaximumLength = sizeof(ClassName);
+ AnsiString.MaximumLength = *lpcbClass;
+ }
+
+ ErrorCode = RegQueryInfoKeyW (hKey,
+ UnicodeString.Buffer,
+ lpcbClass,
+ lpReserved,
+ lpcSubKeys,
+ lpcbMaxSubKeyLen,
+ lpcbMaxClassLen,
+ lpcValues,
+ lpcbMaxValueNameLen,
+ lpcbMaxValueLen,
+ lpcbSecurityDescriptor,
+ lpftLastWriteTime);
+ if ((ErrorCode == ERROR_SUCCESS) && (lpClass != NULL))
+ {
+ AnsiString.Buffer = lpClass;
+ AnsiString.Length = 0;
+ UnicodeString.Length = *lpcbClass * sizeof(WCHAR);
+ RtlUnicodeStringToAnsiString (&AnsiString,
+ &UnicodeString,
+ FALSE);
+ *lpcbClass = AnsiString.Length;
+ lpClass[AnsiString.Length] = 0;
+ }
+
+ return ErrorCode;
}
/************************************************************************
- * RegQueryMultipleValuesA
+ * RegQueryInfoKeyW
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegQueryMultipleValuesA(
- HKEY hKey,
- PVALENT val_list,
- DWORD num_vals,
- LPSTR lpValueBuf,
- LPDWORD ldwTotsize
- )
+LONG STDCALL
+RegQueryInfoKeyW (HKEY hKey,
+ LPWSTR lpClass,
+ LPDWORD lpcbClass,
+ LPDWORD lpReserved,
+ LPDWORD lpcSubKeys,
+ LPDWORD lpcbMaxSubKeyLen,
+ LPDWORD lpcbMaxClassLen,
+ LPDWORD lpcValues,
+ LPDWORD lpcbMaxValueNameLen,
+ LPDWORD lpcbMaxValueLen,
+ LPDWORD lpcbSecurityDescriptor,
+ PFILETIME lpftLastWriteTime)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ KEY_FULL_INFORMATION FullInfoBuffer;
+ PKEY_FULL_INFORMATION FullInfo;
+ ULONG FullInfoSize;
+ ULONG ClassLength = 0;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+ ULONG Length;
+ LONG ErrorCode = ERROR_SUCCESS;
+
+ if ((lpClass) && (!lpcbClass))
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ Status = MapDefaultKey (&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ if (lpClass != NULL)
+ {
+ if (*lpcbClass > 0)
+ {
+ ClassLength = min(*lpcbClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
+ }
+ else
+ {
+ ClassLength = 0;
+ }
+
+ FullInfoSize = sizeof(KEY_FULL_INFORMATION) + ((ClassLength + 3) & ~3);
+ FullInfo = RtlAllocateHeap (ProcessHeap,
+ 0,
+ FullInfoSize);
+ if (FullInfo == NULL)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+
+ FullInfo->ClassLength = ClassLength;
+ }
+ else
+ {
+ FullInfoSize = sizeof(KEY_FULL_INFORMATION);
+ FullInfo = &FullInfoBuffer;
+ FullInfo->ClassLength = 0;
+ }
+ FullInfo->ClassOffset = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
+
+ Status = NtQueryKey (KeyHandle,
+ KeyFullInformation,
+ FullInfo,
+ FullInfoSize,
+ &Length);
+ TRACE("NtQueryKey() returned status 0x%X\n", Status);
+ if (!NT_SUCCESS(Status))
+ {
+ if (lpClass != NULL)
+ {
+ RtlFreeHeap (ProcessHeap,
+ 0,
+ FullInfo);
+ }
+
+ return RtlNtStatusToDosError (Status);
+ }
+
+ TRACE("SubKeys %d\n", FullInfo->SubKeys);
+ if (lpcSubKeys != NULL)
+ {
+ *lpcSubKeys = FullInfo->SubKeys;
+ }
+
+ TRACE("MaxNameLen %lu\n", FullInfo->MaxNameLen);
+ if (lpcbMaxSubKeyLen != NULL)
+ {
+ *lpcbMaxSubKeyLen = FullInfo->MaxNameLen / sizeof(WCHAR) + 1;
+ }
+
+ TRACE("MaxClassLen %lu\n", FullInfo->MaxClassLen);
+ if (lpcbMaxClassLen != NULL)
+ {
+ *lpcbMaxClassLen = FullInfo->MaxClassLen / sizeof(WCHAR) + 1;
+ }
+
+ TRACE("Values %lu\n", FullInfo->Values);
+ if (lpcValues != NULL)
+ {
+ *lpcValues = FullInfo->Values;
+ }
+
+ TRACE("MaxValueNameLen %lu\n", FullInfo->MaxValueNameLen);
+ if (lpcbMaxValueNameLen != NULL)
+ {
+ *lpcbMaxValueNameLen = FullInfo->MaxValueNameLen / sizeof(WCHAR) + 1;
+ }
+
+ TRACE("MaxValueDataLen %lu\n", FullInfo->MaxValueDataLen);
+ if (lpcbMaxValueLen != NULL)
+ {
+ *lpcbMaxValueLen = FullInfo->MaxValueDataLen;
+ }
+
+ if (lpcbSecurityDescriptor != NULL)
+ {
+ Status = NtQuerySecurityObject(KeyHandle,
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ NULL,
+ 0,
+ lpcbSecurityDescriptor);
+ if (!NT_SUCCESS(Status))
+ {
+ if (lpClass != NULL)
+ {
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ FullInfo);
+ }
+
+ return RtlNtStatusToDosError (Status);
+ }
+ }
+
+ if (lpftLastWriteTime != NULL)
+ {
+ lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart;
+ lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart;
+ }
+
+ if (lpClass != NULL)
+ {
+ if (FullInfo->ClassLength > ClassLength)
+ {
+ ErrorCode = ERROR_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ RtlCopyMemory (lpClass,
+ FullInfo->Class,
+ FullInfo->ClassLength);
+ *lpcbClass = FullInfo->ClassLength / sizeof(WCHAR);
+ lpClass[*lpcbClass] = 0;
+ }
+
+ RtlFreeHeap (ProcessHeap,
+ 0,
+ FullInfo);
+ }
+
+ return ErrorCode;
}
/************************************************************************
- * RegQueryMultipleValuesW
+ * RegQueryMultipleValuesA
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegQueryMultipleValuesW(
- HKEY hKey,
- PVALENT val_list,
- DWORD num_vals,
- LPWSTR lpValueBuf,
- LPDWORD ldwTotsize
- )
+LONG STDCALL
+RegQueryMultipleValuesA (HKEY hKey,
+ PVALENTA val_list,
+ DWORD num_vals,
+ LPSTR lpValueBuf,
+ LPDWORD ldwTotsize)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ ULONG i;
+ DWORD maxBytes = *ldwTotsize;
+ LPSTR bufptr = (LPSTR)lpValueBuf;
+ LONG ErrorCode;
+
+ if (maxBytes >= (1024*1024))
+ return ERROR_TRANSFER_TOO_LONG;
+
+ *ldwTotsize = 0;
+
+ TRACE("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
+ hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
+
+ for (i = 0; i < num_vals; i++)
+ {
+ val_list[i].ve_valuelen = 0;
+ ErrorCode = RegQueryValueExA (hKey,
+ val_list[i].ve_valuename,
+ NULL,
+ NULL,
+ NULL,
+ &val_list[i].ve_valuelen);
+ if (ErrorCode != ERROR_SUCCESS)
+ {
+ return ErrorCode;
+ }
+
+ if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
+ {
+ ErrorCode = RegQueryValueExA (hKey,
+ val_list[i].ve_valuename,
+ NULL,
+ &val_list[i].ve_type,
+ (LPBYTE)bufptr,
+ &val_list[i].ve_valuelen);
+ if (ErrorCode != ERROR_SUCCESS)
+ {
+ return ErrorCode;
+ }
+
+ val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
+
+ bufptr += val_list[i].ve_valuelen;
+ }
+
+ *ldwTotsize += val_list[i].ve_valuelen;
+ }
+
+ return (lpValueBuf != NULL && *ldwTotsize <= maxBytes) ? ERROR_SUCCESS : ERROR_MORE_DATA;
}
/************************************************************************
- * RegQueryValueA
+ * RegQueryMultipleValuesW
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegQueryValueA(
- HKEY hKey,
- LPCSTR lpSubKey,
- LPSTR lpValue,
- PLONG lpcbValue
- )
+LONG STDCALL
+RegQueryMultipleValuesW (HKEY hKey,
+ PVALENTW val_list,
+ DWORD num_vals,
+ LPWSTR lpValueBuf,
+ LPDWORD ldwTotsize)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ ULONG i;
+ DWORD maxBytes = *ldwTotsize;
+ LPSTR bufptr = (LPSTR)lpValueBuf;
+ LONG ErrorCode;
+
+ if (maxBytes >= (1024*1024))
+ return ERROR_TRANSFER_TOO_LONG;
+
+ *ldwTotsize = 0;
+
+ TRACE ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
+ hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
+
+ for (i = 0; i < num_vals; i++)
+ {
+ val_list[i].ve_valuelen = 0;
+ ErrorCode = RegQueryValueExW (hKey,
+ val_list[i].ve_valuename,
+ NULL,
+ NULL,
+ NULL,
+ &val_list[i].ve_valuelen);
+ if (ErrorCode != ERROR_SUCCESS)
+ {
+ return ErrorCode;
+ }
+
+ if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
+ {
+ ErrorCode = RegQueryValueExW (hKey,
+ val_list[i].ve_valuename,
+ NULL,
+ &val_list[i].ve_type,
+ (LPBYTE)bufptr,
+ &val_list[i].ve_valuelen);
+ if (ErrorCode != ERROR_SUCCESS)
+ {
+ return ErrorCode;
+ }
+
+ val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
+
+ bufptr += val_list[i].ve_valuelen;
+ }
+
+ *ldwTotsize += val_list[i].ve_valuelen;
+ }
+
+ return (lpValueBuf != NULL && *ldwTotsize <= maxBytes) ? ERROR_SUCCESS : ERROR_MORE_DATA;
}
/************************************************************************
- * RegQueryValueExA
+ * RegQueryValueExW
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegQueryValueExA(
- HKEY hKey,
- LPSTR lpValueName,
- LPDWORD lpReserved,
- LPDWORD lpType,
- LPBYTE lpData,
- LPDWORD lpcbData
- )
+LONG STDCALL
+RegQueryValueExW (HKEY hKey,
+ LPCWSTR lpValueName,
+ LPDWORD lpReserved,
+ LPDWORD lpType,
+ LPBYTE lpData,
+ LPDWORD lpcbData)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
+ UNICODE_STRING ValueName;
+ NTSTATUS Status;
+ ULONG BufferSize;
+ ULONG ResultSize;
+ HANDLE KeyHandle;
+ LONG ErrorCode = ERROR_SUCCESS;
+ ULONG MaxCopy = lpcbData != NULL && lpData != NULL ? *lpcbData : 0;
+
+ TRACE("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
+ hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0);
+
+ Status = MapDefaultKey (&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ if (lpData != NULL && lpcbData == NULL)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ RtlInitUnicodeString (&ValueName,
+ lpValueName);
+ BufferSize = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MaxCopy;
+ ValueInfo = RtlAllocateHeap (ProcessHeap,
+ 0,
+ BufferSize);
+ if (ValueInfo == NULL)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+
+ Status = NtQueryValueKey (KeyHandle,
+ &ValueName,
+ KeyValuePartialInformation,
+ ValueInfo,
+ BufferSize,
+ &ResultSize);
+ TRACE("Status 0x%X\n", Status);
+ if (Status == STATUS_BUFFER_OVERFLOW)
+ {
+ /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
+ MaxCopy = 0;
+ ErrorCode = lpData ? ERROR_MORE_DATA : ERROR_SUCCESS;
+ }
+ else if (!NT_SUCCESS(Status))
+ {
+ ErrorCode = RtlNtStatusToDosError (Status);
+ MaxCopy = 0;
+ if (lpcbData != NULL)
+ {
+ ResultSize = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + *lpcbData;
+ }
+ }
+
+ if (lpType != NULL)
+ {
+ *lpType = ValueInfo->Type;
+ }
+
+ if (NT_SUCCESS(Status) && lpData != NULL)
+ {
+ RtlMoveMemory (lpData,
+ ValueInfo->Data,
+ min(ValueInfo->DataLength, MaxCopy));
+ }
+
+ if ((ValueInfo->Type == REG_SZ) ||
+ (ValueInfo->Type == REG_MULTI_SZ) ||
+ (ValueInfo->Type == REG_EXPAND_SZ))
+ {
+ if (lpData != NULL && MaxCopy > ValueInfo->DataLength)
+ {
+ ((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0;
+ }
+
+ if (lpcbData != NULL)
+ {
+ *lpcbData = (ResultSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]));
+ TRACE("(string) Returning Size: %lu\n", *lpcbData);
+ }
+ }
+ else
+ {
+ if (lpcbData != NULL)
+ {
+ *lpcbData = ResultSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
+ TRACE("(other) Returning Size: %lu\n", *lpcbData);
+ }
+ }
+
+ TRACE("Type %d Size %d\n", ValueInfo->Type, ValueInfo->DataLength);
+
+ RtlFreeHeap (ProcessHeap,
+ 0,
+ ValueInfo);
+
+ return ErrorCode;
}
/************************************************************************
- * RegQueryValueExW
+ * RegQueryValueExA
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegQueryValueExW(
- HKEY hKey,
- LPWSTR lpValueName,
- LPDWORD lpReserved,
- LPDWORD lpType,
- LPBYTE lpData,
- LPDWORD lpcbData
- )
-{
- PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
- UNICODE_STRING ValueName;
- NTSTATUS Status;
- DWORD dwError = ERROR_SUCCESS;
- ULONG BufferSize;
- ULONG ResultSize;
-
- RtlInitUnicodeString (&ValueName,
- lpValueName);
-
- BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + *lpcbData;
- ValueInfo = RtlAllocateHeap (RtlGetProcessHeap(),
- 0,
- BufferSize);
- if (ValueInfo == NULL)
- return ERROR_OUTOFMEMORY;
+LONG STDCALL
+RegQueryValueExA (HKEY hKey,
+ LPCSTR lpValueName,
+ LPDWORD lpReserved,
+ LPDWORD lpType,
+ LPBYTE lpData,
+ LPDWORD lpcbData)
+{
+ UNICODE_STRING ValueName;
+ UNICODE_STRING ValueData;
+ ANSI_STRING AnsiString;
+ LONG ErrorCode;
+ DWORD Length;
+ DWORD Type;
+
+ TRACE("hKey 0x%X lpValueName %s lpData 0x%X lpcbData %d\n",
+ hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0);
+
+ if (lpData != NULL && lpcbData == NULL)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if (lpData)
+ {
+ ValueData.Length = 0;
+ ValueData.MaximumLength = (*lpcbData + 1) * sizeof(WCHAR);
+ ValueData.Buffer = RtlAllocateHeap (ProcessHeap,
+ 0,
+ ValueData.MaximumLength);
+ if (!ValueData.Buffer)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ ValueData.Buffer = NULL;
+ ValueData.Length = 0;
+ ValueData.MaximumLength = 0;
+ }
+
+ RtlCreateUnicodeStringFromAsciiz (&ValueName,
+ (LPSTR)lpValueName);
+
+ Length = (lpcbData == NULL) ? 0 : *lpcbData * sizeof(WCHAR);
+ ErrorCode = RegQueryValueExW (hKey,
+ ValueName.Buffer,
+ lpReserved,
+ &Type,
+ (lpData == NULL) ? NULL : (LPBYTE)ValueData.Buffer,
+ &Length);
+ TRACE("ErrorCode %lu\n", ErrorCode);
+ RtlFreeUnicodeString(&ValueName);
+
+ if (ErrorCode == ERROR_SUCCESS ||
+ ErrorCode == ERROR_MORE_DATA)
+ {
+ if (lpType != NULL)
+ {
+ *lpType = Type;
+ }
- Status = NtQueryValueKey (hKey,
- &ValueName,
- KeyValuePartialInformation,
- ValueInfo,
- BufferSize,
- &ResultSize);
- if (!NT_SUCCESS(Status))
+ if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ))
{
- dwError = RtlNtStatusToDosError(Status);
-
- SetLastError(dwError);
+ if (ErrorCode == ERROR_SUCCESS && ValueData.Buffer != NULL)
+ {
+ RtlInitAnsiString(&AnsiString, NULL);
+ AnsiString.Buffer = (LPSTR)lpData;
+ AnsiString.MaximumLength = *lpcbData;
+ ValueData.Length = Length;
+ ValueData.MaximumLength = ValueData.Length + sizeof(WCHAR);
+ RtlUnicodeStringToAnsiString(&AnsiString, &ValueData, FALSE);
+ }
+ Length = Length / sizeof(WCHAR);
}
- else
+ else if (ErrorCode == ERROR_SUCCESS && ValueData.Buffer != NULL)
+ {
+ if (*lpcbData < Length)
+ {
+ ErrorCode = ERROR_MORE_DATA;
+ }
+ else
+ {
+ RtlMoveMemory(lpData, ValueData.Buffer, Length);
+ }
+ }
+
+ if (lpcbData != NULL)
{
- *lpType = ValueInfo->Type;
- memcpy (lpData, ValueInfo->Data, ValueInfo->DataLength);
- if (ValueInfo->Type == REG_SZ)
- ((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0;
+ *lpcbData = Length;
}
- *lpcbData = (DWORD)ResultSize;
+ }
- RtlFreeHeap (RtlGetProcessHeap(), 0, ValueInfo);
+ if (ValueData.Buffer != NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, ValueData.Buffer);
+ }
- return dwError;
+ return ErrorCode;
}
/************************************************************************
- * RegQueryValueW
+ * RegQueryValueA
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegQueryValueW(
- HKEY hKey,
- LPCWSTR lpSubKey,
- LPWSTR lpValue,
- PLONG lpcbValue
- )
+LONG STDCALL
+RegQueryValueA (HKEY hKey,
+ LPCSTR lpSubKey,
+ LPSTR lpValue,
+ PLONG lpcbValue)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ WCHAR SubKeyNameBuffer[MAX_PATH+1];
+ UNICODE_STRING SubKeyName;
+ UNICODE_STRING Value;
+ ANSI_STRING AnsiString;
+ LONG ValueSize;
+ LONG ErrorCode;
+
+ TRACE("hKey 0x%X lpSubKey %s lpValue %p lpcbValue %d\n",
+ hKey, lpSubKey, lpValue, lpcbValue ? *lpcbValue : 0);
+
+ if (lpValue != NULL &&
+ lpcbValue == NULL)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ RtlInitUnicodeString (&SubKeyName,
+ NULL);
+ RtlInitUnicodeString (&Value,
+ NULL);
+ if (lpSubKey != NULL &&
+ strlen(lpSubKey) != 0)
+ {
+ RtlInitAnsiString (&AnsiString,
+ (LPSTR)lpSubKey);
+ SubKeyName.Buffer = &SubKeyNameBuffer[0];
+ SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
+ RtlAnsiStringToUnicodeString (&SubKeyName,
+ &AnsiString,
+ FALSE);
+ }
+
+ if (lpValue != NULL)
+ {
+ ValueSize = *lpcbValue * sizeof(WCHAR);
+ Value.MaximumLength = ValueSize;
+ Value.Buffer = RtlAllocateHeap (ProcessHeap,
+ 0,
+ ValueSize);
+ if (Value.Buffer == NULL)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ ValueSize = 0;
+ }
+
+ ErrorCode = RegQueryValueW (hKey,
+ (LPCWSTR)SubKeyName.Buffer,
+ Value.Buffer,
+ &ValueSize);
+ if (ErrorCode == ERROR_SUCCESS)
+ {
+ Value.Length = ValueSize;
+ RtlInitAnsiString (&AnsiString,
+ NULL);
+ AnsiString.Buffer = lpValue;
+ AnsiString.MaximumLength = *lpcbValue;
+ RtlUnicodeStringToAnsiString (&AnsiString,
+ &Value,
+ FALSE);
+ }
+
+ *lpcbValue = ValueSize;
+ if (Value.Buffer != NULL)
+ {
+ RtlFreeHeap (ProcessHeap,
+ 0,
+ Value.Buffer);
+ }
+
+ return ErrorCode;
}
/************************************************************************
- * RegReplaceKeyA
+ * RegQueryValueW
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegReplaceKeyA(
- HKEY hKey,
- LPCSTR lpSubKey,
- LPCSTR lpNewFile,
- LPCSTR lpOldFile
- )
+LONG STDCALL
+RegQueryValueW (HKEY hKey,
+ LPCWSTR lpSubKey,
+ LPWSTR lpValue,
+ PLONG lpcbValue)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING SubKeyString;
+ HANDLE KeyHandle;
+ HANDLE RealKey;
+ LONG ErrorCode;
+ BOOL CloseRealKey;
+ NTSTATUS Status;
+
+ TRACE("hKey 0x%X lpSubKey %S lpValue %p lpcbValue %d\n",
+ hKey, lpSubKey, lpValue, lpcbValue ? *lpcbValue : 0);
+
+ Status = MapDefaultKey (&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ if (lpSubKey != NULL &&
+ wcslen(lpSubKey) != 0)
+ {
+ RtlInitUnicodeString (&SubKeyString,
+ (LPWSTR)lpSubKey);
+ InitializeObjectAttributes (&ObjectAttributes,
+ &SubKeyString,
+ OBJ_CASE_INSENSITIVE,
+ KeyHandle,
+ NULL);
+ Status = NtOpenKey (&RealKey,
+ KEY_QUERY_VALUE,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+ CloseRealKey = TRUE;
+ }
+ else
+ {
+ RealKey = hKey;
+ CloseRealKey = FALSE;
+ }
+
+ ErrorCode = RegQueryValueExW (RealKey,
+ NULL,
+ NULL,
+ NULL,
+ (LPBYTE)lpValue,
+ (LPDWORD)lpcbValue);
+ if (CloseRealKey)
+ {
+ NtClose (RealKey);
+ }
+
+ return ErrorCode;
}
/************************************************************************
- * RegReplaceKeyW
+ * RegReplaceKeyA
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegReplaceKeyW(
- HKEY hKey,
- LPCWSTR lpSubKey,
- LPCWSTR lpNewFile,
- LPCWSTR lpOldFile
- )
+LONG STDCALL
+RegReplaceKeyA (HKEY hKey,
+ LPCSTR lpSubKey,
+ LPCSTR lpNewFile,
+ LPCSTR lpOldFile)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ UNICODE_STRING SubKey;
+ UNICODE_STRING NewFile;
+ UNICODE_STRING OldFile;
+ LONG ErrorCode;
+
+ RtlCreateUnicodeStringFromAsciiz (&SubKey,
+ (PCSZ)lpSubKey);
+ RtlCreateUnicodeStringFromAsciiz (&OldFile,
+ (PCSZ)lpOldFile);
+ RtlCreateUnicodeStringFromAsciiz (&NewFile,
+ (PCSZ)lpNewFile);
+
+ ErrorCode = RegReplaceKeyW (hKey,
+ SubKey.Buffer,
+ NewFile.Buffer,
+ OldFile.Buffer);
+
+ RtlFreeUnicodeString (&OldFile);
+ RtlFreeUnicodeString (&NewFile);
+ RtlFreeUnicodeString (&SubKey);
+
+ return ErrorCode;
}
/************************************************************************
- * RegRestoreKeyA
+ * RegReplaceKeyW
+ *
+ * @unimplemented
*/
-LONG
-STDCALL
-RegRestoreKeyA(
- HKEY hKey,
- LPCSTR lpFile,
- DWORD dwFlags
- )
+LONG STDCALL
+RegReplaceKeyW (HKEY hKey,
+ LPCWSTR lpSubKey,
+ LPCWSTR lpNewFile,
+ LPCWSTR lpOldFile)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ OBJECT_ATTRIBUTES KeyObjectAttributes;
+ OBJECT_ATTRIBUTES NewObjectAttributes;
+ OBJECT_ATTRIBUTES OldObjectAttributes;
+ UNICODE_STRING SubKeyName;
+ UNICODE_STRING NewFileName;
+ UNICODE_STRING OldFileName;
+ BOOLEAN CloseRealKey;
+ HANDLE RealKeyHandle;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+
+ if (hKey == HKEY_PERFORMANCE_DATA)
+ {
+ return ERROR_INVALID_HANDLE;
+ }
+
+ Status = MapDefaultKey (&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ /* Open the real key */
+ if (lpSubKey != NULL && *lpSubKey != (WCHAR)0)
+ {
+ RtlInitUnicodeString (&SubKeyName,
+ (PWSTR)lpSubKey);
+ InitializeObjectAttributes (&KeyObjectAttributes,
+ &SubKeyName,
+ OBJ_CASE_INSENSITIVE,
+ KeyHandle,
+ NULL);
+ Status = NtOpenKey (&RealKeyHandle,
+ MAXIMUM_ALLOWED,
+ &KeyObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+ CloseRealKey = TRUE;
+ }
+ else
+ {
+ RealKeyHandle = KeyHandle;
+ CloseRealKey = FALSE;
+ }
+
+ /* Convert new file name */
+ if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpNewFile,
+ &NewFileName,
+ NULL,
+ NULL))
+ {
+ if (CloseRealKey)
+ {
+ NtClose (RealKeyHandle);
+ }
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ InitializeObjectAttributes (&NewObjectAttributes,
+ &NewFileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ /* Convert old file name */
+ if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpOldFile,
+ &OldFileName,
+ NULL,
+ NULL))
+ {
+ RtlFreeUnicodeString (&NewFileName);
+ if (CloseRealKey)
+ {
+ NtClose (RealKeyHandle);
+ }
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ InitializeObjectAttributes (&OldObjectAttributes,
+ &OldFileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtReplaceKey (&NewObjectAttributes,
+ RealKeyHandle,
+ &OldObjectAttributes);
+
+ RtlFreeUnicodeString (&OldFileName);
+ RtlFreeUnicodeString (&NewFileName);
+
+ if (CloseRealKey)
+ {
+ NtClose (RealKeyHandle);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegRestoreKeyW
+ * RegRestoreKeyA
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegRestoreKeyW(
- HKEY hKey,
- LPCWSTR lpFile,
- DWORD dwFlags
- )
+LONG STDCALL
+RegRestoreKeyA (HKEY hKey,
+ LPCSTR lpFile,
+ DWORD dwFlags)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ UNICODE_STRING FileName;
+ LONG ErrorCode;
+
+ RtlCreateUnicodeStringFromAsciiz (&FileName,
+ (PCSZ)lpFile);
+
+ ErrorCode = RegRestoreKeyW (hKey,
+ FileName.Buffer,
+ dwFlags);
+
+ RtlFreeUnicodeString (&FileName);
+
+ return ErrorCode;
}
/************************************************************************
- * RegSaveKeyA
+ * RegRestoreKeyW
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegSaveKeyA(
- HKEY hKey,
- LPCSTR lpFile,
- LPSECURITY_ATTRIBUTES lpSecurityAttributes
- )
+LONG STDCALL
+RegRestoreKeyW (HKEY hKey,
+ LPCWSTR lpFile,
+ DWORD dwFlags)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING FileName;
+ HANDLE FileHandle;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+
+ if (hKey == HKEY_PERFORMANCE_DATA)
+ {
+ return ERROR_INVALID_HANDLE;
+ }
+
+ Status = MapDefaultKey (&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile,
+ &FileName,
+ NULL,
+ NULL))
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ InitializeObjectAttributes (&ObjectAttributes,
+ &FileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile (&FileHandle,
+ FILE_GENERIC_READ,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ RtlFreeUnicodeString (&FileName);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ Status = NtRestoreKey (KeyHandle,
+ FileHandle,
+ (ULONG)dwFlags);
+ NtClose (FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegSaveKeyW
+ * RegSaveKeyA
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegSaveKeyW(
- HKEY hKey,
- LPCWSTR lpFile,
- LPSECURITY_ATTRIBUTES lpSecurityAttributes
- )
+LONG STDCALL
+RegSaveKeyA (HKEY hKey,
+ LPCSTR lpFile,
+ LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ UNICODE_STRING FileName;
+ LONG ErrorCode;
+
+ RtlCreateUnicodeStringFromAsciiz (&FileName,
+ (LPSTR)lpFile);
+ ErrorCode = RegSaveKeyW (hKey,
+ FileName.Buffer,
+ lpSecurityAttributes);
+ RtlFreeUnicodeString (&FileName);
+
+ return ErrorCode;
}
/************************************************************************
- * RegSetKeySecurity
+ * RegSaveKeyW
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegSetKeySecurity(
- HKEY hKey,
- SECURITY_INFORMATION SecurityInformation, /* FIXME: ULONG? */
- PSECURITY_DESCRIPTOR pSecurityDescriptor
- )
+LONG STDCALL
+RegSaveKeyW (HKEY hKey,
+ LPCWSTR lpFile,
+ LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING FileName;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE FileHandle;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+
+ Status = MapDefaultKey (&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ if (!RtlDosPathNameToNtPathName_U ((PWSTR)lpFile,
+ &FileName,
+ NULL,
+ NULL))
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if (lpSecurityAttributes != NULL)
+ {
+ SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
+ }
+
+ InitializeObjectAttributes (&ObjectAttributes,
+ &FileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ SecurityDescriptor);
+ Status = NtCreateFile (&FileHandle,
+ GENERIC_WRITE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ,
+ FILE_CREATE,
+ FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0);
+ RtlFreeUnicodeString (&FileName);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ Status = NtSaveKey (KeyHandle,
+ FileHandle);
+ NtClose (FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegSetValueA
+ * RegSetKeySecurity
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegSetValueA(
- HKEY hKey,
- LPCSTR lpSubKey,
- DWORD dwType,
- LPCSTR lpData,
- DWORD cbData
- )
+LONG STDCALL
+RegSetKeySecurity (HKEY hKey,
+ SECURITY_INFORMATION SecurityInformation,
+ PSECURITY_DESCRIPTOR pSecurityDescriptor)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+
+ if (hKey == HKEY_PERFORMANCE_DATA)
+ {
+ return ERROR_INVALID_HANDLE;
+ }
+
+ Status = MapDefaultKey (&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ Status = NtSetSecurityObject (KeyHandle,
+ SecurityInformation,
+ pSecurityDescriptor);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegSetValueExA
+ * RegSetValueExA
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegSetValueExA(
- HKEY hKey,
- LPCSTR lpValueName,
- DWORD Reserved,
- DWORD dwType,
- CONST BYTE *lpData,
- DWORD cbData
- )
+LONG STDCALL
+RegSetValueExA (HKEY hKey,
+ LPCSTR lpValueName,
+ DWORD Reserved,
+ DWORD dwType,
+ CONST BYTE* lpData,
+ DWORD cbData)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ UNICODE_STRING ValueName;
+ LPWSTR pValueName;
+ ANSI_STRING AnsiString;
+ UNICODE_STRING Data;
+ LONG ErrorCode;
+ LPBYTE pData;
+ DWORD DataSize;
+
+ if (lpValueName != NULL &&
+ strlen(lpValueName) != 0)
+ {
+ RtlCreateUnicodeStringFromAsciiz (&ValueName,
+ (PSTR)lpValueName);
+ pValueName = (LPWSTR)ValueName.Buffer;
+ }
+ else
+ {
+ pValueName = NULL;
+ }
+
+ if (((dwType == REG_SZ) ||
+ (dwType == REG_MULTI_SZ) ||
+ (dwType == REG_EXPAND_SZ)) &&
+ (cbData != 0))
+ {
+ /* NT adds one if the caller forgot the NULL-termination character */
+ if (lpData[cbData - 1] != '\0')
+ {
+ cbData++;
+ }
+
+ RtlInitAnsiString (&AnsiString,
+ NULL);
+ AnsiString.Buffer = (PSTR)lpData;
+ AnsiString.Length = cbData - 1;
+ AnsiString.MaximumLength = cbData;
+ RtlAnsiStringToUnicodeString (&Data,
+ &AnsiString,
+ TRUE);
+ pData = (LPBYTE)Data.Buffer;
+ DataSize = cbData * sizeof(WCHAR);
+ }
+ else
+ {
+ RtlInitUnicodeString (&Data,
+ NULL);
+ pData = (LPBYTE)lpData;
+ DataSize = cbData;
+ }
+
+ ErrorCode = RegSetValueExW (hKey,
+ pValueName,
+ Reserved,
+ dwType,
+ pData,
+ DataSize);
+ if (pValueName != NULL)
+ {
+ RtlFreeHeap (ProcessHeap,
+ 0,
+ ValueName.Buffer);
+ }
+
+ if (Data.Buffer != NULL)
+ {
+ RtlFreeHeap (ProcessHeap,
+ 0,
+ Data.Buffer);
+ }
+
+ return ErrorCode;
}
/************************************************************************
- * RegSetValueExW
+ * RegSetValueExW
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegSetValueExW(
- HKEY hKey,
- LPCWSTR lpValueName,
- DWORD Reserved,
- DWORD dwType,
- CONST BYTE *lpData,
- DWORD cbData
- )
-{
- UNICODE_STRING ValueName;
- NTSTATUS Status;
+LONG STDCALL
+RegSetValueExW (HKEY hKey,
+ LPCWSTR lpValueName,
+ DWORD Reserved,
+ DWORD dwType,
+ CONST BYTE* lpData,
+ DWORD cbData)
+{
+ UNICODE_STRING ValueName;
+ PUNICODE_STRING pValueName;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+
+ Status = MapDefaultKey (&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ if (lpValueName != NULL)
+ {
+ RtlInitUnicodeString (&ValueName,
+ lpValueName);
+ }
+ else
+ {
+ RtlInitUnicodeString (&ValueName, L"");
+ }
+ pValueName = &ValueName;
+
+ if (((dwType == REG_SZ) ||
+ (dwType == REG_MULTI_SZ) ||
+ (dwType == REG_EXPAND_SZ)) &&
+ (cbData != 0) && (*(((PWCHAR)lpData) + (cbData / sizeof(WCHAR)) - 1) != L'\0'))
+ {
+ /* NT adds one if the caller forgot the NULL-termination character */
+ cbData += sizeof(WCHAR);
+ }
+
+ Status = NtSetValueKey (KeyHandle,
+ pValueName,
+ 0,
+ dwType,
+ (PVOID)lpData,
+ (ULONG)cbData);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
+}
- RtlInitUnicodeString (&ValueName,
- lpValueName);
- Status = NtSetValueKey (hKey,
- &ValueName,
- 0,
- dwType,
- (PVOID)lpData,
- (ULONG)cbData);
- if (!NT_SUCCESS(Status))
- {
- LONG ErrorCode = RtlNtStatusToDosError(Status);
+/************************************************************************
+ * RegSetValueA
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegSetValueA (HKEY hKey,
+ LPCSTR lpSubKey,
+ DWORD dwType,
+ LPCSTR lpData,
+ DWORD cbData)
+{
+ LONG ret;
+ HKEY hSubKey;
- SetLastError (ErrorCode);
- return ErrorCode;
- }
+ if (dwType != REG_SZ)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
- return ERROR_SUCCESS;
+ if (lpSubKey != NULL && lpSubKey[0] != '\0')
+ {
+ ret = RegCreateKeyA(hKey,
+ lpSubKey,
+ &hSubKey);
+
+ if (ret != ERROR_SUCCESS)
+ {
+ return ret;
+ }
+ }
+ else
+ hSubKey = hKey;
+
+ ret = RegSetValueExA(hSubKey,
+ NULL,
+ 0,
+ REG_SZ,
+ (CONST BYTE*)lpData,
+ strlen(lpData) + 1);
+
+ if (hSubKey != hKey)
+ {
+ RegCloseKey(hSubKey);
+ }
+
+ return ret;
}
/************************************************************************
- * RegSetValueW
+ * RegSetValueW
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegSetValueW(
- HKEY hKey,
- LPCWSTR lpSubKey,
- DWORD dwType,
- LPCWSTR lpData,
- DWORD cbData
- )
+LONG STDCALL
+RegSetValueW (HKEY hKey,
+ LPCWSTR lpSubKey,
+ DWORD dwType,
+ LPCWSTR lpData,
+ DWORD cbData)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING SubKeyString;
+ HANDLE KeyHandle;
+ HANDLE RealKey;
+ BOOL CloseRealKey;
+ NTSTATUS Status;
+ LONG ErrorCode;
+
+ Status = MapDefaultKey (&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ if ((lpSubKey) && (wcslen(lpSubKey) != 0))
+ {
+ RtlInitUnicodeString (&SubKeyString,
+ (LPWSTR)lpSubKey);
+ InitializeObjectAttributes (&ObjectAttributes,
+ &SubKeyString,
+ OBJ_CASE_INSENSITIVE,
+ KeyHandle,
+ NULL);
+ Status = NtOpenKey (&RealKey,
+ KEY_SET_VALUE,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+ CloseRealKey = TRUE;
+ }
+ else
+ {
+ RealKey = hKey;
+ CloseRealKey = FALSE;
+ }
+
+ ErrorCode = RegSetValueExW (RealKey,
+ NULL,
+ 0,
+ dwType,
+ (LPBYTE)lpData,
+ cbData);
+ if (CloseRealKey == TRUE)
+ {
+ NtClose (RealKey);
+ }
+
+ return ErrorCode;
}
/************************************************************************
- * RegUnLoadKeyA
+ * RegUnLoadKeyA
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegUnLoadKeyA(
- HKEY hKey,
- LPCSTR lpSubKey
- )
+LONG STDCALL
+RegUnLoadKeyA (HKEY hKey,
+ LPCSTR lpSubKey)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ UNICODE_STRING KeyName;
+ DWORD ErrorCode;
+
+ RtlCreateUnicodeStringFromAsciiz (&KeyName,
+ (LPSTR)lpSubKey);
+
+ ErrorCode = RegUnLoadKeyW (hKey,
+ KeyName.Buffer);
+
+ RtlFreeUnicodeString (&KeyName);
+
+ return ErrorCode;
}
/************************************************************************
- * RegUnLoadKeyW
+ * RegUnLoadKeyW
+ *
+ * @implemented
*/
-LONG
-STDCALL
-RegUnLoadKeyW(
- HKEY hKey,
- LPCWSTR lpSubKey
- )
-{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+LONG STDCALL
+RegUnLoadKeyW (HKEY hKey,
+ LPCWSTR lpSubKey)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+
+ if (hKey == HKEY_PERFORMANCE_DATA)
+ {
+ return ERROR_INVALID_HANDLE;
+ }
+
+ Status = MapDefaultKey (&KeyHandle, hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ RtlInitUnicodeString (&KeyName,
+ (LPWSTR)lpSubKey);
+
+ InitializeObjectAttributes (&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ KeyHandle,
+ NULL);
+
+ Status = NtUnloadKey (&ObjectAttributes);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
}
/* EOF */