From 43e433ed3f1619adce50d48d5a9692aabae88ae3 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Sun, 12 Jan 2014 21:37:29 +0000 Subject: [PATCH] [FREELDR] Completely rewrite the registry code. The old code was first loading the system hive and parsing it, duplicating each and every key and value into a custom freeldr specific registry format and used the latter to access the data. This was extremely slow when larger hive files (the one from a normal win 2003 installation is 2.5 MB vs 250kb in reactos) were imported. The new code uses the hive data directly. It's less code, faster and uses much less memory. In the same move, refactor some mkhive code and move it into cmlib to be shared with freeldr. svn path=/trunk/; revision=61595 --- reactos/boot/freeldr/freeldr/CMakeLists.txt | 1 - .../boot/freeldr/freeldr/reactos/binhive.c | 343 ------- .../boot/freeldr/freeldr/reactos/registry.c | 959 ++++++++---------- reactos/lib/cmlib/CMakeLists.txt | 1 + reactos/lib/cmlib/cmdata.h | 2 + reactos/lib/cmlib/cmlib.h | 48 + reactos/lib/cmlib/cmtools.c | 222 ++++ reactos/tools/mkhive/cmi.c | 172 +--- reactos/tools/mkhive/mkhive.h | 7 - 9 files changed, 688 insertions(+), 1067 deletions(-) delete mode 100644 reactos/boot/freeldr/freeldr/reactos/binhive.c create mode 100644 reactos/lib/cmlib/cmtools.c diff --git a/reactos/boot/freeldr/freeldr/CMakeLists.txt b/reactos/boot/freeldr/freeldr/CMakeLists.txt index d837fd65e09..af8b8949f71 100644 --- a/reactos/boot/freeldr/freeldr/CMakeLists.txt +++ b/reactos/boot/freeldr/freeldr/CMakeLists.txt @@ -62,7 +62,6 @@ list(APPEND FREELDR_COMMON_SOURCE reactos/registry.c reactos/arcname.c reactos/archwsup.c - reactos/binhive.c ui/directui.c ui/gui.c ui/minitui.c diff --git a/reactos/boot/freeldr/freeldr/reactos/binhive.c b/reactos/boot/freeldr/freeldr/reactos/binhive.c deleted file mode 100644 index 51cb587d54a..00000000000 --- a/reactos/boot/freeldr/freeldr/reactos/binhive.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * FreeLoader - * - * Copyright (C) 2001 Rex Jolliff - * Copyright (C) 2001 Eric Kohl - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include - -#define REG_DATA_SIZE_MASK 0x7FFFFFFF -#define REG_DATA_IN_OFFSET 0x80000000 - -DBG_DEFAULT_CHANNEL(REGISTRY); - -/* FUNCTIONS ****************************************************************/ - -static -PVOID -NTAPI -CmpAllocate (SIZE_T Size, BOOLEAN Paged, ULONG Tag) -{ - return FrLdrHeapAllocateEx(FrLdrDefaultHeap, Size, Tag); -} - - -static -VOID -NTAPI -CmpFree (PVOID Ptr, IN ULONG Quota) -{ - FrLdrHeapFreeEx(FrLdrDefaultHeap, Ptr, 0); -} - -static -BOOLEAN -RegImportValue ( - PHHIVE Hive, - PCM_KEY_VALUE ValueCell, - FRLDRHKEY Key) -{ - PVOID DataCell; - PWCHAR wName; - LONG Error; - ULONG DataLength; - ULONG i; - - if (ValueCell->Signature != CM_KEY_VALUE_SIGNATURE) - { - ERR("Invalid key cell!\n"); - return FALSE; - } - - if (ValueCell->Flags & VALUE_COMP_NAME) - { - wName = FrLdrTempAlloc((ValueCell->NameLength + 1) * sizeof(WCHAR), TAG_REG_NAME); - for (i = 0; i < ValueCell->NameLength; i++) - { - wName[i] = ((PCHAR)ValueCell->Name)[i]; - } - wName[ValueCell->NameLength] = 0; - } - else - { - wName = FrLdrTempAlloc(ValueCell->NameLength + sizeof(WCHAR), TAG_REG_NAME); - memcpy(wName, ValueCell->Name, ValueCell->NameLength); - wName[ValueCell->NameLength / sizeof(WCHAR)] = 0; - } - - DataLength = ValueCell->DataLength & REG_DATA_SIZE_MASK; - - TRACE("ValueName: '%S'\n", wName); - TRACE("DataLength: %u\n", DataLength); - - if (DataLength <= sizeof(HCELL_INDEX) && (ValueCell->DataLength & REG_DATA_IN_OFFSET)) - { - Error = RegSetValue(Key, - wName, - ValueCell->Type, - (PCHAR)&ValueCell->Data, - DataLength); - if (Error != ERROR_SUCCESS) - { - ERR("RegSetValue() failed!\n"); - FrLdrTempFree(wName, TAG_REG_NAME); - return FALSE; - } - } - else - { - DataCell = (PVOID)HvGetCell(Hive, ValueCell->Data); - TRACE("DataCell: %x\n", DataCell); - - Error = RegSetValue(Key, - wName, - ValueCell->Type, - DataCell, - DataLength); - - if (Error != ERROR_SUCCESS) - { - ERR("RegSetValue() failed!\n"); - FrLdrTempFree(wName, TAG_REG_NAME); - return FALSE; - } - } - - FrLdrTempFree(wName, TAG_REG_NAME); - - return TRUE; -} - -static -BOOLEAN -RegImportSubKey( - PHHIVE Hive, - PCM_KEY_NODE KeyCell, - FRLDRHKEY ParentKey); - -static -BOOLEAN -RegImportIndexSubKey( - PHHIVE Hive, - PCM_KEY_INDEX IndexCell, - FRLDRHKEY ParentKey) -{ - ULONG i; - - TRACE("IndexCell: %x\n", IndexCell); - - /* Enumerate and add subkeys */ - if ((IndexCell->Signature == CM_KEY_INDEX_ROOT) || - (IndexCell->Signature == CM_KEY_INDEX_LEAF)) - { - for (i = 0; i < IndexCell->Count; i++) - { - PCM_KEY_INDEX SubIndexCell = HvGetCell(Hive, IndexCell->List[i]); - if (!RegImportIndexSubKey(Hive, SubIndexCell, ParentKey)) - return FALSE; - } - } - else if ((IndexCell->Signature == CM_KEY_FAST_LEAF) || - (IndexCell->Signature == CM_KEY_HASH_LEAF)) - { - PCM_KEY_FAST_INDEX HashCell = (PCM_KEY_FAST_INDEX)IndexCell; - for (i = 0; i < HashCell->Count; i++) - { - PCM_KEY_NODE SubKeyCell = HvGetCell(Hive, HashCell->List[i].Cell); - if (!RegImportSubKey(Hive, SubKeyCell, ParentKey)) - return FALSE; - } - } - else - { - ASSERT(FALSE); - } - - return TRUE; -} - - -static -BOOLEAN -RegImportSubKey( - PHHIVE Hive, - PCM_KEY_NODE KeyCell, - FRLDRHKEY ParentKey) -{ - PCM_KEY_INDEX IndexCell; - PVALUE_LIST_CELL ValueListCell; - PCM_KEY_VALUE ValueCell = NULL; - PWCHAR wName; - FRLDRHKEY SubKey; - LONG Error; - ULONG i; - - TRACE("KeyCell: %x\n", KeyCell); - TRACE("KeyCell->Signature: %x\n", KeyCell->Signature); - if (KeyCell->Signature != CM_KEY_NODE_SIGNATURE) - { - ERR("Invalid key cell Signature!\n"); - return FALSE; - } - - if (KeyCell->Flags & KEY_COMP_NAME) - { - wName = FrLdrTempAlloc((KeyCell->NameLength + 1) * sizeof(WCHAR), TAG_REG_NAME); - for (i = 0; i < KeyCell->NameLength; i++) - { - wName[i] = ((PCHAR)KeyCell->Name)[i]; - } - wName[KeyCell->NameLength] = 0; - } - else - { - wName = FrLdrTempAlloc(KeyCell->NameLength + sizeof(WCHAR), TAG_REG_NAME); - memcpy(wName, KeyCell->Name, KeyCell->NameLength); - wName[KeyCell->NameLength / sizeof(WCHAR)] = 0; - } - - TRACE("KeyName: '%S'\n", wName); - - /* Create new sub key */ - Error = RegCreateKey(ParentKey, wName, &SubKey); - FrLdrTempFree(wName, TAG_REG_NAME); - if (Error != ERROR_SUCCESS) - { - ERR("RegCreateKey() failed!\n"); - return FALSE; - } - TRACE("Subkeys: %u\n", KeyCell->SubKeyCounts); - TRACE("Values: %u\n", KeyCell->ValueList.Count); - - /* Enumerate and add values */ - if (KeyCell->ValueList.Count > 0) - { - ValueListCell = (PVALUE_LIST_CELL)HvGetCell(Hive, KeyCell->ValueList.List); - TRACE("ValueListCell: %x\n", ValueListCell); - - for (i = 0; i < KeyCell->ValueList.Count; i++) - { - TRACE("ValueOffset[%d]: %x\n", i, ValueListCell->ValueOffset[i]); - - ValueCell = (PCM_KEY_VALUE) HvGetCell (Hive, ValueListCell->ValueOffset[i]); - - TRACE("ValueCell[%d]: %x\n", i, ValueCell); - - if (!RegImportValue(Hive, ValueCell, SubKey)) - return FALSE; - } - } - - /* Enumerate and add subkeys */ - if (KeyCell->SubKeyCounts[Stable] > 0) - { - IndexCell = HvGetCell (Hive, KeyCell->SubKeyLists[Stable]); - - if (!RegImportIndexSubKey(Hive, IndexCell, SubKey)) - return FALSE; - } - - return TRUE; -} - - -BOOLEAN -RegImportBinaryHive( - PCHAR ChunkBase, - ULONG ChunkSize) -{ - PCM_KEY_NODE KeyCell; - PCM_KEY_FAST_INDEX HashCell; - PCM_KEY_NODE SubKeyCell; - FRLDRHKEY SystemKey; - ULONG i; - LONG Error; - PCMHIVE CmHive; - PHHIVE Hive; - NTSTATUS Status; - - TRACE("RegImportBinaryHive(%x, %u) called\n", ChunkBase, ChunkSize); - - CmHive = CmpAllocate(sizeof(CMHIVE), TRUE, 0); - Status = HvInitialize(&CmHive->Hive, - HINIT_FLAT, - 0, - 0, - ChunkBase, - CmpAllocate, - CmpFree, - NULL, - NULL, - NULL, - NULL, - 1, - NULL); - if (!NT_SUCCESS(Status)) - { - CmpFree(CmHive, 0); - ERR("Invalid hive Signature!\n"); - return FALSE; - } - - Hive = &CmHive->Hive; - KeyCell = (PCM_KEY_NODE)HvGetCell(Hive, Hive->BaseBlock->RootCell); - TRACE("KeyCell: %x\n", KeyCell); - TRACE("KeyCell->Signature: %x\n", KeyCell->Signature); - if (KeyCell->Signature != CM_KEY_NODE_SIGNATURE) - { - ERR("Invalid key cell Signature!\n"); - return FALSE; - } - - TRACE("Subkeys: %u\n", KeyCell->SubKeyCounts); - TRACE("Values: %u\n", KeyCell->ValueList.Count); - - /* Open 'System' key */ - Error = RegOpenKey(NULL, L"\\Registry\\Machine\\SYSTEM", &SystemKey); - if (Error != ERROR_SUCCESS) - { - ERR("Failed to open 'system' key!\n"); - return FALSE; - } - - /* Enumerate and add subkeys */ - if (KeyCell->SubKeyCounts[Stable] > 0) - { - HashCell = (PCM_KEY_FAST_INDEX)HvGetCell(Hive, KeyCell->SubKeyLists[Stable]); - TRACE("HashCell: %x\n", HashCell); - TRACE("SubKeyCounts: %x\n", KeyCell->SubKeyCounts[Stable]); - - for (i = 0; i < KeyCell->SubKeyCounts[Stable]; i++) - { - TRACE("Cell[%d]: %x\n", i, HashCell->List[i].Cell); - - SubKeyCell = (PCM_KEY_NODE)HvGetCell(Hive, HashCell->List[i].Cell); - - TRACE("SubKeyCell[%d]: %x\n", i, SubKeyCell); - - if (!RegImportSubKey(Hive, SubKeyCell, SystemKey)) - return FALSE; - } - } - - return TRUE; -} - -/* EOF */ diff --git a/reactos/boot/freeldr/freeldr/reactos/registry.c b/reactos/boot/freeldr/freeldr/reactos/registry.c index 75f44cd716b..f80ff8e9725 100644 --- a/reactos/boot/freeldr/freeldr/reactos/registry.c +++ b/reactos/boot/freeldr/freeldr/reactos/registry.c @@ -1,7 +1,7 @@ /* * FreeLoader * - * Copyright (C) 2001, 2002 Eric Kohl + * Copyright (C) 2001, 2002 Timo Kreuzer * * 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 @@ -19,53 +19,72 @@ */ #include +#include #include DBG_DEFAULT_CHANNEL(REGISTRY); -static FRLDRHKEY RootKey; +static PCMHIVE CmHive; +static PCM_KEY_NODE RootKeyNode; +static FRLDRHKEY CurrentControlSetKey; + +BOOLEAN +RegImportBinaryHive( + _In_ PCHAR ChunkBase, + _In_ ULONG ChunkSize) +{ + 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)) + { + CmpFree(CmHive, 0); + ERR("Invalid hive Signature!\n"); + return FALSE; + } + + /* Save the root key node */ + RootKeyNode = HvGetCell(&CmHive->Hive, Hive->BaseBlock->RootCell); + + TRACE("RegImportBinaryHive done\n"); + return TRUE; +} VOID -RegInitializeRegistry (VOID) +RegInitializeRegistry(VOID) { - /* Create root key */ - RootKey = FrLdrHeapAlloc(sizeof(KEY), TAG_REG_KEY); - - InitializeListHead(&RootKey->SubKeyList); - InitializeListHead(&RootKey->ValueList); - InitializeListHead(&RootKey->KeyList); - - RootKey->SubKeyCount = 0; - RootKey->ValueCount = 0; - - RootKey->NameSize = 4; - RootKey->Name = FrLdrHeapAlloc(4, TAG_REG_NAME); - wcscpy (RootKey->Name, L"\\"); - - RootKey->DataType = 0; - RootKey->DataSize = 0; - RootKey->Data = NULL; - - /* Create 'SYSTEM' key */ - RegCreateKey (RootKey, - L"Registry\\Machine\\SYSTEM", - NULL); + /* 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", @@ -132,627 +151,439 @@ RegInitCurrentControlSet(BOOLEAN LastKnownGood) Error = RegOpenKey(SystemKey, ControlSetKeyName, - &ControlSetKey); + &CurrentControlSetKey); if (Error != ERROR_SUCCESS) { - ERR("RegOpenKey(ControlSetKey) failed (Error %lu)\n", Error); - return Error; - } - - Error = RegCreateKey(SystemKey, - L"CurrentControlSet", - &LinkKey); - if (Error != ERROR_SUCCESS) - { - ERR("RegCreateKey(LinkKey) failed (Error %lu)\n", Error); - return Error; - } - - Error = RegSetValue(LinkKey, - NULL, - REG_LINK, - (PCHAR)&ControlSetKey, - sizeof(PVOID)); - if (Error != ERROR_SUCCESS) - { - ERR("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; - SIZE_T subkeyLength; - SIZE_T stringLength; - ULONG NameSize; - int CmpResult; - - TRACE("KeyName '%S'\n", KeyName); - - if (*KeyName == L'\\') + /* Check if there are any characters left */ + if (RemainingPath->Length < sizeof(WCHAR)) { - KeyName++; - CurrentKey = RootKey; - } - else if (ParentKey == NULL) - { - CurrentKey = RootKey; - } - else - { - CurrentKey = ParentKey; + /* Nothing left, bail out early */ + return FALSE; } - /* Check whether current key is a link */ - if (CurrentKey->DataType == REG_LINK) + /* The next path elements starts with the remaining path */ + NextElement->Buffer = RemainingPath->Buffer; + + /* Loop until the path element ends */ + while ((RemainingPath->Length >= sizeof(WCHAR)) && + (RemainingPath->Buffer[0] != '\\')) { - CurrentKey = (FRLDRHKEY)CurrentKey->Data; + /* Skip this character */ + RemainingPath->Buffer++; + RemainingPath->Length -= sizeof(WCHAR); } - while (*KeyName != 0) + NextElement->Length = (RemainingPath->Buffer - NextElement->Buffer) * sizeof(WCHAR); + NextElement->MaximumLength = NextElement->Length; + + /* Check if the path element ended with a path separator */ + if (RemainingPath->Length >= sizeof(WCHAR)) { - TRACE("KeyName '%S'\n", KeyName); + /* Skip the path separator */ + ASSERT(RemainingPath->Buffer[0] == '\\'); + RemainingPath->Buffer++; + RemainingPath->Length -= sizeof(WCHAR); + } - if (*KeyName == L'\\') - KeyName++; - p = wcschr(KeyName, L'\\'); - if ((p != NULL) && (p != KeyName)) + /* Return whether we got any characters */ + return TRUE; +} + +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); + + /* Check the cell type */ + if ((IndexCell->Signature == CM_KEY_INDEX_ROOT) || + (IndexCell->Signature == CM_KEY_INDEX_LEAF)) + { + ASSERT(FALSE); + + /* Enumerate subindex cells */ + for (i = 0; i < IndexCell->Count; i++) { - subkeyLength = p - KeyName; - stringLength = subkeyLength + 1; - name = KeyName; - } - else - { - subkeyLength = wcslen(KeyName); - stringLength = subkeyLength; - name = KeyName; - } - NameSize = (ULONG)((subkeyLength + 1) * sizeof(WCHAR)); + /* Get the subindex cell and call the function recursively */ + PCM_KEY_INDEX SubIndexCell = HvGetCell(Hive, IndexCell->List[i]); - Ptr = CurrentKey->SubKeyList.Flink; - CmpResult = 1; - while (Ptr != &CurrentKey->SubKeyList) - { - TRACE("Ptr 0x%x\n", Ptr); - - SearchKey = CONTAINING_RECORD(Ptr, KEY, KeyList); - TRACE("SearchKey 0x%x\n", SearchKey); - TRACE("Searching '%S'\n", SearchKey->Name); - CmpResult = _wcsnicmp(SearchKey->Name, name, subkeyLength); - - if (CmpResult == 0 && SearchKey->NameSize == NameSize) break; - else if (CmpResult == -1) break; - - Ptr = Ptr->Flink; - } - - if (CmpResult != 0) - { - /* no key found -> create new subkey */ - NewKey = FrLdrHeapAlloc(sizeof(KEY), TAG_REG_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)FrLdrHeapAlloc(NewKey->NameSize, TAG_REG_NAME); - if (NewKey->Name == NULL) return ERROR_OUTOFMEMORY; - - memcpy(NewKey->Name, name, NewKey->NameSize - sizeof(WCHAR)); - NewKey->Name[subkeyLength] = 0; - - TRACE("NewKey 0x%x\n", NewKey); - TRACE("NewKey '%S' Length %d\n", NewKey->Name, NewKey->NameSize); - - CurrentKey = NewKey; - } - else - { - CurrentKey = SearchKey; - - /* Check whether current key is a link */ - if (CurrentKey->DataType == REG_LINK) + SubKeyNode = RegpFindSubkeyInIndex(Hive, SubIndexCell, SubKeyName); + if (SubKeyNode != NULL) { - 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 ((IndexCell->Signature == CM_KEY_FAST_LEAF) || + (IndexCell->Signature == CM_KEY_HASH_LEAF)) { - if (Index == Count) break; + /* Directly enumerate subkey nodes */ + PCM_KEY_FAST_INDEX HashCell = (PCM_KEY_FAST_INDEX)IndexCell; + for (i = 0; i < HashCell->Count; i++) + { + SubKeyNode = HvGetCell(Hive, HashCell->List[i].Cell); + ASSERT(SubKeyNode->Signature == CM_KEY_NODE_SIGNATURE); - Count++; - Ptr = Ptr->Flink; - } - - if (Ptr == &Key->SubKeyList) return ERROR_NO_MORE_ITEMS; - - SearchKey = CONTAINING_RECORD(Ptr, KEY, KeyList); - - TRACE("Name '%S' Length %d\n", SearchKey->Name, SearchKey->NameSize); - - Size = min(SearchKey->NameSize, *NameSize); - *NameSize = Size; - memcpy(Name, SearchKey->Name, Size); - - return ERROR_SUCCESS; -} - - -LONG -RegOpenKey(FRLDRHKEY ParentKey, - PCWSTR KeyName, - PFRLDRHKEY Key) -{ - PLIST_ENTRY Ptr; - FRLDRHKEY SearchKey = NULL; - FRLDRHKEY CurrentKey; - PWCHAR p; - PCWSTR name; - SIZE_T subkeyLength; - SIZE_T stringLength; - ULONG NameSize; - - TRACE("KeyName '%S'\n", KeyName); - - *Key = NULL; - - if (*KeyName == L'\\') - { - KeyName++; - CurrentKey = RootKey; - } - else if (ParentKey == NULL) - { - CurrentKey = RootKey; + TRACE(" RegpFindSubkeyInIndex: checking '%.*s'\n", + SubKeyNode->NameLength, SubKeyNode->Name); + if (CmCompareKeyName(SubKeyNode, SubKeyName, TRUE)) + { + return SubKeyNode; + } + } } else { - CurrentKey = ParentKey; + ASSERT(FALSE); } - /* Check whether current key is a link */ - if (CurrentKey->DataType == REG_LINK) + return NULL; +} + +// FIXME: optionally return the subkey node/handle as optimization +LONG +RegEnumKey( + _In_ FRLDRHKEY Key, + _In_ ULONG Index, + _Out_ PWCHAR Name, + _Inout_ ULONG* NameSize) +{ + 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])) { - CurrentKey = (FRLDRHKEY)CurrentKey->Data; + TRACE("RegEnumKey index out of bounds\n"); + return ERROR_NO_MORE_ITEMS; } - while (*KeyName != 0) + /* 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)) { - TRACE("KeyName '%S'\n", KeyName); + /* Get the value cell */ + HashCell = (PCM_KEY_FAST_INDEX)IndexCell; + SubKeyNode = HvGetCell(Hive, HashCell->List[Index].Cell); + } + else + { + ASSERT(FALSE); + } - if (*KeyName == L'\\') KeyName++; - p = wcschr(KeyName, L'\\'); - if ((p != NULL) && (p != KeyName)) + *NameSize = CmCopyKeyName(SubKeyNode, Name, *NameSize); + + TRACE("RegEnumKey done -> %u, '%.*s'\n", *NameSize, *NameSize, Name); + return STATUS_SUCCESS; +} + +LONG +RegOpenKey( + _In_ FRLDRHKEY ParentKey, + _In_z_ PCWSTR KeyName, + _Out_ PFRLDRHKEY Key) +{ + UNICODE_STRING RemainingPath, SubKeyName; + UNICODE_STRING RegistryStartPath = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\SYSTEM"); + 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); + + /* Initialize the remaining path name */ + RtlInitUnicodeString(&RemainingPath, KeyName); + + /* Get the parent key node */ + KeyNode = (PCM_KEY_NODE)ParentKey; + + /* 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] != '\\') { - subkeyLength = p - KeyName; - stringLength = subkeyLength + 1; - name = KeyName; - } - else - { - subkeyLength = wcslen(KeyName); - stringLength = subkeyLength; - name = KeyName; - } - NameSize = (ULONG)((subkeyLength + 1) * sizeof(WCHAR)); - - Ptr = CurrentKey->SubKeyList.Flink; - while (Ptr != &CurrentKey->SubKeyList) - { - TRACE("Ptr 0x%x\n", Ptr); - - SearchKey = CONTAINING_RECORD(Ptr, KEY, KeyList); - - TRACE("SearchKey 0x%x\n", SearchKey); - TRACE("Searching '%S'\n", SearchKey->Name); - - if (SearchKey->NameSize == NameSize && - _wcsnicmp(SearchKey->Name, name, subkeyLength) == 0) break; - - Ptr = Ptr->Flink; + /* The key path is not absolute */ + ERR("RegOpenKey: invalid path '%S' (%wZ)\n", KeyName, &RemainingPath); + return ERROR_PATH_NOT_FOUND; } - if (Ptr == &CurrentKey->SubKeyList) + /* Skip initial path separator */ + RemainingPath.Buffer++; + RemainingPath.Length -= sizeof(WCHAR); + + /* Get the first 3 path elements */ + GetNextPathElement(&SubKeyName1, &RemainingPath); + GetNextPathElement(&SubKeyName2, &RemainingPath); + GetNextPathElement(&SubKeyName3, &RemainingPath); + TRACE("RegOpenKey: %wZ / %wZ / %wZ\n", &SubKeyName1, &SubKeyName2, &SubKeyName3); + + /* 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; + } + + /* Use the root key */ + KeyNode = RootKeyNode; + } + + ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE); + + /* Check if this is the root key */ + if (KeyNode == RootKeyNode) + { + UNICODE_STRING TempPath = RemainingPath; + + /* Get the first path element */ + GetNextPathElement(&SubKeyName, &TempPath); + + /* Check if this is CurrentControlSet */ + if (RtlEqualUnicodeString(&SubKeyName, &CurrentControlSet, TRUE)) + { + /* Use the CurrentControlSetKey and update the remaining path */ + KeyNode = (PCM_KEY_NODE)CurrentControlSetKey; + RemainingPath = TempPath; + } + } + + TRACE("RegOpenKey: RemainingPath '%wZ'\n", &RemainingPath); + + /* Loop while there are path elements */ + while (GetNextPathElement(&SubKeyName, &RemainingPath)) + { + TRACE("RegOpenKey: next element '%wZ'\n", &SubKeyName); + + /* Check if there is any subkey */ + if (KeyNode->SubKeyCounts[Stable] == 0) { return ERROR_PATH_NOT_FOUND; } - else + + /* Get the top level index cell */ + IndexCell = HvGetCell(Hive, KeyNode->SubKeyLists[Stable]); + + /* Get the next sub key */ + KeyNode = RegpFindSubkeyInIndex(Hive, IndexCell, &SubKeyName); + if (KeyNode == NULL) { - CurrentKey = SearchKey; - /* Check whether current key is a link */ - if (CurrentKey->DataType == REG_LINK) - { - CurrentKey = (FRLDRHKEY)CurrentKey->Data; - } + ERR("Did not find sub key '%wZ' (full %S)\n", &RemainingPath, KeyName); + return ERROR_PATH_NOT_FOUND; } - - KeyName = KeyName + stringLength; } - if (Key != NULL) - *Key = CurrentKey; - + TRACE("RegOpenKey done\n"); + *Key = (FRLDRHKEY)KeyNode; return ERROR_SUCCESS; } - -LONG -RegSetValue(FRLDRHKEY Key, - PCWSTR ValueName, - ULONG Type, - PCSTR 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) { - PLIST_ENTRY Ptr; - PVALUE Value = NULL; + ULONG DataLength; - TRACE("Key 0x%p, ValueName '%S', Type %ld, Data 0x%p, DataSize %ld\n", - Key, ValueName, Type, Data, DataSize); - - if ((ValueName == NULL) || (*ValueName == 0)) + /* Does the caller want the type? */ + if (Type != NULL) { - /* set default value */ - if ((Key->Data != NULL) && (Key->DataSize > sizeof(PUCHAR))) - { - FrLdrHeapFree(Key->Data, TAG_REG_KEY_DATA); - } - - if (DataSize <= sizeof(PUCHAR)) - { - Key->DataSize = DataSize; - Key->DataType = Type; - memcpy(&Key->Data, Data, DataSize); - } - else - { - Key->Data = FrLdrHeapAlloc(DataSize, TAG_REG_KEY_DATA); - Key->DataSize = DataSize; - Key->DataType = Type; - memcpy(Key->Data, Data, DataSize); - } + *Type = ValueCell->Type; } - else + + /* Does the caller provide DataSize? */ + if (DataSize != NULL) { - /* set non-default value */ - Ptr = Key->ValueList.Flink; - while (Ptr != &Key->ValueList) + /* Get the data length */ + DataLength = ValueCell->DataLength & REG_DATA_SIZE_MASK; + + /* Does the caller want the data? */ + if ((Data != NULL) && (*DataSize != 0)) { - Value = CONTAINING_RECORD(Ptr, VALUE, ValueList); - - TRACE("Value->Name '%S'\n", Value->Name); - - if (_wcsicmp(Value->Name, ValueName) == 0) break; - - Ptr = Ptr->Flink; - } - - if (Ptr == &Key->ValueList) - { - /* add new value */ - TRACE("No value found - adding new value\n"); - - Value = (PVALUE)FrLdrHeapAlloc(sizeof(VALUE), TAG_REG_VALUE); - if (Value == NULL) return ERROR_OUTOFMEMORY; - - InsertTailList(&Key->ValueList, &Value->ValueList); - Key->ValueCount++; - - Value->NameSize = (ULONG)(wcslen(ValueName)+1) * sizeof(WCHAR); - Value->Name = FrLdrHeapAlloc(Value->NameSize, TAG_REG_NAME); - if (Value->Name == NULL) return ERROR_OUTOFMEMORY; - wcscpy(Value->Name, ValueName); - Value->DataType = REG_NONE; - Value->DataSize = 0; - Value->Data = NULL; - } - - /* set new value */ - if ((Value->Data != NULL) && (Value->DataSize > sizeof(PUCHAR))) - { - FrLdrHeapFree(Value->Data, TAG_REG_KEY_DATA); - } - - if (DataSize <= sizeof(PUCHAR)) - { - Value->DataSize = DataSize; - Value->DataType = Type; - memcpy(&Value->Data, Data, DataSize); - } - else - { - Value->Data = FrLdrHeapAlloc(DataSize, TAG_REG_KEY_DATA); - if (Value->Data == NULL) return ERROR_OUTOFMEMORY; - Value->DataType = Type; - Value->DataSize = DataSize; - memcpy(Value->Data, Data, DataSize); - } - } - return(ERROR_SUCCESS); -} - - -LONG -RegQueryValue(FRLDRHKEY Key, - PCWSTR ValueName, - ULONG* Type, - PUCHAR Data, - ULONG* DataSize) -{ - ULONG Size; - PLIST_ENTRY Ptr; - PVALUE Value = NULL; - - if ((ValueName == NULL) || (*ValueName == 0)) - { - /* 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)) + /* Check where the data is stored */ + if ((DataLength <= sizeof(HCELL_INDEX)) && + (ValueCell->DataLength & REG_DATA_IN_OFFSET)) { - Size = min(Key->DataSize, *DataSize); - memcpy(Data, &Key->Data, Size); - *DataSize = Size; + /* The data member contains the data */ + RtlCopyMemory(Data, + &ValueCell->Data, + min(*DataSize, DataLength)); } else { - Size = min(Key->DataSize, *DataSize); - memcpy(Data, Key->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 = Key->DataSize; - } + + /* Return the actual data length */ + *DataSize = DataLength; } - else +} + +LONG +RegQueryValue( + _In_ FRLDRHKEY Key, + _In_z_ PCWSTR ValueName, + _Out_opt_ ULONG* Type, + _Out_opt_ PUCHAR Data, + _Inout_opt_ ULONG* DataSize) +{ + 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) { - /* query non-default value */ - Ptr = Key->ValueList.Flink; - while (Ptr != &Key->ValueList) + TRACE("RegQueryValue no values in key (%.*s)\n", + KeyNode->NameLength, KeyNode->Name); + return ERROR_INVALID_PARAMETER; + } + + /* Initialize value name string */ + RtlInitUnicodeString(&ValueNameString, ValueName); + + ValueListCell = (PVALUE_LIST_CELL)HvGetCell(Hive, KeyNode->ValueList.List); + TRACE("ValueListCell: %x\n", ValueListCell); + + /* 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]); + + /* Compare the value name */ + TRACE("checking %.*s\n", ValueCell->NameLength, ValueCell->Name); + if (CmCompareKeyValueName(ValueCell, &ValueNameString, TRUE)) { - Value = CONTAINING_RECORD(Ptr, VALUE, ValueList); - - TRACE("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; - - if (Type != NULL) *Type = Value->DataType; - if ((Data != NULL) && (DataSize != NULL)) - { - if (Value->DataSize <= sizeof(PUCHAR)) - { - Size = min(Value->DataSize, *DataSize); - memcpy(Data, &Value->Data, Size); - *DataSize = Size; - } - else - { - Size = min(Value->DataSize, *DataSize); - memcpy(Data, Value->Data, Size); - *DataSize = Size; - } - } - else if ((Data == NULL) && (DataSize != NULL)) - { - *DataSize = Value->DataSize; + RepGetValueData(Hive, ValueCell, Type, Data, DataSize); + TRACE("RegQueryValue success\n"); + return STATUS_SUCCESS; } } - return ERROR_SUCCESS; + TRACE("RegQueryValue value not found\n"); + return ERROR_INVALID_PARAMETER; } LONG -RegDeleteValue(FRLDRHKEY Key, - PCWSTR ValueName) +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 = NULL; + 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); - if ((ValueName == NULL) || (*ValueName == 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->ValueList.Count == 0) || + (Index >= KeyNode->ValueList.Count)) { - /* delete default value */ - if (Key->Data != NULL) FrLdrHeapFree(Key->Data, TAG_REG_KEY_DATA); - Key->Data = NULL; - Key->DataSize = 0; - Key->DataType = 0; - } - 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; - } - - if (Ptr == &Key->ValueList) return ERROR_INVALID_PARAMETER; - - /* delete value */ - Key->ValueCount--; - if (Value->Name != NULL) FrLdrHeapFree(Value->Name, TAG_REG_NAME); - Value->Name = NULL; - Value->NameSize = 0; - - if (Value->DataSize > sizeof(PUCHAR)) - { - if (Value->Data != NULL) FrLdrHeapFree(Value->Data, TAG_REG_KEY_DATA); - } - Value->Data = NULL; - Value->DataSize = 0; - Value->DataType = 0; - - RemoveEntryList(&Value->ValueList); - FrLdrHeapFree(Value, TAG_REG_VALUE); - } - return ERROR_SUCCESS; -} - - -LONG -RegEnumValue(FRLDRHKEY Key, - ULONG Index, - PWCHAR ValueName, - ULONG* NameSize, - ULONG* Type, - PUCHAR Data, - 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; - } + ERR("RegEnumValue: index invalid\n"); + return ERROR_NO_MORE_ITEMS; } - Ptr = Key->ValueList.Flink; - while (Ptr != &Key->ValueList) - { - if (Index == Count) break; + ValueListCell = (PVALUE_LIST_CELL)HvGetCell(Hive, KeyNode->ValueList.List); + TRACE("ValueListCell: %x\n", ValueListCell); - Count++; - Ptr = Ptr->Flink; + /* Get the value cell */ + ValueCell = HvGetCell(Hive, ValueListCell->ValueOffset[Index]); + ASSERT(ValueCell != NULL); + + if (NameSize != NULL) + { + *NameSize = CmCopyKeyValueName(ValueCell, ValueName, *NameSize); } - if (Ptr == &Key->ValueList) return ERROR_NO_MORE_ITEMS; + RepGetValueData(Hive, ValueCell, Type, Data, DataSize); - Value = CONTAINING_RECORD(Ptr, VALUE, ValueList); - - /* enumerate non-default value */ - if (ValueName != NULL) + if (DataSize != NULL) { - memcpy(ValueName, Value->Name, min(Value->NameSize, *NameSize)); - } - if (Type != NULL) *Type = Value->DataType; - - if (Data != NULL) - { - if (Value->DataSize <= sizeof(PUCHAR)) + if ((Data != NULL) && (*DataSize != 0)) { - memcpy(Data, &Value->Data, min(Value->DataSize, *DataSize)); - } - else - { - memcpy(Data, Value->Data, min(Value->DataSize, *DataSize)); + RtlCopyMemory(Data, + &ValueCell->Data, + min(*DataSize, ValueCell->DataLength)); } + + *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; - - return Key->ValueCount; + TRACE("RegEnumValue done\n"); + return STATUS_SUCCESS; } /* EOF */ diff --git a/reactos/lib/cmlib/CMakeLists.txt b/reactos/lib/cmlib/CMakeLists.txt index 707707b28a2..a692c3a3653 100644 --- a/reactos/lib/cmlib/CMakeLists.txt +++ b/reactos/lib/cmlib/CMakeLists.txt @@ -6,6 +6,7 @@ add_definitions( list(APPEND SOURCE cminit.c + cmtools.c hivebin.c hivecell.c hiveinit.c diff --git a/reactos/lib/cmlib/cmdata.h b/reactos/lib/cmlib/cmdata.h index a717f73f50f..393efd4861a 100644 --- a/reactos/lib/cmlib/cmdata.h +++ b/reactos/lib/cmlib/cmdata.h @@ -11,6 +11,8 @@ #define REG_INIT_HASH_TABLE_SIZE 3 #define REG_EXTEND_HASH_TABLE_SIZE 4 #define REG_VALUE_LIST_CELL_MULTIPLE 4 +#define REG_DATA_SIZE_MASK 0x7FFFFFFF +#define REG_DATA_IN_OFFSET 0x80000000 // // Key Types diff --git a/reactos/lib/cmlib/cmlib.h b/reactos/lib/cmlib/cmlib.h index d0b76710130..a5a0b473abb 100644 --- a/reactos/lib/cmlib/cmlib.h +++ b/reactos/lib/cmlib/cmlib.h @@ -15,6 +15,11 @@ #include #include + #ifdef _WIN32 + #define strncasecmp _strnicmp + #define strcasecmp _stricmp + #endif//_WIN32 + // Definitions copied from // We only want to include host headers, so we define them manually #define STATUS_SUCCESS ((NTSTATUS)0x00000000) @@ -312,6 +317,49 @@ VOID CMAPI CmPrepareHive( PHHIVE RegistryHive); +BOOLEAN +NTAPI +CmCompareHash( + IN PCUNICODE_STRING KeyName, + IN PCHAR HashString, + IN BOOLEAN CaseInsensitive); + +BOOLEAN +NTAPI +CmComparePackedNames( + IN PCUNICODE_STRING Name, + IN PVOID NameBuffer, + IN USHORT NameBufferSize, + IN BOOLEAN NamePacked, + IN BOOLEAN CaseInsensitive); + +BOOLEAN +NTAPI +CmCompareKeyName( + IN PCM_KEY_NODE KeyCell, + IN PCUNICODE_STRING KeyName, + IN BOOLEAN CaseInsensitive); + +BOOLEAN +NTAPI +CmCompareKeyValueName( + IN PCM_KEY_VALUE ValueCell, + IN PCUNICODE_STRING KeyName, + IN BOOLEAN CaseInsensitive); + +ULONG +NTAPI +CmCopyKeyName( + IN PCM_KEY_NODE KeyNode, + _Out_ PWCHAR KeyNameBuffer, + _Inout_ ULONG BufferLength); + +ULONG +NTAPI +CmCopyKeyValueName( + _In_ PCM_KEY_VALUE ValueCell, + _Out_ PWCHAR ValueNameBuffer, + _Inout_ ULONG BufferLength); BOOLEAN CMAPI diff --git a/reactos/lib/cmlib/cmtools.c b/reactos/lib/cmlib/cmtools.c new file mode 100644 index 00000000000..8c948462cdc --- /dev/null +++ b/reactos/lib/cmlib/cmtools.c @@ -0,0 +1,222 @@ +/* + * PROJECT: registry manipulation library + * LICENSE: GPL - See COPYING in the top level directory + * COPYRIGHT: Copyright 2005 Filip Navara + * Copyright 2001 - 2005 Eric Kohl + */ + +#include "cmlib.h" +#define NDEBUG +#include + +BOOLEAN +NTAPI +CmCompareHash( + IN PCUNICODE_STRING KeyName, + IN PCHAR HashString, + IN BOOLEAN CaseInsensitive) +{ + CHAR Buffer[4]; + + Buffer[0] = (KeyName->Length >= 2) ? (CHAR)KeyName->Buffer[0] : 0; + Buffer[1] = (KeyName->Length >= 4) ? (CHAR)KeyName->Buffer[1] : 0; + Buffer[2] = (KeyName->Length >= 6) ? (CHAR)KeyName->Buffer[2] : 0; + Buffer[3] = (KeyName->Length >= 8) ? (CHAR)KeyName->Buffer[3] : 0; + + if (CaseInsensitive) + { + return (strncasecmp(Buffer, HashString, 4) == 0); + } + else + { + return (strncmp(Buffer, HashString, 4) == 0); + } +} + +BOOLEAN +NTAPI +CmComparePackedNames( + IN PCUNICODE_STRING CompareName, + IN PVOID Name, + IN USHORT NameLength, + IN BOOLEAN NamePacked, + IN BOOLEAN CaseInsensitive) +{ + ULONG i; + + if (NamePacked == TRUE) + { + PUCHAR PackedName = (PUCHAR)Name; + + if (CompareName->Length != NameLength * sizeof(WCHAR)) + { + //DPRINT1("Length doesn'T match %lu / %lu\n", CompareName->Length, NameLength); + return FALSE; + } + + if (CaseInsensitive) + { + for (i = 0; i < CompareName->Length / sizeof(WCHAR); i++) + { + //DbgPrint("%c/%c,", + // RtlUpcaseUnicodeChar(CompareName->Buffer[i]), + // RtlUpcaseUnicodeChar(PackedName[i])); + if (RtlUpcaseUnicodeChar(CompareName->Buffer[i]) != + RtlUpcaseUnicodeChar(PackedName[i])) + { + //DbgPrint("\nFailed!\n"); + return FALSE; + } + } + //DbgPrint("\nSuccess!\n"); + } + else + { + for (i = 0; i < CompareName->Length / sizeof(WCHAR); i++) + { + if (CompareName->Buffer[i] != PackedName[i]) + return FALSE; + } + } + + } + else + { + PWCHAR UnicodeName = (PWCHAR)Name; + + if (CompareName->Length != NameLength) + return FALSE; + + if (CaseInsensitive) + { + for (i = 0; i < CompareName->Length / sizeof(WCHAR); i++) + { + if (RtlUpcaseUnicodeChar(CompareName->Buffer[i]) != + RtlUpcaseUnicodeChar(UnicodeName[i])) + return FALSE; + } + } + else + { + for (i = 0; i < CompareName->Length / sizeof(WCHAR); i++) + { + if (CompareName->Buffer[i] != UnicodeName[i]) + return FALSE; + } + } + } + + return TRUE; +} + + +BOOLEAN +NTAPI +CmCompareKeyName( + IN PCM_KEY_NODE KeyNode, + IN PCUNICODE_STRING KeyName, + IN BOOLEAN CaseInsensitive) +{ + ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE); + return CmComparePackedNames(KeyName, + KeyNode->Name, + KeyNode->NameLength, + (KeyNode->Flags & KEY_COMP_NAME) ? TRUE : FALSE, + CaseInsensitive); +} + +BOOLEAN +NTAPI +CmCompareKeyValueName( + IN PCM_KEY_VALUE ValueCell, + IN PCUNICODE_STRING ValueName, + IN BOOLEAN CaseInsensitive) +{ + ASSERT(ValueCell->Signature == CM_KEY_VALUE_SIGNATURE); + return CmComparePackedNames(ValueName, + ValueCell->Name, + ValueCell->NameLength, + (ValueCell->Flags & VALUE_COMP_NAME) ? TRUE : FALSE, + CaseInsensitive); +} + +ULONG +NTAPI +CmCopyPackedName( + _Out_ PWCHAR Buffer, + _In_ ULONG BufferLength, + _In_ PVOID Name, + _In_ USHORT NameLength, + _In_ BOOLEAN NamePacked) +{ + ULONG CharCount, i; + ASSERT(Name != 0); + ASSERT(NameLength != 0); + + if (NamePacked == TRUE) + { + NameLength *= sizeof(WCHAR); + CharCount = min(BufferLength, NameLength) / sizeof(WCHAR); + + if (Buffer != NULL) + { + PUCHAR PackedName = (PUCHAR)Name; + + for (i = 0; i < CharCount; i++) + { + Buffer[i] = PackedName[i]; + } + } + } + else + { + CharCount = min(BufferLength, NameLength) / sizeof(WCHAR); + + if (Buffer != NULL) + { + PWCHAR UnicodeName = (PWCHAR)Name; + + for (i = 0; i < CharCount; i++) + { + Buffer[i] = UnicodeName[i]; + } + } + } + + if (BufferLength >= NameLength + sizeof(UNICODE_NULL)) + { + Buffer[NameLength / sizeof(WCHAR)] = '\0'; + } + + return NameLength + sizeof(WCHAR); +} + +ULONG +NTAPI +CmCopyKeyName( + IN PCM_KEY_NODE KeyNode, + _Out_ PWCHAR KeyNameBuffer, + _Inout_ ULONG BufferLength) +{ + ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE); + return CmCopyPackedName(KeyNameBuffer, + BufferLength, + KeyNode->Name, + KeyNode->NameLength, + (KeyNode->Flags & KEY_COMP_NAME) ? TRUE : FALSE); +} + +ULONG +NTAPI +CmCopyKeyValueName( + _In_ PCM_KEY_VALUE ValueCell, + _Out_ PWCHAR ValueNameBuffer, + _Inout_ ULONG BufferLength) +{ + ASSERT(ValueCell->Signature == CM_KEY_VALUE_SIGNATURE); + return CmCopyPackedName(ValueNameBuffer, + BufferLength, + ValueCell->Name, + ValueCell->NameLength, + (ValueCell->Flags & VALUE_COMP_NAME) ? TRUE : FALSE); +} diff --git a/reactos/tools/mkhive/cmi.c b/reactos/tools/mkhive/cmi.c index d470eda4c21..df8b89475b2 100644 --- a/reactos/tools/mkhive/cmi.c +++ b/reactos/tools/mkhive/cmi.c @@ -442,82 +442,6 @@ CmiCompareHashI( return (strncasecmp(Buffer, HashString, 4) == 0); } -static BOOLEAN -CmiCompareKeyNames( - IN PCUNICODE_STRING KeyName, - IN PCM_KEY_NODE KeyCell) -{ - PWCHAR UnicodeName; - USHORT i; - - if (KeyCell->Flags & KEY_COMP_NAME) - { - if (KeyName->Length != KeyCell->NameLength * sizeof(WCHAR)) - return FALSE; - - for (i = 0; i < KeyCell->NameLength; i++) - { - if (KeyName->Buffer[i] != ((PCHAR)KeyCell->Name)[i]) - return FALSE; - } - } - else - { - if (KeyName->Length != KeyCell->NameLength) - return FALSE; - - UnicodeName = (PWCHAR)KeyCell->Name; - for (i = 0; i < KeyCell->NameLength / sizeof(WCHAR); i++) - { - if (KeyName->Buffer[i] != UnicodeName[i]) - return FALSE; - } - } - - return TRUE; -} - -static BOOLEAN -CmiCompareKeyNamesI( - IN PCUNICODE_STRING KeyName, - IN PCM_KEY_NODE KeyCell) -{ - PWCHAR UnicodeName; - USHORT i; - - DPRINT("Flags: %hx\n", KeyCell->Flags); - - if (KeyCell->Flags & KEY_COMP_NAME) - { - if (KeyName->Length != KeyCell->NameLength * sizeof(WCHAR)) - return FALSE; - - /* FIXME: use _strnicmp */ - for (i = 0; i < KeyCell->NameLength; i++) - { - if (RtlUpcaseUnicodeChar(KeyName->Buffer[i]) != - RtlUpcaseUnicodeChar(((PCHAR)KeyCell->Name)[i])) - return FALSE; - } - } - else - { - if (KeyName->Length != KeyCell->NameLength) - return FALSE; - - UnicodeName = (PWCHAR)KeyCell->Name; - /* FIXME: use _strnicmp */ - for (i = 0; i < KeyCell->NameLength / sizeof(WCHAR); i++) - { - if (RtlUpcaseUnicodeChar(KeyName->Buffer[i]) != - RtlUpcaseUnicodeChar(UnicodeName[i])) - return FALSE; - } - } - - return TRUE; -} - NTSTATUS CmiScanForSubKey( IN PCMHIVE RegistryHive, @@ -529,6 +453,7 @@ CmiScanForSubKey( { PCM_KEY_FAST_INDEX HashBlock; PCM_KEY_NODE CurSubKeyCell; + BOOLEAN CaseInsensitive; ULONG Storage; ULONG i; @@ -537,6 +462,7 @@ CmiScanForSubKey( ASSERT(RegistryHive); *pSubKeyCell = NULL; + CaseInsensitive = (Attributes & OBJ_CASE_INSENSITIVE) != 0; for (Storage = Stable; Storage < HTYPE_COUNT; Storage++) { @@ -553,40 +479,20 @@ CmiScanForSubKey( for (i = 0; i < KeyCell->SubKeyCounts[Storage]; i++) { - if (Attributes & OBJ_CASE_INSENSITIVE) - { - if ((HashBlock->List[i].HashKey == 0 - || CmiCompareHashI(SubKeyName, (PCHAR)&HashBlock->List[i].HashKey))) - { - CurSubKeyCell = (PCM_KEY_NODE)HvGetCell ( - &RegistryHive->Hive, - HashBlock->List[i].Cell); + if ((HashBlock->List[i].HashKey == 0) || + (CmCompareHash(SubKeyName, (PCHAR)&HashBlock->List[i].HashKey, CaseInsensitive))) + { + CurSubKeyCell = (PCM_KEY_NODE)HvGetCell ( + &RegistryHive->Hive, + HashBlock->List[i].Cell); - if (CmiCompareKeyNamesI(SubKeyName, CurSubKeyCell)) - { - *pSubKeyCell = CurSubKeyCell; - *pBlockOffset = HashBlock->List[i].Cell; - return STATUS_SUCCESS; - } - } - } - else - { - if ((HashBlock->List[i].HashKey == 0 - || CmiCompareHash(SubKeyName, (PCHAR)&HashBlock->List[i].HashKey))) - { - CurSubKeyCell = (PCM_KEY_NODE)HvGetCell ( - &RegistryHive->Hive, - HashBlock->List[i].Cell); - - if (CmiCompareKeyNames(SubKeyName, CurSubKeyCell)) - { - *pSubKeyCell = CurSubKeyCell; - *pBlockOffset = HashBlock->List[i].Cell; - return STATUS_SUCCESS; - } - } - } + if (CmCompareKeyName(CurSubKeyCell, SubKeyName, CaseInsensitive)) + { + *pSubKeyCell = CurSubKeyCell; + *pBlockOffset = HashBlock->List[i].Cell; + return STATUS_SUCCESS; + } + } } } @@ -754,44 +660,6 @@ CmiAddValueKey( return STATUS_SUCCESS; } -static BOOLEAN -CmiComparePackedNames( - IN PCUNICODE_STRING Name, - IN PUCHAR NameBuffer, - IN USHORT NameBufferSize, - IN BOOLEAN NamePacked) -{ - PWCHAR UNameBuffer; - ULONG i; - - if (NamePacked == TRUE) - { - if (Name->Length != NameBufferSize * sizeof(WCHAR)) - return FALSE; - - for (i = 0; i < Name->Length / sizeof(WCHAR); i++) - { - if (RtlUpcaseUnicodeChar(Name->Buffer[i]) != RtlUpcaseUnicodeChar((WCHAR)NameBuffer[i])) - return FALSE; - } - } - else - { - if (Name->Length != NameBufferSize) - return FALSE; - - UNameBuffer = (PWCHAR)NameBuffer; - - for (i = 0; i < Name->Length / sizeof(WCHAR); i++) - { - if (RtlUpcaseUnicodeChar(Name->Buffer[i]) != RtlUpcaseUnicodeChar(UNameBuffer[i])) - return FALSE; - } - } - - return TRUE; -} - NTSTATUS CmiScanForValueKey( IN PCMHIVE RegistryHive, @@ -823,11 +691,11 @@ CmiScanForValueKey( &RegistryHive->Hive, ValueListCell->ValueOffset[i]); - if (CmiComparePackedNames( - ValueName, - (PUCHAR)CurValueCell->Name, - CurValueCell->NameLength, - (BOOLEAN)((CurValueCell->Flags & VALUE_COMP_NAME) ? TRUE : FALSE))) + if (CmComparePackedNames(ValueName, + (PUCHAR)CurValueCell->Name, + CurValueCell->NameLength, + (CurValueCell->Flags & VALUE_COMP_NAME) ? TRUE : FALSE, + TRUE)) { *pValueCell = CurValueCell; *pValueCellOffset = ValueListCell->ValueOffset[i]; diff --git a/reactos/tools/mkhive/mkhive.h b/reactos/tools/mkhive/mkhive.h index 3af9e5c78f8..ecb4463697e 100644 --- a/reactos/tools/mkhive/mkhive.h +++ b/reactos/tools/mkhive/mkhive.h @@ -130,13 +130,6 @@ extern LIST_ENTRY CmiHiveListHead; #define min(a, b) (((a) < (b)) ? (a) : (b)) #endif -#ifdef _WIN32 -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#else -#include -#endif//_WIN32 - #ifndef _MSC_VER #define _In_ #define _Out_