[MKHIVE] Create reparse points, and use them instead of pseudo-connections between cells

svn path=/trunk/; revision=64552
This commit is contained in:
Hervé Poussineau 2014-10-05 21:30:57 +00:00
parent 6435bdf92c
commit dc6d1450bc
5 changed files with 135 additions and 88 deletions

View file

@ -330,16 +330,19 @@ CmiCreateSubKey(
NTSTATUS
CmiAddSubKey(
IN PCMHIVE RegistryHive,
IN PCM_KEY_NODE ParentKeyCell,
IN HCELL_INDEX ParentKeyCellOffset,
IN PCUNICODE_STRING SubKeyName,
IN ULONG CreateOptions,
OUT PCM_KEY_NODE *pSubKeyCell,
OUT HCELL_INDEX *pBlockOffset)
{
PCM_KEY_NODE ParentKeyCell;
HCELL_INDEX NKBOffset;
NTSTATUS Status;
ParentKeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, ParentKeyCellOffset);
if (!ParentKeyCell)
return STATUS_UNSUCCESSFUL;
VERIFY_KEY_CELL(ParentKeyCell);
/* Create the new key */
@ -396,18 +399,22 @@ CmiCompareHashI(
NTSTATUS
CmiScanForSubKey(
IN PCMHIVE RegistryHive,
IN PCM_KEY_NODE KeyCell,
IN HCELL_INDEX ParentKeyCellOffset,
IN PCUNICODE_STRING SubKeyName,
IN ULONG Attributes,
OUT PCM_KEY_NODE *pSubKeyCell,
OUT HCELL_INDEX *pBlockOffset)
{
PCM_KEY_NODE KeyCell;
PCM_KEY_FAST_INDEX HashBlock;
PCM_KEY_NODE CurSubKeyCell;
BOOLEAN CaseInsensitive;
ULONG Storage;
ULONG i;
KeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, ParentKeyCellOffset);
if (!KeyCell)
return STATUS_UNSUCCESSFUL;
VERIFY_KEY_CELL(KeyCell);
ASSERT(RegistryHive);
@ -528,13 +535,13 @@ CmiAllocateValueCell(
NTSTATUS
CmiAddValueKey(
IN PCMHIVE RegistryHive,
IN PCM_KEY_NODE KeyCell,
IN HCELL_INDEX KeyCellOffset,
IN PCUNICODE_STRING ValueName,
OUT PCM_KEY_VALUE *pValueCell,
OUT HCELL_INDEX *pValueCellOffset)
{
PVALUE_LIST_CELL ValueListCell;
PCM_KEY_NODE KeyCell;
PCM_KEY_VALUE NewValueCell;
HCELL_INDEX ValueListCellOffset;
HCELL_INDEX NewValueCellOffset;
@ -542,6 +549,9 @@ CmiAddValueKey(
HSTORAGE_TYPE Storage;
NTSTATUS Status;
KeyCell = HvGetCell(&RegistryHive->Hive, KeyCellOffset);
if (!KeyCell)
return STATUS_UNSUCCESSFUL;
Storage = (KeyCell->Flags & KEY_IS_VOLATILE) ? Volatile : Stable;
if (KeyCell->ValueList.List == HCELL_NIL)
{
@ -614,15 +624,19 @@ CmiAddValueKey(
NTSTATUS
CmiScanForValueKey(
IN PCMHIVE RegistryHive,
IN PCM_KEY_NODE KeyCell,
IN HCELL_INDEX KeyCellOffset,
IN PCUNICODE_STRING ValueName,
OUT PCM_KEY_VALUE *pValueCell,
OUT HCELL_INDEX *pValueCellOffset)
{
PCM_KEY_NODE KeyCell;
PVALUE_LIST_CELL ValueListCell;
PCM_KEY_VALUE CurValueCell;
ULONG i;
KeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, KeyCellOffset);
if (!KeyCell)
return STATUS_UNSUCCESSFUL;
*pValueCell = NULL;
*pValueCellOffset = HCELL_NIL;

View file

@ -33,7 +33,6 @@ CmiInitializeTempHive(
NTSTATUS
CmiAddSubKey(
IN PCMHIVE RegistryHive,
IN PCM_KEY_NODE ParentKeyCell,
IN HCELL_INDEX ParentKeyCellOffset,
IN PCUNICODE_STRING SubKeyName,
IN ULONG CreateOptions,
@ -43,7 +42,7 @@ CmiAddSubKey(
NTSTATUS
CmiScanForSubKey(
IN PCMHIVE RegistryHive,
IN PCM_KEY_NODE KeyCell,
IN HCELL_INDEX ParentKeyCellOffset,
IN PCUNICODE_STRING SubKeyName,
IN ULONG Attributes,
OUT PCM_KEY_NODE *pSubKeyCell,
@ -52,7 +51,6 @@ CmiScanForSubKey(
NTSTATUS
CmiAddValueKey(
IN PCMHIVE RegistryHive,
IN PCM_KEY_NODE KeyCell,
IN HCELL_INDEX KeyCellOffset,
IN PCUNICODE_STRING ValueName,
OUT PCM_KEY_VALUE *pValueCell,
@ -61,7 +59,7 @@ CmiAddValueKey(
NTSTATUS
CmiScanForValueKey(
IN PCMHIVE RegistryHive,
IN PCM_KEY_NODE KeyCell,
IN HCELL_INDEX KeyCellOffset,
IN PCUNICODE_STRING ValueName,
OUT PCM_KEY_VALUE *pValueCell,
OUT HCELL_INDEX *pValueCellOffset);

View file

@ -52,6 +52,9 @@ unsigned char BitScanReverse(ULONG * const Index, unsigned long Mask);
#define BitScanReverse64 _BitScanReverse64
#endif
typedef DWORD REGSAM;
typedef LPVOID LPSECURITY_ATTRIBUTES;
NTSTATUS NTAPI
RtlAnsiStringToUnicodeString(
IN OUT PUNICODE_STRING UniDest,

View file

@ -51,8 +51,7 @@ CMHIVE SystemHive; /* \Registry\Machine\SYSTEM */
static PMEMKEY
CreateInMemoryStructure(
IN PCMHIVE RegistryHive,
IN HCELL_INDEX KeyCellOffset,
IN PCUNICODE_STRING KeyName)
IN HCELL_INDEX KeyCellOffset)
{
PMEMKEY Key;
@ -60,54 +59,50 @@ CreateInMemoryStructure(
if (!Key)
return NULL;
InitializeListHead (&Key->SubKeyList);
InitializeListHead (&Key->KeyList);
Key->RegistryHive = RegistryHive;
Key->KeyCellOffset = Key->KeyCellOffsetInParentHive = KeyCellOffset;
Key->KeyCell = (PCM_KEY_NODE)HvGetCell (&RegistryHive->Hive, Key->KeyCellOffset);
if (!Key->KeyCell)
{
free(Key);
return NULL;
}
Key->KeyCell->SubKeyLists[Stable] = HCELL_NIL;
Key->KeyCell->SubKeyLists[Volatile] = HCELL_NIL;
Key->KeyCellOffset = KeyCellOffset;
return Key;
}
LIST_ENTRY CmiReparsePointsHead;
static LONG
RegpOpenOrCreateKey(
IN HKEY hParentKey,
IN PCWSTR KeyName,
IN BOOL AllowCreation,
IN BOOL Volatile,
OUT PHKEY Key)
{
PWSTR LocalKeyName;
PWSTR End;
UNICODE_STRING KeyString;
NTSTATUS Status;
PMEMKEY ParentKey;
PREPARSE_POINT CurrentReparsePoint;
PMEMKEY CurrentKey;
PCMHIVE ParentRegistryHive;
HCELL_INDEX ParentCellOffset;
PLIST_ENTRY Ptr;
PCM_KEY_NODE SubKeyCell;
HCELL_INDEX BlockOffset;
BOOLEAN ParentIsSystem = FALSE;
DPRINT("RegpCreateOpenKey('%S')\n", KeyName);
if (*KeyName == L'\\')
{
KeyName++;
ParentKey = RootKey;
ParentRegistryHive = RootKey->RegistryHive;
ParentCellOffset = RootKey->KeyCellOffset;
}
else if (hParentKey == NULL)
{
ParentKey = RootKey;
ParentRegistryHive = RootKey->RegistryHive;
ParentCellOffset = RootKey->KeyCellOffset;
}
else
{
ParentKey = HKEY_TO_MEMKEY(RootKey);
ParentRegistryHive = HKEY_TO_MEMKEY(RootKey)->RegistryHive;
ParentCellOffset = HKEY_TO_MEMKEY(RootKey)->KeyCellOffset;
}
LocalKeyName = (PWSTR)KeyName;
@ -130,77 +125,55 @@ RegpOpenOrCreateKey(
}
}
/* Redirect from 'CurrentControlSet' to 'ControlSet001' */
if (!strncmpiW(LocalKeyName, L"CurrentControlSet", 17) && ParentIsSystem)
{
RtlInitUnicodeString(&KeyString, L"ControlSet001");
ParentIsSystem = FALSE;
}
else
{
ParentIsSystem = (strncmpiW(LocalKeyName, L"SYSTEM", 6) == 0);
}
Status = CmiScanForSubKey(
ParentKey->RegistryHive,
ParentKey->KeyCell,
ParentRegistryHive,
ParentCellOffset,
&KeyString,
OBJ_CASE_INSENSITIVE,
&SubKeyCell,
&BlockOffset);
if (NT_SUCCESS(Status))
{
/* Check subkey in memory structure */
Ptr = ParentKey->SubKeyList.Flink;
while (Ptr != &ParentKey->SubKeyList)
/* Search for a possible reparse point */
Ptr = CmiReparsePointsHead.Flink;
while (Ptr != &CmiReparsePointsHead)
{
CurrentKey = CONTAINING_RECORD(Ptr, MEMKEY, KeyList);
if (CurrentKey->KeyCellOffsetInParentHive == BlockOffset)
CurrentReparsePoint = CONTAINING_RECORD(Ptr, REPARSE_POINT, ListEntry);
if (CurrentReparsePoint->SourceHive == ParentRegistryHive &&
CurrentReparsePoint->SourceKeyCellOffset == BlockOffset)
{
goto nextsubkey;
ParentRegistryHive = CurrentReparsePoint->DestinationHive;
BlockOffset = CurrentReparsePoint->DestinationKeyCellOffset;
break;
}
Ptr = Ptr->Flink;
}
/* If we go there, this means that key exists, but we don't know it */
ASSERT(FALSE);
}
if (AllowCreation && Status == STATUS_OBJECT_NAME_NOT_FOUND)
else if (Status == STATUS_OBJECT_NAME_NOT_FOUND && AllowCreation)
{
Status = CmiAddSubKey(
ParentKey->RegistryHive,
ParentKey->KeyCell,
ParentKey->KeyCellOffset,
ParentRegistryHive,
ParentCellOffset,
&KeyString,
0,
Volatile ? REG_OPTION_VOLATILE : 0,
&SubKeyCell,
&BlockOffset);
if (NT_SUCCESS(Status))
{
/* Now, SubKeyCell/BlockOffset are valid */
CurrentKey = CreateInMemoryStructure(
ParentKey->RegistryHive,
BlockOffset,
&KeyString);
if (!CurrentKey)
return ERROR_OUTOFMEMORY;
/* Add CurrentKey in ParentKey */
InsertTailList(&ParentKey->SubKeyList, &CurrentKey->KeyList);
}
}
if (!NT_SUCCESS(Status))
return ERROR_UNSUCCESSFUL;
nextsubkey:
ParentKey = CurrentKey;
ParentCellOffset = BlockOffset;
if (End)
LocalKeyName = End + 1;
else
break;
}
*Key = MEMKEY_TO_HKEY(ParentKey);
CurrentKey = CreateInMemoryStructure(ParentRegistryHive, ParentCellOffset);
if (!CurrentKey)
return ERROR_OUTOFMEMORY;
*Key = MEMKEY_TO_HKEY(CurrentKey);
return ERROR_SUCCESS;
}
@ -211,7 +184,7 @@ RegCreateKeyW(
IN LPCWSTR lpSubKey,
OUT PHKEY phkResult)
{
return RegpOpenOrCreateKey(hKey, lpSubKey, TRUE, phkResult);
return RegpOpenOrCreateKey(hKey, lpSubKey, TRUE, FALSE, phkResult);
}
static PWSTR
@ -270,7 +243,26 @@ RegOpenKeyW(
IN LPCWSTR lpSubKey,
OUT PHKEY phkResult)
{
return RegpOpenOrCreateKey(hKey, lpSubKey, FALSE, phkResult);
return RegpOpenOrCreateKey(hKey, lpSubKey, FALSE, FALSE, phkResult);
}
LONG WINAPI
RegCreateKeyExW(
IN HKEY hKey,
IN LPCWSTR lpSubKey,
IN DWORD Reserved,
IN LPWSTR lpClass OPTIONAL,
IN DWORD dwOptions,
IN REGSAM samDesired,
IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL,
OUT PHKEY phkResult,
OUT LPDWORD lpdwDisposition OPTIONAL)
{
return RegpOpenOrCreateKey(hKey,
lpSubKey,
TRUE,
(dwOptions & REG_OPTION_VOLATILE) != 0,
phkResult);
}
LONG WINAPI
@ -308,7 +300,7 @@ RegpOpenOrCreateValue(
Status = CmiScanForValueKey(
ParentKey->RegistryHive,
ParentKey->KeyCell,
ParentKey->KeyCellOffset,
&ValueString,
ValueCell,
ValueCellOffset);
@ -316,7 +308,6 @@ RegpOpenOrCreateValue(
{
Status = CmiAddValueKey(
ParentKey->RegistryHive,
ParentKey->KeyCell,
ParentKey->KeyCellOffset,
&ValueString,
ValueCell,
@ -428,9 +419,6 @@ RegSetValueExW(
HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCellOffset, FALSE);
}
if (cbData > Key->KeyCell->MaxValueDataLen)
Key->KeyCell->MaxValueDataLen = cbData;
HvMarkCellDirty(&Key->RegistryHive->Hive, Key->KeyCellOffset, FALSE);
DPRINT("Return status 0x%08x\n", Status);
@ -482,27 +470,46 @@ ConnectRegistry(
IN LPCWSTR Path)
{
NTSTATUS Status;
PREPARSE_POINT ReparsePoint;
PMEMKEY NewKey;
LONG rc;
ReparsePoint = (PREPARSE_POINT)malloc(sizeof(REPARSE_POINT));
if (!ReparsePoint)
return FALSE;
Status = CmiInitializeTempHive(HiveToConnect);
if (!NT_SUCCESS(Status))
{
DPRINT1("CmiInitializeTempHive() failed with status 0x%08x\n", Status);
free(ReparsePoint);
return FALSE;
}
/* Create key */
rc = RegCreateKeyW(
rc = RegCreateKeyExW(
RootKey,
Path,
(PHKEY)&NewKey);
0,
NULL,
REG_OPTION_VOLATILE,
0,
NULL,
(PHKEY)&NewKey,
NULL);
if (rc != ERROR_SUCCESS)
{
free(ReparsePoint);
return FALSE;
}
ReparsePoint->SourceHive = NewKey->RegistryHive;
ReparsePoint->SourceKeyCellOffset = NewKey->KeyCellOffset;
NewKey->RegistryHive = HiveToConnect;
NewKey->KeyCellOffset = HiveToConnect->Hive.BaseBlock->RootCell;
NewKey->KeyCell = (PCM_KEY_NODE)HvGetCell (&HiveToConnect->Hive, NewKey->KeyCellOffset);
ReparsePoint->DestinationHive = NewKey->RegistryHive;
ReparsePoint->DestinationKeyCellOffset = NewKey->KeyCellOffset;
InsertTailList(&CmiReparsePointsHead, &ReparsePoint->ListEntry);
return TRUE;
}
@ -513,9 +520,11 @@ RegInitializeRegistry(VOID)
{
UNICODE_STRING RootKeyName = RTL_CONSTANT_STRING(L"\\");
NTSTATUS Status;
HKEY ControlSetKey;
PMEMKEY ControlSetKey, CurrentControlSetKey;
PREPARSE_POINT ReparsePoint;
InitializeListHead(&CmiHiveListHead);
InitializeListHead(&CmiReparsePointsHead);
Status = CmiInitializeTempHive(&RootHive);
if (!NT_SUCCESS(Status))
@ -526,8 +535,7 @@ RegInitializeRegistry(VOID)
RootKey = CreateInMemoryStructure(
&RootHive,
RootHive.Hive.BaseBlock->RootCell,
&RootKeyName);
RootHive.Hive.BaseBlock->RootCell);
/* Create DEFAULT key */
ConnectRegistry(
@ -563,7 +571,27 @@ RegInitializeRegistry(VOID)
RegCreateKeyW(
NULL,
L"Registry\\Machine\\SYSTEM\\ControlSet001",
&ControlSetKey);
(HKEY*)&ControlSetKey);
/* Create 'CurrentControlSet' key */
RegCreateKeyExW(
NULL,
L"Registry\\Machine\\SYSTEM\\CurrentControlSet",
0,
NULL,
REG_OPTION_VOLATILE,
0,
NULL,
(HKEY*)&CurrentControlSetKey,
NULL);
/* Connect 'CurrentControlSet' to 'ControlSet001' */
ReparsePoint = (PREPARSE_POINT)malloc(sizeof(REPARSE_POINT));
ReparsePoint->SourceHive = CurrentControlSetKey->RegistryHive;
ReparsePoint->SourceKeyCellOffset = CurrentControlSetKey->KeyCellOffset;
ReparsePoint->DestinationHive = ControlSetKey->RegistryHive;
ReparsePoint->DestinationKeyCellOffset = ControlSetKey->KeyCellOffset;
InsertTailList(&CmiReparsePointsHead, &ReparsePoint->ListEntry);
}
VOID

View file

@ -6,15 +6,19 @@
#pragma once
typedef struct _REPARSE_POINT
{
LIST_ENTRY ListEntry;
PCMHIVE SourceHive;
HCELL_INDEX SourceKeyCellOffset;
PCMHIVE DestinationHive;
HCELL_INDEX DestinationKeyCellOffset;
} REPARSE_POINT, *PREPARSE_POINT;
typedef struct _MEMKEY
{
LIST_ENTRY KeyList;
LIST_ENTRY SubKeyList;
/* Information on hard disk structure */
HCELL_INDEX KeyCellOffsetInParentHive;
HCELL_INDEX KeyCellOffset;
PCM_KEY_NODE KeyCell;
PCMHIVE RegistryHive;
} MEMKEY, *PMEMKEY;