* UPDATE HISTORY:
* Created 01/11/98
* 19990309 EA Stubs
+ * 20050502 Fireball imported some stuff from WINE
*/
/* INCLUDES *****************************************************************/
-#include "advapi32.h"
+#include <advapi32.h>
#define NDEBUG
-#include <debug.h>
+#include <wine/debug.h>
/* DEFINES ******************************************************************/
#define REG_MAX_NAME_SIZE 256
#define REG_MAX_DATA_SIZE 2048
+/* 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;
+static BOOLEAN DefaultHandlesDisabled = FALSE;
/* PROTOTYPES ***************************************************************/
static NTSTATUS MapDefaultKey (PHANDLE ParentKey, HKEY Key);
static VOID CloseDefaultKeys(VOID);
+#define CloseDefaultKey(Handle) \
+ if ((ULONG_PTR)Handle & 0x1) { \
+ NtClose(Handle); \
+ }
static NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle);
static NTSTATUS OpenLocalMachineKey (PHANDLE KeyHandle);
/* 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
BOOL
RegInitialize (VOID)
{
- DPRINT("RegInitialize()\n");
+ TRACE("RegInitialize()\n");
ProcessHeap = RtlGetProcessHeap();
RtlZeroMemory (DefaultHandleTable,
BOOL
RegCleanup (VOID)
{
- DPRINT("RegCleanup()\n");
+ TRACE("RegCleanup()\n");
CloseDefaultKeys ();
RtlDeleteCriticalSection (&HandleTableCS);
static NTSTATUS
-MapDefaultKey (PHANDLE RealKey,
- HKEY Key)
+MapDefaultKey (OUT PHANDLE RealKey,
+ IN HKEY Key)
{
PHANDLE Handle;
ULONG Index;
+ BOOLEAN DoOpen;
NTSTATUS Status = STATUS_SUCCESS;
- DPRINT("MapDefaultKey (Key %x)\n", Key);
+ TRACE("MapDefaultKey (Key %x)\n", Key);
if (((ULONG)Key & 0xF0000000) != 0x80000000)
{
- *RealKey = (HANDLE)Key;
+ *RealKey = (HANDLE)((ULONG_PTR)Key & ~0x1);
return STATUS_SUCCESS;
}
}
RtlEnterCriticalSection (&HandleTableCS);
- Handle = &DefaultHandleTable[Index];
- if (*Handle == NULL)
+
+ if (!DefaultHandlesDisabled)
+ {
+ Handle = &DefaultHandleTable[Index];
+ DoOpen = (*Handle == NULL);
+ }
+ else
+ {
+ Handle = RealKey;
+ DoOpen = TRUE;
+ }
+
+ if (DoOpen)
{
/* create/open the default handle */
switch (Index)
break;
default:
- DPRINT("MapDefaultHandle() no handle creator\n");
+ WARN("MapDefaultHandle() no handle creator\n");
Status = STATUS_INVALID_PARAMETER;
+ break;
}
}
- RtlLeaveCriticalSection (&HandleTableCS);
- if (NT_SUCCESS(Status))
- {
- *RealKey = *Handle;
- }
+ if (NT_SUCCESS(Status))
+ {
+ if (!DefaultHandlesDisabled)
+ *RealKey = *Handle;
+ else
+ *(PULONG_PTR)Handle |= 0x1;
+ }
+
+ RtlLeaveCriticalSection (&HandleTableCS);
return Status;
}
OpenClassesRootKey (PHANDLE KeyHandle)
{
OBJECT_ATTRIBUTES Attributes;
- UNICODE_STRING KeyName = ROS_STRING_INITIALIZER(L"\\Registry\\Machine\\Software\\CLASSES");
+ UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\CLASSES");
- DPRINT("OpenClassesRootKey()\n");
+ TRACE("OpenClassesRootKey()\n");
InitializeObjectAttributes (&Attributes,
&KeyName,
OpenLocalMachineKey (PHANDLE KeyHandle)
{
OBJECT_ATTRIBUTES Attributes;
- UNICODE_STRING KeyName = ROS_STRING_INITIALIZER(L"\\Registry\\Machine");
+ UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine");
NTSTATUS Status;
- DPRINT("OpenLocalMachineKey()\n");
+ TRACE("OpenLocalMachineKey()\n");
InitializeObjectAttributes (&Attributes,
&KeyName,
MAXIMUM_ALLOWED,
&Attributes);
- DPRINT("NtOpenKey(%wZ) => %08x\n", &KeyName, Status);
+ TRACE("NtOpenKey(%wZ) => %08x\n", &KeyName, Status);
return Status;
}
OpenUsersKey (PHANDLE KeyHandle)
{
OBJECT_ATTRIBUTES Attributes;
- UNICODE_STRING KeyName = ROS_STRING_INITIALIZER(L"\\Registry\\User");
+ UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\User");
- DPRINT("OpenUsersKey()\n");
+ TRACE("OpenUsersKey()\n");
InitializeObjectAttributes (&Attributes,
&KeyName,
NULL,
NULL);
return NtOpenKey (KeyHandle,
- KEY_ALL_ACCESS,
+ MAXIMUM_ALLOWED,
&Attributes);
}
{
OBJECT_ATTRIBUTES Attributes;
UNICODE_STRING KeyName =
- ROS_STRING_INITIALIZER(L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
+ RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
- DPRINT("OpenCurrentConfigKey()\n");
+ TRACE("OpenCurrentConfigKey()\n");
InitializeObjectAttributes (&Attributes,
&KeyName,
}
+/************************************************************************
+ * RegDisablePredefinedCacheEx
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegDisablePredefinedCacheEx(VOID)
+{
+ RtlEnterCriticalSection (&HandleTableCS);
+ DefaultHandlesDisabled = TRUE;
+ RtlLeaveCriticalSection (&HandleTableCS);
+ return ERROR_SUCCESS;
+}
+
+
/************************************************************************
* RegCloseKey
*
LONG STDCALL
RegCloseKey (HKEY hKey)
{
- LONG ErrorCode;
NTSTATUS Status;
/* don't close null handle or a pseudo handle */
Status = NtClose (hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
return ERROR_SUCCESS;
/************************************************************************
- * RegConnectRegistryA
+ * RegCopyTreeW
*
* @unimplemented
*/
LONG STDCALL
-RegConnectRegistryA (LPCSTR lpMachineName,
- HKEY hKey,
- PHKEY phkResult)
+RegCopyTreeW(IN HKEY hKeySrc,
+ IN LPCWSTR lpSubKey OPTIONAL,
+ IN HKEY hKeyDest)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return ERROR_CALL_NOT_IMPLEMENTED;
+ HANDLE DestKeyHandle, KeyHandle, CurKey, SubKeyHandle = NULL;
+ NTSTATUS Status;
+
+ Status = MapDefaultKey(&KeyHandle,
+ hKeySrc);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+
+ Status = MapDefaultKey(&DestKeyHandle,
+ hKeyDest);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup2;
+ }
+
+ 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))
+ {
+ goto Cleanup;
+ }
+
+ CurKey = SubKeyHandle;
+ }
+ else
+ CurKey = KeyHandle;
+
+ /* FIXME - copy all keys and values recursively */
+ Status = STATUS_NOT_IMPLEMENTED;
+
+ if (SubKeyHandle != NULL)
+ {
+ NtClose(SubKeyHandle);
+ }
+
+Cleanup:
+ CloseDefaultKey(DestKeyHandle);
+Cleanup2:
+ CloseDefaultKey(KeyHandle);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+
+ return ERROR_SUCCESS;
+}
+
+
+/************************************************************************
+ * RegCopyTreeA
+ *
+ * @implemented
+ */
+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;
+}
+
+
+/************************************************************************
+ * RegConnectRegistryA
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegConnectRegistryA (IN LPCSTR lpMachineName,
+ IN HKEY hKey,
+ OUT PHKEY phkResult)
+{
+ UNICODE_STRING MachineName;
+ LONG Ret;
+
+ if (lpMachineName != NULL)
+ {
+ if (!RtlCreateUnicodeStringFromAsciiz(&MachineName,
+ (LPSTR)lpMachineName))
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+ }
+ else
+ RtlInitUnicodeString(&MachineName,
+ NULL);
+
+ Ret = RegConnectRegistryW(MachineName.Buffer,
+ hKey,
+ phkResult);
+
+ RtlFreeUnicodeString(&MachineName);
+
+ return Ret;
}
ClassString,
dwOptions,
(PULONG)lpdwDisposition);
- DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes->ObjectName, Status);
+ TRACE("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes->ObjectName, Status);
if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
return Status;
NULL,
0,
&Disposition);
- DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
+ TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
}
if (!NT_SUCCESS(Status))
break;
}
Status = NtCreateKey (&LocalKeyHandle,
- KEY_ALL_ACCESS,
+ KEY_CREATE_SUB_KEY,
&LocalObjectAttributes,
0,
NULL,
0,
&Disposition);
- DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
+ TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
if (!NT_SUCCESS(Status))
break;
}
UNICODE_STRING ClassString;
OBJECT_ATTRIBUTES Attributes;
HANDLE ParentKey;
- LONG ErrorCode;
NTSTATUS Status;
- DPRINT("RegCreateKeyExA() called\n");
+ TRACE("RegCreateKeyExA() called\n");
/* get the real parent key */
Status = MapDefaultKey (&ParentKey,
- hKey);
+ hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
- DPRINT("ParentKey %x\n", (ULONG)ParentKey);
+ TRACE("ParentKey %x\n", (ULONG)ParentKey);
if (lpClass != NULL)
{
RtlFreeUnicodeString (&ClassString);
}
- DPRINT("Status %x\n", Status);
+ CloseDefaultKey(ParentKey);
+
+ TRACE("Status %x\n", Status);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
return ERROR_SUCCESS;
UNICODE_STRING ClassString;
OBJECT_ATTRIBUTES Attributes;
HANDLE ParentKey;
- LONG ErrorCode;
NTSTATUS Status;
- DPRINT("RegCreateKeyExW() called\n");
+ TRACE("RegCreateKeyExW() called\n");
/* get the real parent key */
Status = MapDefaultKey (&ParentKey,
- hKey);
+ hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError(Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError(Status);
}
- DPRINT("ParentKey %x\n", (ULONG)ParentKey);
+ TRACE("ParentKey %x\n", (ULONG)ParentKey);
RtlInitUnicodeString (&ClassString,
lpClass);
dwOptions,
samDesired,
lpdwDisposition);
- DPRINT("Status %x\n", Status);
+
+ CloseDefaultKey(ParentKey);
+
+ TRACE("Status %x\n", Status);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
return ERROR_SUCCESS;
0,
NULL,
0,
- KEY_ALL_ACCESS,
+ MAXIMUM_ALLOWED,
NULL,
phkResult,
NULL);
0,
NULL,
0,
- KEY_ALL_ACCESS,
+ MAXIMUM_ALLOWED,
NULL,
phkResult,
NULL);
HANDLE ParentKey;
HANDLE TargetKey;
NTSTATUS Status;
- LONG ErrorCode;
Status = MapDefaultKey (&ParentKey,
- hKey);
+ hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
RtlCreateUnicodeStringFromAsciiz (&SubKeyName,
InitializeObjectAttributes(&ObjectAttributes,
&SubKeyName,
OBJ_CASE_INSENSITIVE,
- (HANDLE)ParentKey,
+ ParentKey,
NULL);
Status = NtOpenKey (&TargetKey,
RtlFreeUnicodeString (&SubKeyName);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ goto Cleanup;
}
Status = NtDeleteKey (TargetKey);
NtClose (TargetKey);
+
+Cleanup:
+ CloseDefaultKey(ParentKey);
+
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError(Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError(Status);
}
return ERROR_SUCCESS;
HANDLE ParentKey;
HANDLE TargetKey;
NTSTATUS Status;
- LONG ErrorCode;
Status = MapDefaultKey (&ParentKey,
- hKey);
+ hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
RtlInitUnicodeString (&SubKeyName,
InitializeObjectAttributes (&ObjectAttributes,
&SubKeyName,
OBJ_CASE_INSENSITIVE,
- (HANDLE)ParentKey,
+ ParentKey,
NULL);
Status = NtOpenKey (&TargetKey,
DELETE,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ goto Cleanup;
}
Status = NtDeleteKey (TargetKey);
NtClose (TargetKey);
+
+Cleanup:
+ CloseDefaultKey(ParentKey);
+
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
return ERROR_SUCCESS;
/************************************************************************
- * RegDeleteValueA
+ * RegDeleteKeyValueW
*
* @implemented
*/
LONG STDCALL
-RegDeleteValueA (HKEY hKey,
- LPCSTR lpValueName)
+RegDeleteKeyValueW(IN HKEY hKey,
+ IN LPCWSTR lpSubKey OPTIONAL,
+ IN LPCWSTR lpValueName OPTIONAL)
{
- UNICODE_STRING ValueName;
- HANDLE KeyHandle;
- LONG ErrorCode;
- NTSTATUS Status;
+ UNICODE_STRING ValueName;
+ HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
+ NTSTATUS Status;
- Status = MapDefaultKey (&KeyHandle,
- hKey);
- if (!NT_SUCCESS(Status))
+ Status = MapDefaultKey(&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError(Status);
}
- RtlCreateUnicodeStringFromAsciiz (&ValueName,
- (LPSTR)lpValueName);
- Status = NtDeleteValueKey (KeyHandle,
- &ValueName);
- RtlFreeUnicodeString (&ValueName);
- if (!NT_SUCCESS(Status))
+ if (lpSubKey != NULL)
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ 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))
+ {
+ goto Cleanup;
+ }
+
+ CurKey = SubKeyHandle;
}
+ else
+ CurKey = KeyHandle;
- return ERROR_SUCCESS;
+ RtlInitUnicodeString(&ValueName,
+ (LPWSTR)lpValueName);
+
+ Status = NtDeleteValueKey(CurKey,
+ &ValueName);
+
+ if (SubKeyHandle != NULL)
+ {
+ NtClose(SubKeyHandle);
+ }
+
+Cleanup:
+ CloseDefaultKey(KeyHandle);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegDeleteValueW
+ * RegDeleteKeyValueA
*
* @implemented
*/
LONG STDCALL
-RegDeleteValueW (HKEY hKey,
- LPCWSTR lpValueName)
+RegDeleteKeyValueA(IN HKEY hKey,
+ IN LPCSTR lpSubKey OPTIONAL,
+ IN LPCSTR lpValueName OPTIONAL)
{
- UNICODE_STRING ValueName;
- NTSTATUS Status;
- LONG ErrorCode;
- HANDLE KeyHandle;
-
- Status = MapDefaultKey (&KeyHandle,
- hKey);
- if (!NT_SUCCESS(Status))
+ UNICODE_STRING SubKey, ValueName;
+ LONG Ret;
+
+ if (lpSubKey != NULL)
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ if (!RtlCreateUnicodeStringFromAsciiz(&SubKey,
+ (LPSTR)lpSubKey))
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
}
+ else
+ RtlInitUnicodeString(&SubKey,
+ NULL);
- RtlInitUnicodeString (&ValueName,
- (LPWSTR)lpValueName);
-
- Status = NtDeleteValueKey (KeyHandle,
- &ValueName);
- if (!NT_SUCCESS(Status))
+ if (lpValueName != NULL)
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ if (!RtlCreateUnicodeStringFromAsciiz(&ValueName,
+ (LPSTR)lpValueName))
+ {
+ RtlFreeUnicodeString(&SubKey);
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
}
+ else
+ RtlInitUnicodeString(&ValueName,
+ NULL);
- return ERROR_SUCCESS;
+ Ret = RegDeleteKeyValueW(hKey,
+ SubKey.Buffer,
+ SubKey.Buffer);
+
+ RtlFreeUnicodeString(&SubKey);
+ RtlFreeUnicodeString(&ValueName);
+
+ return Ret;
+}
+
+
+static NTSTATUS
+RegpDeleteTree(IN HKEY hKey,
+ OUT PBOOLEAN KeysDeleted)
+{
+ typedef struct
+ {
+ LIST_ENTRY ListEntry;
+ HANDLE KeyHandle;
+ } REGP_DEL_KEYS, *PREG_DEL_KEYS;
+
+ LIST_ENTRY delQueueHead;
+ PREG_DEL_KEYS delKeys, newDelKeys;
+ HANDLE ProcessHeap;
+ ULONG BufferSize;
+ PKEY_BASIC_INFORMATION BasicInfo;
+ PREG_DEL_KEYS KeyDelRoot;
+ NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status2 = STATUS_SUCCESS;
+
+ *KeysDeleted = FALSE;
+
+ InitializeListHead(&delQueueHead);
+
+ ProcessHeap = RtlGetProcessHeap();
+
+ /* NOTE: no need to allocate enough memory for an additional KEY_BASIC_INFORMATION
+ structure for the root key, we only do that for subkeys as we need to
+ allocate REGP_DEL_KEYS structures anyway! */
+ KeyDelRoot = RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(REGP_DEL_KEYS));
+ if (KeyDelRoot != NULL)
+ {
+ KeyDelRoot->KeyHandle = hKey;
+ InsertTailList(&delQueueHead,
+ &KeyDelRoot->ListEntry);
+
+ do
+ {
+ delKeys = CONTAINING_RECORD(delQueueHead.Flink,
+ REGP_DEL_KEYS,
+ ListEntry);
+
+ BufferSize = 0;
+ BasicInfo = NULL;
+ newDelKeys = NULL;
+
+ReadFirstSubKey:
+ /* check if this key contains subkeys and delete them first by queuing
+ them at the head of the list */
+ Status2 = NtEnumerateKey(delKeys->KeyHandle,
+ 0,
+ KeyBasicInformation,
+ BasicInfo,
+ BufferSize,
+ &BufferSize);
+
+ if (NT_SUCCESS(Status2))
+ {
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING SubKeyName;
+
+ ASSERT(newDelKeys != NULL);
+ ASSERT(BasicInfo != NULL);
+
+ /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
+ SubKeyName.Length = BasicInfo->NameLength;
+ SubKeyName.MaximumLength = BasicInfo->NameLength;
+ SubKeyName.Buffer = BasicInfo->Name;
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &SubKeyName,
+ OBJ_CASE_INSENSITIVE,
+ delKeys->KeyHandle,
+ NULL);
+
+ /* open the subkey */
+ Status2 = NtOpenKey(&newDelKeys->KeyHandle,
+ DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status2))
+ {
+ goto SubKeyFailure;
+ }
+
+ /* enqueue this key to the head of the deletion queue */
+ InsertHeadList(&delQueueHead,
+ &newDelKeys->ListEntry);
+
+ /* try again from the head of the list */
+ continue;
+ }
+ else
+ {
+ if (Status2 == STATUS_BUFFER_TOO_SMALL)
+ {
+ newDelKeys = RtlAllocateHeap(ProcessHeap,
+ 0,
+ BufferSize + sizeof(REGP_DEL_KEYS));
+ if (newDelKeys != NULL)
+ {
+ BasicInfo = (PKEY_BASIC_INFORMATION)(newDelKeys + 1);
+
+ /* try again */
+ goto ReadFirstSubKey;
+ }
+ else
+ {
+ /* don't break, let's try to delete as many keys as possible */
+ Status2 = STATUS_INSUFFICIENT_RESOURCES;
+ goto SubKeyFailureNoFree;
+ }
+ }
+ else if (Status2 == STATUS_BUFFER_OVERFLOW)
+ {
+ PREG_DEL_KEYS newDelKeys2;
+
+ ASSERT(newDelKeys != NULL);
+
+ /* we need more memory to query the key name */
+ newDelKeys2 = RtlReAllocateHeap(ProcessHeap,
+ 0,
+ newDelKeys,
+ BufferSize + sizeof(REGP_DEL_KEYS));
+ if (newDelKeys2 != NULL)
+ {
+ newDelKeys = newDelKeys2;
+ BasicInfo = (PKEY_BASIC_INFORMATION)(newDelKeys + 1);
+
+ /* try again */
+ goto ReadFirstSubKey;
+ }
+ else
+ {
+ /* don't break, let's try to delete as many keys as possible */
+ Status2 = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+SubKeyFailure:
+ ASSERT(newDelKeys != NULL);
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ newDelKeys);
+
+SubKeyFailureNoFree:
+ /* don't break, let's try to delete as many keys as possible */
+ if (Status2 != STATUS_NO_MORE_ENTRIES && NT_SUCCESS(Status))
+ {
+ Status = Status2;
+ }
+ }
+
+ Status2 = NtDeleteKey(delKeys->KeyHandle);
+
+ /* NOTE: do NOT close the handle anymore, it's invalid already! */
+
+ if (!NT_SUCCESS(Status2) && NT_SUCCESS(Status))
+ {
+ /* don't break, let's try to delete as many keys as possible */
+ Status = Status2;
+ }
+
+ /* remove the entry from the list */
+ RemoveEntryList(&delKeys->ListEntry);
+
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ delKeys);
+ } while (!IsListEmpty(&delQueueHead));
+
+ *KeysDeleted = TRUE;
+ }
+ else
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+
+ return Status;
}
/************************************************************************
- * RegEnumKeyA
+ * RegDeleteTreeW
*
* @implemented
*/
LONG STDCALL
-RegEnumKeyA (HKEY hKey,
- DWORD dwIndex,
- LPSTR lpName,
- DWORD cbName)
+RegDeleteTreeW(IN HKEY hKey,
+ IN LPCWSTR lpSubKey OPTIONAL)
{
- DWORD dwLength;
+ BOOLEAN KeysDeleted;
+ HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
+ NTSTATUS Status;
- dwLength = cbName;
- return RegEnumKeyExA (hKey,
- dwIndex,
- lpName,
- &dwLength,
- NULL,
- NULL,
- NULL,
- NULL);
+ 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))
+ {
+ goto Cleanup;
+ }
+
+ CurKey = SubKeyHandle;
+ }
+ else
+ CurKey = KeyHandle;
+
+ Status = RegpDeleteTree(CurKey,
+ &KeysDeleted);
+
+ if (!KeysDeleted)
+ {
+ /* only close handles of keys that weren't deleted! */
+ if (SubKeyHandle != NULL)
+ {
+ NtClose(SubKeyHandle);
+ }
+
+Cleanup:
+ CloseDefaultKey(KeyHandle);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+
+ return ERROR_SUCCESS;
}
/************************************************************************
- * RegEnumKeyW
+ * RegDeleteTreeA
*
* @implemented
*/
LONG STDCALL
-RegEnumKeyW (HKEY hKey,
- DWORD dwIndex,
- LPWSTR lpName,
- DWORD cbName)
+RegDeleteTreeA(IN HKEY hKey,
+ IN LPCSTR lpSubKey OPTIONAL)
{
- DWORD dwLength;
+ UNICODE_STRING SubKeyName;
+ LONG Ret;
- dwLength = cbName;
- return RegEnumKeyExW (hKey,
- dwIndex,
- lpName,
- &dwLength,
- NULL,
- NULL,
- NULL,
- NULL);
+ 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;
}
/************************************************************************
- * RegEnumKeyExA
+ * RegSetKeyValueW
*
* @implemented
*/
LONG STDCALL
-RegEnumKeyExA (HKEY hKey,
- DWORD dwIndex,
- LPSTR lpName,
- LPDWORD lpcbName,
- LPDWORD lpReserved,
- LPSTR lpClass,
- LPDWORD lpcbClass,
- PFILETIME lpftLastWriteTime)
+RegSetKeyValueW(IN HKEY hKey,
+ IN LPCWSTR lpSubKey OPTIONAL,
+ IN LPCWSTR lpValueName OPTIONAL,
+ IN DWORD dwType,
+ IN LPCVOID lpData OPTIONAL,
+ IN DWORD cbData)
{
- 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;
+ HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
+ NTSTATUS Status;
+ LONG Ret;
- DPRINT("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))
+ Status = MapDefaultKey(&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
{
- SetLastError (ERROR_INVALID_PARAMETER);
- return ERROR_INVALID_PARAMETER;
+ return RtlNtStatusToDosError(Status);
}
-
- Status = MapDefaultKey(&KeyHandle,
- hKey);
- if (!NT_SUCCESS(Status))
+
+ if (lpSubKey != NULL)
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ 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))
+ {
+ Ret = RtlNtStatusToDosError(Status);
+ goto Cleanup;
+ }
+
+ CurKey = SubKeyHandle;
}
+ else
+ CurKey = KeyHandle;
+
+ Ret = RegSetValueExW(CurKey,
+ lpValueName,
+ 0,
+ dwType,
+ lpData,
+ cbData);
- if (*lpcbName > 0)
+ if (SubKeyHandle != NULL)
{
- NameLength = min (*lpcbName - 1 , REG_MAX_NAME_SIZE) * sizeof (WCHAR);
+ NtClose(SubKeyHandle);
}
- else
+
+Cleanup:
+ CloseDefaultKey(KeyHandle);
+
+ return Ret;
+}
+
+
+/************************************************************************
+ * 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, CurKey, SubKeyHandle = NULL;
+ NTSTATUS Status;
+ LONG Ret;
+
+ Status = MapDefaultKey(&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
{
- NameLength = 0;
+ return RtlNtStatusToDosError(Status);
}
- if (lpClass)
+ if (lpSubKey != NULL)
{
- if (*lpcbClass > 0)
- {
- ClassLength = min (*lpcbClass -1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
- }
- else
- {
- ClassLength = 0;
- }
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING SubKeyName;
- /* The class name should start at a dword boundary */
- BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength + 3) & ~3) + ClassLength;
+ if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName,
+ (LPSTR)lpSubKey))
+ {
+ Ret = ERROR_NOT_ENOUGH_MEMORY;
+ goto Cleanup;
+ }
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &SubKeyName,
+ OBJ_CASE_INSENSITIVE,
+ KeyHandle,
+ NULL);
+
+ Status = NtOpenKey(&SubKeyHandle,
+ KEY_SET_VALUE,
+ &ObjectAttributes);
+
+ RtlFreeUnicodeString(&SubKeyName);
+
+ if (!NT_SUCCESS(Status))
+ {
+ Ret = RtlNtStatusToDosError(Status);
+ goto Cleanup;
+ }
+
+ CurKey = SubKeyHandle;
}
- else
+ else
+ CurKey = KeyHandle;
+
+ Ret = RegSetValueExA(CurKey,
+ lpValueName,
+ 0,
+ dwType,
+ lpData,
+ cbData);
+
+ if (SubKeyHandle != NULL)
{
- BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength;
+ NtClose(SubKeyHandle);
}
+
+Cleanup:
+ CloseDefaultKey(KeyHandle);
- KeyInfo = RtlAllocateHeap (ProcessHeap,
- 0,
- BufferSize);
- if (KeyInfo == NULL)
+ return Ret;
+}
+
+
+/************************************************************************
+ * RegDeleteValueA
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegDeleteValueA (HKEY hKey,
+ LPCSTR lpValueName)
+{
+ UNICODE_STRING ValueName;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+
+ Status = MapDefaultKey (&KeyHandle,
+ hKey);
+ if (!NT_SUCCESS(Status))
{
- SetLastError (ERROR_OUTOFMEMORY);
- return ERROR_OUTOFMEMORY;
+ return RtlNtStatusToDosError (Status);
}
- Status = NtEnumerateKey (KeyHandle,
- (ULONG)dwIndex,
- lpClass == NULL ? KeyBasicInformation : KeyNodeInformation,
- KeyInfo,
- BufferSize,
- &ResultSize);
- DPRINT("NtEnumerateKey() returned status 0x%X\n", Status);
+ RtlCreateUnicodeStringFromAsciiz (&ValueName,
+ (LPSTR)lpValueName);
+ Status = NtDeleteValueKey (KeyHandle,
+ &ValueName);
+ RtlFreeUnicodeString (&ValueName);
+
+ CloseDefaultKey(KeyHandle);
+
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
+ return RtlNtStatusToDosError (Status);
}
- else
+
+ 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))
{
- if (lpClass == NULL)
+ return RtlNtStatusToDosError (Status);
+ }
+
+ RtlInitUnicodeString (&ValueName,
+ (LPWSTR)lpValueName);
+
+ Status = NtDeleteValueKey (KeyHandle,
+ &ValueName);
+
+ CloseDefaultKey(KeyHandle);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+
+ return ERROR_SUCCESS;
+}
+
+
+/************************************************************************
+ * RegEnumKeyA
+ *
+ * @implemented
+ */
+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);
+}
+
+
+/************************************************************************
+ * RegEnumKeyW
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegEnumKeyW (HKEY hKey,
+ DWORD dwIndex,
+ LPWSTR lpName,
+ DWORD cbName)
+{
+ DWORD dwLength;
+
+ dwLength = cbName;
+ return RegEnumKeyExW (hKey,
+ dwIndex,
+ lpName,
+ &dwLength,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+}
+
+
+/************************************************************************
+ * RegEnumKeyExA
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegEnumKeyExA (HKEY hKey,
+ DWORD dwIndex,
+ LPSTR lpName,
+ LPDWORD lpcbName,
+ LPDWORD lpReserved,
+ LPSTR lpClass,
+ LPDWORD lpcbClass,
+ PFILETIME lpftLastWriteTime)
+{
+ union
{
- 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;
- }
+ 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;
+
+ 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;
}
- else
+
+ Status = MapDefaultKey(&KeyHandle, hKey);
+ if (!NT_SUCCESS(Status))
{
- 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;
- }
+ return RtlNtStatusToDosError (Status);
}
- if (ErrorCode == ERROR_SUCCESS)
+ if (*lpcbName > 0)
{
- 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)
+ NameLength = min (*lpcbName - 1 , REG_MAX_NAME_SIZE) * sizeof (WCHAR);
+ }
+ else
+ {
+ NameLength = 0;
+ }
+
+ if (lpClass)
+ {
+ if (*lpcbClass > 0)
{
- lpftLastWriteTime->dwLowDateTime = KeyInfo->Basic.LastWriteTime.u.LowPart;
- lpftLastWriteTime->dwHighDateTime = KeyInfo->Basic.LastWriteTime.u.HighPart;
+ ClassLength = min (*lpcbClass -1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
}
- else
+ else
{
- lpftLastWriteTime->dwLowDateTime = KeyInfo->Node.LastWriteTime.u.LowPart;
- lpftLastWriteTime->dwHighDateTime = KeyInfo->Node.LastWriteTime.u.HighPart;
+ 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;
}
- }
- DPRINT("Key Namea0 Length %d\n", StringU.Length);
- DPRINT("Key Namea1 Length %d\n", NameLength);
- DPRINT("Key Namea Length %d\n", *lpcbName);
- DPRINT("Key Namea %s\n", lpName);
+ KeyInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize);
+ if (KeyInfo == NULL)
+ {
+ ErrorCode = ERROR_OUTOFMEMORY;
+ goto Cleanup;
+ }
- RtlFreeHeap (ProcessHeap,
- 0,
- KeyInfo);
+ Status = NtEnumerateKey (KeyHandle,
+ (ULONG)dwIndex,
+ lpClass == NULL ? KeyBasicInformation : KeyNodeInformation,
+ 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
+ {
+ StringU.Buffer = KeyInfo->Basic.Name;
+ StringU.Length = KeyInfo->Basic.NameLength;
+ StringU.MaximumLength = KeyInfo->Basic.NameLength;
+ }
+ }
+ 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)
- {
- SetLastError(ErrorCode);
- }
+ 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;
+ }
+ }
+ }
+ }
- return ErrorCode;
+ 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);
+
+Cleanup:
+ CloseDefaultKey(KeyHandle);
+
+ return ErrorCode;
}
NTSTATUS Status;
Status = MapDefaultKey(&KeyHandle,
- hKey);
+ hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
if (*lpcbName > 0)
BufferSize);
if (KeyInfo == NULL)
{
- SetLastError (ERROR_OUTOFMEMORY);
- return ERROR_OUTOFMEMORY;
+ ErrorCode = ERROR_OUTOFMEMORY;
+ goto Cleanup;
}
Status = NtEnumerateKey (KeyHandle,
KeyInfo,
BufferSize,
&ResultSize);
- DPRINT("NtEnumerateKey() returned status 0x%X\n", Status);
+ TRACE("NtEnumerateKey() returned status 0x%X\n", Status);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError (Status);
0,
KeyInfo);
- if (ErrorCode != ERROR_SUCCESS)
- {
- SetLastError(ErrorCode);
- }
+Cleanup:
+ CloseDefaultKey(KeyHandle);
return ErrorCode;
}
-
/************************************************************************
* RegEnumValueA
*
* @implemented
*/
LONG STDCALL
-RegEnumValueA (HKEY hKey,
- DWORD dwIndex,
- LPSTR lpValueName,
- LPDWORD lpcbValueName,
- LPDWORD lpReserved,
- LPDWORD lpType,
- LPBYTE lpData,
- LPDWORD lpcbData)
+RegEnumValueA( HKEY hKey, DWORD index, LPSTR value, LPDWORD val_count,
+ LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
{
- union
- {
- KEY_VALUE_FULL_INFORMATION Full;
- KEY_VALUE_BASIC_INFORMATION Basic;
- } *ValueInfo;
-
- ULONG NameLength;
- ULONG BufferSize;
- ULONG DataLength = 0;
- ULONG ResultSize;
- HANDLE KeyHandle;
- LONG ErrorCode;
- NTSTATUS Status;
- UNICODE_STRING StringU;
- ANSI_STRING StringA;
- BOOL IsStringType;
-
- ErrorCode = ERROR_SUCCESS;
+ 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);
+ }
- Status = MapDefaultKey (&KeyHandle,
- hKey);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
- }
+ total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
+ if (data) total_size += *count;
+ total_size = min( sizeof(buffer), total_size );
- if (*lpcbValueName > 0)
- {
- NameLength = min (*lpcbValueName - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
- }
- else
- {
- NameLength = 0;
- }
+ status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
+ buffer, total_size, &total_size );
+ if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
- if (lpData)
+ /* 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))
{
- DataLength = min (*lpcbData * sizeof(WCHAR), REG_MAX_DATA_SIZE);
- BufferSize = ((sizeof(KEY_VALUE_FULL_INFORMATION) + NameLength + 3) & ~3) + DataLength;
- }
- else
- {
- BufferSize = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameLength;
- }
-
- ValueInfo = RtlAllocateHeap (ProcessHeap,
- 0,
- BufferSize);
- if (ValueInfo == NULL)
- {
- SetLastError(ERROR_OUTOFMEMORY);
- return ERROR_OUTOFMEMORY;
- }
+ /* 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 )))
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+ info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
+ status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
+ buf_ptr, total_size, &total_size );
+ }
- Status = NtEnumerateValueKey (KeyHandle,
- (ULONG)dwIndex,
- lpData ? KeyValueFullInformation : KeyValueBasicInformation,
- ValueInfo,
- BufferSize,
- &ResultSize);
+ if (status) goto done;
- DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- }
- else
- {
- if (lpData)
+ if (is_string(info->Type))
{
- IsStringType = (ValueInfo->Full.Type == REG_SZ) ||
- (ValueInfo->Full.Type == REG_MULTI_SZ) ||
- (ValueInfo->Full.Type == REG_EXPAND_SZ);
- if (ValueInfo->Full.NameLength > NameLength ||
- (!IsStringType && ValueInfo->Full.DataLength > *lpcbData) ||
- ValueInfo->Full.DataLength > DataLength)
- {
- ErrorCode = ERROR_BUFFER_OVERFLOW;
- }
- else
- {
- if (IsStringType)
- {
- StringU.Buffer = (PWCHAR)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset);
- StringU.Length = ValueInfo->Full.DataLength;
- StringU.MaximumLength = DataLength;
- StringA.Buffer = (PCHAR)lpData;
- StringA.Length = 0;
- StringA.MaximumLength = *lpcbData;
- RtlUnicodeStringToAnsiString (&StringA,
- &StringU,
- FALSE);
- *lpcbData = StringA.Length;
- }
- else
- {
- RtlCopyMemory (lpData,
- (PVOID)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset),
- ValueInfo->Full.DataLength);
- *lpcbData = ValueInfo->Full.DataLength;
- }
-
- StringU.Buffer = ValueInfo->Full.Name;
- StringU.Length = ValueInfo->Full.NameLength;
- StringU.MaximumLength = NameLength;
- }
- }
- else
- {
- if (ValueInfo->Basic.NameLength > NameLength)
- {
- ErrorCode = ERROR_BUFFER_OVERFLOW;
- }
- else
- {
- StringU.Buffer = ValueInfo->Basic.Name;
- StringU.Length = ValueInfo->Basic.NameLength;
- StringU.MaximumLength = NameLength;
- }
- }
+ 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 (ErrorCode == ERROR_SUCCESS)
+ if (value && !status)
{
- StringA.Buffer = (PCHAR)lpValueName;
- StringA.Length = 0;
- StringA.MaximumLength = *lpcbValueName;
- RtlUnicodeStringToAnsiString (&StringA,
- &StringU,
- FALSE);
- StringA.Buffer[StringA.Length] = 0;
- *lpcbValueName = StringA.Length;
- if (lpType)
- {
- *lpType = lpData ? ValueInfo->Full.Type : ValueInfo->Basic.Type;
- }
- }
- }
+ DWORD len;
- RtlFreeHeap (ProcessHeap,
- 0,
- ValueInfo);
- if (ErrorCode != ERROR_SUCCESS)
- {
- SetLastError(ErrorCode);
+ 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;
- return ErrorCode;
-}
+ if (type) *type = info->Type;
+ if (count) *count = info->DataLength;
+ done:
+ if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+ CloseDefaultKey(KeyHandle);
+ 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)
+RegEnumValueW( HKEY hKey, DWORD index, LPWSTR value, PDWORD val_count,
+ PDWORD reserved, PDWORD type, LPBYTE data, PDWORD count )
{
- union
- {
- KEY_VALUE_FULL_INFORMATION Full;
- KEY_VALUE_BASIC_INFORMATION Basic;
- } *ValueInfo;
+ 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 );
- ULONG NameLength;
- ULONG BufferSize;
- ULONG DataLength = 0;
- ULONG ResultSize;
- HANDLE KeyHandle;
- LONG ErrorCode;
- NTSTATUS Status;
+ //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
+ // hkey, index, value, val_count, reserved, type, data, count );
- ErrorCode = ERROR_SUCCESS;
+ /* NT only checks count, not val_count */
+ if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
- Status = MapDefaultKey (&KeyHandle,
- hKey);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
- }
+ status = MapDefaultKey (&KeyHandle, hKey);
+ if (!NT_SUCCESS(status))
+ {
+ return RtlNtStatusToDosError (status);
+ }
- if (*lpcbValueName > 0)
- {
- NameLength = min (*lpcbValueName - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
- }
- else
- {
- NameLength = 0;
- }
+ total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
+ if (data) total_size += *count;
+ total_size = min( sizeof(buffer), total_size );
- if (lpData)
- {
- DataLength = min(*lpcbData, REG_MAX_DATA_SIZE);
- BufferSize = ((sizeof(KEY_VALUE_FULL_INFORMATION) + NameLength + 3) & ~3) + DataLength;
- }
- else
- {
- BufferSize = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameLength;
- }
- ValueInfo = RtlAllocateHeap (ProcessHeap,
- 0,
- BufferSize);
- if (ValueInfo == NULL)
- {
- SetLastError (ERROR_OUTOFMEMORY);
- return ERROR_OUTOFMEMORY;
- }
- Status = NtEnumerateValueKey (KeyHandle,
- (ULONG)dwIndex,
- lpData ? KeyValueFullInformation : KeyValueBasicInformation,
- ValueInfo,
- BufferSize,
- &ResultSize);
+ status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
+ buffer, total_size, &total_size );
+ if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
- DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- }
- else
+ if (value || data)
{
- if (lpData)
- {
- if (ValueInfo->Full.DataLength > DataLength ||
- ValueInfo->Full.NameLength > NameLength)
- {
- ErrorCode = ERROR_BUFFER_OVERFLOW;
- }
- else
- {
- RtlCopyMemory (lpValueName,
- ValueInfo->Full.Name,
- ValueInfo->Full.NameLength);
- *lpcbValueName = (DWORD)(ValueInfo->Full.NameLength / sizeof(WCHAR));
- lpValueName[*lpcbValueName] = 0;
- RtlCopyMemory (lpData,
- (PVOID)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset),
- ValueInfo->Full.DataLength);
- *lpcbData = (DWORD)ValueInfo->Full.DataLength;
- }
- }
- else
- {
- if (ValueInfo->Basic.NameLength > NameLength)
- {
- ErrorCode = ERROR_BUFFER_OVERFLOW;
- }
- else
- {
- RtlCopyMemory (lpValueName,
- ValueInfo->Basic.Name,
- ValueInfo->Basic.NameLength);
- *lpcbValueName = (DWORD)(ValueInfo->Basic.NameLength / sizeof(WCHAR));
- lpValueName[*lpcbValueName] = 0;
- }
- if (NULL != lpcbData)
- {
- *lpcbData = (DWORD)ValueInfo->Full.DataLength;
- }
- }
+ /* 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 )))
+ {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+ info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
+ status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
+ buf_ptr, total_size, &total_size );
+ }
- if (ErrorCode == ERROR_SUCCESS && lpType != NULL)
- {
- *lpType = lpData ? ValueInfo->Full.Type : ValueInfo->Basic.Type;
- }
- }
+ if (status) goto done;
- RtlFreeHeap (ProcessHeap,
- 0,
- ValueInfo);
+ 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 (ErrorCode != ERROR_SUCCESS)
- {
- SetLastError (ErrorCode);
+ 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;
- return ErrorCode;
-}
+ overflow:
+ if (type) *type = info->Type;
+ if (count) *count = info->DataLength;
+ done:
+ if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+ CloseDefaultKey(KeyHandle);
+ return RtlNtStatusToDosError(status);
+}
/************************************************************************
* RegFlushKey
RegFlushKey(HKEY hKey)
{
HANDLE KeyHandle;
- LONG ErrorCode;
NTSTATUS Status;
if (hKey == HKEY_PERFORMANCE_DATA)
}
Status = MapDefaultKey (&KeyHandle,
- hKey);
+ hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
Status = NtFlushKey (KeyHandle);
+
+ CloseDefaultKey(KeyHandle);
+
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
return ERROR_SUCCESS;
LPDWORD lpcbSecurityDescriptor)
{
HANDLE KeyHandle;
- LONG ErrorCode;
NTSTATUS Status;
if (hKey == HKEY_PERFORMANCE_DATA)
{
- SetLastError(ERROR_INVALID_HANDLE);
return ERROR_INVALID_HANDLE;
}
Status = MapDefaultKey(&KeyHandle,
- hKey);
+ hKey);
if (!NT_SUCCESS(Status))
{
- DPRINT("MapDefaultKey() failed (Status %lx)\n", Status);
- ErrorCode = RtlNtStatusToDosError(Status);
- SetLastError(ErrorCode);
- return ErrorCode;
+ TRACE("MapDefaultKey() failed (Status %lx)\n", Status);
+ return RtlNtStatusToDosError (Status);
}
Status = NtQuerySecurityObject(KeyHandle,
pSecurityDescriptor,
*lpcbSecurityDescriptor,
lpcbSecurityDescriptor);
+
+ CloseDefaultKey(KeyHandle);
+
if (!NT_SUCCESS(Status))
{
- DPRINT("NtQuerySecurityObject() failed (Status %lx)\n", Status);
- ErrorCode = RtlNtStatusToDosError(Status);
- SetLastError(ErrorCode);
- return ErrorCode;
+ WARN("NtQuerySecurityObject() failed (Status %lx)\n", Status);
+ return RtlNtStatusToDosError (Status);
}
return ERROR_SUCCESS;
UNICODE_STRING FileName;
UNICODE_STRING KeyName;
HANDLE KeyHandle;
- LONG ErrorCode;
NTSTATUS Status;
+ LONG ErrorCode = ERROR_SUCCESS;
if (hKey == HKEY_PERFORMANCE_DATA)
{
- SetLastError(ERROR_INVALID_HANDLE);
return ERROR_INVALID_HANDLE;
}
Status = MapDefaultKey (&KeyHandle,
- hKey);
+ hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile,
NULL,
NULL))
{
- SetLastError (ERROR_BAD_PATHNAME);
- return ERROR_BAD_PATHNAME;
+ ErrorCode = ERROR_BAD_PATHNAME;
+ goto Cleanup;
}
InitializeObjectAttributes (&FileObjectAttributes,
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ goto Cleanup;
}
- return ERROR_SUCCESS;
+Cleanup:
+ CloseDefaultKey(KeyHandle);
+
+ return ErrorCode;
}
IO_STATUS_BLOCK IoStatusBlock;
HANDLE KeyHandle;
NTSTATUS Status;
+ LONG ErrorCode = ERROR_SUCCESS;
if (hKey == HKEY_PERFORMANCE_DATA)
{
}
Status = MapDefaultKey (&KeyHandle,
- hKey);
+ hKey);
if (!NT_SUCCESS(Status))
{
return RtlNtStatusToDosError (Status);
fAsynchronous);
if (!NT_SUCCESS(Status) && Status != STATUS_TIMEOUT)
{
- return RtlNtStatusToDosError (Status);
+ ErrorCode = RtlNtStatusToDosError (Status);
}
- return ERROR_SUCCESS;
+ CloseDefaultKey(KeyHandle);
+
+ return ErrorCode;
}
/************************************************************************
- * RegOpenKeyA
+ * RegOpenCurrentUser
*
* @implemented
*/
LONG STDCALL
-RegOpenKeyA (HKEY hKey,
- LPCSTR lpSubKey,
- PHKEY phkResult)
+RegOpenCurrentUser (IN REGSAM samDesired,
+ OUT PHKEY phkResult)
{
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING SubKeyString;
- HANDLE KeyHandle;
- LONG ErrorCode;
NTSTATUS Status;
- DPRINT("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n", hKey, lpSubKey, phkResult);
- Status = MapDefaultKey (&KeyHandle,
- hKey);
+ Status = RtlOpenCurrentUser((ACCESS_MASK)samDesired,
+ (PHANDLE)phkResult);
if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
- }
+ {
+ /* NOTE - don't set the last error code! just return the error! */
+ return RtlNtStatusToDosError(Status);
+ }
- RtlCreateUnicodeStringFromAsciiz (&SubKeyString,
- (LPSTR)lpSubKey);
- InitializeObjectAttributes (&ObjectAttributes,
- &SubKeyString,
- OBJ_CASE_INSENSITIVE,
- KeyHandle,
- NULL);
- Status = NtOpenKey ((PHANDLE)phkResult,
- MAXIMUM_ALLOWED,
- &ObjectAttributes);
- RtlFreeUnicodeString (&SubKeyString);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
- }
+ return ERROR_SUCCESS;
+}
+
+
+/************************************************************************
+ * RegOpenKeyA
+ *
+ * 20050503 Fireball - imported from WINE
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegOpenKeyA (HKEY hKey,
+ LPCSTR lpSubKey,
+ PHKEY phkResult)
+{
+ TRACE("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n", hKey, lpSubKey, phkResult);
- return ERROR_SUCCESS;
+ if (!lpSubKey || !*lpSubKey)
+ {
+ *phkResult = hKey;
+ return ERROR_SUCCESS;
+ }
+
+ return RegOpenKeyExA( hKey, lpSubKey, 0, MAXIMUM_ALLOWED, phkResult);
}
*
* 19981101 Ariadne
* 19990525 EA
+ * 20050503 Fireball - imported from WINE
*
* @implemented
*/
LPCWSTR lpSubKey,
PHKEY phkResult)
{
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING SubKeyString;
- HANDLE KeyHandle;
- LONG ErrorCode;
- NTSTATUS Status;
-
- DPRINT("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n", hKey, lpSubKey, phkResult);
- Status = MapDefaultKey (&KeyHandle,
- hKey);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
- }
-
- RtlInitUnicodeString (&SubKeyString,
- (LPWSTR)lpSubKey);
- InitializeObjectAttributes (&ObjectAttributes,
- &SubKeyString,
- OBJ_CASE_INSENSITIVE,
- KeyHandle,
- NULL);
- Status = NtOpenKey ((PHANDLE)phkResult,
- MAXIMUM_ALLOWED,
- &ObjectAttributes);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError(ErrorCode);
- return ErrorCode;
- }
+ TRACE("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n", hKey, lpSubKey, phkResult);
- return ERROR_SUCCESS;
+ if (!lpSubKey || !*lpSubKey)
+ {
+ *phkResult = hKey;
+ return ERROR_SUCCESS;
+ }
+ return RegOpenKeyExW(hKey, lpSubKey, 0, MAXIMUM_ALLOWED, phkResult);
}
REGSAM samDesired,
PHKEY phkResult)
{
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING SubKeyString;
- HANDLE KeyHandle;
- LONG ErrorCode;
- NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING SubKeyString;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+ LONG ErrorCode = ERROR_SUCCESS;
- DPRINT("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
- hKey, lpSubKey, ulOptions, samDesired, phkResult);
- Status = MapDefaultKey (&KeyHandle,
- hKey);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
- }
+ TRACE("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
+ hKey, lpSubKey, ulOptions, samDesired, phkResult);
- 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 (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
- }
+ Status = MapDefaultKey (&KeyHandle, hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
- return ERROR_SUCCESS;
+ 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 (Status);
+ }
+
+ CloseDefaultKey(KeyHandle);
+
+ return ErrorCode;
}
REGSAM samDesired,
PHKEY phkResult)
{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING SubKeyString;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+ LONG ErrorCode = ERROR_SUCCESS;
+
+ TRACE("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
+ hKey, lpSubKey, ulOptions, samDesired, phkResult);
+
+ 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))
+ {
+ ErrorCode = RtlNtStatusToDosError (Status);
+ }
+
+ CloseDefaultKey(KeyHandle);
+
+ return ErrorCode;
+}
+
+
+/************************************************************************
+ * RegOpenUserClassesRoot
+ *
+ * @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;
- UNICODE_STRING SubKeyString;
- HANDLE KeyHandle;
- LONG ErrorCode;
NTSTATUS Status;
- DPRINT("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
- hKey, lpSubKey, ulOptions, samDesired, phkResult);
- Status = MapDefaultKey (&KeyHandle,
- hKey);
+ /* 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! */
+ return RtlNtStatusToDosError (Status);
+ }
+
+ 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))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
- }
+ {
+ 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! */
+ return RtlNtStatusToDosError (Status);
+ }
+
+ /*
+ * 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
+ */
- if (lpSubKey != NULL)
- {
- RtlInitUnicodeString (&SubKeyString,
- (LPWSTR)lpSubKey);
- }
- else
- {
- RtlInitUnicodeString (&SubKeyString,
- (LPWSTR)L"");
- }
InitializeObjectAttributes (&ObjectAttributes,
- &SubKeyString,
+ &UserClassesKeyRoot,
OBJ_CASE_INSENSITIVE,
- KeyHandle,
+ NULL,
NULL);
- Status = NtOpenKey ((PHANDLE)phkResult,
- samDesired,
- &ObjectAttributes);
+
+ Status = NtOpenKey((PHANDLE)phkResult,
+ samDesired,
+ &ObjectAttributes);
+
+ RtlFreeUnicodeString(&UserSidString);
+ RtlFreeUnicodeString(&UserClassesKeyRoot);
+
if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
- }
+ {
+ return RtlNtStatusToDosError (Status);
+ }
return ERROR_SUCCESS;
}
ULONG ClassLength = 0;
HANDLE KeyHandle;
NTSTATUS Status;
- LONG ErrorCode = ERROR_SUCCESS;
ULONG Length;
+ LONG ErrorCode = ERROR_SUCCESS;
if ((lpClass) && (!lpcbClass))
{
- SetLastError(ERROR_INVALID_PARAMETER);
return ERROR_INVALID_PARAMETER;
}
hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
if (lpClass != NULL)
FullInfoSize);
if (FullInfo == NULL)
{
- SetLastError (ERROR_OUTOFMEMORY);
- return ERROR_OUTOFMEMORY;
+ ErrorCode = ERROR_OUTOFMEMORY;
+ goto Cleanup;
}
FullInfo->ClassLength = ClassLength;
FullInfo,
FullInfoSize,
&Length);
- DPRINT("NtQueryKey() returned status 0x%X\n", Status);
+ TRACE("NtQueryKey() returned status 0x%X\n", Status);
if (!NT_SUCCESS(Status))
{
if (lpClass != NULL)
}
ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ goto Cleanup;
}
- DPRINT("SubKeys %d\n", FullInfo->SubKeys);
+ TRACE("SubKeys %d\n", FullInfo->SubKeys);
if (lpcSubKeys != NULL)
{
*lpcSubKeys = FullInfo->SubKeys;
}
- DPRINT("MaxNameLen %lu\n", FullInfo->MaxNameLen);
+ TRACE("MaxNameLen %lu\n", FullInfo->MaxNameLen);
if (lpcbMaxSubKeyLen != NULL)
{
*lpcbMaxSubKeyLen = FullInfo->MaxNameLen / sizeof(WCHAR) + 1;
}
- DPRINT("MaxClassLen %lu\n", FullInfo->MaxClassLen);
+ TRACE("MaxClassLen %lu\n", FullInfo->MaxClassLen);
if (lpcbMaxClassLen != NULL)
{
*lpcbMaxClassLen = FullInfo->MaxClassLen / sizeof(WCHAR) + 1;
}
- DPRINT("Values %lu\n", FullInfo->Values);
+ TRACE("Values %lu\n", FullInfo->Values);
if (lpcValues != NULL)
{
*lpcValues = FullInfo->Values;
}
- DPRINT("MaxValueNameLen %lu\n", FullInfo->MaxValueNameLen);
+ TRACE("MaxValueNameLen %lu\n", FullInfo->MaxValueNameLen);
if (lpcbMaxValueNameLen != NULL)
{
*lpcbMaxValueNameLen = FullInfo->MaxValueNameLen / sizeof(WCHAR) + 1;
}
- DPRINT("MaxValueDataLen %lu\n", FullInfo->MaxValueDataLen);
+ TRACE("MaxValueDataLen %lu\n", FullInfo->MaxValueDataLen);
if (lpcbMaxValueLen != NULL)
{
*lpcbMaxValueLen = FullInfo->MaxValueDataLen;
FullInfo);
}
- ErrorCode = RtlNtStatusToDosError(Status);
- SetLastError(ErrorCode);
- return ErrorCode;
+ ErrorCode = RtlNtStatusToDosError (Status);
+ goto Cleanup;
}
}
FullInfo);
}
- if (ErrorCode != ERROR_SUCCESS)
- {
- SetLastError (ErrorCode);
- }
-
+Cleanup:
+ CloseDefaultKey(KeyHandle);
+
return ErrorCode;
}
*ldwTotsize = 0;
- DPRINT ("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
+ TRACE("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
for (i = 0; i < num_vals; i++)
*ldwTotsize = 0;
- DPRINT ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
+ TRACE ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
for (i = 0; i < num_vals; i++)
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
UNICODE_STRING ValueName;
NTSTATUS Status;
- LONG ErrorCode = ERROR_SUCCESS;
ULONG BufferSize;
ULONG ResultSize;
HANDLE KeyHandle;
+ LONG ErrorCode = ERROR_SUCCESS;
ULONG MaxCopy = lpcbData != NULL && lpData != NULL ? *lpcbData : 0;
- DPRINT("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
+ 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))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
if (lpData != NULL && lpcbData == NULL)
{
- SetLastError (ERROR_INVALID_PARAMETER);
- return ERROR_INVALID_PARAMETER;
+ ErrorCode = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
}
RtlInitUnicodeString (&ValueName,
BufferSize);
if (ValueInfo == NULL)
{
- SetLastError(ERROR_OUTOFMEMORY);
- return ERROR_OUTOFMEMORY;
+ ErrorCode = ERROR_OUTOFMEMORY;
+ goto Cleanup;
}
- Status = NtQueryValueKey (hKey,
+ Status = NtQueryValueKey (KeyHandle,
&ValueName,
KeyValuePartialInformation,
ValueInfo,
BufferSize,
&ResultSize);
- DPRINT("Status 0x%X\n", Status);
+ TRACE("Status 0x%X\n", Status);
if (Status == STATUS_BUFFER_OVERFLOW)
{
/* Return ERROR_SUCCESS and the buffer space needed for a successful call */
else if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
MaxCopy = 0;
if (lpcbData != NULL)
{
if (lpcbData != NULL)
{
*lpcbData = (ResultSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]));
- DPRINT("(string) Returning Size: %lu\n", *lpcbData);
+ TRACE("(string) Returning Size: %lu\n", *lpcbData);
}
}
else
if (lpcbData != NULL)
{
*lpcbData = ResultSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
- DPRINT("(other) Returning Size: %lu\n", *lpcbData);
+ TRACE("(other) Returning Size: %lu\n", *lpcbData);
}
}
- DPRINT("Type %d Size %d\n", ValueInfo->Type, ValueInfo->DataLength);
+ TRACE("Type %d Size %d\n", ValueInfo->Type, ValueInfo->DataLength);
RtlFreeHeap (ProcessHeap,
0,
ValueInfo);
+Cleanup:
+ CloseDefaultKey(KeyHandle);
+
return ErrorCode;
}
DWORD Length;
DWORD Type;
- DPRINT("hKey 0x%X lpValueName %s lpData 0x%X lpcbData %d\n",
+ TRACE("hKey 0x%X lpValueName %s lpData 0x%X lpcbData %d\n",
hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0);
if (lpData != NULL && lpcbData == NULL)
{
- SetLastError(ERROR_INVALID_PARAMETER);
return ERROR_INVALID_PARAMETER;
}
ValueData.MaximumLength);
if (!ValueData.Buffer)
{
- SetLastError(ERROR_OUTOFMEMORY);
return ERROR_OUTOFMEMORY;
}
}
&Type,
(lpData == NULL) ? NULL : (LPBYTE)ValueData.Buffer,
&Length);
- DPRINT("ErrorCode %lu\n", ErrorCode);
+ TRACE("ErrorCode %lu\n", ErrorCode);
RtlFreeUnicodeString(&ValueName);
if (ErrorCode == ERROR_SUCCESS ||
LONG ValueSize;
LONG ErrorCode;
- DPRINT("hKey 0x%X lpSubKey %s lpValue %p lpcbValue %d\n",
+ TRACE("hKey 0x%X lpSubKey %s lpValue %p lpcbValue %d\n",
hKey, lpSubKey, lpValue, lpcbValue ? *lpcbValue : 0);
if (lpValue != NULL &&
lpcbValue == NULL)
{
- SetLastError(ERROR_INVALID_PARAMETER);
return ERROR_INVALID_PARAMETER;
}
ValueSize);
if (Value.Buffer == NULL)
{
- SetLastError(ERROR_OUTOFMEMORY);
return ERROR_OUTOFMEMORY;
}
}
BOOL CloseRealKey;
NTSTATUS Status;
- DPRINT("hKey 0x%X lpSubKey %S lpValue %p lpcbValue %d\n",
+ TRACE("hKey 0x%X lpSubKey %S lpValue %p lpcbValue %d\n",
hKey, lpSubKey, lpValue, lpcbValue ? *lpcbValue : 0);
Status = MapDefaultKey (&KeyHandle,
- hKey);
+ hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
if (lpSubKey != NULL &&
KeyHandle,
NULL);
Status = NtOpenKey (&RealKey,
- KEY_ALL_ACCESS,
+ KEY_QUERY_VALUE,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ goto Cleanup;
}
CloseRealKey = TRUE;
}
NtClose (RealKey);
}
+Cleanup:
+ CloseDefaultKey(KeyHandle);
+
return ErrorCode;
}
BOOLEAN CloseRealKey;
HANDLE RealKeyHandle;
HANDLE KeyHandle;
- LONG ErrorCode;
NTSTATUS Status;
+ LONG ErrorCode = ERROR_SUCCESS;
if (hKey == HKEY_PERFORMANCE_DATA)
{
}
Status = MapDefaultKey (&KeyHandle,
- hKey);
+ hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
/* Open the real key */
KeyHandle,
NULL);
Status = NtOpenKey (&RealKeyHandle,
- KEY_ALL_ACCESS,
+ MAXIMUM_ALLOWED,
&KeyObjectAttributes);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ goto Cleanup;
}
CloseRealKey = TRUE;
}
{
NtClose (RealKeyHandle);
}
- SetLastError (ERROR_INVALID_PARAMETER);
- return ERROR_INVALID_PARAMETER;
+ ErrorCode = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
}
InitializeObjectAttributes (&NewObjectAttributes,
{
NtClose (RealKeyHandle);
}
- SetLastError (ERROR_INVALID_PARAMETER);
- return ERROR_INVALID_PARAMETER;
+ ErrorCode = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
}
InitializeObjectAttributes (&OldObjectAttributes,
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
- return ERROR_SUCCESS;
+Cleanup:
+ CloseDefaultKey(KeyHandle);
+
+ return ErrorCode;
}
UNICODE_STRING FileName;
HANDLE FileHandle;
HANDLE KeyHandle;
- LONG ErrorCode;
NTSTATUS Status;
if (hKey == HKEY_PERFORMANCE_DATA)
}
Status = MapDefaultKey (&KeyHandle,
- hKey);
+ hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile,
NULL,
NULL))
{
- SetLastError (ERROR_INVALID_PARAMETER);
- return ERROR_INVALID_PARAMETER;
+ Status = STATUS_INVALID_PARAMETER;
+ goto Cleanup;
}
InitializeObjectAttributes (&ObjectAttributes,
RtlFreeUnicodeString (&FileName);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ goto Cleanup;
}
Status = NtRestoreKey (KeyHandle,
FileHandle,
(ULONG)dwFlags);
NtClose (FileHandle);
+
+Cleanup:
+ CloseDefaultKey(KeyHandle);
+
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
return ERROR_SUCCESS;
HANDLE FileHandle;
HANDLE KeyHandle;
NTSTATUS Status;
- LONG ErrorCode;
Status = MapDefaultKey (&KeyHandle,
- hKey);
+ hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
if (!RtlDosPathNameToNtPathName_U ((PWSTR)lpFile,
NULL,
NULL))
{
- SetLastError (ERROR_INVALID_PARAMETER);
- return ERROR_INVALID_PARAMETER;
+ Status = STATUS_INVALID_PARAMETER;
+ goto Cleanup;
}
if (lpSecurityAttributes != NULL)
RtlFreeUnicodeString (&FileName);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ goto Cleanup;
}
Status = NtSaveKey (KeyHandle,
FileHandle);
NtClose (FileHandle);
+
+Cleanup:
+ CloseDefaultKey(KeyHandle);
+
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
return ERROR_SUCCESS;
PSECURITY_DESCRIPTOR pSecurityDescriptor)
{
HANDLE KeyHandle;
- LONG ErrorCode;
NTSTATUS Status;
if (hKey == HKEY_PERFORMANCE_DATA)
{
- SetLastError(ERROR_INVALID_HANDLE);
return ERROR_INVALID_HANDLE;
}
Status = MapDefaultKey (&KeyHandle,
- hKey);
+ hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
Status = NtSetSecurityObject (KeyHandle,
SecurityInformation,
pSecurityDescriptor);
+
+ CloseDefaultKey(KeyHandle);
+
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
return ERROR_SUCCESS;
pValueName = NULL;
}
- if ((dwType == REG_SZ) ||
- (dwType == REG_MULTI_SZ) ||
- (dwType == REG_EXPAND_SZ))
+ 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;
+ AnsiString.Length = cbData - 1;
AnsiString.MaximumLength = cbData;
RtlAnsiStringToUnicodeString (&Data,
&AnsiString,
PUNICODE_STRING pValueName;
HANDLE KeyHandle;
NTSTATUS Status;
- LONG ErrorCode;
Status = MapDefaultKey (&KeyHandle,
- hKey);
+ hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
if (lpValueName != NULL)
}
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);
+
+ CloseDefaultKey(KeyHandle);
+
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
return ERROR_SUCCESS;
LPCSTR lpData,
DWORD cbData)
{
- WCHAR SubKeyNameBuffer[MAX_PATH+1];
- UNICODE_STRING SubKeyName;
- UNICODE_STRING Data;
- ANSI_STRING AnsiString;
- LONG DataSize;
- LONG ErrorCode;
-
- if (lpData == NULL)
- {
- SetLastError (ERROR_INVALID_PARAMETER);
- return ERROR_INVALID_PARAMETER;
- }
+ LONG ret;
+ HKEY hSubKey;
- RtlInitUnicodeString (&SubKeyName, NULL);
- RtlInitUnicodeString (&Data, NULL);
- if (lpSubKey != NULL && (strlen(lpSubKey) != 0))
- {
- RtlInitAnsiString (&AnsiString, (LPSTR)lpSubKey);
- SubKeyName.Buffer = &SubKeyNameBuffer[0];
- SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
- RtlAnsiStringToUnicodeString (&SubKeyName, &AnsiString, FALSE);
- }
+ if (dwType != REG_SZ)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
- DataSize = cbData * sizeof(WCHAR);
- Data.MaximumLength = DataSize;
- Data.Buffer = RtlAllocateHeap (ProcessHeap,
- 0,
- DataSize);
- if (Data.Buffer == NULL)
- {
- SetLastError (ERROR_OUTOFMEMORY);
- return ERROR_OUTOFMEMORY;
- }
+ if (lpSubKey != NULL && lpSubKey[0] != '\0')
+ {
+ ret = RegCreateKeyA(hKey,
+ lpSubKey,
+ &hSubKey);
+
+ if (ret != ERROR_SUCCESS)
+ {
+ return ret;
+ }
+ }
+ else
+ hSubKey = hKey;
- ErrorCode = RegSetValueW (hKey,
- (LPCWSTR)SubKeyName.Buffer,
- dwType,
- Data.Buffer,
- DataSize);
+ ret = RegSetValueExA(hSubKey,
+ NULL,
+ 0,
+ REG_SZ,
+ (CONST BYTE*)lpData,
+ strlen(lpData) + 1);
- RtlFreeHeap (ProcessHeap,
- 0,
- Data.Buffer);
+ if (hSubKey != hKey)
+ {
+ RegCloseKey(hSubKey);
+ }
- return ErrorCode;
+ return ret;
}
UNICODE_STRING SubKeyString;
HANDLE KeyHandle;
HANDLE RealKey;
- LONG ErrorCode;
BOOL CloseRealKey;
NTSTATUS Status;
+ LONG ErrorCode;
Status = MapDefaultKey (&KeyHandle,
- hKey);
+ hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
if ((lpSubKey) && (wcslen(lpSubKey) != 0))
KeyHandle,
NULL);
Status = NtOpenKey (&RealKey,
- KEY_ALL_ACCESS,
+ KEY_SET_VALUE,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ goto Cleanup;
}
CloseRealKey = TRUE;
}
NtClose (RealKey);
}
+Cleanup:
+ CloseDefaultKey(KeyHandle);
+
return ErrorCode;
}
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
HANDLE KeyHandle;
- DWORD ErrorCode;
NTSTATUS Status;
if (hKey == HKEY_PERFORMANCE_DATA)
{
- SetLastError(ERROR_INVALID_HANDLE);
return ERROR_INVALID_HANDLE;
}
Status = MapDefaultKey (&KeyHandle, hKey);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
RtlInitUnicodeString (&KeyName,
NULL);
Status = NtUnloadKey (&ObjectAttributes);
+
+ CloseDefaultKey(KeyHandle);
if (!NT_SUCCESS(Status))
{
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
+ return RtlNtStatusToDosError (Status);
}
return ERROR_SUCCESS;
}
+
+/************************************************************************
+ * RegLoadMUIStringW
+ *
+ * @unimplemented
+ */
+LONG STDCALL
+RegLoadMUIStringW(IN HKEY hKey,
+ IN LPCWSTR pszValue OPTIONAL,
+ OUT LPWSTR pszOutBuf,
+ IN ULONG cbOutBuf,
+ IN ULONG Reserved,
+ IN LPCWSTR pszDirectory OPTIONAL)
+{
+ DPRINT1("RegLoadMUIStringW(0x%p, 0x%p, 0x%p, 0x%x, 0x%x, 0x%p) UNIMPLEMENTED!\n",
+ hKey, pszValue, pszOutBuf, cbOutBuf, Reserved, pszDirectory);
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/************************************************************************
+ * RegLoadMUIStringA
+ *
+ * @unimplemented
+ */
+LONG STDCALL
+RegLoadMUIStringA(IN HKEY hKey,
+ IN LPCSTR pszValue OPTIONAL,
+ OUT LPSTR pszOutBuf,
+ IN ULONG cbOutBuf,
+ IN ULONG Reserved,
+ IN LPCSTR pszDirectory OPTIONAL)
+{
+ DPRINT1("RegLoadMUIStringA(0x%p, 0x%p, 0x%p, 0x%x, 0x%x, 0x%p) UNIMPLEMENTED!\n",
+ hKey, pszValue, pszOutBuf, cbOutBuf, Reserved, pszDirectory);
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
/* EOF */