Author: ion Date: Sun May 13 20:58:54 2007 New Revision: 26757
URL: http://svn.reactos.org/svn/reactos?rev=26757&view=rev Log: - Fix critical bug in CmpCopyName, it wasn't compressing names at all. - 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.
Modified: trunk/reactos/include/ddk/winddk.h trunk/reactos/lib/cmlib/cmlib.h trunk/reactos/lib/cmlib/hivecell.c trunk/reactos/lib/cmlib/hivedata.h trunk/reactos/ntoskrnl/config/cm.h trunk/reactos/ntoskrnl/config/cmname.c trunk/reactos/ntoskrnl/config/cmvalue.c
Modified: trunk/reactos/include/ddk/winddk.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ddk/winddk.h?rev=26... ============================================================================== --- trunk/reactos/include/ddk/winddk.h (original) +++ trunk/reactos/include/ddk/winddk.h Sun May 13 20:58:54 2007 @@ -4277,6 +4277,8 @@ 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 @@ IN ULONG Base OPTIONAL, IN OUT PULONG Value);
+#if 0 NTSYSAPI ULONG NTAPI RtlCheckBit( IN PRTL_BITMAP BitMapHeader, IN ULONG BitPosition); +#endif
NTSYSAPI NTSTATUS
Modified: trunk/reactos/lib/cmlib/cmlib.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/cmlib.h?rev=26757... ============================================================================== --- trunk/reactos/lib/cmlib/cmlib.h (original) +++ trunk/reactos/lib/cmlib/cmlib.h Sun May 13 20:58:54 2007 @@ -183,6 +183,12 @@ SIZE_T Size, HV_STORAGE_TYPE Storage);
+BOOLEAN CMAPI +HvIsCellAllocated( + IN PHHIVE RegistryHive, + IN HCELL_INDEX CellIndex +); + HCELL_INDEX CMAPI HvReallocateCell( PHHIVE RegistryHive, @@ -198,6 +204,12 @@ HvMarkCellDirty( PHHIVE RegistryHive, HCELL_INDEX CellOffset); + +BOOLEAN CMAPI +HvIsCellDirty( + IN PHHIVE Hive, + IN HCELL_INDEX Cell +);
BOOLEAN CMAPI HvSyncHive(
Modified: trunk/reactos/lib/cmlib/hivecell.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/hivecell.c?rev=26... ============================================================================== --- trunk/reactos/lib/cmlib/hivecell.c (original) +++ trunk/reactos/lib/cmlib/hivecell.c Sun May 13 20:58:54 2007 @@ -39,6 +39,32 @@ } }
+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, @@ -92,6 +118,20 @@
RtlSetBits(&RegistryHive->DirtyVector, 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
Modified: trunk/reactos/lib/cmlib/hivedata.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/hivedata.h?rev=26... ============================================================================== --- trunk/reactos/lib/cmlib/hivedata.h (original) +++ trunk/reactos/lib/cmlib/hivedata.h Sun May 13 20:58:54 2007 @@ -39,6 +39,9 @@ #define HCELL_TYPE_SHIFT 31 #define HCELL_BLOCK_SHIFT 12 #define HCELL_OFFSET_SHIFT 0 + +#define HvGetCellType(Cell) \ + ((ULONG)((Cell & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT))
#include <pshpack1.h>
Modified: trunk/reactos/ntoskrnl/config/cm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cm.h?rev=26... ============================================================================== --- trunk/reactos/ntoskrnl/config/cm.h (original) +++ trunk/reactos/ntoskrnl/config/cm.h Sun May 13 20:58:54 2007 @@ -35,6 +35,13 @@ #else #define CMTRACE(x, ...) DPRINT(__VA_ARGS__) #endif + + +// +// Hack since bigkeys are not yet supported +// +#define ASSERT_VALUE_BIG(h, s) \ + ASSERTMSG("Big keys not supported!", !CmpIsKeyValueBig(h, s));
// // Tag for all registry allocations @@ -678,6 +685,8 @@ extern KTIMER CmiWorkerTimer; VOID NTAPI CmiWorkerThread(IN PVOID Param); PVOID NTAPI CmpRosGetHardwareHive(OUT PULONG Length); +NTSTATUS CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1, IN PVOID Argument2); +VOID CmiSyncHives(VOID); #define HIVE_NO_FILE 0x00000002 ///////////////////////////////////////////////////////////////////////////////
@@ -1010,6 +1019,34 @@ IN PHHIVE Hive, IN PCM_KEY_VALUE Value, OUT PULONG Length +); + +NTSTATUS +NTAPI +CmpSetValueDataNew( + IN PHHIVE Hive, + IN PVOID Data, + IN ULONG DataSize, + IN ULONG StorageType, + IN HCELL_INDEX ValueCell, + OUT PHCELL_INDEX DataCell +); + +NTSTATUS +NTAPI +CmpAddValueToList( + IN PHHIVE Hive, + IN HCELL_INDEX ValueCell, + IN ULONG Index, + IN ULONG Type, + IN OUT PCHILD_LIST ChildList +); + +BOOLEAN +NTAPI +CmpFreeValue( + IN PHHIVE Hive, + IN HCELL_INDEX Cell );
//
Modified: trunk/reactos/ntoskrnl/config/cmname.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmname.c?re... ============================================================================== --- trunk/reactos/ntoskrnl/config/cmname.c (original) +++ trunk/reactos/ntoskrnl/config/cmname.c Sun May 13 20:58:54 2007 @@ -45,7 +45,7 @@ }
/* Copy this character */ - Destination[i] = Source->Buffer[i]; + ((PCHAR)Destination)[i] = (CHAR)(Source->Buffer[i]); }
/* Compressed name, return length */
Modified: trunk/reactos/ntoskrnl/config/cmvalue.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmvalue.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/config/cmvalue.c (original) +++ trunk/reactos/ntoskrnl/config/cmvalue.c Sun May 13 20:58:54 2007 @@ -13,9 +13,87 @@ #define NDEBUG #include "debug.h"
-/* GLOBALS *******************************************************************/ - /* FUNCTIONS *****************************************************************/ + +BOOLEAN +NTAPI +CmpMarkValueDataDirty(IN PHHIVE Hive, + IN PCM_KEY_VALUE Value) +{ + ULONG KeySize; + PAGED_CODE(); + + /* Make sure there's actually any data */ + if (Value->Data != HCELL_NIL) + { + /* If this is a small key, there's no need to have it dirty */ + if (CmpIsKeyValueSmall(&KeySize, Value->DataLength)) return TRUE; + + /* Check if this is a big key */ + ASSERT_VALUE_BIG(Hive, KeySize); + + /* Normal value, just mark it dirty */ + HvMarkCellDirty(Hive, Value->Data); + } + + /* Operation complete */ + return TRUE; +} + +BOOLEAN +NTAPI +CmpFreeValueData(IN PHHIVE Hive, + IN HCELL_INDEX DataCell, + IN ULONG DataLength) +{ + ULONG KeySize; + PAGED_CODE(); + + /* If this is a small key, the data is built-in */ + if (!CmpIsKeyValueSmall(&KeySize, DataLength)) + { + /* If there's no data cell, there's nothing to do */ + if (DataCell == HCELL_NIL) return TRUE; + + /* Make sure the data cell is allocated */ + ASSERT(HvIsCellAllocated(Hive, DataCell)); + + /* Unsupported value type */ + ASSERT_VALUE_BIG(Hive, KeySize); + + /* Normal value, just free the data cell */ + HvFreeCell(Hive, DataCell); + } + + /* Operation complete */ + return TRUE; +} + +BOOLEAN +NTAPI +CmpFreeValue(IN PHHIVE Hive, + IN HCELL_INDEX Cell) +{ + PCM_KEY_VALUE Value; + PAGED_CODE(); + + /* Get the cell data */ + Value = (PCM_KEY_VALUE)HvGetCell(Hive, Cell); + if (!Value) ASSERT(FALSE); + + /* Free it */ + if (!CmpFreeValueData(Hive, Value->Data, Value->DataLength)) + { + /* We failed to free the data, return failure */ + HvReleaseCell(Hive, Cell); + return FALSE; + } + + /* Release the cell and free it */ + HvReleaseCell(Hive, Cell); + HvFreeCell(Hive, Cell); + return TRUE; +}
HCELL_INDEX NTAPI @@ -67,13 +145,8 @@ return TRUE; }
- /* Check if this is a big cell */ - if (CmpIsKeyValueBig(Hive, *Length)) - { - /* FIXME: We don't support big cells */ - DPRINT1("Unsupported cell type!\n"); - while (TRUE); - } + /* Unsupported */ + ASSERT_VALUE_BIG(Hive, *Length);
/* Get the data from the cell */ *Buffer = HvGetCell(Hive, Value->Data); @@ -123,3 +196,114 @@ /* Otherwise, return the cell data */ return Buffer; } + +NTSTATUS +NTAPI +CmpAddValueToList(IN PHHIVE Hive, + IN HCELL_INDEX ValueCell, + IN ULONG Index, + IN ULONG Type, + IN OUT PCHILD_LIST ChildList) +{ + HCELL_INDEX ListCell; + ULONG ChildCount, Length, i; + PCELL_DATA CellData; + PAGED_CODE(); + + /* Sanity check */ + ASSERT((((LONG)Index) >= 0) && (Index <= ChildList->Count)); + + /* Get the number of entries in the child list */ + ChildCount = ChildList->Count; + ChildCount++; + if (ChildCount > 1) + { + /* The cell should be dirty at this point */ + ASSERT(HvIsCellDirty(Hive, ChildList->List)); + + /* Check if we have less then 100 children */ + if (ChildCount < 100) + { + /* Allocate just enough as requested */ + Length = ChildCount * sizeof(HCELL_INDEX); + } + else + { + /* Otherwise, we have quite a few, so allocate a batch */ + Length = ROUND_UP(ChildCount, 100) * sizeof(HCELL_INDEX); + if (Length > HBLOCK_SIZE) + { + /* But make sure we don't allocate beyond our block size */ + Length = ROUND_UP(Length, HBLOCK_SIZE); + } + } + + /* Perform the allocation */ + ListCell = HvReallocateCell(Hive, ChildList->List, Length); + } + else + { + /* This is our first child, so allocate a single cell */ + ListCell = HvAllocateCell(Hive, sizeof(HCELL_INDEX), Type); + } + + /* Fail if we couldn't get a cell */ + if (!ListCell) return STATUS_INSUFFICIENT_RESOURCES; + + /* Set this cell as the child list's list cell */ + ChildList->List = ListCell; + + /* Get the actual key list memory */ + CellData = HvGetCell(Hive, ListCell); + if (!CellData) ASSERT(FALSE); + + /* Loop all the children */ + for (i = ChildCount - 1; i > Index; i--) + { + /* Move them all down */ + CellData->u.KeyList[i] = CellData->u.KeyList[i - 1]; + } + + /* Insert us on top now */ + CellData->u.KeyList[Index] = ValueCell; + ChildList->Count = ChildCount; + + /* Release the list cell and make sure the value cell is dirty */ + HvReleaseCell(Hive, ListCell); + ASSERT(HvIsCellDirty(Hive, ValueCell)); + + /* We're done here */ + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +CmpSetValueDataNew(IN PHHIVE Hive, + IN PVOID Data, + IN ULONG DataSize, + IN ULONG StorageType, + IN HCELL_INDEX ValueCell, + OUT PHCELL_INDEX DataCell) +{ + PCELL_DATA CellData; + PAGED_CODE(); + ASSERT(DataSize > CM_KEY_VALUE_SMALL); + + /* Check if this is a big key */ + ASSERT_VALUE_BIG(Hive, DataSize); + + /* Allocate a data cell */ + *DataCell = HvAllocateCell(Hive, DataSize, StorageType); + if (*DataCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES; + + /* Get the actual data */ + CellData = HvGetCell(Hive, *DataCell); + if (!CellData) ASSERT(FALSE); + + /* Copy our buffer into it */ + RtlCopyMemory(CellData, Data, DataSize); + + /* All done */ + return STATUS_SUCCESS; +} +