/*
* FreeLoader
*
- * Copyright (C) 2001, 2002 Eric Kohl
+ * Copyright (C) 2014 Timo Kreuzer <timo.kreuzer@reactos.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*/
#include <freeldr.h>
+#include <cmlib.h>
#include <debug.h>
-static FRLDRHKEY RootKey;
+DBG_DEFAULT_CHANNEL(REGISTRY);
+static PCMHIVE CmHive;
+static PCM_KEY_NODE RootKeyNode;
+static FRLDRHKEY CurrentControlSetKey;
-VOID
-RegInitializeRegistry (VOID)
+BOOLEAN
+RegImportBinaryHive(
+ _In_ PCHAR ChunkBase,
+ _In_ ULONG ChunkSize)
{
- /* Create root key */
- RootKey = MmHeapAlloc(sizeof(KEY));
-
- InitializeListHead(&RootKey->SubKeyList);
- InitializeListHead(&RootKey->ValueList);
- InitializeListHead(&RootKey->KeyList);
-
- RootKey->SubKeyCount = 0;
- RootKey->ValueCount = 0;
+ NTSTATUS Status;
+ TRACE("RegImportBinaryHive(%p, 0x%lx)\n", ChunkBase, ChunkSize);
+
+ /* Allocate and initialize the hive */
+ CmHive = FrLdrTempAlloc(sizeof(CMHIVE), 'eviH');
+ Status = HvInitialize(&CmHive->Hive,
+ HINIT_FLAT,
+ 0,
+ 0,
+ ChunkBase,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 1,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ FrLdrTempFree(CmHive, 'eviH');
+ ERR("Invalid hive Signature!\n");
+ return FALSE;
+ }
- RootKey->NameSize = 4;
- RootKey->Name = MmHeapAlloc(4);
- wcscpy (RootKey->Name, L"\\");
+ /* Save the root key node */
+ RootKeyNode = HvGetCell(&CmHive->Hive, CmHive->Hive.BaseBlock->RootCell);
- RootKey->DataType = 0;
- RootKey->DataSize = 0;
- RootKey->Data = NULL;
+ TRACE("RegImportBinaryHive done\n");
+ return TRUE;
+}
- /* Create 'SYSTEM' key */
- RegCreateKey (RootKey,
- L"Registry\\Machine\\SYSTEM",
- NULL);
+VOID
+RegInitializeRegistry(VOID)
+{
+ /* Nothing to do */
}
LONG
-RegInitCurrentControlSet(BOOLEAN LastKnownGood)
+RegInitCurrentControlSet(
+ _In_ BOOLEAN LastKnownGood)
{
WCHAR ControlSetKeyName[80];
FRLDRHKEY SelectKey;
FRLDRHKEY SystemKey;
- FRLDRHKEY ControlSetKey;
- FRLDRHKEY LinkKey;
ULONG CurrentSet = 0;
ULONG DefaultSet = 0;
ULONG LastKnownGoodSet = 0;
ULONG DataSize;
LONG Error;
+ TRACE("RegInitCurrentControlSet\n");
Error = RegOpenKey(NULL,
L"\\Registry\\Machine\\SYSTEM\\Select",
&SelectKey);
if (Error != ERROR_SUCCESS)
{
- DPRINTM(DPRINT_REGISTRY, "RegOpenKey() failed (Error %u)\n", (int)Error);
+ ERR("RegOpenKey() failed (Error %u)\n", (int)Error);
return Error;
}
&DataSize);
if (Error != ERROR_SUCCESS)
{
- DPRINTM(DPRINT_REGISTRY, "RegQueryValue('Default') failed (Error %u)\n", (int)Error);
+ ERR("RegQueryValue('Default') failed (Error %u)\n", (int)Error);
return Error;
}
&DataSize);
if (Error != ERROR_SUCCESS)
{
- DPRINTM(DPRINT_REGISTRY, "RegQueryValue('Default') failed (Error %u)\n", (int)Error);
+ ERR("RegQueryValue('Default') failed (Error %u)\n", (int)Error);
return Error;
}
&SystemKey);
if (Error != ERROR_SUCCESS)
{
- DPRINTM(DPRINT_REGISTRY, "RegOpenKey(SystemKey) failed (Error %lu)\n", Error);
+ ERR("RegOpenKey(SystemKey) failed (Error %lu)\n", Error);
return Error;
}
Error = RegOpenKey(SystemKey,
ControlSetKeyName,
- &ControlSetKey);
- if (Error != ERROR_SUCCESS)
- {
- DPRINTM(DPRINT_REGISTRY, "RegOpenKey(ControlSetKey) failed (Error %lu)\n", Error);
- return Error;
- }
-
- Error = RegCreateKey(SystemKey,
- L"CurrentControlSet",
- &LinkKey);
+ &CurrentControlSetKey);
if (Error != ERROR_SUCCESS)
{
- DPRINTM(DPRINT_REGISTRY, "RegCreateKey(LinkKey) failed (Error %lu)\n", Error);
- return Error;
- }
-
- Error = RegSetValue(LinkKey,
- NULL,
- REG_LINK,
- (PCHAR)&ControlSetKey,
- sizeof(PVOID));
- if (Error != ERROR_SUCCESS)
- {
- DPRINTM(DPRINT_REGISTRY, "RegSetValue(LinkKey) failed (Error %lu)\n", Error);
+ ERR("RegOpenKey(CurrentControlSetKey) failed (Error %lu)\n", Error);
return Error;
}
+ TRACE("RegInitCurrentControlSet done\n");
return ERROR_SUCCESS;
}
-
-LONG
-RegCreateKey(FRLDRHKEY ParentKey,
- PCWSTR KeyName,
- PFRLDRHKEY Key)
+static
+BOOLEAN
+GetNextPathElement(
+ _Out_ PUNICODE_STRING NextElement,
+ _Inout_ PUNICODE_STRING RemainingPath)
{
- PLIST_ENTRY Ptr;
- FRLDRHKEY SearchKey = NULL;
- FRLDRHKEY CurrentKey;
- FRLDRHKEY NewKey;
- PWCHAR p;
- PCWSTR name;
- int subkeyLength;
- int stringLength;
- ULONG NameSize;
- int CmpResult;
-
- DPRINTM(DPRINT_REGISTRY, "KeyName '%S'\n", KeyName);
-
- if (*KeyName == L'\\')
- {
- KeyName++;
- CurrentKey = RootKey;
- }
- else if (ParentKey == NULL)
+ /* Check if there are any characters left */
+ if (RemainingPath->Length < sizeof(WCHAR))
{
- CurrentKey = RootKey;
- }
- else
- {
- CurrentKey = ParentKey;
+ /* Nothing left, bail out early */
+ return FALSE;
}
- /* Check whether current key is a link */
- if (CurrentKey->DataType == REG_LINK)
- {
- CurrentKey = (FRLDRHKEY)CurrentKey->Data;
- }
+ /* The next path elements starts with the remaining path */
+ NextElement->Buffer = RemainingPath->Buffer;
- while (*KeyName != 0)
+ /* Loop until the path element ends */
+ while ((RemainingPath->Length >= sizeof(WCHAR)) &&
+ (RemainingPath->Buffer[0] != '\\'))
{
- DPRINTM(DPRINT_REGISTRY, "KeyName '%S'\n", KeyName);
+ /* Skip this character */
+ RemainingPath->Buffer++;
+ RemainingPath->Length -= sizeof(WCHAR);
+ }
- if (*KeyName == L'\\')
- KeyName++;
- p = wcschr(KeyName, L'\\');
- if ((p != NULL) && (p != KeyName))
- {
- subkeyLength = p - KeyName;
- stringLength = subkeyLength + 1;
- name = KeyName;
- }
- else
- {
- subkeyLength = wcslen(KeyName);
- stringLength = subkeyLength;
- name = KeyName;
- }
- NameSize = (subkeyLength + 1) * sizeof(WCHAR);
+ NextElement->Length = (RemainingPath->Buffer - NextElement->Buffer) * sizeof(WCHAR);
+ NextElement->MaximumLength = NextElement->Length;
- Ptr = CurrentKey->SubKeyList.Flink;
- CmpResult = 1;
- while (Ptr != &CurrentKey->SubKeyList)
- {
- DPRINTM(DPRINT_REGISTRY, "Ptr 0x%x\n", Ptr);
+ /* Check if the path element ended with a path separator */
+ if (RemainingPath->Length >= sizeof(WCHAR))
+ {
+ /* Skip the path separator */
+ ASSERT(RemainingPath->Buffer[0] == '\\');
+ RemainingPath->Buffer++;
+ RemainingPath->Length -= sizeof(WCHAR);
+ }
- SearchKey = CONTAINING_RECORD(Ptr, KEY, KeyList);
- DPRINTM(DPRINT_REGISTRY, "SearchKey 0x%x\n", SearchKey);
- DPRINTM(DPRINT_REGISTRY, "Searching '%S'\n", SearchKey->Name);
- CmpResult = _wcsnicmp(SearchKey->Name, name, subkeyLength);
+ /* Return whether we got any characters */
+ return TRUE;
+}
- if (CmpResult == 0 && SearchKey->NameSize == NameSize) break;
- else if (CmpResult == -1) break;
+static
+PCM_KEY_NODE
+RegpFindSubkeyInIndex(
+ _In_ PHHIVE Hive,
+ _In_ PCM_KEY_INDEX IndexCell,
+ _In_ PUNICODE_STRING SubKeyName)
+{
+ PCM_KEY_NODE SubKeyNode;
+ ULONG i;
+ TRACE("RegpFindSubkeyInIndex('%wZ')\n", SubKeyName);
- Ptr = Ptr->Flink;
- }
+ /* Check the cell type */
+ if ((IndexCell->Signature == CM_KEY_INDEX_ROOT) ||
+ (IndexCell->Signature == CM_KEY_INDEX_LEAF))
+ {
+ ASSERT(FALSE);
- if (CmpResult != 0)
+ /* Enumerate subindex cells */
+ for (i = 0; i < IndexCell->Count; i++)
{
- /* no key found -> create new subkey */
- NewKey = MmHeapAlloc(sizeof(KEY));
- if (NewKey == NULL) return ERROR_OUTOFMEMORY;
-
- InitializeListHead(&NewKey->SubKeyList);
- InitializeListHead(&NewKey->ValueList);
-
- NewKey->SubKeyCount = 0;
- NewKey->ValueCount = 0;
-
- NewKey->DataType = 0;
- NewKey->DataSize = 0;
- NewKey->Data = NULL;
-
- InsertTailList(Ptr, &NewKey->KeyList);
- CurrentKey->SubKeyCount++;
-
- NewKey->NameSize = NameSize;
- NewKey->Name = (PWCHAR)MmHeapAlloc(NewKey->NameSize);
- if (NewKey->Name == NULL) return ERROR_OUTOFMEMORY;
+ /* Get the subindex cell and call the function recursively */
+ PCM_KEY_INDEX SubIndexCell = HvGetCell(Hive, IndexCell->List[i]);
- memcpy(NewKey->Name, name, NewKey->NameSize - sizeof(WCHAR));
- NewKey->Name[subkeyLength] = 0;
-
- DPRINTM(DPRINT_REGISTRY, "NewKey 0x%x\n", NewKey);
- DPRINTM(DPRINT_REGISTRY, "NewKey '%S' Length %d\n", NewKey->Name, NewKey->NameSize);
-
- CurrentKey = NewKey;
+ SubKeyNode = RegpFindSubkeyInIndex(Hive, SubIndexCell, SubKeyName);
+ if (SubKeyNode != NULL)
+ {
+ return SubKeyNode;
+ }
}
- else
+ }
+ else if ((IndexCell->Signature == CM_KEY_FAST_LEAF) ||
+ (IndexCell->Signature == CM_KEY_HASH_LEAF))
+ {
+ /* Directly enumerate subkey nodes */
+ PCM_KEY_FAST_INDEX HashCell = (PCM_KEY_FAST_INDEX)IndexCell;
+ for (i = 0; i < HashCell->Count; i++)
{
- CurrentKey = SearchKey;
+ SubKeyNode = HvGetCell(Hive, HashCell->List[i].Cell);
+ ASSERT(SubKeyNode->Signature == CM_KEY_NODE_SIGNATURE);
- /* Check whether current key is a link */
- if (CurrentKey->DataType == REG_LINK)
+ TRACE(" RegpFindSubkeyInIndex: checking '%.*s'\n",
+ SubKeyNode->NameLength, SubKeyNode->Name);
+ if (CmCompareKeyName(SubKeyNode, SubKeyName, TRUE))
{
- CurrentKey = (FRLDRHKEY)CurrentKey->Data;
+ return SubKeyNode;
}
}
-
- KeyName = KeyName + stringLength;
}
-
- if (Key != NULL) *Key = CurrentKey;
-
- return ERROR_SUCCESS;
-}
-
-
-LONG
-RegDeleteKey(FRLDRHKEY Key,
- PCWSTR Name)
-{
-
- if (wcschr(Name, L'\\') != NULL) return ERROR_INVALID_PARAMETER;
-
- return ERROR_SUCCESS;
-}
-
-
-LONG
-RegEnumKey(FRLDRHKEY Key,
- ULONG Index,
- PWCHAR Name,
- ULONG* NameSize)
-{
- PLIST_ENTRY Ptr;
- FRLDRHKEY SearchKey;
- ULONG Count = 0;
- ULONG Size;
-
- Ptr = Key->SubKeyList.Flink;
- while (Ptr != &Key->SubKeyList)
+ else
{
- if (Index == Count) break;
-
- Count++;
- Ptr = Ptr->Flink;
+ ASSERT(FALSE);
}
- if (Ptr == &Key->SubKeyList) return ERROR_NO_MORE_ITEMS;
-
- SearchKey = CONTAINING_RECORD(Ptr, KEY, KeyList);
-
- DPRINTM(DPRINT_REGISTRY, "Name '%S' Length %d\n", SearchKey->Name, SearchKey->NameSize);
-
- Size = min(SearchKey->NameSize, *NameSize);
- *NameSize = Size;
- memcpy(Name, SearchKey->Name, Size);
-
- return ERROR_SUCCESS;
+ return NULL;
}
-
LONG
-RegOpenKey(FRLDRHKEY ParentKey,
- PCWSTR KeyName,
- PFRLDRHKEY Key)
+RegEnumKey(
+ _In_ FRLDRHKEY Key,
+ _In_ ULONG Index,
+ _Out_ PWCHAR Name,
+ _Inout_ ULONG* NameSize,
+ _Out_opt_ FRLDRHKEY *SubKey)
{
- PLIST_ENTRY Ptr;
- FRLDRHKEY SearchKey = NULL;
- FRLDRHKEY CurrentKey;
- PWCHAR p;
- PCWSTR name;
- int subkeyLength;
- int stringLength;
- ULONG NameSize;
-
- DPRINTM(DPRINT_REGISTRY, "KeyName '%S'\n", KeyName);
-
- *Key = NULL;
-
- if (*KeyName == L'\\')
+ PHHIVE Hive = &CmHive->Hive;
+ PCM_KEY_NODE KeyNode, SubKeyNode;
+ PCM_KEY_INDEX IndexCell;
+ PCM_KEY_FAST_INDEX HashCell;
+ TRACE("RegEnumKey(%p, %lu, %p, %p->%u)\n",
+ Key, Index, Name, NameSize, NameSize ? *NameSize : 0);
+
+ /* Get the key node */
+ KeyNode = (PCM_KEY_NODE)Key;
+ ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE);
+
+ /* Check if the index is valid */
+ if ((KeyNode->SubKeyCounts[Stable] == 0) ||
+ (Index >= KeyNode->SubKeyCounts[Stable]))
{
- KeyName++;
- CurrentKey = RootKey;
+ TRACE("RegEnumKey index out of bounds\n");
+ return ERROR_NO_MORE_ITEMS;
}
- else if (ParentKey == NULL)
+
+ /* Get the index cell */
+ IndexCell = HvGetCell(Hive, KeyNode->SubKeyLists[Stable]);
+ TRACE("IndexCell: %x, SubKeyCounts: %x\n", IndexCell, KeyNode->SubKeyCounts[Stable]);
+
+ /* Check the cell type */
+ if ((IndexCell->Signature == CM_KEY_FAST_LEAF) ||
+ (IndexCell->Signature == CM_KEY_HASH_LEAF))
{
- CurrentKey = RootKey;
+ /* Get the value cell */
+ HashCell = (PCM_KEY_FAST_INDEX)IndexCell;
+ SubKeyNode = HvGetCell(Hive, HashCell->List[Index].Cell);
}
else
{
- CurrentKey = ParentKey;
+ ASSERT(FALSE);
}
- /* Check whether current key is a link */
- if (CurrentKey->DataType == REG_LINK)
+ *NameSize = CmCopyKeyName(SubKeyNode, Name, *NameSize);
+
+ if (SubKey != NULL)
{
- CurrentKey = (FRLDRHKEY)CurrentKey->Data;
+ *SubKey = (FRLDRHKEY)SubKeyNode;
}
- while (*KeyName != 0)
- {
- DPRINTM(DPRINT_REGISTRY, "KeyName '%S'\n", KeyName);
+ TRACE("RegEnumKey done -> %u, '%.*s'\n", *NameSize, *NameSize, Name);
+ return STATUS_SUCCESS;
+}
- if (*KeyName == L'\\') KeyName++;
- p = wcschr(KeyName, L'\\');
- if ((p != NULL) && (p != KeyName))
- {
- subkeyLength = p - KeyName;
- stringLength = subkeyLength + 1;
- name = KeyName;
- }
- else
- {
- subkeyLength = wcslen(KeyName);
- stringLength = subkeyLength;
- name = KeyName;
- }
- NameSize = (subkeyLength + 1) * sizeof(WCHAR);
+LONG
+RegOpenKey(
+ _In_ FRLDRHKEY ParentKey,
+ _In_z_ PCWSTR KeyName,
+ _Out_ PFRLDRHKEY Key)
+{
+ UNICODE_STRING RemainingPath, SubKeyName;
+ UNICODE_STRING CurrentControlSet = RTL_CONSTANT_STRING(L"CurrentControlSet");
+ PHHIVE Hive = &CmHive->Hive;
+ PCM_KEY_NODE KeyNode;
+ PCM_KEY_INDEX IndexCell;
+ TRACE("RegOpenKey(%p, '%S', %p)\n", ParentKey, KeyName, Key);
- Ptr = CurrentKey->SubKeyList.Flink;
- while (Ptr != &CurrentKey->SubKeyList)
- {
- DPRINTM(DPRINT_REGISTRY, "Ptr 0x%x\n", Ptr);
+ /* Initialize the remaining path name */
+ RtlInitUnicodeString(&RemainingPath, KeyName);
- SearchKey = CONTAINING_RECORD(Ptr, KEY, KeyList);
+ /* Get the parent key node */
+ KeyNode = (PCM_KEY_NODE)ParentKey;
- DPRINTM(DPRINT_REGISTRY, "SearchKey 0x%x\n", SearchKey);
- DPRINTM(DPRINT_REGISTRY, "Searching '%S'\n", SearchKey->Name);
+ /* Check if we have a parent key */
+ if (KeyNode == NULL)
+ {
+ UNICODE_STRING SubKeyName1, SubKeyName2, SubKeyName3;
+ UNICODE_STRING RegistryPath = RTL_CONSTANT_STRING(L"Registry");
+ UNICODE_STRING MachinePath = RTL_CONSTANT_STRING(L"MACHINE");
+ UNICODE_STRING SystemPath = RTL_CONSTANT_STRING(L"SYSTEM");
+ TRACE("RegOpenKey: absolute path\n");
+
+ if ((RemainingPath.Length < sizeof(WCHAR)) ||
+ RemainingPath.Buffer[0] != '\\')
+ {
+ /* The key path is not absolute */
+ ERR("RegOpenKey: invalid path '%S' (%wZ)\n", KeyName, &RemainingPath);
+ return ERROR_PATH_NOT_FOUND;
+ }
- if (SearchKey->NameSize == NameSize &&
- _wcsnicmp(SearchKey->Name, name, subkeyLength) == 0) break;
+ /* Skip initial path separator */
+ RemainingPath.Buffer++;
+ RemainingPath.Length -= sizeof(WCHAR);
- Ptr = Ptr->Flink;
- }
+ /* Get the first 3 path elements */
+ GetNextPathElement(&SubKeyName1, &RemainingPath);
+ GetNextPathElement(&SubKeyName2, &RemainingPath);
+ GetNextPathElement(&SubKeyName3, &RemainingPath);
+ TRACE("RegOpenKey: %wZ / %wZ / %wZ\n", &SubKeyName1, &SubKeyName2, &SubKeyName3);
- if (Ptr == &CurrentKey->SubKeyList)
+ /* Check if we have the correct path */
+ if (!RtlEqualUnicodeString(&SubKeyName1, &RegistryPath, TRUE) ||
+ !RtlEqualUnicodeString(&SubKeyName2, &MachinePath, TRUE) ||
+ !RtlEqualUnicodeString(&SubKeyName3, &SystemPath, TRUE))
{
+ /* The key path is not inside HKLM\Machine\System */
+ ERR("RegOpenKey: invalid path '%S' (%wZ)\n", KeyName, &RemainingPath);
return ERROR_PATH_NOT_FOUND;
}
- else
- {
- CurrentKey = SearchKey;
-
- /* Check whether current key is a link */
- if (CurrentKey->DataType == REG_LINK)
- {
- CurrentKey = (FRLDRHKEY)CurrentKey->Data;
- }
- }
- KeyName = KeyName + stringLength;
+ /* Use the root key */
+ KeyNode = RootKeyNode;
}
- if (Key != NULL)
- *Key = CurrentKey;
+ ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE);
- return ERROR_SUCCESS;
-}
-
-
-LONG
-RegSetValue(FRLDRHKEY Key,
- PCWSTR ValueName,
- ULONG Type,
- PCSTR Data,
- ULONG DataSize)
-{
- PLIST_ENTRY Ptr;
- PVALUE Value = NULL;
-
- DPRINTM(DPRINT_REGISTRY, "Key 0x%p, ValueName '%S', Type %ld, Data 0x%p, DataSize %ld\n",
- Key, ValueName, Type, Data, DataSize);
-
- if ((ValueName == NULL) || (*ValueName == 0))
+ /* Check if this is the root key */
+ if (KeyNode == RootKeyNode)
{
- /* set default value */
- if ((Key->Data != NULL) && (Key->DataSize > sizeof(PUCHAR)))
- {
- MmHeapFree(Key->Data);
- }
+ UNICODE_STRING TempPath = RemainingPath;
- if (DataSize <= sizeof(PUCHAR))
- {
- Key->DataSize = DataSize;
- Key->DataType = Type;
- memcpy(&Key->Data, Data, DataSize);
- }
- else
+ /* Get the first path element */
+ GetNextPathElement(&SubKeyName, &TempPath);
+
+ /* Check if this is CurrentControlSet */
+ if (RtlEqualUnicodeString(&SubKeyName, &CurrentControlSet, TRUE))
{
- Key->Data = MmHeapAlloc(DataSize);
- Key->DataSize = DataSize;
- Key->DataType = Type;
- memcpy(Key->Data, Data, DataSize);
+ /* Use the CurrentControlSetKey and update the remaining path */
+ KeyNode = (PCM_KEY_NODE)CurrentControlSetKey;
+ RemainingPath = TempPath;
}
}
- else
- {
- /* set non-default value */
- Ptr = Key->ValueList.Flink;
- while (Ptr != &Key->ValueList)
- {
- Value = CONTAINING_RECORD(Ptr, VALUE, ValueList);
-
- DPRINTM(DPRINT_REGISTRY, "Value->Name '%S'\n", Value->Name);
- if (_wcsicmp(Value->Name, ValueName) == 0) break;
+ TRACE("RegOpenKey: RemainingPath '%wZ'\n", &RemainingPath);
- Ptr = Ptr->Flink;
- }
+ /* Loop while there are path elements */
+ while (GetNextPathElement(&SubKeyName, &RemainingPath))
+ {
+ TRACE("RegOpenKey: next element '%wZ'\n", &SubKeyName);
- if (Ptr == &Key->ValueList)
+ /* Check if there is any subkey */
+ if (KeyNode->SubKeyCounts[Stable] == 0)
{
- /* add new value */
- DPRINTM(DPRINT_REGISTRY, "No value found - adding new value\n");
-
- Value = (PVALUE)MmHeapAlloc(sizeof(VALUE));
- if (Value == NULL) return ERROR_OUTOFMEMORY;
-
- InsertTailList(&Key->ValueList, &Value->ValueList);
- Key->ValueCount++;
-
- Value->NameSize = (wcslen(ValueName)+1) * sizeof(WCHAR);
- Value->Name = MmHeapAlloc(Value->NameSize);
- if (Value->Name == NULL) return ERROR_OUTOFMEMORY;
- wcscpy(Value->Name, ValueName);
- Value->DataType = REG_NONE;
- Value->DataSize = 0;
- Value->Data = NULL;
+ return ERROR_PATH_NOT_FOUND;
}
- /* set new value */
- if ((Value->Data != NULL) && (Value->DataSize > sizeof(PUCHAR)))
- {
- MmHeapFree(Value->Data);
- }
+ /* Get the top level index cell */
+ IndexCell = HvGetCell(Hive, KeyNode->SubKeyLists[Stable]);
- if (DataSize <= sizeof(PUCHAR))
+ /* Get the next sub key */
+ KeyNode = RegpFindSubkeyInIndex(Hive, IndexCell, &SubKeyName);
+ if (KeyNode == NULL)
{
- Value->DataSize = DataSize;
- Value->DataType = Type;
- memcpy(&Value->Data, Data, DataSize);
- }
- else
- {
- Value->Data = MmHeapAlloc(DataSize);
- if (Value->Data == NULL) return ERROR_OUTOFMEMORY;
- Value->DataType = Type;
- Value->DataSize = DataSize;
- memcpy(Value->Data, Data, DataSize);
+
+ ERR("Did not find sub key '%wZ' (full %S)\n", &RemainingPath, KeyName);
+ return ERROR_PATH_NOT_FOUND;
}
}
- return(ERROR_SUCCESS);
-}
+ TRACE("RegOpenKey done\n");
+ *Key = (FRLDRHKEY)KeyNode;
+ return ERROR_SUCCESS;
+}
-LONG
-RegQueryValue(FRLDRHKEY Key,
- PCWSTR ValueName,
- ULONG* Type,
- PUCHAR Data,
- ULONG* DataSize)
+static
+VOID
+RepGetValueData(
+ _In_ PHHIVE Hive,
+ _In_ PCM_KEY_VALUE ValueCell,
+ _Out_opt_ ULONG* Type,
+ _Out_opt_ PUCHAR Data,
+ _Inout_opt_ ULONG* DataSize)
{
- ULONG Size;
- PLIST_ENTRY Ptr;
- PVALUE Value = NULL;
+ ULONG DataLength;
- if ((ValueName == NULL) || (*ValueName == 0))
+ /* Does the caller want the type? */
+ if (Type != NULL)
{
- /* query default value */
- if (Key->Data == NULL) return ERROR_INVALID_PARAMETER;
-
- if (Type != NULL)
- *Type = Key->DataType;
- if ((Data != NULL) && (DataSize != NULL))
- {
- if (Key->DataSize <= sizeof(PUCHAR))
- {
- Size = min(Key->DataSize, *DataSize);
- memcpy(Data, &Key->Data, Size);
- *DataSize = Size;
- }
- else
- {
- Size = min(Key->DataSize, *DataSize);
- memcpy(Data, Key->Data, Size);
- *DataSize = Size;
- }
- }
- else if ((Data == NULL) && (DataSize != NULL))
- {
- *DataSize = Key->DataSize;
- }
+ *Type = ValueCell->Type;
}
- else
- {
- /* query non-default value */
- Ptr = Key->ValueList.Flink;
- while (Ptr != &Key->ValueList)
- {
- Value = CONTAINING_RECORD(Ptr, VALUE, ValueList);
-
- DPRINTM(DPRINT_REGISTRY, "Searching for '%S'. Value name '%S'\n", ValueName, Value->Name);
- if (_wcsicmp(Value->Name, ValueName) == 0) break;
-
- Ptr = Ptr->Flink;
- }
-
- if (Ptr == &Key->ValueList) return ERROR_INVALID_PARAMETER;
+ /* Does the caller provide DataSize? */
+ if (DataSize != NULL)
+ {
+ /* Get the data length */
+ DataLength = ValueCell->DataLength & REG_DATA_SIZE_MASK;
- if (Type != NULL) *Type = Value->DataType;
- if ((Data != NULL) && (DataSize != NULL))
+ /* Does the caller want the data? */
+ if ((Data != NULL) && (*DataSize != 0))
{
- if (Value->DataSize <= sizeof(PUCHAR))
+ /* Check where the data is stored */
+ if ((DataLength <= sizeof(HCELL_INDEX)) &&
+ (ValueCell->DataLength & REG_DATA_IN_OFFSET))
{
- Size = min(Value->DataSize, *DataSize);
- memcpy(Data, &Value->Data, Size);
- *DataSize = Size;
+ /* The data member contains the data */
+ RtlCopyMemory(Data,
+ &ValueCell->Data,
+ min(*DataSize, DataLength));
}
else
{
- Size = min(Value->DataSize, *DataSize);
- memcpy(Data, Value->Data, Size);
- *DataSize = Size;
+ /* The data member contains the data cell index */
+ PVOID DataCell = HvGetCell(Hive, ValueCell->Data);
+ RtlCopyMemory(Data,
+ DataCell,
+ min(*DataSize, ValueCell->DataLength));
}
+
}
- else if ((Data == NULL) && (DataSize != NULL))
- {
- *DataSize = Value->DataSize;
- }
- }
- return ERROR_SUCCESS;
+ /* Return the actual data length */
+ *DataSize = DataLength;
+ }
}
-
LONG
-RegDeleteValue(FRLDRHKEY Key,
- PCWSTR ValueName)
+RegQueryValue(
+ _In_ FRLDRHKEY Key,
+ _In_z_ PCWSTR ValueName,
+ _Out_opt_ ULONG* Type,
+ _Out_opt_ PUCHAR Data,
+ _Inout_opt_ ULONG* DataSize)
{
- PLIST_ENTRY Ptr;
- PVALUE Value = NULL;
-
- if ((ValueName == NULL) || (*ValueName == 0))
+ PHHIVE Hive = &CmHive->Hive;
+ PCM_KEY_NODE KeyNode;
+ PCM_KEY_VALUE ValueCell;
+ PVALUE_LIST_CELL ValueListCell;
+ UNICODE_STRING ValueNameString;
+ ULONG i;
+ TRACE("RegQueryValue(%p, '%S', %p, %p, %p)\n",
+ Key, ValueName, Type, Data, DataSize);
+
+ /* Get the key node */
+ KeyNode = (PCM_KEY_NODE)Key;
+ ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE);
+
+ /* Check if there are any values */
+ if (KeyNode->ValueList.Count == 0)
{
- /* delete default value */
- if (Key->Data != NULL) MmFreeMemory(Key->Data);
- Key->Data = NULL;
- Key->DataSize = 0;
- Key->DataType = 0;
+ TRACE("RegQueryValue no values in key (%.*s)\n",
+ KeyNode->NameLength, KeyNode->Name);
+ return ERROR_INVALID_PARAMETER;
}
- else
- {
- /* delete non-default value */
- Ptr = Key->ValueList.Flink;
- while (Ptr != &Key->ValueList)
- {
- Value = CONTAINING_RECORD(Ptr, VALUE, ValueList);
- if (_wcsicmp(Value->Name, ValueName) == 0) break;
- Ptr = Ptr->Flink;
- }
+ /* Initialize value name string */
+ RtlInitUnicodeString(&ValueNameString, ValueName);
- if (Ptr == &Key->ValueList) return ERROR_INVALID_PARAMETER;
+ ValueListCell = (PVALUE_LIST_CELL)HvGetCell(Hive, KeyNode->ValueList.List);
+ TRACE("ValueListCell: %x\n", ValueListCell);
- /* delete value */
- Key->ValueCount--;
- if (Value->Name != NULL) MmFreeMemory(Value->Name);
- Value->Name = NULL;
- Value->NameSize = 0;
+ /* Loop all values */
+ for (i = 0; i < KeyNode->ValueList.Count; i++)
+ {
+ /* Get the subkey node and check the name */
+ ValueCell = HvGetCell(Hive, ValueListCell->ValueOffset[i]);
- if (Value->DataSize > sizeof(PUCHAR))
+ /* Compare the value name */
+ TRACE("checking %.*s\n", ValueCell->NameLength, ValueCell->Name);
+ if (CmCompareKeyValueName(ValueCell, &ValueNameString, TRUE))
{
- if (Value->Data != NULL) MmFreeMemory(Value->Data);
+ RepGetValueData(Hive, ValueCell, Type, Data, DataSize);
+ TRACE("RegQueryValue success\n");
+ return STATUS_SUCCESS;
}
- Value->Data = NULL;
- Value->DataSize = 0;
- Value->DataType = 0;
-
- RemoveEntryList(&Value->ValueList);
- MmFreeMemory(Value);
}
- return ERROR_SUCCESS;
+
+ TRACE("RegQueryValue value not found\n");
+ return ERROR_INVALID_PARAMETER;
}
LONG
-RegEnumValue(FRLDRHKEY Key,
- ULONG Index,
- PWCHAR ValueName,
- ULONG* NameSize,
- ULONG* Type,
- PUCHAR Data,
- ULONG* DataSize)
+RegEnumValue(
+ _In_ FRLDRHKEY Key,
+ _In_ ULONG Index,
+ _Out_ PWCHAR ValueName,
+ _Inout_ ULONG* NameSize,
+ _Out_ ULONG* Type,
+ _Out_ PUCHAR Data,
+ _Inout_ ULONG* DataSize)
{
- PLIST_ENTRY Ptr;
- PVALUE Value;
- ULONG Count = 0;
-
- if (Key->Data != NULL)
- {
- if (Index > 0)
- {
- Index--;
- }
- else
- {
- /* enumerate default value */
- if (ValueName != NULL) *ValueName = 0;
- if (Type != NULL) *Type = Key->DataType;
- if (Data != NULL)
- {
- if (Key->DataSize <= sizeof(PUCHAR))
- {
- memcpy(Data, &Key->Data, min(Key->DataSize, *DataSize));
- }
- else
- {
- memcpy(Data, Key->Data, min(Key->DataSize, *DataSize));
- }
- }
-
- if (DataSize != NULL) *DataSize = min(Key->DataSize, *DataSize);
-
- return ERROR_SUCCESS;
- }
- }
-
- Ptr = Key->ValueList.Flink;
- while (Ptr != &Key->ValueList)
+ PHHIVE Hive = &CmHive->Hive;
+ PCM_KEY_NODE KeyNode;
+ PCM_KEY_VALUE ValueCell;
+ PVALUE_LIST_CELL ValueListCell;
+ TRACE("RegEnumValue(%p, %lu, %S, %p, %p, %p, %p (%lu))\n",
+ Key, Index, ValueName, NameSize, Type, Data, DataSize, *DataSize);
+
+ /* Get the key node */
+ KeyNode = (PCM_KEY_NODE)Key;
+ ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE);
+
+ /* Check if the index is valid */
+ if ((KeyNode->ValueList.Count == 0) ||
+ (Index >= KeyNode->ValueList.Count))
{
- if (Index == Count) break;
-
- Count++;
- Ptr = Ptr->Flink;
+ ERR("RegEnumValue: index invalid\n");
+ return ERROR_NO_MORE_ITEMS;
}
- if (Ptr == &Key->ValueList) return ERROR_NO_MORE_ITEMS;
+ ValueListCell = (PVALUE_LIST_CELL)HvGetCell(Hive, KeyNode->ValueList.List);
+ TRACE("ValueListCell: %x\n", ValueListCell);
- Value = CONTAINING_RECORD(Ptr, VALUE, ValueList);
+ /* Get the value cell */
+ ValueCell = HvGetCell(Hive, ValueListCell->ValueOffset[Index]);
+ ASSERT(ValueCell != NULL);
- /* enumerate non-default value */
- if (ValueName != NULL)
+ if (NameSize != NULL)
{
- memcpy(ValueName, Value->Name, min(Value->NameSize, *NameSize));
+ *NameSize = CmCopyKeyValueName(ValueCell, ValueName, *NameSize);
}
- if (Type != NULL) *Type = Value->DataType;
- if (Data != NULL)
+ RepGetValueData(Hive, ValueCell, Type, Data, DataSize);
+
+ if (DataSize != NULL)
{
- if (Value->DataSize <= sizeof(PUCHAR))
- {
- memcpy(Data, &Value->Data, min(Value->DataSize, *DataSize));
- }
- else
+ if ((Data != NULL) && (*DataSize != 0))
{
- memcpy(Data, Value->Data, min(Value->DataSize, *DataSize));
+ RtlCopyMemory(Data,
+ &ValueCell->Data,
+ min(*DataSize, ValueCell->DataLength));
}
- }
-
- if (DataSize != NULL) *DataSize = min(Value->DataSize, *DataSize);
-
- return ERROR_SUCCESS;
-}
-
-ULONG
-RegGetSubKeyCount (FRLDRHKEY Key)
-{
- return Key->SubKeyCount;
-}
-
-
-ULONG
-RegGetValueCount (FRLDRHKEY Key)
-{
- if (Key->DataSize != 0) return Key->ValueCount + 1;
+ *DataSize = ValueCell->DataLength;
+ }
- return Key->ValueCount;
+ TRACE("RegEnumValue done\n");
+ return STATUS_SUCCESS;
}
/* EOF */