Files
reactos/reactos/lib/advapi32/reg/reg.c
Robert Dickenson 24ef4d36dc added a whole bunch of hacks #ifdef'd into the header section to support private test build.
totally turned the contents upside down so functions are implicitly declared before use without header prototypes.

svn path=/trunk/; revision=3726
2002-11-10 13:44:48 +00:00

2634 lines
52 KiB
C

/* $Id: reg.c,v 1.19 2002/11/10 13:44:48 robd Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/advapi32/reg/reg.c
* PURPOSE: Registry functions
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
* UPDATE HISTORY:
* Created 01/11/98
* 19990309 EA Stubs
*/
#ifdef WIN32_REGDBG
#include "cm_win32.h"
#ifdef __GNUC__
#define WINAPI __stdcall
#define WINAPIV __cdecl
#define APIENTRY __stdcall
#define DECLSPEC_IMPORT __declspec(dllimport)
#define DECLSPEC_EXPORT __declspec(dllexport)
#define DECLARE_HANDLE(n) typedef HANDLE n
#define HKEY_PERFORMANCE_DATA ((HKEY)0x80000004)
#define ERROR_SUCCESS 0L
#define ERROR_INVALID_HANDLE 6L
#define ERROR_OUTOFMEMORY 14L
#define ERROR_INVALID_PARAMETER 87L
#define ERROR_CALL_NOT_IMPLEMENTED 120L
#define ERROR_MORE_DATA 234L
void WINAPI SetLastError(DWORD);
BOOLEAN
STDCALL
RtlDosPathNameToNtPathName_U (
PWSTR dosname,
PUNICODE_STRING ntname,
PWSTR *shortname,
PCURDIR nah);
NTSTATUS
STDCALL
RtlInitializeCriticalSection(LPCRITICAL_SECTION lpcs);
NTSTATUS
STDCALL
RtlDeleteCriticalSection(LPCRITICAL_SECTION lpcs);
NTSTATUS
STDCALL
RtlLeaveCriticalSection(LPCRITICAL_SECTION lpcs);
NTSTATUS
STDCALL
RtlEnterCriticalSection(LPCRITICAL_SECTION lpcs);
DECLARE_HANDLE(HKEY);
typedef HKEY *PHKEY;
typedef ACCESS_MASK REGSAM;
typedef struct value_entA {
LPSTR ve_valuename;
DWORD ve_valuelen;
DWORD ve_valueptr;
DWORD ve_type;
} VALENTA,*PVALENTA;
typedef struct value_entW {
LPWSTR ve_valuename;
DWORD ve_valuelen;
DWORD ve_valueptr;
DWORD ve_type;
} VALENTW,*PVALENTW;
#endif
#undef STDCALL
#define STDCALL _stdcall
#undef RegSetValueEx
#undef RegCreateKeyEx
#undef RegQueryInfoKey
#undef RegDeleteKey
#undef RegOpenKey
#undef RegOpenKeyEx
#undef RegEnumKeyEx
#undef RegEnumValue
#else
#include <ddk/ntddk.h>
#include <ntdll/rtl.h>
#include <windows.h>
#include <wchar.h>
#define NDEBUG
#include <debug.h>
#endif
#define CHECK_STATUS \
{ \
if (!NT_SUCCESS(Status)) \
{ \
LONG _ErrorCode = RtlNtStatusToDosError(Status); \
SetLastError(_ErrorCode); \
return _ErrorCode; \
} \
}
/* GLOBALS *******************************************************************/
#define MAX_DEFAULT_HANDLES 6
static CRITICAL_SECTION HandleTableCS;
static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES];
/* PROTOTYPES ****************************************************************/
static NTSTATUS MapDefaultKey (PHKEY 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 *****************************************************************/
inline RegiTerminateWideString(LPWSTR String, DWORD Length)
{
LPWSTR AfterString = String + Length;
*AfterString = 0;
}
/************************************************************************
* RegInitDefaultHandles
*/
BOOL
RegInitialize (VOID)
{
DPRINT("RegInitialize()\n");
RtlZeroMemory (DefaultHandleTable,
MAX_DEFAULT_HANDLES * sizeof(HANDLE));
RtlInitializeCriticalSection(&HandleTableCS);
return TRUE;
}
/************************************************************************
* RegInit
*/
BOOL
RegCleanup(VOID)
{
DPRINT("RegCleanup()\n");
CloseDefaultKeys();
RtlDeleteCriticalSection(&HandleTableCS);
return TRUE;
}
static NTSTATUS
MapDefaultKey(PHKEY 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 0: /* HKEY_CLASSES_ROOT */
Status = OpenClassesRootKey(Handle);
break;
case 1: /* HKEY_CURRENT_USER */
Status = RtlOpenCurrentUser(KEY_ALL_ACCESS,
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;
default:
DPRINT("MapDefaultHandle() no handle creator\n");
Status = STATUS_INVALID_PARAMETER;
}
}
RtlLeaveCriticalSection(&HandleTableCS);
if (NT_SUCCESS(Status))
{
*RealKey = (HKEY)*Handle;
}
return Status;
}
static VOID
CloseDefaultKeys(VOID)
{
ULONG i;
RtlEnterCriticalSection(&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 = UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine\\Software\\CLASSES");
DPRINT("OpenClassesRootKey()\n");
InitializeObjectAttributes(&Attributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
return(NtOpenKey(KeyHandle,
KEY_ALL_ACCESS,
&Attributes));
}
static NTSTATUS
OpenLocalMachineKey(PHANDLE KeyHandle)
{
OBJECT_ATTRIBUTES Attributes;
UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine");
DPRINT("OpenLocalMachineKey()\n");
InitializeObjectAttributes(&Attributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
return(NtOpenKey(KeyHandle,
KEY_ALL_ACCESS,
&Attributes));
}
static NTSTATUS
OpenUsersKey(PHANDLE KeyHandle)
{
OBJECT_ATTRIBUTES Attributes;
UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry\\User");
DPRINT("OpenUsersKey()\n");
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 =
UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
DPRINT("OpenCurrentConfigKey()\n");
InitializeObjectAttributes(&Attributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
return(NtOpenKey(KeyHandle,
KEY_ALL_ACCESS,
&Attributes));
}
/************************************************************************
* RegCloseKey
*/
LONG STDCALL
RegCloseKey(HKEY hKey)
{
NTSTATUS Status;
/* 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;
}
return ERROR_SUCCESS;
}
/************************************************************************
* RegConnectRegistryA
*/
LONG STDCALL
RegConnectRegistryA(LPCSTR lpMachineName,
HKEY hKey,
PHKEY phkResult)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
* RegConnectRegistryW
*/
LONG STDCALL
RegConnectRegistryW(LPCWSTR lpMachineName,
HKEY hKey,
PHKEY phkResult)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
* RegCreateKeyExA
*/
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);
if (lpClass != NULL)
RtlCreateUnicodeStringFromAsciiz(&ClassString,
lpClass);
RtlCreateUnicodeStringFromAsciiz(&SubKeyString,
(LPSTR)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);
RtlFreeUnicodeString(&SubKeyString);
if (lpClass != NULL)
RtlFreeUnicodeString(&ClassString);
DPRINT("Status %x\n", Status);
if (!NT_SUCCESS(Status))
{
LONG ErrorCode = RtlNtStatusToDosError(Status);
SetLastError (ErrorCode);
return ErrorCode;
}
return(ERROR_SUCCESS);
}
/************************************************************************
* RegCreateKeyExW
*/
LONG STDCALL
RegCreateKeyExW(HKEY hKey,
LPCWSTR lpSubKey,
DWORD Reserved,
LPWSTR 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;
}
/************************************************************************
* RegCreateKeyA
*/
LONG STDCALL
RegCreateKeyA(HKEY hKey,
LPCSTR lpSubKey,
PHKEY phkResult)
{
return(RegCreateKeyExA(hKey,
lpSubKey,
0,
NULL,
0,
KEY_ALL_ACCESS,
NULL,
phkResult,
NULL));
}
/************************************************************************
* RegCreateKeyW
*/
LONG STDCALL
RegCreateKeyW(HKEY hKey,
LPCWSTR lpSubKey,
PHKEY phkResult)
{
return(RegCreateKeyExW(hKey,
lpSubKey,
0,
NULL,
0,
KEY_ALL_ACCESS,
NULL,
phkResult,
NULL));
}
/************************************************************************
* RegDeleteKeyA
*/
LONG
STDCALL
RegDeleteKeyA(
HKEY hKey,
LPCSTR lpSubKey
)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING SubKeyStringW;
ANSI_STRING SubKeyStringA;
// HANDLE ParentKey;
HKEY 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;
}
/************************************************************************
* RegDeleteKeyW
*/
LONG
STDCALL
RegDeleteKeyW(
HKEY hKey,
LPCWSTR lpSubKey
)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING SubKeyString;
HKEY 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);
SetLastError (ErrorCode);
return ErrorCode;
}
Status = NtDeleteKey(TargetKey);
NtClose(TargetKey);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError (ErrorCode);
return ErrorCode;
}
return ERROR_SUCCESS;
}
/************************************************************************
* RegDeleteValueA
*/
LONG
STDCALL
RegDeleteValueA(
HKEY hKey,
LPCSTR lpValueName
)
{
UNICODE_STRING ValueNameW;
ANSI_STRING ValueNameA;
NTSTATUS Status;
LONG ErrorCode;
HKEY KeyHandle;
Status = MapDefaultKey(&KeyHandle,
hKey);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError (ErrorCode);
return ErrorCode;
}
RtlInitAnsiString(&ValueNameA,
(LPSTR)lpValueName);
RtlAnsiStringToUnicodeString(&ValueNameW,
&ValueNameA,
TRUE);
Status = NtDeleteValueKey(KeyHandle,
&ValueNameW);
RtlFreeUnicodeString (&ValueNameW);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError (ErrorCode);
return ErrorCode;
}
return ERROR_SUCCESS;
}
/************************************************************************
* RegDeleteValueW
*/
LONG
STDCALL
RegDeleteValueW(
HKEY hKey,
LPCWSTR lpValueName
)
{
UNICODE_STRING ValueName;
NTSTATUS Status;
LONG ErrorCode;
HKEY KeyHandle;
Status = MapDefaultKey(&KeyHandle,
hKey);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError (ErrorCode);
return ErrorCode;
}
RtlInitUnicodeString(&ValueName,
(LPWSTR)lpValueName);
Status = NtDeleteValueKey(KeyHandle,
&ValueName);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError (ErrorCode);
return ErrorCode;
}
return ERROR_SUCCESS;
}
/************************************************************************
* RegEnumKeyExW
*/
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;
HKEY KeyHandle;
Status = MapDefaultKey(&KeyHandle, hKey);
if (!NT_SUCCESS(Status))
{
dwError = RtlNtStatusToDosError(Status);
SetLastError (dwError);
return dwError;
}
BufferSize = sizeof (KEY_NODE_INFORMATION) + *lpcbName * sizeof(WCHAR);
if (lpClass)
BufferSize += *lpcbClass;
//
// I think this is a memory leak, always allocated again below ???
//
// KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
//
/* We don't know the exact size of the data returned, so call
NtEnumerateKey() with a buffer size determined from parameters
to this function. If that call fails with a status code of
STATUS_BUFFER_OVERFLOW, allocate a new buffer and try again */
while (TRUE) {
KeyInfo = RtlAllocateHeap(
RtlGetProcessHeap(),
0,
BufferSize);
if (KeyInfo == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
return ERROR_OUTOFMEMORY;
}
Status = NtEnumerateKey(
KeyHandle,
(ULONG)dwIndex,
KeyNodeInformation,
KeyInfo,
BufferSize,
&ResultSize);
DPRINT("NtEnumerateKey() returned status 0x%X\n", Status);
if (Status == STATUS_BUFFER_OVERFLOW)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
BufferSize = ResultSize;
continue;
}
if (!NT_SUCCESS(Status))
{
dwError = RtlNtStatusToDosError(Status);
SetLastError(dwError);
break;
}
else
{
if ((lpClass) && (*lpcbClass != 0) && (KeyInfo->ClassLength > *lpcbClass))
{
dwError = ERROR_MORE_DATA;
SetLastError(dwError);
break;
}
RtlMoveMemory(lpName, KeyInfo->Name, KeyInfo->NameLength);
*lpcbName = (DWORD)(KeyInfo->NameLength / sizeof(WCHAR));
RegiTerminateWideString(lpName, *lpcbName);
if (lpClass)
{
RtlMoveMemory(lpClass,
(PVOID)((ULONG_PTR)KeyInfo->Name + KeyInfo->ClassOffset),
KeyInfo->ClassLength);
*lpcbClass = (DWORD)(KeyInfo->ClassLength / sizeof(WCHAR));
}
if (lpftLastWriteTime)
{
/* FIXME: Fill lpftLastWriteTime */
}
break;
}
}
RtlFreeHeap (RtlGetProcessHeap(), 0, KeyInfo);
return dwError;
}
/************************************************************************
* RegEnumKeyW
*/
LONG
STDCALL
RegEnumKeyW(
HKEY hKey,
DWORD dwIndex,
LPWSTR lpName,
DWORD cbName
)
{
DWORD dwLength = cbName;
return RegEnumKeyExW(hKey,
dwIndex,
lpName,
&dwLength,
NULL,
NULL,
NULL,
NULL);
}
/************************************************************************
* RegEnumKeyExA
*/
LONG
STDCALL
RegEnumKeyExA(
HKEY hKey,
DWORD dwIndex,
LPSTR lpName,
LPDWORD lpcbName,
LPDWORD lpReserved,
LPSTR lpClass,
LPDWORD lpcbClass,
PFILETIME lpftLastWriteTime
)
{
WCHAR Name[MAX_PATH+1];
UNICODE_STRING UnicodeStringName;
WCHAR Class[MAX_PATH+1];
UNICODE_STRING UnicodeStringClass;
ANSI_STRING AnsiString;
LONG ErrorCode;
DWORD NameLength;
DWORD ClassLength;
DPRINT("hKey 0x%x dwIndex %d lpName 0x%x *lpcbName %d lpClass 0x%x lpcbClass %d\n",
hKey, dwIndex, lpName, *lpcbName, lpClass, lpcbClass);
if ((lpClass) && (!lpcbClass))
{
SetLastError(ERROR_INVALID_PARAMETER);
return ERROR_INVALID_PARAMETER;
}
RtlInitUnicodeString(&UnicodeStringName, NULL);
UnicodeStringName.Buffer = &Name[0];
UnicodeStringName.MaximumLength = sizeof(Name);
RtlInitUnicodeString(&UnicodeStringClass, NULL);
if (lpClass)
{
UnicodeStringClass.Buffer = &Class[0];
UnicodeStringClass.MaximumLength = sizeof(Class);
ClassLength = *lpcbClass;
}
else
{
ClassLength = 0;
}
NameLength = *lpcbName;
ErrorCode = RegEnumKeyExW(
hKey,
dwIndex,
UnicodeStringName.Buffer,
&NameLength,
lpReserved,
UnicodeStringClass.Buffer,
&ClassLength,
lpftLastWriteTime);
if (ErrorCode != ERROR_SUCCESS)
return ErrorCode;
UnicodeStringName.Length = NameLength * sizeof(WCHAR);
UnicodeStringClass.Length = ClassLength * sizeof(WCHAR);
RtlInitAnsiString(&AnsiString, NULL);
AnsiString.Buffer = lpName;
AnsiString.MaximumLength = *lpcbName;
RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeStringName, FALSE);
*lpcbName = AnsiString.Length;
DPRINT("Key Namea0 Length %d\n", UnicodeStringName.Length);
DPRINT("Key Namea1 Length %d\n", NameLength);
DPRINT("Key Namea Length %d\n", *lpcbName);
DPRINT("Key Namea %s\n", lpName);
if (lpClass)
{
RtlInitAnsiString(&AnsiString, NULL);
AnsiString.Buffer = lpClass;
AnsiString.MaximumLength = *lpcbClass;
RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeStringClass, FALSE);
*lpcbClass = AnsiString.Length;
}
return ERROR_SUCCESS;
}
/************************************************************************
* RegEnumKeyA
*/
LONG
STDCALL
RegEnumKeyA(
HKEY hKey,
DWORD dwIndex,
LPSTR lpName,
DWORD cbName
)
{
DWORD dwLength = cbName;
return RegEnumKeyExA(hKey,
dwIndex,
lpName,
&dwLength,
NULL,
NULL,
NULL,
NULL);
}
/************************************************************************
* RegEnumValueW
*/
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;
HKEY KeyHandle;
Status = MapDefaultKey(&KeyHandle, hKey);
if (!NT_SUCCESS(Status))
{
dwError = RtlNtStatusToDosError(Status);
SetLastError(dwError);
return(dwError);
}
BufferSize = sizeof (KEY_VALUE_FULL_INFORMATION) +
*lpcbValueName * sizeof(WCHAR);
if (lpcbData)
BufferSize += *lpcbData;
/* We don't know the exact size of the data returned, so call
NtEnumerateValueKey() with a buffer size determined from parameters
to this function. If that call fails with a status code of
STATUS_BUFFER_OVERFLOW, allocate a new buffer and try again */
while (TRUE) {
ValueInfo = RtlAllocateHeap(
RtlGetProcessHeap(),
0,
BufferSize);
if (ValueInfo == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
return ERROR_OUTOFMEMORY;
}
Status = NtEnumerateValueKey(
KeyHandle,
(ULONG)dwIndex,
KeyValueFullInformation,
ValueInfo,
BufferSize,
&ResultSize);
DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
if (Status == STATUS_BUFFER_OVERFLOW)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
BufferSize = ResultSize;
continue;
}
if (!NT_SUCCESS(Status))
{
dwError = RtlNtStatusToDosError(Status);
SetLastError(dwError);
break;
}
else
{
if ((lpData) && (*lpcbData != 0) && (ValueInfo->DataLength > *lpcbData))
{
dwError = ERROR_MORE_DATA;
SetLastError(dwError);
break;
}
memcpy(lpValueName, ValueInfo->Name, ValueInfo->NameLength);
*lpcbValueName = (DWORD)(ValueInfo->NameLength / sizeof(WCHAR));
RegiTerminateWideString(lpValueName, *lpcbValueName);
if (lpType)
*lpType = ValueInfo->Type;
if (lpData)
{
memcpy(lpData,
//(PVOID)((ULONG_PTR)ValueInfo->Name + ValueInfo->DataOffset),
(PVOID)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset),
ValueInfo->DataLength);
*lpcbData = (DWORD)ValueInfo->DataLength;
/*
RtlCopyMemory((PCHAR) ValueFullInformation + ValueFullInformation->DataOffset,
DataCell->Data,
ValueCell->DataSize & LONG_MAX);
*/
}
break;
}
}
RtlFreeHeap (RtlGetProcessHeap(), 0, ValueInfo);
return dwError;
}
/************************************************************************
* RegEnumValueA
*/
LONG
STDCALL
RegEnumValueA(
HKEY hKey,
DWORD dwIndex,
LPSTR lpValueName,
LPDWORD lpcbValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
)
{
WCHAR ValueName[MAX_PATH+1];
UNICODE_STRING UnicodeString;
ANSI_STRING AnsiString;
LONG ErrorCode;
DWORD ValueNameLength;
BYTE* lpDataBuffer = NULL;
DWORD cbData = 0;
DWORD Type;
ANSI_STRING AnsiDataString;
UNICODE_STRING UnicodeDataString;
if (lpData != NULL /*&& lpcbData != NULL*/) {
cbData = *lpcbData; // this should always be valid if lpData is valid
lpDataBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, (*lpcbData) * sizeof(WCHAR));
if (lpDataBuffer == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return ERROR_OUTOFMEMORY;
}
}
RtlInitUnicodeString(&UnicodeString, NULL);
UnicodeString.Buffer = &ValueName[0];
UnicodeString.MaximumLength = sizeof(ValueName);
ValueNameLength = *lpcbValueName;
ErrorCode = RegEnumValueW(
hKey,
dwIndex,
UnicodeString.Buffer,
&ValueNameLength,
lpReserved,
&Type,
lpDataBuffer,
&cbData);
if (ErrorCode != ERROR_SUCCESS)
return ErrorCode;
UnicodeString.Length = ValueNameLength * sizeof(WCHAR);
RtlInitAnsiString(&AnsiString, NULL);
AnsiString.Buffer = lpValueName;
AnsiString.MaximumLength = *lpcbValueName;
RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
*lpcbValueName = AnsiString.Length;
// if (lpData != lpDataBuffer) { // did we use a temp buffer
if (lpDataBuffer) { // did we use a temp buffer
if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ)) {
RtlInitUnicodeString(&UnicodeDataString, NULL);
UnicodeDataString.Buffer = lpDataBuffer;
UnicodeDataString.MaximumLength = (*lpcbData) * sizeof(WCHAR);
UnicodeDataString.Length = cbData /* * sizeof(WCHAR)*/;
RtlInitAnsiString(&AnsiDataString, NULL);
AnsiDataString.Buffer = lpData;
AnsiDataString.MaximumLength = *lpcbData;
RtlUnicodeStringToAnsiString(&AnsiDataString, &UnicodeDataString, FALSE);
*lpcbData = AnsiDataString.Length;
// else if (Type == REG_EXPAND_SZ) {
} else {
memcpy(lpData, lpDataBuffer, min(*lpcbData, cbData));
*lpcbData = cbData;
}
RtlFreeHeap(RtlGetProcessHeap(), 0, lpDataBuffer);
}
if (lpType != NULL) {
*lpType = Type;
}
return ERROR_SUCCESS;
}
/************************************************************************
* RegFlushKey
*/
LONG STDCALL
RegFlushKey(HKEY hKey)
{
HKEY KeyHandle;
NTSTATUS Status;
LONG ErrorCode;
if (hKey == HKEY_PERFORMANCE_DATA)
return(ERROR_SUCCESS);
Status = MapDefaultKey(&KeyHandle,
hKey);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError(ErrorCode);
return(ErrorCode);
}
Status = NtFlushKey(KeyHandle);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError(ErrorCode);
return(ErrorCode);
}
return(ERROR_SUCCESS);
}
/************************************************************************
* RegGetKeySecurity
*/
LONG
STDCALL
RegGetKeySecurity (
HKEY hKey,
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR pSecurityDescriptor,
LPDWORD lpcbSecurityDescriptor
)
{
UNIMPLEMENTED;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
* RegLoadKeyA
*/
LONG
STDCALL
RegLoadKeyA(
HKEY hKey,
LPCSTR lpSubKey,
LPCSTR lpFile
)
{
UNIMPLEMENTED;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
* RegLoadKeyW
*/
LONG
STDCALL
RegLoadKeyW(
HKEY hKey,
LPCWSTR lpSubKey,
LPCWSTR lpFile
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
* RegNotifyChangeKeyValue
*/
LONG
STDCALL
RegNotifyChangeKeyValue(
HKEY hKey,
BOOL bWatchSubtree,
DWORD dwNotifyFilter,
HANDLE hEvent,
BOOL fAsynchronous
)
{
UNIMPLEMENTED;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
* RegOpenKeyA
*/
LONG STDCALL
RegOpenKeyA(HKEY hKey,
LPCSTR lpSubKey,
PHKEY phkResult)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING SubKeyString;
HKEY KeyHandle;
LONG ErrorCode;
NTSTATUS Status;
Status = MapDefaultKey(&KeyHandle,
hKey);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError(ErrorCode);
return(ErrorCode);
}
RtlCreateUnicodeStringFromAsciiz(&SubKeyString,
(LPSTR)lpSubKey);
InitializeObjectAttributes(&ObjectAttributes,
&SubKeyString,
OBJ_CASE_INSENSITIVE,
KeyHandle,
NULL);
Status = NtOpenKey(phkResult,
KEY_ALL_ACCESS,
&ObjectAttributes);
RtlFreeUnicodeString(&SubKeyString);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError(ErrorCode);
return(ErrorCode);
}
return(ERROR_SUCCESS);
}
/************************************************************************
* RegOpenKeyW
*
* 19981101 Ariadne
* 19990525 EA
*/
LONG
STDCALL
RegOpenKeyW (
HKEY hKey,
LPCWSTR lpSubKey,
PHKEY phkResult
)
{
NTSTATUS errCode;
UNICODE_STRING SubKeyString;
OBJECT_ATTRIBUTES ObjectAttributes;
HKEY KeyHandle;
LONG ErrorCode;
errCode = MapDefaultKey(&KeyHandle,
hKey);
if (!NT_SUCCESS(errCode))
{
ErrorCode = RtlNtStatusToDosError(errCode);
SetLastError (ErrorCode);
return ErrorCode;
}
RtlInitUnicodeString(&SubKeyString,
(LPWSTR)lpSubKey);
InitializeObjectAttributes(&ObjectAttributes,
&SubKeyString,
OBJ_CASE_INSENSITIVE,
KeyHandle,
NULL);
errCode = NtOpenKey(
phkResult,
KEY_ALL_ACCESS,
& ObjectAttributes
);
if ( !NT_SUCCESS(errCode) )
{
ErrorCode = RtlNtStatusToDosError(errCode);
SetLastError(ErrorCode);
return ErrorCode;
}
return ERROR_SUCCESS;
}
/************************************************************************
* RegOpenKeyExA
*/
LONG STDCALL
RegOpenKeyExA(HKEY hKey,
LPCSTR lpSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING SubKeyString;
HKEY KeyHandle;
LONG ErrorCode;
NTSTATUS Status;
Status = MapDefaultKey(&KeyHandle,
hKey);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError(ErrorCode);
return(ErrorCode);
}
RtlCreateUnicodeStringFromAsciiz(&SubKeyString,
(LPSTR)lpSubKey);
InitializeObjectAttributes(&ObjectAttributes,
&SubKeyString,
OBJ_CASE_INSENSITIVE,
KeyHandle,
NULL);
Status = NtOpenKey(phkResult,
samDesired,
&ObjectAttributes);
RtlFreeUnicodeString(&SubKeyString);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError(ErrorCode);
return(ErrorCode);
}
return(ERROR_SUCCESS);
}
/************************************************************************
* RegOpenKeyExW
*/
LONG STDCALL
RegOpenKeyExW(HKEY hKey,
LPCWSTR lpSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING SubKeyString;
HKEY KeyHandle;
LONG ErrorCode;
NTSTATUS Status;
Status = MapDefaultKey(&KeyHandle,
hKey);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError (ErrorCode);
return(ErrorCode);
}
if (lpSubKey != NULL) {
RtlInitUnicodeString(&SubKeyString,
(LPWSTR)lpSubKey);
} else {
RtlInitUnicodeString(&SubKeyString,
(LPWSTR)L"");
}
InitializeObjectAttributes(&ObjectAttributes,
&SubKeyString,
OBJ_CASE_INSENSITIVE,
KeyHandle,
NULL);
Status = NtOpenKey(phkResult,
samDesired,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError(ErrorCode);
return(ErrorCode);
}
return(ERROR_SUCCESS);
}
/************************************************************************
* RegQueryInfoKeyW
*/
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
)
{
KEY_FULL_INFORMATION FullInfoBuffer;
PKEY_FULL_INFORMATION FullInfo;
ULONG FullInfoSize;
HKEY KeyHandle;
NTSTATUS Status;
LONG ErrorCode;
ULONG Length;
if ((lpClass) && (!lpcbClass))
{
SetLastError(ERROR_INVALID_PARAMETER);
return ERROR_INVALID_PARAMETER;
}
Status = MapDefaultKey(&KeyHandle, hKey);
CHECK_STATUS;
if (lpClass)
{
FullInfoSize = sizeof(KEY_FULL_INFORMATION) + *lpcbClass;
FullInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullInfoSize);
if (!FullInfo)
{
SetLastError(ERROR_OUTOFMEMORY);
return ERROR_OUTOFMEMORY;
}
FullInfo->ClassLength = *lpcbClass;
}
else
{
FullInfoSize = sizeof(KEY_FULL_INFORMATION);
FullInfo = &FullInfoBuffer;
FullInfo->ClassLength = 1;
}
FullInfo->ClassOffset = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
Status = NtQueryKey(
KeyHandle,
KeyFullInformation,
FullInfo,
FullInfoSize,
&Length);
if (!NT_SUCCESS(Status))
{
if (lpClass)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, FullInfo);
}
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError(ErrorCode);
return ErrorCode;
}
if (lpcSubKeys)
{
*lpcSubKeys = FullInfo->SubKeys;
}
if (lpcbMaxSubKeyLen)
{
*lpcbMaxSubKeyLen = FullInfo->MaxNameLen;
}
if (lpcbMaxClassLen)
{
*lpcbMaxClassLen = FullInfo->MaxClassLen;
}
if (lpcValues)
{
*lpcValues = FullInfo->Values;
}
if (lpcbMaxValueNameLen)
{
*lpcbMaxValueNameLen = FullInfo->MaxValueNameLen;
}
if (lpcbMaxValueLen)
{
*lpcbMaxValueLen = FullInfo->MaxValueDataLen;
}
if (lpcbSecurityDescriptor)
{
*lpcbSecurityDescriptor = 0;
/* FIXME */
}
if (lpftLastWriteTime != NULL)
{
lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart;
lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart;
}
if (lpClass)
{
wcsncpy(lpClass, FullInfo->Class, *lpcbClass);
RtlFreeHeap(RtlGetProcessHeap(), 0, FullInfo);
}
SetLastError(ERROR_SUCCESS);
return ERROR_SUCCESS;
}
/************************************************************************
* RegQueryInfoKeyA
*/
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)
{
UnicodeString.Buffer = &ClassName[0];
UnicodeString.MaximumLength = sizeof(ClassName);
}
ErrorCode = RegQueryInfoKeyW(
hKey,
UnicodeString.Buffer,
lpcbClass,
lpReserved,
lpcSubKeys,
lpcbMaxSubKeyLen,
lpcbMaxClassLen,
lpcValues,
lpcbMaxValueNameLen,
lpcbMaxValueLen,
lpcbSecurityDescriptor,
lpftLastWriteTime);
if ((ErrorCode == ERROR_SUCCESS) && (lpClass))
{
RtlInitAnsiString(&AnsiString, NULL);
AnsiString.Buffer = lpClass;
AnsiString.MaximumLength = *lpcbClass;
RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
*lpcbClass = AnsiString.Length;
}
return ErrorCode;
}
/************************************************************************
* RegQueryMultipleValuesA
*/
LONG
STDCALL
RegQueryMultipleValuesA(
HKEY hKey,
PVALENTA val_list,
DWORD num_vals,
LPSTR lpValueBuf,
LPDWORD ldwTotsize
)
{
UNIMPLEMENTED;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
* RegQueryMultipleValuesW
*/
LONG
STDCALL
RegQueryMultipleValuesW(
HKEY hKey,
PVALENTW val_list,
DWORD num_vals,
LPWSTR lpValueBuf,
LPDWORD ldwTotsize
)
{
UNIMPLEMENTED;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
* RegQueryValueExW
*/
LONG
STDCALL
RegQueryValueExW(
HKEY hKey,
LPCWSTR 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;
HKEY KeyHandle;
DPRINT("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))
{
dwError = RtlNtStatusToDosError(Status);
SetLastError(dwError);
return(dwError);
}
if ((lpData) && (!lpcbData))
{
SetLastError(ERROR_INVALID_PARAMETER);
return ERROR_INVALID_PARAMETER;
}
RtlInitUnicodeString (&ValueName,
lpValueName);
BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + *lpcbData;
ValueInfo = RtlAllocateHeap (RtlGetProcessHeap(),
0,
BufferSize);
if (ValueInfo == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
return ERROR_OUTOFMEMORY;
}
Status = NtQueryValueKey (hKey,
&ValueName,
KeyValuePartialInformation,
ValueInfo,
BufferSize,
&ResultSize);
DPRINT("Status 0x%X\n", Status);
if (Status == STATUS_BUFFER_TOO_SMALL)
{
/* Return ERROR_SUCCESS and the buffer space needed for a successful call */
dwError = ERROR_SUCCESS;
}
else if (!NT_SUCCESS(Status))
{
dwError = RtlNtStatusToDosError(Status);
SetLastError(dwError);
}
else
{
if (lpType)
{
*lpType = ValueInfo->Type;
}
RtlMoveMemory(lpData, ValueInfo->Data, ValueInfo->DataLength);
if ((ValueInfo->Type == REG_SZ) ||
(ValueInfo->Type == REG_MULTI_SZ) ||
(ValueInfo->Type == REG_EXPAND_SZ))
{
((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0;
}
}
DPRINT("Type %d ResultSize %d\n", ValueInfo->Type, ResultSize);
*lpcbData = (DWORD)ResultSize;
RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
return dwError;
}
/************************************************************************
* RegQueryValueExA
*/
LONG
STDCALL
RegQueryValueExA(
HKEY hKey,
LPCSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
)
{
WCHAR ValueNameBuffer[MAX_PATH+1];
UNICODE_STRING ValueName;
UNICODE_STRING ValueData;
ANSI_STRING AnsiString;
LONG ErrorCode;
DWORD ResultSize;
DWORD Type;
/* FIXME: HKEY_PERFORMANCE_DATA is special, see MS SDK */
if ((lpData) && (!lpcbData))
{
SetLastError(ERROR_INVALID_PARAMETER);
return ERROR_INVALID_PARAMETER;
}
RtlInitUnicodeString(&ValueData, NULL);
if (lpData)
{
ValueData.MaximumLength = *lpcbData * sizeof(WCHAR);
ValueData.Buffer = RtlAllocateHeap(
RtlGetProcessHeap(),
0,
ValueData.MaximumLength);
if (!ValueData.Buffer)
{
SetLastError(ERROR_OUTOFMEMORY);
return ERROR_OUTOFMEMORY;
}
}
RtlInitAnsiString(&AnsiString, (LPSTR)lpValueName);
RtlInitUnicodeString(&ValueName, NULL);
ValueName.Buffer = &ValueNameBuffer[0];
ValueName.MaximumLength = sizeof(ValueNameBuffer);
RtlAnsiStringToUnicodeString(&ValueName, &AnsiString, FALSE);
if (lpcbData)
{
ResultSize = *lpcbData;
}
else
{
ResultSize = 0;
}
ErrorCode = RegQueryValueExW(
hKey,
ValueName.Buffer,
lpReserved,
&Type,
(LPBYTE)ValueData.Buffer,
&ResultSize);
if ((ErrorCode == ERROR_SUCCESS) && (ValueData.Buffer != NULL))
{
if (lpType)
{
*lpType = Type;
}
if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ))
{
ValueData.Length = ResultSize;
RtlInitAnsiString(&AnsiString, NULL);
AnsiString.Buffer = lpData;
AnsiString.MaximumLength = *lpcbData;
RtlUnicodeStringToAnsiString(&AnsiString, &ValueData, FALSE);
}
else
{
RtlMoveMemory(lpData, ValueData.Buffer, ResultSize);
}
}
if (lpcbData)
{
*lpcbData = ResultSize;
}
if (ValueData.Buffer)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, ValueData.Buffer);
}
return ErrorCode;
}
/************************************************************************
* RegQueryValueW
*/
LONG
STDCALL
RegQueryValueW(
HKEY hKey,
LPCWSTR lpSubKey,
LPWSTR lpValue,
PLONG lpcbValue
)
{
NTSTATUS errCode;
UNICODE_STRING SubKeyString;
OBJECT_ATTRIBUTES ObjectAttributes;
HKEY KeyHandle;
HANDLE RealKey;
LONG ErrorCode;
BOOL CloseRealKey;
errCode = MapDefaultKey(&KeyHandle, hKey);
if (!NT_SUCCESS(errCode))
{
ErrorCode = RtlNtStatusToDosError(errCode);
SetLastError (ErrorCode);
return ErrorCode;
}
if ((lpSubKey) && (wcslen(lpSubKey) != 0))
{
RtlInitUnicodeString(&SubKeyString,
(LPWSTR)lpSubKey);
InitializeObjectAttributes(&ObjectAttributes,
&SubKeyString,
OBJ_CASE_INSENSITIVE,
KeyHandle,
NULL);
errCode = NtOpenKey(
&RealKey,
KEY_ALL_ACCESS,
& ObjectAttributes
);
if ( !NT_SUCCESS(errCode) )
{
ErrorCode = RtlNtStatusToDosError(errCode);
SetLastError(ErrorCode);
return ErrorCode;
}
CloseRealKey = TRUE;
}
else
{
RealKey = hKey;
CloseRealKey = FALSE;
}
ErrorCode = RegQueryValueExW(
RealKey,
NULL,
NULL,
NULL,
(LPBYTE)lpValue,
(LPDWORD)lpcbValue);
if (CloseRealKey)
{
NtClose(RealKey);
}
return ErrorCode;
}
/************************************************************************
* RegQueryValueA
*/
LONG
STDCALL
RegQueryValueA(
HKEY hKey,
LPCSTR lpSubKey,
LPSTR lpValue,
PLONG lpcbValue
)
{
WCHAR SubKeyNameBuffer[MAX_PATH+1];
UNICODE_STRING SubKeyName;
UNICODE_STRING Value;
ANSI_STRING AnsiString;
LONG ValueSize;
LONG ErrorCode;
if ((lpValue) && (!lpcbValue))
{
SetLastError(ERROR_INVALID_PARAMETER);
return ERROR_INVALID_PARAMETER;
}
RtlInitUnicodeString(&SubKeyName, NULL);
RtlInitUnicodeString(&Value, NULL);
if ((lpSubKey) && (strlen(lpSubKey) != 0))
{
RtlInitAnsiString(&AnsiString, (LPSTR)lpSubKey);
SubKeyName.Buffer = &SubKeyNameBuffer[0];
SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
RtlAnsiStringToUnicodeString(&SubKeyName, &AnsiString, FALSE);
}
if (lpValue)
{
ValueSize = *lpcbValue * sizeof(WCHAR);
Value.MaximumLength = ValueSize;
Value.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, ValueSize);
if (!Value.Buffer)
{
SetLastError(ERROR_OUTOFMEMORY);
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)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, Value.Buffer);
}
return ErrorCode;
}
/************************************************************************
* RegReplaceKeyA
*/
LONG
STDCALL
RegReplaceKeyA(
HKEY hKey,
LPCSTR lpSubKey,
LPCSTR lpNewFile,
LPCSTR lpOldFile
)
{
UNIMPLEMENTED;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
* RegReplaceKeyW
*/
LONG
STDCALL
RegReplaceKeyW(
HKEY hKey,
LPCWSTR lpSubKey,
LPCWSTR lpNewFile,
LPCWSTR lpOldFile
)
{
UNIMPLEMENTED;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
* RegRestoreKeyA
*/
LONG
STDCALL
RegRestoreKeyA(
HKEY hKey,
LPCSTR lpFile,
DWORD dwFlags
)
{
UNIMPLEMENTED;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
* RegRestoreKeyW
*/
LONG
STDCALL
RegRestoreKeyW(
HKEY hKey,
LPCWSTR lpFile,
DWORD dwFlags
)
{
UNIMPLEMENTED;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
* RegSaveKeyW
*/
LONG STDCALL
RegSaveKeyW(HKEY hKey,
LPCWSTR lpFile,
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING NtName;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE FileHandle;
HKEY KeyHandle;
NTSTATUS Status;
LONG ErrorCode;
Status = MapDefaultKey(&KeyHandle,
hKey);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError(ErrorCode);
return(ErrorCode);
}
if (!RtlDosPathNameToNtPathName_U((LPWSTR)lpFile,
&NtName,
NULL,
NULL))
{
SetLastError(ERROR_INVALID_PARAMETER);
return(ERROR_INVALID_PARAMETER);
}
if (lpSecurityAttributes != NULL)
SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
InitializeObjectAttributes(&ObjectAttributes,
&NtName,
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(&NtName);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError(ErrorCode);
return(ErrorCode);
}
Status = NtSaveKey(KeyHandle,
FileHandle);
NtClose(FileHandle);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError(ErrorCode);
return(ErrorCode);
}
return(ERROR_SUCCESS);
}
/************************************************************************
* RegSaveKeyA
*/
LONG STDCALL
RegSaveKeyA(HKEY hKey,
LPCSTR lpFile,
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
UNICODE_STRING FileName;
LONG ErrorCode;
RtlCreateUnicodeStringFromAsciiz(&FileName,
(LPSTR)lpFile);
ErrorCode = RegSaveKeyW(hKey,
FileName.Buffer,
lpSecurityAttributes);
RtlFreeUnicodeString(&FileName);
return(ErrorCode);
}
/************************************************************************
* RegSetKeySecurity
*/
LONG
STDCALL
RegSetKeySecurity(
HKEY hKey,
SECURITY_INFORMATION SecurityInformation, /* FIXME: ULONG? */
PSECURITY_DESCRIPTOR pSecurityDescriptor
)
{
UNIMPLEMENTED;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
* RegSetValueExW
*/
LONG
STDCALL
RegSetValueExW(
HKEY hKey,
LPCWSTR lpValueName,
DWORD Reserved,
DWORD dwType,
CONST BYTE *lpData,
DWORD cbData
)
{
UNICODE_STRING ValueName;
PUNICODE_STRING pValueName;
HKEY KeyHandle;
NTSTATUS Status;
LONG ErrorCode;
Status = MapDefaultKey(&KeyHandle, hKey);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError(ErrorCode);
return ErrorCode;
}
if (lpValueName)
{
RtlInitUnicodeString(&ValueName, lpValueName);
pValueName = &ValueName;
}
else
{
pValueName = NULL;
}
Status = NtSetValueKey(
KeyHandle,
pValueName,
0,
dwType,
(PVOID)lpData,
(ULONG)cbData);
if (!NT_SUCCESS(Status))
{
LONG ErrorCode = RtlNtStatusToDosError(Status);
SetLastError (ErrorCode);
return ErrorCode;
}
return ERROR_SUCCESS;
}
/************************************************************************
* RegSetValueExA
*/
LONG
STDCALL
RegSetValueExA(
HKEY hKey,
LPCSTR lpValueName,
DWORD Reserved,
DWORD dwType,
CONST BYTE *lpData,
DWORD cbData
)
{
UNICODE_STRING ValueName;
LPWSTR pValueName;
ANSI_STRING AnsiString;
UNICODE_STRING Data;
LONG ErrorCode;
LPBYTE pData;
DWORD DataSize;
if (!lpData)
{
SetLastError(ERROR_INVALID_PARAMETER);
return ERROR_INVALID_PARAMETER;
}
if ((lpValueName) && (strlen(lpValueName) != 0))
{
RtlCreateUnicodeStringFromAsciiz(&ValueName, (LPSTR)lpValueName);
pValueName = (LPWSTR)ValueName.Buffer;
}
else
{
pValueName = NULL;
}
if ((dwType == REG_SZ) || (dwType == REG_MULTI_SZ) || (dwType == REG_EXPAND_SZ))
{
RtlInitAnsiString(&AnsiString, NULL);
AnsiString.Buffer = (LPSTR)lpData;
AnsiString.Length = cbData;
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)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, ValueName.Buffer);
}
if (Data.Buffer)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, Data.Buffer);
}
return ErrorCode;
}
/************************************************************************
* RegSetValueW
*/
LONG
STDCALL
RegSetValueW(
HKEY hKey,
LPCWSTR lpSubKey,
DWORD dwType,
LPCWSTR lpData,
DWORD cbData
)
{
NTSTATUS errCode;
UNICODE_STRING SubKeyString;
OBJECT_ATTRIBUTES ObjectAttributes;
HKEY KeyHandle;
HANDLE RealKey;
LONG ErrorCode;
BOOL CloseRealKey;
errCode = MapDefaultKey(&KeyHandle, hKey);
if (!NT_SUCCESS(errCode))
{
ErrorCode = RtlNtStatusToDosError(errCode);
SetLastError (ErrorCode);
return ErrorCode;
}
if ((lpSubKey) && (wcslen(lpSubKey) != 0))
{
RtlInitUnicodeString(&SubKeyString,
(LPWSTR)lpSubKey);
InitializeObjectAttributes(&ObjectAttributes,
&SubKeyString,
OBJ_CASE_INSENSITIVE,
KeyHandle,
NULL);
errCode = NtOpenKey(
&RealKey,
KEY_ALL_ACCESS,
& ObjectAttributes
);
if ( !NT_SUCCESS(errCode) )
{
ErrorCode = RtlNtStatusToDosError(errCode);
SetLastError(ErrorCode);
return ErrorCode;
}
CloseRealKey = TRUE;
}
else
{
RealKey = hKey;
CloseRealKey = FALSE;
}
ErrorCode = RegSetValueExW(
RealKey,
NULL,
0,
dwType,
(LPBYTE)lpData,
cbData);
if (CloseRealKey)
{
NtClose(RealKey);
}
return ErrorCode;
}
/************************************************************************
* RegSetValueA
*/
LONG
STDCALL
RegSetValueA(
HKEY hKey,
LPCSTR lpSubKey,
DWORD dwType,
LPCSTR lpData,
DWORD cbData
)
{
WCHAR SubKeyNameBuffer[MAX_PATH+1];
UNICODE_STRING SubKeyName;
UNICODE_STRING Data;
ANSI_STRING AnsiString;
LONG DataSize;
LONG ErrorCode;
if (!lpData)
{
SetLastError(ERROR_INVALID_PARAMETER);
return ERROR_INVALID_PARAMETER;
}
RtlInitUnicodeString(&SubKeyName, NULL);
RtlInitUnicodeString(&Data, NULL);
if ((lpSubKey) && (strlen(lpSubKey) != 0))
{
RtlInitAnsiString(&AnsiString, (LPSTR)lpSubKey);
SubKeyName.Buffer = &SubKeyNameBuffer[0];
SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
RtlAnsiStringToUnicodeString(&SubKeyName, &AnsiString, FALSE);
}
DataSize = cbData * sizeof(WCHAR);
Data.MaximumLength = DataSize;
Data.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, DataSize);
if (!Data.Buffer)
{
SetLastError(ERROR_OUTOFMEMORY);
return ERROR_OUTOFMEMORY;
}
ErrorCode = RegSetValueW(
hKey,
(LPCWSTR)SubKeyName.Buffer,
dwType,
Data.Buffer,
DataSize);
RtlFreeHeap(RtlGetProcessHeap(), 0, Data.Buffer);
return ErrorCode;
}
/************************************************************************
* RegUnLoadKeyA
*/
LONG
STDCALL
RegUnLoadKeyA(
HKEY hKey,
LPCSTR lpSubKey
)
{
UNIMPLEMENTED;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
* RegUnLoadKeyW
*/
LONG
STDCALL
RegUnLoadKeyW(
HKEY hKey,
LPCWSTR lpSubKey
)
{
UNIMPLEMENTED;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/* EOF */