- Fix critical bug in CmpCopyName, it wasn't compressing names at all.
authorAlex Ionescu <aionescu@gmail.com>
Sun, 13 May 2007 16:58:54 +0000 (16:58 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Sun, 13 May 2007 16:58:54 +0000 (16:58 +0000)
- Implement new cmlib routines: HvIsCellAllocated, Doesn't really work fully since we don't support mapped-file hives, but works for the kinds of hives we currently use. HvIsCellDirty, should work as expected.
- Implement new cm routines: CmpMarkValueDataDirty, CmpFreeValueData, CmpFreeValue. There are generic so they can deal with Big, Small or Normal keys.
- Implement CmpAddValueToList, CmpSetValueDataNew.
- Add RtlCheckBit to winddk.h, it's inlined instead of being an actual function call.

svn path=/trunk/; revision=26757

reactos/include/ddk/winddk.h
reactos/lib/cmlib/cmlib.h
reactos/lib/cmlib/hivecell.c
reactos/lib/cmlib/hivedata.h
reactos/ntoskrnl/config/cm.h
reactos/ntoskrnl/config/cmname.c
reactos/ntoskrnl/config/cmvalue.c

index 2492aa1..2d0c4f4 100644 (file)
@@ -4277,6 +4277,8 @@ typedef struct _RTL_BITMAP {
   PULONG  Buffer;
 } RTL_BITMAP, *PRTL_BITMAP;
 
+#define RtlCheckBit(BMH,BP) (((((PLONG)(BMH)->Buffer)[(BP) / 32]) >> ((BP) % 32)) & 0x1)
+
 typedef struct _RTL_BITMAP_RUN {
     ULONG  StartingIndex;
     ULONG  NumberOfBits;
@@ -5806,12 +5808,14 @@ RtlCharToInteger(
   IN ULONG  Base  OPTIONAL,
   IN OUT PULONG  Value);
 
+#if 0
 NTSYSAPI
 ULONG
 NTAPI
 RtlCheckBit(
   IN PRTL_BITMAP  BitMapHeader,
   IN ULONG  BitPosition);
+#endif
 
 NTSYSAPI
 NTSTATUS
index 4971b4b..8e5ff1b 100644 (file)
@@ -183,6 +183,12 @@ HvAllocateCell(
    SIZE_T Size,
    HV_STORAGE_TYPE Storage);
 
+BOOLEAN CMAPI
+HvIsCellAllocated(
+    IN PHHIVE RegistryHive,
+    IN HCELL_INDEX CellIndex
+);
+
 HCELL_INDEX CMAPI
 HvReallocateCell(
    PHHIVE RegistryHive,
@@ -199,6 +205,12 @@ HvMarkCellDirty(
    PHHIVE RegistryHive,
    HCELL_INDEX CellOffset);
 
+BOOLEAN CMAPI
+HvIsCellDirty(
+    IN PHHIVE Hive,
+    IN HCELL_INDEX Cell
+);
+
 BOOLEAN CMAPI
 HvSyncHive(
    PHHIVE RegistryHive);
index 1e84baf..28d2b9e 100644 (file)
@@ -39,6 +39,32 @@ HvpGetCellHeader(
    }
 }
 
+BOOLEAN CMAPI
+HvIsCellAllocated(IN PHHIVE RegistryHive,
+                  IN HCELL_INDEX CellIndex)
+{
+    ULONG Type, Block;
+
+    /* If it's a flat hive, the cell is always allocated */
+    if (RegistryHive->Flat) return TRUE;
+
+    /* Otherwise, get the type and make sure it's valid */
+    Type = HvGetCellType(CellIndex);
+    if (((CellIndex % ~HCELL_TYPE_MASK) > RegistryHive->Storage[Type].Length) ||
+        (CellIndex % (RegistryHive->Version >= 2 ? 8 : 16)))
+    {
+        /* Invalid cell index */
+        return FALSE;
+    }
+
+    /* Try to get the cell block */
+    Block = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
+    if (RegistryHive->Storage[Type].BlockList[Block].Block) return TRUE;
+
+    /* No valid block, fail */
+    return FALSE;
+}
+
 PVOID CMAPI
 HvGetCell(
    PHHIVE RegistryHive,
@@ -94,6 +120,20 @@ HvMarkCellDirty(
               CellBlock, CellLastBlock - CellBlock);
 }
 
+BOOLEAN CMAPI
+HvIsCellDirty(IN PHHIVE Hive,
+              IN HCELL_INDEX Cell)
+{
+    /* Sanity checks */
+    ASSERT(Hive->ReadOnly == FALSE);
+
+    /* Volatile cells are always "dirty" */
+    if (HvGetCellType(Cell) == HvVolatile) return TRUE;
+
+    /* Check if the dirty bit is set */
+    return RtlCheckBit(&Hive->DirtyVector, Cell / HV_BLOCK_SIZE);
+}
+
 static ULONG __inline CMAPI
 HvpComputeFreeListIndex(
    ULONG Size)
index a8022fe..108f677 100644 (file)
@@ -40,6 +40,9 @@ typedef ULONG HCELL_INDEX, *PHCELL_INDEX;
 #define HCELL_BLOCK_SHIFT              12
 #define HCELL_OFFSET_SHIFT             0
 
+#define HvGetCellType(Cell)             \
+    ((ULONG)((Cell & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT))
+
 #include <pshpack1.h>
 
 /**
index 6b0c7a3..6abc1ff 100644 (file)
 #define CMTRACE(x, ...) DPRINT(__VA_ARGS__)\r
 #endif\r
 \r
+\r
+//\r
+// Hack since bigkeys are not yet supported\r
+//\r
+#define ASSERT_VALUE_BIG(h, s)                          \\r
+    ASSERTMSG("Big keys not supported!", !CmpIsKeyValueBig(h, s));\r
+\r
 //\r
 // Tag for all registry allocations\r
 //\r
@@ -678,6 +685,8 @@ extern LIST_ENTRY CmiKeyObjectListHead, CmiConnectedHiveList;
 extern KTIMER CmiWorkerTimer;\r
 VOID NTAPI CmiWorkerThread(IN PVOID Param);\r
 PVOID NTAPI CmpRosGetHardwareHive(OUT PULONG Length);\r
+NTSTATUS CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1, IN PVOID Argument2);\r
+VOID CmiSyncHives(VOID);\r
 #define HIVE_NO_FILE    0x00000002\r
 ///////////////////////////////////////////////////////////////////////////////\r
 \r
@@ -1012,6 +1021,34 @@ CmpValueToData(
     OUT PULONG Length\r
 );\r
 \r
+NTSTATUS\r
+NTAPI\r
+CmpSetValueDataNew(\r
+    IN PHHIVE Hive,\r
+    IN PVOID Data,\r
+    IN ULONG DataSize,\r
+    IN ULONG StorageType,\r
+    IN HCELL_INDEX ValueCell,\r
+    OUT PHCELL_INDEX DataCell\r
+);\r
+\r
+NTSTATUS\r
+NTAPI\r
+CmpAddValueToList(\r
+    IN PHHIVE Hive,\r
+    IN HCELL_INDEX ValueCell,\r
+    IN ULONG Index,\r
+    IN ULONG Type,\r
+    IN OUT PCHILD_LIST ChildList\r
+);\r
+\r
+BOOLEAN\r
+NTAPI\r
+CmpFreeValue(\r
+    IN PHHIVE Hive,\r
+    IN HCELL_INDEX Cell\r
+);\r
+\r
 //\r
 // Boot Routines\r
 //\r
index 81801c2..39bf2be 100644 (file)
@@ -45,7 +45,7 @@ CmpCopyName(IN PHHIVE Hive,
         }\r
 \r
         /* Copy this character */\r
-        Destination[i] = Source->Buffer[i];\r
+        ((PCHAR)Destination)[i] = (CHAR)(Source->Buffer[i]);\r
     }\r
 \r
     /* Compressed name, return length */\r
index 212100c..be39fb4 100644 (file)
 #define NDEBUG\r
 #include "debug.h"\r
 \r
-/* GLOBALS *******************************************************************/\r
-\r
 /* FUNCTIONS *****************************************************************/\r
 \r
+BOOLEAN\r
+NTAPI\r
+CmpMarkValueDataDirty(IN PHHIVE Hive,\r
+                      IN PCM_KEY_VALUE Value)\r
+{\r
+    ULONG KeySize;\r
+    PAGED_CODE();\r
+\r
+    /* Make sure there's actually any data */\r
+    if (Value->Data != HCELL_NIL)\r
+    {\r
+        /* If this is a small key, there's no need to have it dirty */\r
+        if (CmpIsKeyValueSmall(&KeySize, Value->DataLength)) return TRUE;\r
+\r
+        /* Check if this is a big key */\r
+        ASSERT_VALUE_BIG(Hive, KeySize);\r
+\r
+        /* Normal value, just mark it dirty */\r
+        HvMarkCellDirty(Hive, Value->Data);\r
+    }\r
+\r
+    /* Operation complete */\r
+    return TRUE;\r
+}\r
+\r
+BOOLEAN\r
+NTAPI\r
+CmpFreeValueData(IN PHHIVE Hive,\r
+                 IN HCELL_INDEX DataCell,\r
+                 IN ULONG DataLength)\r
+{\r
+    ULONG KeySize;\r
+    PAGED_CODE();\r
+\r
+    /* If this is a small key, the data is built-in */\r
+    if (!CmpIsKeyValueSmall(&KeySize, DataLength))\r
+    {\r
+        /* If there's no data cell, there's nothing to do */\r
+        if (DataCell == HCELL_NIL) return TRUE;\r
+\r
+        /* Make sure the data cell is allocated */\r
+        ASSERT(HvIsCellAllocated(Hive, DataCell));\r
+\r
+        /* Unsupported value type */\r
+        ASSERT_VALUE_BIG(Hive, KeySize);\r
+\r
+        /* Normal value, just free the data cell */\r
+        HvFreeCell(Hive, DataCell);\r
+    }\r
+\r
+    /* Operation complete */\r
+    return TRUE;\r
+}\r
+\r
+BOOLEAN\r
+NTAPI\r
+CmpFreeValue(IN PHHIVE Hive,\r
+             IN HCELL_INDEX Cell)\r
+{\r
+    PCM_KEY_VALUE Value;\r
+    PAGED_CODE();\r
+\r
+    /* Get the cell data */\r
+    Value = (PCM_KEY_VALUE)HvGetCell(Hive, Cell);\r
+    if (!Value) ASSERT(FALSE);\r
+\r
+    /* Free it */\r
+    if (!CmpFreeValueData(Hive, Value->Data, Value->DataLength))\r
+    {\r
+        /* We failed to free the data, return failure */\r
+        HvReleaseCell(Hive, Cell);\r
+        return FALSE;\r
+    }\r
+\r
+    /* Release the cell and free it */\r
+    HvReleaseCell(Hive, Cell);\r
+    HvFreeCell(Hive, Cell);\r
+    return TRUE;\r
+}\r
+\r
 HCELL_INDEX\r
 NTAPI\r
 CmpFindValueByName(IN PHHIVE Hive,\r
@@ -67,13 +145,8 @@ CmpGetValueData(IN PHHIVE Hive,
         return TRUE;\r
     }\r
 \r
-    /* Check if this is a big cell */\r
-    if (CmpIsKeyValueBig(Hive, *Length))\r
-    {\r
-        /* FIXME: We don't support big cells */\r
-        DPRINT1("Unsupported cell type!\n");\r
-        while (TRUE);\r
-    }\r
+    /* Unsupported */\r
+    ASSERT_VALUE_BIG(Hive, *Length);\r
 \r
     /* Get the data from the cell */\r
     *Buffer = HvGetCell(Hive, Value->Data);\r
@@ -123,3 +196,114 @@ CmpValueToData(IN PHHIVE Hive,
     /* Otherwise, return the cell data */\r
     return Buffer;\r
 }\r
+\r
+NTSTATUS\r
+NTAPI\r
+CmpAddValueToList(IN PHHIVE Hive,\r
+                  IN HCELL_INDEX ValueCell,\r
+                  IN ULONG Index,\r
+                  IN ULONG Type,\r
+                  IN OUT PCHILD_LIST ChildList)\r
+{\r
+    HCELL_INDEX ListCell;\r
+    ULONG ChildCount, Length, i;\r
+    PCELL_DATA CellData;\r
+    PAGED_CODE();\r
+\r
+    /* Sanity check */\r
+    ASSERT((((LONG)Index) >= 0) && (Index <= ChildList->Count));\r
+\r
+    /* Get the number of entries in the child list */\r
+    ChildCount = ChildList->Count;\r
+    ChildCount++;\r
+    if (ChildCount > 1)\r
+    {\r
+        /* The cell should be dirty at this point */\r
+        ASSERT(HvIsCellDirty(Hive, ChildList->List));\r
+\r
+        /* Check if we have less then 100 children */\r
+        if (ChildCount < 100)\r
+        {\r
+            /* Allocate just enough as requested */\r
+            Length = ChildCount * sizeof(HCELL_INDEX);\r
+        }\r
+        else\r
+        {\r
+            /* Otherwise, we have quite a few, so allocate a batch */\r
+            Length = ROUND_UP(ChildCount, 100) * sizeof(HCELL_INDEX);\r
+            if (Length > HBLOCK_SIZE)\r
+            {\r
+                /* But make sure we don't allocate beyond our block size */\r
+                Length = ROUND_UP(Length, HBLOCK_SIZE);\r
+            }\r
+        }\r
+\r
+        /* Perform the allocation */\r
+        ListCell = HvReallocateCell(Hive, ChildList->List, Length);\r
+    }\r
+    else\r
+    {\r
+        /* This is our first child, so allocate a single cell */\r
+        ListCell = HvAllocateCell(Hive, sizeof(HCELL_INDEX), Type);\r
+    }\r
+\r
+    /* Fail if we couldn't get a cell */\r
+    if (!ListCell) return STATUS_INSUFFICIENT_RESOURCES;\r
+\r
+    /* Set this cell as the child list's list cell */\r
+    ChildList->List = ListCell;\r
+\r
+    /* Get the actual key list memory */\r
+    CellData = HvGetCell(Hive, ListCell);\r
+    if (!CellData) ASSERT(FALSE);\r
+\r
+    /* Loop all the children */\r
+    for (i = ChildCount - 1; i > Index; i--)\r
+    {\r
+        /* Move them all down */\r
+        CellData->u.KeyList[i] = CellData->u.KeyList[i - 1];\r
+    }\r
+\r
+    /* Insert us on top now */\r
+    CellData->u.KeyList[Index] = ValueCell;\r
+    ChildList->Count = ChildCount;\r
+\r
+    /* Release the list cell and make sure the value cell is dirty */\r
+    HvReleaseCell(Hive, ListCell);\r
+    ASSERT(HvIsCellDirty(Hive, ValueCell));\r
+\r
+    /* We're done here */\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+NTSTATUS\r
+NTAPI\r
+CmpSetValueDataNew(IN PHHIVE Hive,\r
+                   IN PVOID Data,\r
+                   IN ULONG DataSize,\r
+                   IN ULONG StorageType,\r
+                   IN HCELL_INDEX ValueCell,\r
+                   OUT PHCELL_INDEX DataCell)\r
+{\r
+    PCELL_DATA CellData;\r
+    PAGED_CODE();\r
+    ASSERT(DataSize > CM_KEY_VALUE_SMALL);\r
+\r
+    /* Check if this is a big key */\r
+    ASSERT_VALUE_BIG(Hive, DataSize);\r
+\r
+    /* Allocate a data cell */\r
+    *DataCell = HvAllocateCell(Hive, DataSize, StorageType);\r
+    if (*DataCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;\r
+\r
+    /* Get the actual data */\r
+    CellData = HvGetCell(Hive, *DataCell);\r
+    if (!CellData) ASSERT(FALSE);\r
+\r
+    /* Copy our buffer into it */\r
+    RtlCopyMemory(CellData, Data, DataSize);\r
+\r
+    /* All done */\r
+    return STATUS_SUCCESS;\r
+}\r
+\r