[FREELDR]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 17 Jan 2016 01:42:11 +0000 (01:42 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 17 Jan 2016 01:42:11 +0000 (01:42 +0000)
Make FreeLdr fully using the CMLIB library. CORE-10802 #resolve
CORE-10793

svn path=/trunk/; revision=70604

reactos/boot/freeldr/freeldr/windows/registry.c
reactos/boot/freeldr/freeldr/windows/registry.h
reactos/boot/freeldr/freeldr/windows/wlregistry.c

index 0438deb..53de22f 100644 (file)
@@ -29,23 +29,46 @@ static PCMHIVE CmHive;
 static PCM_KEY_NODE RootKeyNode;
 static HKEY CurrentControlSetKey;
 
+PVOID
+NTAPI
+CmpAllocate(
+    IN SIZE_T Size,
+    IN BOOLEAN Paged,
+    IN ULONG Tag)
+{
+    UNREFERENCED_PARAMETER(Paged);
+    UNREFERENCED_PARAMETER(Tag);
+
+    return FrLdrTempAlloc(Size, Tag);
+}
+
+VOID
+NTAPI
+CmpFree(
+    IN PVOID Ptr,
+    IN ULONG Quota)
+{
+    UNREFERENCED_PARAMETER(Quota);
+    FrLdrTempFree(Ptr, 0);
+}
+
 BOOLEAN
 RegImportBinaryHive(
-    _In_ PCHAR ChunkBase,
+    _In_ PVOID ChunkBase,
     _In_ ULONG ChunkSize)
 {
     NTSTATUS Status;
     TRACE("RegImportBinaryHive(%p, 0x%lx)\n", ChunkBase, ChunkSize);
 
     /* Allocate and initialize the hive */
-    CmHive = FrLdrTempAlloc(sizeof(CMHIVE), 'eviH');
+    CmHive = CmpAllocate(sizeof(CMHIVE), FALSE, 'eviH');
     Status = HvInitialize(&CmHive->Hive,
-                          HINIT_FLAT,
+                          HINIT_FLAT, // HINIT_MEMORY_INPLACE
                           0,
                           0,
                           ChunkBase,
-                          NULL,
-                          NULL,
+                          CmpAllocate,
+                          CmpFree,
                           NULL,
                           NULL,
                           NULL,
@@ -54,24 +77,18 @@ RegImportBinaryHive(
                           NULL);
     if (!NT_SUCCESS(Status))
     {
-        FrLdrTempFree(CmHive, 'eviH');
-        ERR("Invalid hive Signature!\n");
+        CmpFree(CmHive, 0);
+        ERR("Corrupted hive %p!\n", ChunkBase);
         return FALSE;
     }
 
     /* Save the root key node */
-    RootKeyNode = HvGetCell(&CmHive->Hive, CmHive->Hive.BaseBlock->RootCell);
+    RootKeyNode = (PCM_KEY_NODE)HvGetCell(&CmHive->Hive, CmHive->Hive.BaseBlock->RootCell);
 
     TRACE("RegImportBinaryHive done\n");
     return TRUE;
 }
 
-VOID
-RegInitializeRegistry(VOID)
-{
-    /* Nothing to do */
-}
-
 LONG
 RegInitCurrentControlSet(
     _In_ BOOLEAN LastKnownGood)
@@ -203,62 +220,6 @@ GetNextPathElement(
     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++)
-        {
-            /* Get the subindex cell and call the function recursively */
-            PCM_KEY_INDEX SubIndexCell = HvGetCell(Hive, IndexCell->List[i]);
-
-            SubKeyNode = RegpFindSubkeyInIndex(Hive, SubIndexCell, SubKeyName);
-            if (SubKeyNode != NULL)
-            {
-                return SubKeyNode;
-            }
-        }
-    }
-    else if ((IndexCell->Signature == CM_KEY_FAST_LEAF) ||
-             (IndexCell->Signature == CM_KEY_HASH_LEAF))
-    {
-        /* Directly enumerate subkey nodes */
-        PCM_KEY_FAST_INDEX HashCell = (PCM_KEY_FAST_INDEX)IndexCell;
-        for (i = 0; i < HashCell->Count; i++)
-        {
-            SubKeyNode = HvGetCell(Hive, HashCell->List[i].Cell);
-            ASSERT(SubKeyNode->Signature == CM_KEY_NODE_SIGNATURE);
-
-            TRACE(" RegpFindSubkeyInIndex: checking '%.*s'\n",
-                  SubKeyNode->NameLength, SubKeyNode->Name);
-            if (CmCompareKeyName(SubKeyNode, SubKeyName, TRUE))
-            {
-                return SubKeyNode;
-            }
-        }
-    }
-    else
-    {
-        ASSERT(FALSE);
-    }
-
-    return NULL;
-}
-
 LONG
 RegEnumKey(
     _In_ HKEY Key,
@@ -269,8 +230,9 @@ RegEnumKey(
 {
     PHHIVE Hive = &CmHive->Hive;
     PCM_KEY_NODE KeyNode, SubKeyNode;
-    PCM_KEY_INDEX IndexCell;
-    PCM_KEY_FAST_INDEX HashCell;
+    HCELL_INDEX CellIndex;
+    USHORT NameLength;
+
     TRACE("RegEnumKey(%p, %lu, %p, %p->%u)\n",
           Key, Index, Name, NameSize, NameSize ? *NameSize : 0);
 
@@ -278,40 +240,52 @@ RegEnumKey(
     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]))
+    CellIndex = CmpFindSubKeyByNumber(Hive, KeyNode, Index);
+    if (CellIndex == HCELL_NIL)
     {
-        TRACE("RegEnumKey index out of bounds\n");
+        TRACE("RegEnumKey index out of bounds (%d) in key (%.*s)\n",
+              Index, KeyNode->NameLength, KeyNode->Name);
         return ERROR_NO_MORE_ITEMS;
     }
 
-    /* Get the index cell */
-    IndexCell = HvGetCell(Hive, KeyNode->SubKeyLists[Stable]);
-    TRACE("IndexCell: %x, SubKeyCounts: %x\n", IndexCell, KeyNode->SubKeyCounts[Stable]);
+    /* Get the value cell */
+    SubKeyNode = (PCM_KEY_NODE)HvGetCell(Hive, CellIndex);
+    ASSERT(SubKeyNode != NULL);
+    ASSERT(SubKeyNode->Signature == CM_KEY_NODE_SIGNATURE);
 
-    /* Check the cell type */
-    if ((IndexCell->Signature == CM_KEY_FAST_LEAF) ||
-        (IndexCell->Signature == CM_KEY_HASH_LEAF))
+    if (SubKeyNode->Flags & KEY_COMP_NAME)
     {
-        /* Get the value cell */
-        HashCell = (PCM_KEY_FAST_INDEX)IndexCell;
-        SubKeyNode = HvGetCell(Hive, HashCell->List[Index].Cell);
+        NameLength = CmpCompressedNameSize(SubKeyNode->Name, SubKeyNode->NameLength);
+
+        /* Compressed name */
+        CmpCopyCompressedName(Name,
+                              *NameSize,
+                              SubKeyNode->Name,
+                              SubKeyNode->NameLength);
     }
     else
     {
-        ASSERT(FALSE);
+        NameLength = SubKeyNode->NameLength;
+
+        /* Normal name */
+        RtlCopyMemory(Name, SubKeyNode->Name,
+                      min(*NameSize, SubKeyNode->NameLength));
+    }
+
+    if (*NameSize >= NameLength + sizeof(WCHAR))
+    {
+        Name[NameLength / sizeof(WCHAR)] = UNICODE_NULL;
     }
 
-    *NameSize = CmCopyKeyName(SubKeyNode, Name, *NameSize);
+    *NameSize = NameLength + sizeof(WCHAR);
+
+    /**/HvReleaseCell(Hive, CellIndex);/**/
 
     if (SubKey != NULL)
-    {
         *SubKey = (HKEY)SubKeyNode;
-    }
 
-    TRACE("RegEnumKey done -> %u, '%.*s'\n", *NameSize, *NameSize, Name);
-    return STATUS_SUCCESS;
+    TRACE("RegEnumKey done -> %u, '%.*S'\n", *NameSize, *NameSize, Name);
+    return ERROR_SUCCESS;
 }
 
 LONG
@@ -324,7 +298,7 @@ RegOpenKey(
     UNICODE_STRING CurrentControlSet = RTL_CONSTANT_STRING(L"CurrentControlSet");
     PHHIVE Hive = &CmHive->Hive;
     PCM_KEY_NODE KeyNode;
-    PCM_KEY_INDEX IndexCell;
+    HCELL_INDEX CellIndex;
     TRACE("RegOpenKey(%p, '%S', %p)\n", ParentKey, KeyName, Key);
 
     /* Initialize the remaining path name */
@@ -400,27 +374,22 @@ RegOpenKey(
     {
         TRACE("RegOpenKey: next element '%wZ'\n", &SubKeyName);
 
-        /* Check if there is any subkey */
-        if (KeyNode->SubKeyCounts[Stable] == 0)
-        {
-            return ERROR_PATH_NOT_FOUND;
-        }
-
-        /* 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)
+        CellIndex = CmpFindSubKeyByName(Hive, KeyNode, &SubKeyName);
+        if (CellIndex == HCELL_NIL)
         {
-
-            ERR("Did not find sub key '%wZ' (full %S)\n", &RemainingPath, KeyName);
+            ERR("Did not find sub key '%wZ' (full %S)\n", &SubKeyName, KeyName);
             return ERROR_PATH_NOT_FOUND;
         }
+
+        /* Get the found key */
+        KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, CellIndex);
+        ASSERT(KeyNode);
     }
 
-    TRACE("RegOpenKey done\n");
     *Key = (HKEY)KeyNode;
+
+    TRACE("RegOpenKey done\n");
     return ERROR_SUCCESS;
 }
 
@@ -434,40 +403,27 @@ RepGetValueData(
     _Inout_opt_ ULONG* DataSize)
 {
     ULONG DataLength;
+    PVOID DataCell;
 
     /* Does the caller want the type? */
     if (Type != NULL)
-    {
         *Type = ValueCell->Type;
-    }
 
     /* Does the caller provide DataSize? */
     if (DataSize != NULL)
     {
-        /* Get the data length */
-        DataLength = ValueCell->DataLength & ~CM_KEY_VALUE_SPECIAL_SIZE;
+        // NOTE: CmpValueToData doesn't support big data (the function will
+        // bugcheck if so), FreeLdr is not supposed to read such data.
+        // If big data is needed, use instead CmpGetValueData.
+        // CmpGetValueData(Hive, ValueCell, DataSize, &DataCell, ...);
+        DataCell = CmpValueToData(Hive, ValueCell, &DataLength);
 
         /* Does the caller want the data? */
         if ((Data != NULL) && (*DataSize != 0))
         {
-            /* Check where the data is stored */
-            if ((DataLength <= sizeof(HCELL_INDEX)) &&
-                (ValueCell->DataLength & CM_KEY_VALUE_SPECIAL_SIZE))
-            {
-                /* The data member contains the data */
-                RtlCopyMemory(Data,
-                              &ValueCell->Data,
-                              min(*DataSize, DataLength));
-            }
-            else
-            {
-                /* The data member contains the data cell index */
-                PVOID DataCell = HvGetCell(Hive, ValueCell->Data);
-                RtlCopyMemory(Data,
-                              DataCell,
-                              min(*DataSize, ValueCell->DataLength));
-            }
-
+            RtlCopyMemory(Data,
+                          DataCell,
+                          min(*DataSize, DataLength));
         }
 
         /* Return the actual data length */
@@ -486,9 +442,9 @@ RegQueryValue(
     PHHIVE Hive = &CmHive->Hive;
     PCM_KEY_NODE KeyNode;
     PCM_KEY_VALUE ValueCell;
-    PVALUE_LIST_CELL ValueListCell;
+    HCELL_INDEX CellIndex;
     UNICODE_STRING ValueNameString;
-    ULONG i;
+
     TRACE("RegQueryValue(%p, '%S', %p, %p, %p)\n",
           Key, ValueName, Type, Data, DataSize);
 
@@ -496,54 +452,50 @@ RegQueryValue(
     KeyNode = (PCM_KEY_NODE)Key;
     ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE);
 
-    /* Check if there are any values */
-    if (KeyNode->ValueList.Count == 0)
+    /* Initialize value name string */
+    RtlInitUnicodeString(&ValueNameString, ValueName);
+    CellIndex = CmpFindValueByName(Hive, KeyNode, &ValueNameString);
+    if (CellIndex == HCELL_NIL)
     {
-        TRACE("RegQueryValue no values in key (%.*s)\n",
+        TRACE("RegQueryValue value not found in key (%.*s)\n",
               KeyNode->NameLength, KeyNode->Name);
-        return ERROR_INVALID_PARAMETER;
+        return ERROR_FILE_NOT_FOUND;
     }
 
-    /* Initialize value name string */
-    RtlInitUnicodeString(&ValueNameString, ValueName);
-
-    ValueListCell = (PVALUE_LIST_CELL)HvGetCell(Hive, KeyNode->ValueList.List);
-    TRACE("ValueListCell: %x\n", ValueListCell);
+    /* Get the value cell */
+    ValueCell = (PCM_KEY_VALUE)HvGetCell(Hive, CellIndex);
+    ASSERT(ValueCell != NULL);
 
-    /* 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]);
+    RepGetValueData(Hive, ValueCell, Type, Data, DataSize);
 
-        /* Compare the value name */
-        TRACE("checking %.*s\n", ValueCell->NameLength, ValueCell->Name);
-        if (CmCompareKeyValueName(ValueCell, &ValueNameString, TRUE))
-        {
-            RepGetValueData(Hive, ValueCell, Type, Data, DataSize);
-            TRACE("RegQueryValue success\n");
-            return STATUS_SUCCESS;
-        }
-    }
+    HvReleaseCell(Hive, CellIndex);
 
-    TRACE("RegQueryValue value not found\n");
-    return ERROR_INVALID_PARAMETER;
+    TRACE("RegQueryValue success\n");
+    return ERROR_SUCCESS;
 }
 
+/*
+ * NOTE: This function is currently unused in FreeLdr; however it is kept here
+ * as an implementation reference of RegEnumValue using CMLIB that may be used
+ * elsewhere in ReactOS.
+ */
+#if 0
 LONG
 RegEnumValue(
     _In_ HKEY Key,
     _In_ ULONG Index,
     _Out_ PWCHAR ValueName,
     _Inout_ ULONG* NameSize,
-    _Out_ ULONG* Type,
-    _Out_ PUCHAR Data,
-    _Inout_ ULONG* DataSize)
+    _Out_opt_ ULONG* Type,
+    _Out_opt_ PUCHAR Data,
+    _Inout_opt_ ULONG* DataSize)
 {
     PHHIVE Hive = &CmHive->Hive;
     PCM_KEY_NODE KeyNode;
+    PCELL_DATA ValueListCell;
     PCM_KEY_VALUE ValueCell;
-    PVALUE_LIST_CELL ValueListCell;
+    USHORT NameLength;
+
     TRACE("RegEnumValue(%p, %lu, %S, %p, %p, %p, %p (%lu))\n",
           Key, Index, ValueName, NameSize, Type, Data, DataSize, *DataSize);
 
@@ -553,40 +505,55 @@ RegEnumValue(
 
     /* Check if the index is valid */
     if ((KeyNode->ValueList.Count == 0) ||
+        (KeyNode->ValueList.List == HCELL_NIL) ||
         (Index >= KeyNode->ValueList.Count))
     {
         ERR("RegEnumValue: index invalid\n");
         return ERROR_NO_MORE_ITEMS;
     }
 
-    ValueListCell = (PVALUE_LIST_CELL)HvGetCell(Hive, KeyNode->ValueList.List);
-    TRACE("ValueListCell: %x\n", ValueListCell);
+    ValueListCell = (PCELL_DATA)HvGetCell(Hive, KeyNode->ValueList.List);
+    ASSERT(ValueListCell != NULL);
 
     /* Get the value cell */
-    ValueCell = HvGetCell(Hive, ValueListCell->ValueOffset[Index]);
+    ValueCell = (PCM_KEY_VALUE)HvGetCell(Hive, ValueListCell->KeyList[Index]);
     ASSERT(ValueCell != NULL);
+    ASSERT(ValueCell->Signature == CM_KEY_VALUE_SIGNATURE);
 
-    if (NameSize != NULL)
+    if (ValueCell->Flags & VALUE_COMP_NAME)
     {
-        *NameSize = CmCopyKeyValueName(ValueCell, ValueName, *NameSize);
+        NameLength = CmpCompressedNameSize(ValueCell->Name, ValueCell->NameLength);
+
+        /* Compressed name */
+        CmpCopyCompressedName(ValueName,
+                              *NameSize,
+                              ValueCell->Name,
+                              ValueCell->NameLength);
     }
+    else
+    {
+        NameLength = ValueCell->NameLength;
 
-    RepGetValueData(Hive, ValueCell, Type, Data, DataSize);
+        /* Normal name */
+        RtlCopyMemory(ValueName, ValueCell->Name,
+                      min(*NameSize, ValueCell->NameLength));
+    }
 
-    if (DataSize != NULL)
+    if (*NameSize >= NameLength + sizeof(WCHAR))
     {
-        if ((Data != NULL) && (*DataSize != 0))
-        {
-            RtlCopyMemory(Data,
-                          &ValueCell->Data,
-                          min(*DataSize, ValueCell->DataLength));
-        }
-
-        *DataSize = ValueCell->DataLength;
+        ValueName[NameLength / sizeof(WCHAR)] = UNICODE_NULL;
     }
 
-    TRACE("RegEnumValue done\n");
-    return STATUS_SUCCESS;
+    *NameSize = NameLength + sizeof(WCHAR);
+
+    RepGetValueData(Hive, ValueCell, Type, Data, DataSize);
+
+    HvReleaseCell(Hive, ValueListCell->KeyList[Index]);
+    HvReleaseCell(Hive, KeyNode->ValueList.List);
+
+    TRACE("RegEnumValue done -> %u, '%.*S'\n", *NameSize, *NameSize, ValueName);
+    return ERROR_SUCCESS;
 }
+#endif
 
 /* EOF */
index 25b18d7..d5f5839 100644 (file)
@@ -23,9 +23,6 @@
 
 typedef HANDLE HKEY, *PHKEY;
 
-VOID
-RegInitializeRegistry(VOID);
-
 LONG
 RegInitCurrentControlSet(BOOLEAN LastKnownGood);
 
@@ -42,13 +39,6 @@ RegOpenKey(HKEY ParentKey,
            PCWSTR KeyName,
            PHKEY Key);
 
-LONG
-RegSetValue(HKEY Key,
-        PCWSTR ValueName,
-        ULONG Type,
-        PCSTR Data,
-        ULONG DataSize);
-
 LONG
 RegQueryValue(HKEY Key,
           PCWSTR ValueName,
@@ -66,7 +56,7 @@ RegEnumValue(HKEY Key,
          ULONG* DataSize);
 
 BOOLEAN
-RegImportBinaryHive(PCHAR ChunkBase,
+RegImportBinaryHive(PVOID ChunkBase,
              ULONG ChunkSize);
 
 #endif /* __REGISTRY_H */
index 8fbfb45..afde24f 100644 (file)
@@ -133,11 +133,8 @@ BOOLEAN WinLdrInitSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
     if (!Success)
         return FALSE;
 
-    // Initialize in-memory registry
-    RegInitializeRegistry();
-
     // Import what was loaded
-    Success = RegImportBinaryHive((PCHAR)VaToPa(LoaderBlock->RegistryBase), LoaderBlock->RegistryLength);
+    Success = RegImportBinaryHive(VaToPa(LoaderBlock->RegistryBase), LoaderBlock->RegistryLength);
     if (!Success)
     {
         UiMessageBox("Importing binary hive failed!");