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_