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=2…
==============================================================================
--- 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=2675…
==============================================================================
--- 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=2…
==============================================================================
--- 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=2…
==============================================================================
--- 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=2…
==============================================================================
--- 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?r…
==============================================================================
--- 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?…
==============================================================================
--- 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;
+}
+