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
*/ */
@ -801,7 +1203,23 @@ STDCALL
RegSaveKeyA( RegSaveKeyA(
HKEY hKey, HKEY hKey,
LPCSTR lpFile, LPCSTR lpFile,
LPSECURITY_ATTRIBUTES lpSecurityAttributes LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
* RegSaveKeyW
*/
LONG
STDCALL
RegSaveKeyW(
HKEY hKey,
LPCWSTR lpFile,
LPSECURITY_ATTRIBUTES lpSecurityAttributes
) )
{ {
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
@ -812,7 +1230,6 @@ RegSaveKeyA(
/************************************************************************ /************************************************************************
* 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,7 +384,8 @@ CmImportHive(PCHAR Chunk)
return; return;
} }
NTSTATUS
NTSTATUS
STDCALL STDCALL
NtCreateKey ( NtCreateKey (
OUT PHANDLE KeyHandle, OUT PHANDLE KeyHandle,
@ -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,7 +525,48 @@ NtDeleteKey (
} }
NTSTATUS 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
STDCALL STDCALL
NtEnumerateKey ( NtEnumerateKey (
IN HANDLE KeyHandle, IN HANDLE KeyHandle,
@ -542,7 +586,7 @@ NtEnumerateKey (
PKEY_BASIC_INFORMATION BasicInformation; PKEY_BASIC_INFORMATION BasicInformation;
PKEY_NODE_INFORMATION NodeInformation; PKEY_NODE_INFORMATION NodeInformation;
PKEY_FULL_INFORMATION FullInformation; PKEY_FULL_INFORMATION FullInformation;
/* Verify that the handle is valid and is a registry key */ /* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle, Status = ObReferenceObjectByHandle(KeyHandle,
KEY_ENUMERATE_SUB_KEYS, KEY_ENUMERATE_SUB_KEYS,
@ -558,11 +602,11 @@ NtEnumerateKey (
/* Get pointer to KeyBlock */ /* Get pointer to KeyBlock */
KeyBlock = KeyObject->KeyBlock; KeyBlock = KeyObject->KeyBlock;
RegistryFile = KeyObject->RegistryFile; RegistryFile = KeyObject->RegistryFile;
/* Get pointer to SubKey */ /* Get pointer to SubKey */
HashTableBlock = CmiGetHashTableBlock(RegistryFile, KeyBlock->HashTableOffset); HashTableBlock = CmiGetHashTableBlock(RegistryFile, KeyBlock->HashTableOffset);
SubKeyBlock = CmiGetKeyFromHashByIndex(RegistryFile, SubKeyBlock = CmiGetKeyFromHashByIndex(RegistryFile,
HashTableBlock, HashTableBlock,
Index); Index);
if (SubKeyBlock == NULL) if (SubKeyBlock == NULL)
{ {
@ -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
@ -675,26 +720,141 @@ NtEnumerateKey (
} }
NTSTATUS NTSTATUS
STDCALL 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
} }
NTSTATUS NTSTATUS
STDCALL STDCALL
NtFlushKey ( NtFlushKey (
IN HANDLE KeyHandle IN HANDLE KeyHandle
@ -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;
@ -828,7 +984,7 @@ NtQueryKey (
PKEY_BASIC_INFORMATION BasicInformation; PKEY_BASIC_INFORMATION BasicInformation;
PKEY_NODE_INFORMATION NodeInformation; PKEY_NODE_INFORMATION NodeInformation;
PKEY_FULL_INFORMATION FullInformation; PKEY_FULL_INFORMATION FullInformation;
/* Verify that the handle is valid and is a registry key */ /* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle, Status = ObReferenceObjectByHandle(KeyHandle,
KEY_READ, KEY_READ,
@ -844,13 +1000,13 @@ NtQueryKey (
/* Get pointer to KeyBlock */ /* Get pointer to KeyBlock */
KeyBlock = KeyObject->KeyBlock; KeyBlock = KeyObject->KeyBlock;
RegistryFile = KeyObject->RegistryFile; RegistryFile = KeyObject->RegistryFile;
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
switch (KeyInformationClass) switch (KeyInformationClass)
{ {
case KeyBasicInformation: case KeyBasicInformation:
/* Check size of buffer */ /* Check size of buffer */
if (Length < sizeof(KEY_BASIC_INFORMATION) + if (Length < sizeof(KEY_BASIC_INFORMATION) +
KeyBlock->NameSize * sizeof(WCHAR)) KeyBlock->NameSize * sizeof(WCHAR))
{ {
Status = STATUS_BUFFER_OVERFLOW; Status = STATUS_BUFFER_OVERFLOW;
@ -862,11 +1018,11 @@ NtQueryKey (
BasicInformation->LastWriteTime = KeyBlock->LastWriteTime; BasicInformation->LastWriteTime = KeyBlock->LastWriteTime;
BasicInformation->TitleIndex = 0; BasicInformation->TitleIndex = 0;
BasicInformation->NameLength = KeyBlock->NameSize; BasicInformation->NameLength = KeyBlock->NameSize;
wcsncpy(BasicInformation->Name, wcsncpy(BasicInformation->Name,
KeyBlock->Name, KeyBlock->Name,
KeyBlock->NameSize); KeyBlock->NameSize);
BasicInformation->Name[KeyBlock->NameSize] = 0; BasicInformation->Name[KeyBlock->NameSize] = 0;
*ResultLength = sizeof(KEY_BASIC_INFORMATION) + *ResultLength = sizeof(KEY_BASIC_INFORMATION) +
KeyBlock->NameSize * sizeof(WCHAR); KeyBlock->NameSize * sizeof(WCHAR);
} }
break; break;
@ -885,12 +1041,12 @@ NtQueryKey (
NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation; NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation;
NodeInformation->LastWriteTime = KeyBlock->LastWriteTime; NodeInformation->LastWriteTime = KeyBlock->LastWriteTime;
NodeInformation->TitleIndex = 0; NodeInformation->TitleIndex = 0;
NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) + NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) +
KeyBlock->NameSize * sizeof(WCHAR); KeyBlock->NameSize * sizeof(WCHAR);
NodeInformation->ClassLength = KeyBlock->ClassSize; NodeInformation->ClassLength = KeyBlock->ClassSize;
NodeInformation->NameLength = KeyBlock->NameSize; NodeInformation->NameLength = KeyBlock->NameSize;
wcsncpy(NodeInformation->Name, wcsncpy(NodeInformation->Name,
KeyBlock->Name, KeyBlock->Name,
KeyBlock->NameSize); KeyBlock->NameSize);
NodeInformation->Name[KeyBlock->NameSize] = 0; NodeInformation->Name[KeyBlock->NameSize] = 0;
if (KeyBlock->ClassSize != 0) if (KeyBlock->ClassSize != 0)
@ -920,7 +1076,7 @@ NtQueryKey (
FullInformation = (PKEY_FULL_INFORMATION) KeyInformation; FullInformation = (PKEY_FULL_INFORMATION) KeyInformation;
FullInformation->LastWriteTime = KeyBlock->LastWriteTime; FullInformation->LastWriteTime = KeyBlock->LastWriteTime;
FullInformation->TitleIndex = 0; FullInformation->TitleIndex = 0;
FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) - FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) -
sizeof(WCHAR); sizeof(WCHAR);
FullInformation->ClassLength = KeyBlock->ClassSize; FullInformation->ClassLength = KeyBlock->ClassSize;
FullInformation->SubKeys = KeyBlock->NumberOfSubKeys; FullInformation->SubKeys = KeyBlock->NumberOfSubKeys;
@ -942,6 +1098,7 @@ NtQueryKey (
} }
break; break;
} }
ObDereferenceObject (KeyObject);
return Status; return Status;
#else #else
@ -950,7 +1107,7 @@ NtQueryKey (
} }
NTSTATUS NTSTATUS
STDCALL STDCALL
NtQueryValueKey ( NtQueryValueKey (
IN HANDLE KeyHandle, IN HANDLE KeyHandle,
@ -1073,7 +1230,8 @@ NtQueryValueKey (
{ {
Status = STATUS_UNSUCCESSFUL; Status = STATUS_UNSUCCESSFUL;
} }
ObDereferenceObject(KeyObject);
return Status; return Status;
#else #else
UNIMPLEMENTED; UNIMPLEMENTED;
@ -1147,58 +1305,27 @@ NtSetValueKey (
#endif #endif
} }
NTSTATUS NTSTATUS
STDCALL 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
STDCALL
NtLoadKey ( NtLoadKey (
PHANDLE KeyHandle, PHANDLE KeyHandle,
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;
} }
@ -1209,11 +1336,11 @@ STDCALL
NtNotifyChangeKey ( NtNotifyChangeKey (
IN HANDLE KeyHandle, IN HANDLE KeyHandle,
IN HANDLE Event, IN HANDLE Event,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL, IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG CompletionFilter, IN ULONG CompletionFilter,
IN BOOLEAN Asynchroneous, IN BOOLEAN Asynchroneous,
OUT PVOID ChangeBuffer, OUT PVOID ChangeBuffer,
IN ULONG Length, IN ULONG Length,
IN BOOLEAN WatchSubtree IN BOOLEAN WatchSubtree
@ -1287,7 +1414,7 @@ NtSetInformationKey (
NTSTATUS NTSTATUS
STDCALL STDCALL
NtUnloadKey ( NtUnloadKey (
HANDLE KeyHandle HANDLE KeyHandle
) )
@ -1297,7 +1424,7 @@ NtUnloadKey (
NTSTATUS NTSTATUS
STDCALL STDCALL
NtInitializeRegistry ( NtInitializeRegistry (
BOOLEAN SetUpBoot BOOLEAN SetUpBoot
) )
@ -1408,7 +1535,7 @@ static NTSTATUS CmiObjectParse(PVOID ParsedObject,
return Status; return Status;
} }
CurKeyBlock = CmiGetKeyBlock(RegistryFile, CurKeyBlock = CmiGetKeyBlock(RegistryFile,
RegistryFile->HeaderBlock->RootKeyBlock); RegistryFile->HeaderBlock->RootKeyBlock);
/* Loop through each key level and find the needed subkey */ /* Loop through each key level and find the needed subkey */
@ -1429,8 +1556,8 @@ static NTSTATUS CmiObjectParse(PVOID ParsedObject,
} }
/* Verify existance of CurKeyName */ /* Verify existance of CurKeyName */
Status = CmiScanForSubKey(RegistryFile, Status = CmiScanForSubKey(RegistryFile,
CurKeyBlock, CurKeyBlock,
&SubKeyBlock, &SubKeyBlock,
CurKeyName, CurKeyName,
STANDARD_RIGHTS_REQUIRED); STANDARD_RIGHTS_REQUIRED);
@ -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);
@ -1650,7 +1774,7 @@ CmiAddKeyToList(PKEY_OBJECT NewKey)
KeReleaseSpinLock(&CmiKeyListLock, OldIrql); KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
} }
static VOID static VOID
CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove) CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
{ {
KIRQL OldIrql; KIRQL OldIrql;
@ -2104,12 +2228,12 @@ CmiScanForSubKey(IN PREGISTRY_FILE RegistryFile,
} }
static NTSTATUS static NTSTATUS
CmiAddSubKey(PREGISTRY_FILE RegistryFile, CmiAddSubKey(PREGISTRY_FILE RegistryFile,
PKEY_BLOCK KeyBlock, PKEY_BLOCK KeyBlock,
PKEY_BLOCK *SubKeyBlock, PKEY_BLOCK *SubKeyBlock,
PWSTR NewSubKeyName, PWSTR NewSubKeyName,
ULONG TitleIndex, ULONG TitleIndex,
PWSTR Class, PWSTR Class,
ULONG CreateOptions) ULONG CreateOptions)
{ {
NTSTATUS Status; NTSTATUS Status;
@ -2128,7 +2252,7 @@ CmiAddSubKey(PREGISTRY_FILE RegistryFile,
} }
if (KeyBlock->HashTableOffset == 0) if (KeyBlock->HashTableOffset == 0)
{ {
Status = CmiAllocateHashTableBlock(RegistryFile, Status = CmiAllocateHashTableBlock(RegistryFile,
&HashBlock, &HashBlock,
REG_INIT_HASH_TABLE_SIZE); REG_INIT_HASH_TABLE_SIZE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -2175,7 +2299,7 @@ CmiAddSubKey(PREGISTRY_FILE RegistryFile,
return Status; return Status;
} }
static NTSTATUS static NTSTATUS
CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile, CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile,
IN PKEY_BLOCK KeyBlock, IN PKEY_BLOCK KeyBlock,
IN PWSTR ValueName, IN PWSTR ValueName,
@ -2185,10 +2309,10 @@ CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile,
PVALUE_LIST_BLOCK ValueListBlock; PVALUE_LIST_BLOCK ValueListBlock;
PVALUE_BLOCK CurValueBlock; PVALUE_BLOCK CurValueBlock;
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;
@ -2421,7 +2582,7 @@ CmiDestroyKeyBlock(PREGISTRY_FILE RegistryFile,
ExFreePool(KeyBlock); ExFreePool(KeyBlock);
} }
else else
{ {
UNIMPLEMENTED; UNIMPLEMENTED;
} }
@ -2466,7 +2627,7 @@ CmiAllocateHashTableBlock(IN PREGISTRY_FILE RegistryFile,
return Status; return Status;
} }
static PHASH_TABLE_BLOCK static PHASH_TABLE_BLOCK
CmiGetHashTableBlock(PREGISTRY_FILE RegistryFile, CmiGetHashTableBlock(PREGISTRY_FILE RegistryFile,
BLOCK_OFFSET HashBlockOffset) BLOCK_OFFSET HashBlockOffset)
{ {
@ -2486,7 +2647,7 @@ CmiGetHashTableBlock(PREGISTRY_FILE RegistryFile,
return HashBlock; return HashBlock;
} }
static PKEY_BLOCK static PKEY_BLOCK
CmiGetKeyFromHashByIndex(PREGISTRY_FILE RegistryFile, CmiGetKeyFromHashByIndex(PREGISTRY_FILE RegistryFile,
PHASH_TABLE_BLOCK HashBlock, PHASH_TABLE_BLOCK HashBlock,
ULONG Index) ULONG Index)
@ -2506,7 +2667,7 @@ CmiGetKeyFromHashByIndex(PREGISTRY_FILE RegistryFile,
return KeyBlock; return KeyBlock;
} }
static NTSTATUS static NTSTATUS
CmiAddKeyToHashTable(PREGISTRY_FILE RegistryFile, CmiAddKeyToHashTable(PREGISTRY_FILE RegistryFile,
PHASH_TABLE_BLOCK HashBlock, PHASH_TABLE_BLOCK HashBlock,
PKEY_BLOCK NewKeyBlock) PKEY_BLOCK NewKeyBlock)
@ -2553,7 +2714,7 @@ static NTSTATUS
CmiAllocateValueBlock(PREGISTRY_FILE RegistryFile, CmiAllocateValueBlock(PREGISTRY_FILE RegistryFile,
PVALUE_BLOCK *ValueBlock, PVALUE_BLOCK *ValueBlock,
IN PWSTR ValueNameBuf, IN PWSTR ValueNameBuf,
IN ULONG Type, IN ULONG Type,
IN PVOID Data, IN PVOID Data,
IN ULONG DataSize) IN ULONG DataSize)
{ {
@ -2610,7 +2771,7 @@ CmiAllocateValueBlock(PREGISTRY_FILE RegistryFile,
static NTSTATUS static NTSTATUS
CmiReplaceValueData(IN PREGISTRY_FILE RegistryFile, CmiReplaceValueData(IN PREGISTRY_FILE RegistryFile,
IN PVALUE_BLOCK ValueBlock, IN PVALUE_BLOCK ValueBlock,
IN ULONG Type, IN ULONG Type,
IN PVOID Data, IN PVOID Data,
IN ULONG DataSize) IN ULONG DataSize)
{ {
@ -2652,8 +2813,7 @@ CmiDestroyValueBlock(PREGISTRY_FILE RegistryFile,
{ {
NTSTATUS Status; NTSTATUS Status;
CHECKPOINT1; Status = CmiDestroyBlock(RegistryFile,
Status = CmiDestroyBlock(RegistryFile,
CmiGetBlock(RegistryFile, CmiGetBlock(RegistryFile,
ValueBlock->DataOffset)); ValueBlock->DataOffset));
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -2710,7 +2870,7 @@ CmiDestroyBlock(PREGISTRY_FILE RegistryFile,
ExFreePool(Block); ExFreePool(Block);
} }
else else
{ {
Status = STATUS_NOT_IMPLEMENTED; Status = STATUS_NOT_IMPLEMENTED;
} }
@ -2756,7 +2916,7 @@ CmiGetBlockOffset(PREGISTRY_FILE RegistryFile,
return BlockOffset; return BlockOffset;
} }
static VOID static VOID
CmiLockBlock(PREGISTRY_FILE RegistryFile, CmiLockBlock(PREGISTRY_FILE RegistryFile,
PVOID Block) PVOID Block)
{ {
@ -2766,7 +2926,7 @@ CmiLockBlock(PREGISTRY_FILE RegistryFile,
} }
} }
static VOID static VOID
CmiReleaseBlock(PREGISTRY_FILE RegistryFile, CmiReleaseBlock(PREGISTRY_FILE RegistryFile,
PVOID Block) PVOID Block)
{ {