-/*\r
- * PROJECT: ReactOS Kernel\r
- * LICENSE: GPL - See COPYING in the top level directory\r
- * FILE: ntoskrnl/config/cmvalue.c\r
- * PURPOSE: Configuration Manager - Cell Values\r
- * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)\r
- */\r
-\r
-/* INCLUDES ******************************************************************/\r
-\r
-#include "ntoskrnl.h"\r
-#include "cm.h"\r
-#define NDEBUG\r
-#include "debug.h"\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, FALSE);\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
- IN PCM_KEY_NODE KeyNode,\r
- IN PUNICODE_STRING Name)\r
-{\r
- HCELL_INDEX CellIndex;\r
-\r
- /* Call the main function */\r
- if (!CmpFindNameInList(Hive,\r
- &KeyNode->ValueList,\r
- Name,\r
- NULL,\r
- &CellIndex))\r
- {\r
- /* Santy check */\r
- ASSERT(CellIndex == HCELL_NIL);\r
- }\r
-\r
- /* Return the index */\r
- return CellIndex;\r
-}\r
-\r
-BOOLEAN\r
-NTAPI\r
-CmpGetValueData(IN PHHIVE Hive,\r
- IN PCM_KEY_VALUE Value,\r
- IN PULONG Length,\r
- OUT PVOID *Buffer,\r
- OUT PBOOLEAN BufferAllocated,\r
- OUT PHCELL_INDEX CellToRelease)\r
-{\r
- PAGED_CODE();\r
-\r
- /* Sanity check */\r
- ASSERT(Value->Signature == CM_KEY_VALUE_SIGNATURE);\r
-\r
- /* Set failure defaults */\r
- *BufferAllocated = FALSE;\r
- *Buffer = NULL;\r
- *CellToRelease = HCELL_NIL;\r
-\r
- /* Check if this is a small key */\r
- if (CmpIsKeyValueSmall(Length, Value->DataLength))\r
- {\r
- /* Return the data immediately */\r
- *Buffer = &Value->Data;\r
- return TRUE;\r
- }\r
-\r
- /* Unsupported */\r
- ASSERT_VALUE_BIG(Hive, *Length);\r
-\r
- /* Get the data from the cell */\r
- *Buffer = HvGetCell(Hive, Value->Data);\r
- if (!(*Buffer)) return FALSE;\r
-\r
- /* Return success and the cell to be released */\r
- *CellToRelease = Value->Data;\r
- return TRUE;\r
-}\r
-\r
-PCELL_DATA\r
-NTAPI\r
-CmpValueToData(IN PHHIVE Hive,\r
- IN PCM_KEY_VALUE Value,\r
- OUT PULONG Length)\r
-{\r
- PCELL_DATA Buffer;\r
- BOOLEAN BufferAllocated;\r
- HCELL_INDEX CellToRelease;\r
- PAGED_CODE();\r
-\r
- /* Sanity check */\r
- ASSERT(Hive->ReleaseCellRoutine == NULL);\r
-\r
- /* Get the actual data */\r
- if (!CmpGetValueData(Hive,\r
- Value,\r
- Length,\r
- (PVOID)&Buffer,\r
- &BufferAllocated,\r
- &CellToRelease))\r
- {\r
- /* We failed */\r
- ASSERT(BufferAllocated == FALSE);\r
- ASSERT(Buffer == NULL);\r
- return NULL;\r
- }\r
-\r
- /* This should never happen!*/\r
- if (BufferAllocated)\r
- {\r
- /* Free the buffer and bugcheck */\r
- ExFreePool(Buffer);\r
- KEBUGCHECKEX(REGISTRY_ERROR, 8, 0, (ULONG_PTR)Hive, (ULONG_PTR)Value);\r
- }\r
-\r
- /* 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, HCELL_NIL);\r
- }\r
-\r
- /* Fail if we couldn't get a cell */\r
- if (ListCell == HCELL_NIL) 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
- ASSERT(CellData != NULL);\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, HCELL_NIL);\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
-NTSTATUS\r
-NTAPI\r
-CmpRemoveValueFromList(IN PHHIVE Hive,\r
- IN ULONG Index,\r
- IN OUT PCHILD_LIST ChildList)\r
-{\r
- ULONG Count;\r
- PCELL_DATA CellData;\r
- HCELL_INDEX NewCell;\r
- PAGED_CODE();\r
-\r
- /* Sanity check */\r
- ASSERT((((LONG)Index) >= 0) && (Index <= ChildList->Count));\r
-\r
- /* Get the new count after removal */\r
- Count = ChildList->Count - 1;\r
- if (Count > 0)\r
- {\r
- /* Get the actual list array */\r
- CellData = HvGetCell(Hive, ChildList->List);\r
- if (!CellData) return STATUS_INSUFFICIENT_RESOURCES;\r
-\r
- /* Make sure cells data have been made dirty */\r
- ASSERT(HvIsCellDirty(Hive, ChildList->List));\r
- ASSERT(HvIsCellDirty(Hive, CellData->u.KeyList[Index]));\r
-\r
- /* Loop the list */\r
- while (Index < Count)\r
- {\r
- /* Move everything up */\r
- CellData->u.KeyList[Index] = CellData->u.KeyList[Index + 1];\r
- Index++;\r
- }\r
-\r
- /* Re-allocate the cell for the list by decreasing the count */\r
- NewCell = HvReallocateCell(Hive,\r
- ChildList->List,\r
- Count * sizeof(HCELL_INDEX));\r
- ASSERT(NewCell != HCELL_NIL);\r
- HvReleaseCell(Hive,ChildList->List);\r
-\r
- /* Update the list cell */\r
- ChildList->List = NewCell;\r
- }\r
- else\r
- {\r
- /* Otherwise, we were the last entry, so free the list entirely */\r
- HvFreeCell(Hive, ChildList->List);\r
- ChildList->List = HCELL_NIL;\r
- }\r
-\r
- /* Update the child list with the new count */\r
- ChildList->Count = Count;\r
- return STATUS_SUCCESS;\r
-}\r
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: ntoskrnl/config/cmvalue.c
+ * PURPOSE: Configuration Manager - Cell Values
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include "ntoskrnl.h"
+#define NDEBUG
+#include "debug.h"
+
+/* 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, FALSE);
+ }
+
+ /* 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
+CmpFindValueByName(IN PHHIVE Hive,
+ IN PCM_KEY_NODE KeyNode,
+ IN PUNICODE_STRING Name)
+{
+ HCELL_INDEX CellIndex;
+
+ /* Call the main function */
+ if (!CmpFindNameInList(Hive,
+ &KeyNode->ValueList,
+ Name,
+ NULL,
+ &CellIndex))
+ {
+ /* Santy check */
+ ASSERT(CellIndex == HCELL_NIL);
+ }
+
+ /* Return the index */
+ return CellIndex;
+}
+
+BOOLEAN
+NTAPI
+CmpGetValueData(IN PHHIVE Hive,
+ IN PCM_KEY_VALUE Value,
+ IN PULONG Length,
+ OUT PVOID *Buffer,
+ OUT PBOOLEAN BufferAllocated,
+ OUT PHCELL_INDEX CellToRelease)
+{
+ PAGED_CODE();
+
+ /* Sanity check */
+ ASSERT(Value->Signature == CM_KEY_VALUE_SIGNATURE);
+
+ /* Set failure defaults */
+ *BufferAllocated = FALSE;
+ *Buffer = NULL;
+ *CellToRelease = HCELL_NIL;
+
+ /* Check if this is a small key */
+ if (CmpIsKeyValueSmall(Length, Value->DataLength))
+ {
+ /* Return the data immediately */
+ *Buffer = &Value->Data;
+ return TRUE;
+ }
+
+ /* Unsupported */
+ ASSERT_VALUE_BIG(Hive, *Length);
+
+ /* Get the data from the cell */
+ *Buffer = HvGetCell(Hive, Value->Data);
+ if (!(*Buffer)) return FALSE;
+
+ /* Return success and the cell to be released */
+ *CellToRelease = Value->Data;
+ return TRUE;
+}
+
+PCELL_DATA
+NTAPI
+CmpValueToData(IN PHHIVE Hive,
+ IN PCM_KEY_VALUE Value,
+ OUT PULONG Length)
+{
+ PCELL_DATA Buffer;
+ BOOLEAN BufferAllocated;
+ HCELL_INDEX CellToRelease;
+ PAGED_CODE();
+
+ /* Sanity check */
+ ASSERT(Hive->ReleaseCellRoutine == NULL);
+
+ /* Get the actual data */
+ if (!CmpGetValueData(Hive,
+ Value,
+ Length,
+ (PVOID)&Buffer,
+ &BufferAllocated,
+ &CellToRelease))
+ {
+ /* We failed */
+ ASSERT(BufferAllocated == FALSE);
+ ASSERT(Buffer == NULL);
+ return NULL;
+ }
+
+ /* This should never happen!*/
+ if (BufferAllocated)
+ {
+ /* Free the buffer and bugcheck */
+ CmpFree(Buffer, 0);
+ KeBugCheckEx(REGISTRY_ERROR, 8, 0, (ULONG_PTR)Hive, (ULONG_PTR)Value);
+ }
+
+ /* 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, HCELL_NIL);
+ }
+
+ /* Fail if we couldn't get a cell */
+ if (ListCell == HCELL_NIL) 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);
+ ASSERT(CellData != NULL);
+
+ /* 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, HCELL_NIL);
+ 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;
+}
+
+NTSTATUS
+NTAPI
+CmpRemoveValueFromList(IN PHHIVE Hive,
+ IN ULONG Index,
+ IN OUT PCHILD_LIST ChildList)
+{
+ ULONG Count;
+ PCELL_DATA CellData;
+ HCELL_INDEX NewCell;
+ PAGED_CODE();
+
+ /* Sanity check */
+ ASSERT((((LONG)Index) >= 0) && (Index <= ChildList->Count));
+
+ /* Get the new count after removal */
+ Count = ChildList->Count - 1;
+ if (Count > 0)
+ {
+ /* Get the actual list array */
+ CellData = HvGetCell(Hive, ChildList->List);
+ if (!CellData) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Make sure cells data have been made dirty */
+ ASSERT(HvIsCellDirty(Hive, ChildList->List));
+ ASSERT(HvIsCellDirty(Hive, CellData->u.KeyList[Index]));
+
+ /* Loop the list */
+ while (Index < Count)
+ {
+ /* Move everything up */
+ CellData->u.KeyList[Index] = CellData->u.KeyList[Index + 1];
+ Index++;
+ }
+
+ /* Re-allocate the cell for the list by decreasing the count */
+ NewCell = HvReallocateCell(Hive,
+ ChildList->List,
+ Count * sizeof(HCELL_INDEX));
+ ASSERT(NewCell != HCELL_NIL);
+ HvReleaseCell(Hive,ChildList->List);
+
+ /* Update the list cell */
+ ChildList->List = NewCell;
+ }
+ else
+ {
+ /* Otherwise, we were the last entry, so free the list entirely */
+ HvFreeCell(Hive, ChildList->List);
+ ChildList->List = HCELL_NIL;
+ }
+
+ /* Update the child list with the new count */
+ ChildList->Count = Count;
+ return STATUS_SUCCESS;
+}