Implemented basic registry functions

svn path=/trunk/; revision=1346
This commit is contained in:
Eric Kohl 2000-09-08 22:55:14 +00:00
parent 16625529a2
commit 4b34e5c2de
2 changed files with 735 additions and 143 deletions

View file

@ -1,4 +1,4 @@
/* $Id: reg.c,v 1.9 2000/09/06 19:58:47 ekohl Exp $ /* $Id: reg.c,v 1.10 2000/09/08 22:54:13 ekohl Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -42,7 +42,7 @@ static NTSTATUS OpenLocalMachineKey (PHANDLE KeyHandle);
BOOL BOOL
RegInitialize (VOID) RegInitialize (VOID)
{ {
DPRINT1("RegInitialize()\n"); DPRINT("RegInitialize()\n");
RtlZeroMemory (DefaultHandleTable, RtlZeroMemory (DefaultHandleTable,
MAX_DEFAULT_HANDLES * sizeof(HANDLE)); MAX_DEFAULT_HANDLES * sizeof(HANDLE));
@ -58,7 +58,7 @@ RegInitialize (VOID)
BOOL BOOL
RegCleanup(VOID) RegCleanup(VOID)
{ {
DPRINT1("RegCleanup()\n"); DPRINT("RegCleanup()\n");
CloseDefaultKeys(); CloseDefaultKeys();
RtlDeleteCriticalSection(&HandleTableCS); RtlDeleteCriticalSection(&HandleTableCS);
@ -67,24 +67,23 @@ RegCleanup(VOID)
static NTSTATUS static NTSTATUS
MapDefaultKey (PHKEY ParentKey, MapDefaultKey (PHKEY RealKey,
HKEY Key) HKEY Key)
{ {
PHANDLE Handle; PHANDLE Handle;
ULONG Index; ULONG Index;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
DPRINT1("MapDefaultKey (Key %x)\n", Key); DPRINT("MapDefaultKey (Key %x)\n", Key);
if (((ULONG)Key & 0xF0000000) != 0x80000000) if (((ULONG)Key & 0xF0000000) != 0x80000000)
{ {
*ParentKey = Key; *RealKey = Key;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
/* Handle special cases here */ /* Handle special cases here */
Index = (ULONG)Key & 0x0FFFFFFF; Index = (ULONG)Key & 0x0FFFFFFF;
DPRINT1("Index %x\n", Index);
if (Index >= MAX_DEFAULT_HANDLES) if (Index >= MAX_DEFAULT_HANDLES)
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
@ -102,18 +101,16 @@ DPRINT1("Index %x\n", Index);
break; break;
default: default:
DPRINT1("MapDefaultHandle() no handle creator\n"); DPRINT("MapDefaultHandle() no handle creator\n");
Status = STATUS_INVALID_PARAMETER; Status = STATUS_INVALID_PARAMETER;
} }
} }
RtlLeaveCriticalSection(&HandleTableCS); RtlLeaveCriticalSection(&HandleTableCS);
DPRINT1("Status %x\n", Status);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
*ParentKey = (HKEY)*Handle; *RealKey = (HKEY)*Handle;
} }
return Status; return Status;
@ -145,7 +142,7 @@ OpenLocalMachineKey (PHANDLE KeyHandle)
OBJECT_ATTRIBUTES Attributes; OBJECT_ATTRIBUTES Attributes;
UNICODE_STRING KeyName; UNICODE_STRING KeyName;
DPRINT1("OpenLocalMachineKey()\n"); DPRINT("OpenLocalMachineKey()\n");
RtlInitUnicodeString(&KeyName, RtlInitUnicodeString(&KeyName,
L"\\Registry\\Machine"); L"\\Registry\\Machine");
@ -206,6 +203,22 @@ RegConnectRegistryA(
} }
/************************************************************************
* RegConnectRegistryW
*/
LONG
STDCALL
RegConnectRegistryW(
LPWSTR lpMachineName,
HKEY hKey,
PHKEY phkResult
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************ /************************************************************************
* RegCreateKeyA * RegCreateKeyA
*/ */
@ -297,7 +310,7 @@ RegCreateKeyExW(
NTSTATUS Status; NTSTATUS Status;
HKEY ParentKey; HKEY ParentKey;
DPRINT1("RegCreateKeyExW() called\n"); DPRINT("RegCreateKeyExW() called\n");
/* get the real parent key */ /* get the real parent key */
Status = MapDefaultKey (&ParentKey, hKey); Status = MapDefaultKey (&ParentKey, hKey);
@ -309,7 +322,7 @@ RegCreateKeyExW(
return ErrorCode; return ErrorCode;
} }
DPRINT1("ParentKey %x\n", (ULONG)ParentKey); DPRINT("ParentKey %x\n", (ULONG)ParentKey);
RtlInitUnicodeString (&ClassString, lpClass); RtlInitUnicodeString (&ClassString, lpClass);
RtlInitUnicodeString (&SubKeyString, lpSubKey); RtlInitUnicodeString (&SubKeyString, lpSubKey);
@ -327,7 +340,7 @@ RegCreateKeyExW(
(lpClass == NULL)? NULL : &ClassString, (lpClass == NULL)? NULL : &ClassString,
dwOptions, dwOptions,
(PULONG)lpdwDisposition); (PULONG)lpdwDisposition);
DPRINT1("Status %x\n", Status); DPRINT("Status %x\n", Status);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
LONG ErrorCode = RtlNtStatusToDosError(Status); LONG ErrorCode = RtlNtStatusToDosError(Status);
@ -335,7 +348,6 @@ RegCreateKeyExW(
SetLastError (ErrorCode); SetLastError (ErrorCode);
return ErrorCode; return ErrorCode;
} }
DPRINT1("Returned handle %x\n", (ULONG)*phkResult);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -366,8 +378,56 @@ RegDeleteKeyW(
LPCWSTR lpSubKey LPCWSTR lpSubKey
) )
{ {
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); OBJECT_ATTRIBUTES ObjectAttributes;
return ERROR_CALL_NOT_IMPLEMENTED; UNICODE_STRING SubKeyString;
HANDLE ParentKey;
HANDLE TargetKey;
NTSTATUS Status;
LONG ErrorCode;
Status = MapDefaultKey(&ParentKey,
hKey);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError (ErrorCode);
return ErrorCode;
}
RtlInitUnicodeString(&SubKeyString,
(LPWSTR)lpSubKey);
InitializeObjectAttributes (&ObjectAttributes,
&SubKeyString,
OBJ_CASE_INSENSITIVE,
(HANDLE)ParentKey,
NULL);
Status = NtOpenKey (&TargetKey,
DELETE,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError (ErrorCode);
return ErrorCode;
}
Status = NtDeleteKey(TargetKey);
NtClose(TargetKey);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError (ErrorCode);
return ErrorCode;
}
return ERROR_SUCCESS;
} }
@ -396,8 +456,35 @@ RegDeleteValueW(
LPCWSTR lpValueName LPCWSTR lpValueName
) )
{ {
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); UNICODE_STRING ValueName;
return ERROR_CALL_NOT_IMPLEMENTED; NTSTATUS Status;
LONG ErrorCode;
HANDLE KeyHandle;
Status = MapDefaultKey(&KeyHandle,
hKey);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError (ErrorCode);
return ErrorCode;
}
RtlInitUnicodeString(&ValueName,
lpValueName);
Status = NtDeleteValueKey(KeyHandle,
&ValueName);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError(Status);
SetLastError (ErrorCode);
return ErrorCode;
}
return ERROR_SUCCESS;
} }
@ -439,6 +526,111 @@ RegEnumKeyExA(
} }
/************************************************************************
* 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;
HANDLE 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;
KeyInfo = RtlAllocateHeap (RtlGetProcessHeap(),
0,
BufferSize);
if (KeyInfo == NULL)
return ERROR_OUTOFMEMORY;
Status = NtEnumerateKey (KeyHandle,
(ULONG)dwIndex,
KeyNodeInformation,
KeyInfo,
BufferSize,
&ResultSize);
if (!NT_SUCCESS(Status))
{
dwError = RtlNtStatusToDosError(Status);
SetLastError(dwError);
}
else
{
memcpy (lpName, KeyInfo->Name, KeyInfo->NameLength);
*lpcbName = (DWORD)(KeyInfo->NameLength / sizeof(WCHAR)) - 1;
if (lpClass)
{
memcpy (lpClass,
KeyInfo->Name + KeyInfo->ClassOffset,
KeyInfo->ClassLength);
*lpcbClass = (DWORD)(KeyInfo->ClassLength / sizeof(WCHAR)) - 1;
}
if (lpftLastWriteTime)
{
}
}
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);
}
/************************************************************************ /************************************************************************
* RegEnumValueA * RegEnumValueA
*/ */
@ -460,6 +652,73 @@ RegEnumValueA(
} }
/************************************************************************
* 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;
BufferSize = sizeof (KEY_VALUE_FULL_INFORMATION) +
*lpcbValueName * sizeof(WCHAR);
if (lpcbData)
BufferSize += *lpcbData;
ValueInfo = RtlAllocateHeap (RtlGetProcessHeap(),
0,
BufferSize);
if (ValueInfo == NULL)
return ERROR_OUTOFMEMORY;
Status = NtEnumerateValueKey (hKey,
(ULONG)dwIndex,
KeyValueFullInformation,
ValueInfo,
BufferSize,
&ResultSize);
if (!NT_SUCCESS(Status))
{
dwError = RtlNtStatusToDosError(Status);
SetLastError(dwError);
}
else
{
memcpy (lpValueName, ValueInfo->Name, ValueInfo->NameLength);
*lpcbValueName = (DWORD)(ValueInfo->NameLength / sizeof(WCHAR)) - 1;
if (lpType)
*lpType = ValueInfo->Type;
if (lpData)
{
memcpy (lpData,
ValueInfo->Name + ValueInfo->DataOffset,
ValueInfo->DataLength);
*lpcbValueName = (DWORD)ValueInfo->DataLength;
}
}
RtlFreeHeap (RtlGetProcessHeap(), 0, ValueInfo);
return dwError;
}
/************************************************************************ /************************************************************************
* RegFlushKey * RegFlushKey
*/ */
@ -477,7 +736,6 @@ RegFlushKey(
/************************************************************************ /************************************************************************
* RegGetKeySecurity * RegGetKeySecurity
*/ */
#if 0
LONG LONG
STDCALL STDCALL
RegGetKeySecurity ( RegGetKeySecurity (
@ -490,7 +748,6 @@ RegGetKeySecurity (
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
} }
#endif
/************************************************************************ /************************************************************************
@ -577,25 +834,39 @@ RegOpenKeyW (
NTSTATUS errCode; NTSTATUS errCode;
UNICODE_STRING SubKeyString; UNICODE_STRING SubKeyString;
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE KeyHandle;
LONG ErrorCode;
SubKeyString.Buffer = (LPWSTR)lpSubKey; errCode = MapDefaultKey(&KeyHandle,
SubKeyString.Length = wcslen(SubKeyString.Buffer); hKey);
SubKeyString.MaximumLength = SubKeyString.Length; if (!NT_SUCCESS(errCode))
{
ErrorCode = RtlNtStatusToDosError(errCode);
SetLastError (ErrorCode);
return ErrorCode;
}
RtlInitUnicodeString(&SubKeyString,
(LPWSTR)lpSubKey);
InitializeObjectAttributes(&ObjectAttributes,
&SubKeyString,
OBJ_CASE_INSENSITIVE,
KeyHandle,
NULL);
ObjectAttributes.RootDirectory = hKey;
ObjectAttributes.ObjectName = & SubKeyString;
ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE;
errCode = NtOpenKey( errCode = NtOpenKey(
phkResult, phkResult,
GENERIC_ALL, KEY_ALL_ACCESS,
& ObjectAttributes & ObjectAttributes
); );
if ( !NT_SUCCESS(errCode) ) if ( !NT_SUCCESS(errCode) )
{ {
LONG LastError = RtlNtStatusToDosError(errCode); ErrorCode = RtlNtStatusToDosError(errCode);
SetLastError(LastError); SetLastError(ErrorCode);
return LastError; return ErrorCode;
} }
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -632,8 +903,32 @@ RegOpenKeyExW(
PHKEY phkResult PHKEY phkResult
) )
{ {
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); NTSTATUS errCode;
return ERROR_CALL_NOT_IMPLEMENTED; UNICODE_STRING SubKeyString;
OBJECT_ATTRIBUTES ObjectAttributes;
RtlInitUnicodeString(&SubKeyString,
(LPWSTR)lpSubKey);
InitializeObjectAttributes(&ObjectAttributes,
&SubKeyString,
OBJ_CASE_INSENSITIVE,
(HANDLE)hKey,
NULL);
errCode = NtOpenKey(
phkResult,
samDesired,
& ObjectAttributes
);
if ( !NT_SUCCESS(errCode) )
{
LONG LastError = RtlNtStatusToDosError(errCode);
SetLastError(LastError);
return LastError;
}
return ERROR_SUCCESS;
} }
@ -705,6 +1000,24 @@ RegQueryMultipleValuesA(
} }
/************************************************************************
* RegQueryMultipleValuesW
*/
LONG
STDCALL
RegQueryMultipleValuesW(
HKEY hKey,
PVALENT val_list,
DWORD num_vals,
LPWSTR lpValueBuf,
LPDWORD ldwTotsize
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************ /************************************************************************
* RegQueryValueA * RegQueryValueA
*/ */
@ -754,6 +1067,62 @@ RegQueryValueExW(
LPBYTE lpData, LPBYTE lpData,
LPDWORD lpcbData LPDWORD lpcbData
) )
{
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
UNICODE_STRING ValueName;
NTSTATUS Status;
DWORD dwError = ERROR_SUCCESS;
ULONG BufferSize;
ULONG ResultSize;
RtlInitUnicodeString (&ValueName,
lpValueName);
BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + *lpcbData;
ValueInfo = RtlAllocateHeap (RtlGetProcessHeap(),
0,
BufferSize);
if (ValueInfo == NULL)
return ERROR_OUTOFMEMORY;
Status = NtQueryValueKey (hKey,
&ValueName,
KeyValuePartialInformation,
ValueInfo,
BufferSize,
&ResultSize);
if (!NT_SUCCESS(Status))
{
dwError = RtlNtStatusToDosError(Status);
SetLastError(dwError);
}
else
{
*lpType = ValueInfo->Type;
memcpy (lpData, ValueInfo->Data, ValueInfo->DataLength);
if (ValueInfo->Type == REG_SZ)
((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0;
}
*lpcbData = (DWORD)ResultSize;
RtlFreeHeap (RtlGetProcessHeap(), 0, ValueInfo);
return dwError;
}
/************************************************************************
* RegQueryValueW
*/
LONG
STDCALL
RegQueryValueW(
HKEY hKey,
LPCWSTR lpSubKey,
LPWSTR lpValue,
PLONG lpcbValue
)
{ {
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
@ -777,6 +1146,23 @@ RegReplaceKeyA(
} }
/************************************************************************
* RegReplaceKeyW
*/
LONG
STDCALL
RegReplaceKeyW(
HKEY hKey,
LPCWSTR lpSubKey,
LPCWSTR lpNewFile,
LPCWSTR lpOldFile
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************ /************************************************************************
* RegRestoreKeyA * RegRestoreKeyA
*/ */
@ -793,6 +1179,22 @@ RegRestoreKeyA(
} }
/************************************************************************
* RegRestoreKeyW
*/
LONG
STDCALL
RegRestoreKeyW(
HKEY hKey,
LPCWSTR lpFile,
DWORD dwFlags
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************ /************************************************************************
* RegSaveKeyA * RegSaveKeyA
*/ */
@ -809,10 +1211,25 @@ RegSaveKeyA(
} }
/************************************************************************
* RegSaveKeyW
*/
LONG
STDCALL
RegSaveKeyW(
HKEY hKey,
LPCWSTR lpFile,
LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************ /************************************************************************
* RegSetKeySecurity * RegSetKeySecurity
*/ */
#if 0
LONG LONG
STDCALL STDCALL
RegSetKeySecurity( RegSetKeySecurity(
@ -824,7 +1241,7 @@ RegSetKeySecurity(
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
} }
#endif
/************************************************************************ /************************************************************************
* RegSetValueA * RegSetValueA
@ -933,4 +1350,19 @@ RegUnLoadKeyA(
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
} }
/************************************************************************
* RegUnLoadKeyW
*/
LONG
STDCALL
RegUnLoadKeyW(
HKEY hKey,
LPCWSTR lpSubKey
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/* EOF */ /* EOF */

View file

@ -1,4 +1,4 @@
/* $Id: registry.c,v 1.28 2000/09/06 19:59:54 ekohl Exp $ /* $Id: registry.c,v 1.29 2000/09/08 22:55:14 ekohl Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -16,7 +16,7 @@
#include <internal/ob.h> #include <internal/ob.h>
#include <wchar.h> #include <wchar.h>
//#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
#define PROTO_REG 1 /* Comment out to disable */ #define PROTO_REG 1 /* Comment out to disable */
@ -227,6 +227,10 @@ static NTSTATUS CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile,
IN PKEY_BLOCK KeyBlock, IN PKEY_BLOCK KeyBlock,
IN PWSTR ValueName, IN PWSTR ValueName,
OUT PVALUE_BLOCK *ValueBlock); OUT PVALUE_BLOCK *ValueBlock);
static NTSTATUS CmiGetValueFromKeyByIndex(IN PREGISTRY_FILE RegistryFile,
IN PKEY_BLOCK KeyBlock,
IN ULONG Index,
OUT PVALUE_BLOCK *ValueBlock);
static NTSTATUS CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile, static NTSTATUS CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile,
IN PKEY_BLOCK KeyBlock, IN PKEY_BLOCK KeyBlock,
IN PWSTR ValueNameBuf, IN PWSTR ValueNameBuf,
@ -364,7 +368,6 @@ CmInitializeRegistry(VOID)
{ {
return; return;
} }
CHECKPOINT;
CmiReleaseBlock(CmiVolatileFile, KeyBlock); CmiReleaseBlock(CmiVolatileFile, KeyBlock);
/* FIXME: create remaining structure needed for default handles */ /* FIXME: create remaining structure needed for default handles */
@ -373,6 +376,7 @@ CHECKPOINT;
#endif #endif
} }
VOID VOID
CmImportHive(PCHAR Chunk) CmImportHive(PCHAR Chunk)
{ {
@ -380,6 +384,7 @@ CmImportHive(PCHAR Chunk)
return; return;
} }
NTSTATUS NTSTATUS
STDCALL STDCALL
NtCreateKey ( NtCreateKey (
@ -432,7 +437,6 @@ NtCreateKey (
{ {
*Disposition = REG_OPENED_EXISTING_KEY; *Disposition = REG_OPENED_EXISTING_KEY;
} }
DPRINT1("KeyHandle (opened) %x\n", *KeyHandle);
return Status; return Status;
} }
@ -472,7 +476,6 @@ DPRINT1("KeyHandle (opened) %x\n", *KeyHandle);
FALSE, FALSE,
KeyHandle); KeyHandle);
DPRINT1("Status %x KeyHandle (created) %x\n", Status, *KeyHandle);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
*Disposition = REG_CREATED_NEW_KEY; *Disposition = REG_CREATED_NEW_KEY;
@ -522,6 +525,47 @@ NtDeleteKey (
} }
NTSTATUS
STDCALL
NtDeleteValueKey (
IN HANDLE KeyHandle,
IN PUNICODE_STRING ValueName
)
{
#ifdef PROTO_REG
NTSTATUS Status;
PKEY_OBJECT KeyObject;
PREGISTRY_FILE RegistryFile;
PKEY_BLOCK KeyBlock;
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_QUERY_VALUE,
CmiKeyType,
UserMode,
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* Get pointer to KeyBlock */
KeyBlock = KeyObject->KeyBlock;
RegistryFile = KeyObject->RegistryFile;
Status = CmiDeleteValueFromKey(RegistryFile,
KeyBlock,
ValueName->Buffer);
ObDereferenceObject(KeyObject);
return Status;
#else
UNIMPLEMENTED;
#endif
}
NTSTATUS NTSTATUS
STDCALL STDCALL
NtEnumerateKey ( NtEnumerateKey (
@ -575,7 +619,7 @@ NtEnumerateKey (
case KeyBasicInformation: case KeyBasicInformation:
/* Check size of buffer */ /* Check size of buffer */
if (Length < sizeof(KEY_BASIC_INFORMATION) + if (Length < sizeof(KEY_BASIC_INFORMATION) +
SubKeyBlock->NameSize * sizeof(WCHAR)) (SubKeyBlock->NameSize + 1) * sizeof(WCHAR))
{ {
Status = STATUS_BUFFER_OVERFLOW; Status = STATUS_BUFFER_OVERFLOW;
} }
@ -585,7 +629,7 @@ NtEnumerateKey (
BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation; BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation;
BasicInformation->LastWriteTime = SubKeyBlock->LastWriteTime; BasicInformation->LastWriteTime = SubKeyBlock->LastWriteTime;
BasicInformation->TitleIndex = Index; BasicInformation->TitleIndex = Index;
BasicInformation->NameLength = SubKeyBlock->NameSize; BasicInformation->NameLength = (SubKeyBlock->NameSize + 1) * sizeof(WCHAR);
wcsncpy(BasicInformation->Name, wcsncpy(BasicInformation->Name,
SubKeyBlock->Name, SubKeyBlock->Name,
SubKeyBlock->NameSize); SubKeyBlock->NameSize);
@ -598,7 +642,7 @@ NtEnumerateKey (
case KeyNodeInformation: case KeyNodeInformation:
/* Check size of buffer */ /* Check size of buffer */
if (Length < sizeof(KEY_NODE_INFORMATION) + if (Length < sizeof(KEY_NODE_INFORMATION) +
SubKeyBlock->NameSize * sizeof(WCHAR) + (SubKeyBlock->NameSize + 1) * sizeof(WCHAR) +
(SubKeyBlock->ClassSize + 1) * sizeof(WCHAR)) (SubKeyBlock->ClassSize + 1) * sizeof(WCHAR))
{ {
Status = STATUS_BUFFER_OVERFLOW; Status = STATUS_BUFFER_OVERFLOW;
@ -612,7 +656,7 @@ NtEnumerateKey (
NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) + NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) +
SubKeyBlock->NameSize * sizeof(WCHAR); SubKeyBlock->NameSize * sizeof(WCHAR);
NodeInformation->ClassLength = SubKeyBlock->ClassSize; NodeInformation->ClassLength = SubKeyBlock->ClassSize;
NodeInformation->NameLength = SubKeyBlock->NameSize; NodeInformation->NameLength = (SubKeyBlock->NameSize + 1) * sizeof(WCHAR);
wcsncpy(NodeInformation->Name, wcsncpy(NodeInformation->Name,
SubKeyBlock->Name, SubKeyBlock->Name,
SubKeyBlock->NameSize); SubKeyBlock->NameSize);
@ -667,6 +711,7 @@ NtEnumerateKey (
break; break;
} }
CmiReleaseBlock(RegistryFile, SubKeyBlock); CmiReleaseBlock(RegistryFile, SubKeyBlock);
ObDereferenceObject (KeyObject);
return Status; return Status;
#else #else
@ -680,14 +725,129 @@ STDCALL
NtEnumerateValueKey ( NtEnumerateValueKey (
IN HANDLE KeyHandle, IN HANDLE KeyHandle,
IN ULONG Index, IN ULONG Index,
IN KEY_VALUE_INFORMATION_CLASS KeyInformationClass, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
OUT PVOID KeyInformation, OUT PVOID KeyValueInformation,
IN ULONG Length, IN ULONG Length,
OUT PULONG ResultLength OUT PULONG ResultLength
) )
{ {
#ifdef PROTO_REG #ifdef PROTO_REG
UNIMPLEMENTED; NTSTATUS Status;
PKEY_OBJECT KeyObject;
PREGISTRY_FILE RegistryFile;
PKEY_BLOCK KeyBlock;
PVALUE_BLOCK ValueBlock;
PVOID DataBlock;
PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation;
PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation;
PKEY_VALUE_FULL_INFORMATION ValueFullInformation;
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_QUERY_VALUE,
CmiKeyType,
UserMode,
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* Get pointer to KeyBlock */
KeyBlock = KeyObject->KeyBlock;
RegistryFile = KeyObject->RegistryFile;
/* Get Value block of interest */
Status = CmiGetValueFromKeyByIndex(RegistryFile,
KeyBlock,
Index,
&ValueBlock);
if (!NT_SUCCESS(Status))
{
return Status;
}
else if (ValueBlock != NULL)
{
switch (KeyValueInformationClass)
{
case KeyValueBasicInformation:
*ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) +
(ValueBlock->NameSize + 1) * sizeof(WCHAR);
if (Length < *ResultLength)
{
Status = STATUS_BUFFER_OVERFLOW;
}
else
{
ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION)
KeyValueInformation;
ValueBasicInformation->TitleIndex = 0;
ValueBasicInformation->Type = ValueBlock->DataType;
ValueBasicInformation->NameLength =
(ValueBlock->NameSize + 1) * sizeof(WCHAR);
wcscpy(ValueBasicInformation->Name, ValueBlock->Name);
}
break;
case KeyValuePartialInformation:
*ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
ValueBlock->DataSize;
if (Length < *ResultLength)
{
Status = STATUS_BUFFER_OVERFLOW;
}
else
{
ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)
KeyValueInformation;
ValuePartialInformation->TitleIndex = 0;
ValuePartialInformation->Type = ValueBlock->DataType;
ValuePartialInformation->DataLength = ValueBlock->DataSize;
DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset);
RtlCopyMemory(ValuePartialInformation->Data,
DataBlock,
ValueBlock->DataSize);
CmiReleaseBlock(RegistryFile, DataBlock);
}
break;
case KeyValueFullInformation:
*ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) +
(ValueBlock->NameSize + 1) * sizeof(WCHAR) + ValueBlock->DataSize;
if (Length < *ResultLength)
{
Status = STATUS_BUFFER_OVERFLOW;
}
else
{
ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)
KeyValueInformation;
ValueFullInformation->TitleIndex = 0;
ValueFullInformation->Type = ValueBlock->DataType;
ValueFullInformation->DataOffset =
sizeof(KEY_VALUE_FULL_INFORMATION) +
ValueBlock->NameSize * sizeof(WCHAR);
ValueFullInformation->DataLength = ValueBlock->DataSize;
ValueFullInformation->NameLength =
(ValueBlock->NameSize + 1) * sizeof(WCHAR);
wcscpy(ValueFullInformation->Name, ValueBlock->Name);
DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset);
RtlCopyMemory(&ValueFullInformation->Name[ValueBlock->NameSize + 1],
DataBlock,
ValueBlock->DataSize);
CmiReleaseBlock(RegistryFile, DataBlock);
}
break;
}
}
else
{
Status = STATUS_UNSUCCESSFUL;
}
ObDereferenceObject(KeyObject);
return Status;
#else #else
UNIMPLEMENTED; UNIMPLEMENTED;
#endif #endif
@ -750,8 +910,6 @@ NtOpenKey (
KeyHandle); KeyHandle);
ExFreePool(KeyNameBuf); ExFreePool(KeyNameBuf);
DPRINT1("Status %x KeyHandle (opened) %x\n", Status, *KeyHandle);
return Status; return Status;
} }
@ -794,7 +952,6 @@ DPRINT1("Status %x KeyHandle (opened) %x\n", Status, *KeyHandle);
NewKey->RegistryFile = FileToUse; NewKey->RegistryFile = FileToUse;
NewKey->KeyBlock = KeyBlock; NewKey->KeyBlock = KeyBlock;
CmiAddKeyToList(NewKey); CmiAddKeyToList(NewKey);
DPRINT1("KeyHandle (created) %x\n", *KeyHandle);
Status = ObCreateHandle(PsGetCurrentProcess(), Status = ObCreateHandle(PsGetCurrentProcess(),
NewKey, NewKey,
@ -802,7 +959,6 @@ DPRINT1("KeyHandle (created) %x\n", *KeyHandle);
FALSE, FALSE,
KeyHandle); KeyHandle);
DPRINT1("Status %x KeyHandle (created) %x\n", Status, *KeyHandle);
return Status; return Status;
#else #else
UNIMPLEMENTED; UNIMPLEMENTED;
@ -942,6 +1098,7 @@ NtQueryKey (
} }
break; break;
} }
ObDereferenceObject (KeyObject);
return Status; return Status;
#else #else
@ -1073,6 +1230,7 @@ NtQueryValueKey (
{ {
Status = STATUS_UNSUCCESSFUL; Status = STATUS_UNSUCCESSFUL;
} }
ObDereferenceObject(KeyObject);
return Status; return Status;
#else #else
@ -1147,43 +1305,6 @@ NtSetValueKey (
#endif #endif
} }
NTSTATUS
STDCALL
NtDeleteValueKey (
IN HANDLE KeyHandle,
IN PUNICODE_STRING ValueName
)
{
#ifdef PROTO_REG
NTSTATUS Status;
PKEY_OBJECT KeyObject;
PREGISTRY_FILE RegistryFile;
PKEY_BLOCK KeyBlock;
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_QUERY_VALUE,
CmiKeyType,
UserMode,
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* Get pointer to KeyBlock */
KeyBlock = KeyObject->KeyBlock;
RegistryFile = KeyObject->RegistryFile;
Status = CmiDeleteValueFromKey(RegistryFile,
KeyBlock,
ValueName->Buffer);
return Status;
#else
UNIMPLEMENTED;
#endif
}
NTSTATUS NTSTATUS
STDCALL STDCALL
@ -1192,13 +1313,19 @@ NtLoadKey (
OBJECT_ATTRIBUTES ObjectAttributes OBJECT_ATTRIBUTES ObjectAttributes
) )
{ {
UNIMPLEMENTED; return NtLoadKey2(KeyHandle,
ObjectAttributes,
0);
} }
NTSTATUS NTSTATUS
STDCALL STDCALL
NtLoadKey2(VOID) NtLoadKey2 (
PHANDLE KeyHandle,
OBJECT_ATTRIBUTES ObjectAttributes,
ULONG Unknown3
)
{ {
UNIMPLEMENTED; UNIMPLEMENTED;
} }
@ -1514,8 +1641,6 @@ CmiBuildKeyPath(PWSTR *KeyPath, POBJECT_ATTRIBUTES ObjectAttributes)
ObjectHeader = 0; ObjectHeader = 0;
if (ObjectAttributes->RootDirectory != NULL) if (ObjectAttributes->RootDirectory != NULL)
{ {
DbgPrint ("RootDirectory %x\n", ObjectAttributes->RootDirectory);
DbgPrint ("KeyName %wZ\n", ObjectAttributes->ObjectName);
/* FIXME: determine type of object for RootDirectory */ /* FIXME: determine type of object for RootDirectory */
Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory, Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
KEY_READ, KEY_READ,
@ -1525,7 +1650,6 @@ DbgPrint ("KeyName %wZ\n", ObjectAttributes->ObjectName);
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
CHECKPOINT1;
return Status; return Status;
} }
ObjectHeader = BODY_TO_HEADER(ObjectBody); ObjectHeader = BODY_TO_HEADER(ObjectBody);
@ -2188,7 +2312,7 @@ CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile,
ValueListBlock = CmiGetBlock(RegistryFile, ValueListBlock = CmiGetBlock(RegistryFile,
KeyBlock->ValuesOffset); KeyBlock->ValuesOffset);
*ValueBlock = NULL; *ValueBlock = NULL;
if (ValueListBlock == 0) if (ValueListBlock == NULL)
{ {
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -2210,6 +2334,40 @@ CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile,
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
static NTSTATUS
CmiGetValueFromKeyByIndex(IN PREGISTRY_FILE RegistryFile,
IN PKEY_BLOCK KeyBlock,
IN ULONG Index,
OUT PVALUE_BLOCK *ValueBlock)
{
PVALUE_LIST_BLOCK ValueListBlock;
PVALUE_BLOCK CurValueBlock;
ValueListBlock = CmiGetBlock(RegistryFile,
KeyBlock->ValuesOffset);
*ValueBlock = NULL;
if (ValueListBlock == NULL)
{
return STATUS_NO_MORE_ENTRIES;
}
if (Index >= KeyBlock->NumberOfValues)
{
return STATUS_NO_MORE_ENTRIES;
}
CurValueBlock = CmiGetBlock(RegistryFile,
ValueListBlock->Values[Index]);
if (CurValueBlock != NULL)
{
*ValueBlock = CurValueBlock;
}
CmiReleaseBlock(RegistryFile, CurValueBlock);
CmiReleaseBlock(RegistryFile, ValueListBlock);
return STATUS_SUCCESS;
}
static NTSTATUS static NTSTATUS
CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile, CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile,
IN PKEY_BLOCK KeyBlock, IN PKEY_BLOCK KeyBlock,
@ -2246,6 +2404,8 @@ CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile,
ValueBlock); ValueBlock);
return Status; return Status;
} }
KeyBlock->ValuesOffset = CmiGetBlockOffset(RegistryFile,
ValueListBlock);
} }
else if (KeyBlock->NumberOfValues % REG_VALUE_LIST_BLOCK_MULTIPLE) else if (KeyBlock->NumberOfValues % REG_VALUE_LIST_BLOCK_MULTIPLE)
{ {
@ -2268,6 +2428,7 @@ CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile,
CmiDestroyBlock(RegistryFile, ValueListBlock); CmiDestroyBlock(RegistryFile, ValueListBlock);
ValueListBlock = NewValueListBlock; ValueListBlock = NewValueListBlock;
} }
ValueListBlock->Values[KeyBlock->NumberOfValues] = ValueListBlock->Values[KeyBlock->NumberOfValues] =
CmiGetBlockOffset(RegistryFile, ValueBlock); CmiGetBlockOffset(RegistryFile, ValueBlock);
KeyBlock->NumberOfValues++; KeyBlock->NumberOfValues++;
@ -2347,7 +2508,7 @@ CmiAllocateKeyBlock(IN PREGISTRY_FILE RegistryFile,
NewKeySize = sizeof(KEY_BLOCK) + NewKeySize = sizeof(KEY_BLOCK) +
(wcslen(KeyName) + 1) * sizeof(WCHAR) + (wcslen(KeyName) + 1) * sizeof(WCHAR) +
(Class != NULL ? (wcslen(Class) + 1) * sizeof(WCHAR) : 0); (Class != NULL ? (wcslen(Class) + 1) * sizeof(WCHAR) : 0);
DPRINT ("NewKeySize: %lu\n", NewKeySize); DPRINT ("NewKeySize: %lu\n", NewKeySize);
//CHECKPOINT; //CHECKPOINT;
NewKeyBlock = ExAllocatePool(NonPagedPool, NewKeySize); NewKeyBlock = ExAllocatePool(NonPagedPool, NewKeySize);
//CHECKPOINT; //CHECKPOINT;
@ -2652,7 +2813,6 @@ CmiDestroyValueBlock(PREGISTRY_FILE RegistryFile,
{ {
NTSTATUS Status; NTSTATUS Status;
CHECKPOINT1;
Status = CmiDestroyBlock(RegistryFile, Status = CmiDestroyBlock(RegistryFile,
CmiGetBlock(RegistryFile, CmiGetBlock(RegistryFile,
ValueBlock->DataOffset)); ValueBlock->DataOffset));