Author: ion
Date: Sun May 13 22:39:35 2007
New Revision: 26760
URL:
http://svn.reactos.org/svn/reactos?rev=26760&view=rev
Log:
- HvGetCellSize should return the correct positive length instead of the raw negative
length. Update code and callers to match.
- Add cmapi.c file containing internal Cm* APIs for the Nt counterparts and to make it
easier to seperate the handle->object code, SEH and callback parts.
- Remove CmiAddValueToKey, CmiAllocateValueCell since we have new routines for this.
- Make NtSetValueKey a simple wrapper around CmSetValueKey.
- Implement CmSetValueKey based on previous code, but use newer Cm APIs instead (this also
fixes some cell allocation bugs regarding Stable/Volatile storage).
- New code is more conservative with HvMakeCellDirty calls when they're not needed,
and is more scalable to support big cells in the future.
Added:
trunk/reactos/ntoskrnl/config/cmapi.c
Modified:
trunk/reactos/lib/cmlib/hivecell.c
trunk/reactos/ntoskrnl/cm/cm.h
trunk/reactos/ntoskrnl/cm/ntfunc.c
trunk/reactos/ntoskrnl/cm/regfile.c
trunk/reactos/ntoskrnl/config/cm.h
trunk/reactos/ntoskrnl/config/cmvalue.c
trunk/reactos/ntoskrnl/ntoskrnl.rbuild
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 22:39:35 2007
@@ -82,17 +82,16 @@
}
LONG CMAPI
-HvGetCellSize(
- PHHIVE RegistryHive,
- PVOID Cell)
-{
- PHCELL CellHeader;
-
- CellHeader = (PHCELL)Cell - 1;
- if (CellHeader->Size < 0)
- return CellHeader->Size + sizeof(HCELL);
- else
- return CellHeader->Size - sizeof(HCELL);
+HvGetCellSize(IN PHHIVE Hive,
+ IN PVOID Address)
+{
+ PHCELL CellHeader;
+ LONG Size;
+
+ CellHeader = (PHCELL)Address - 1;
+ Size = CellHeader->Size * -1;
+ Size -= sizeof(HCELL);
+ return Size;
}
VOID CMAPI
@@ -375,8 +374,8 @@
OldCell = HvGetCell(RegistryHive, CellIndex);
OldCellSize = HvGetCellSize(RegistryHive, OldCell);
- ASSERT(OldCellSize < 0);
-
+ ASSERT(OldCellSize > 0);
+
/*
* If new data size is larger than the current, destroy current
* data block and allocate a new one.
@@ -384,14 +383,14 @@
* FIXME: Merge with adjacent free cell if possible.
* FIXME: Implement shrinking.
*/
- if (Size > (ULONG)-OldCellSize)
+ if (Size > OldCellSize)
{
NewCellIndex = HvAllocateCell(RegistryHive, Size, Storage);
if (NewCellIndex == HCELL_NULL)
return HCELL_NULL;
NewCell = HvGetCell(RegistryHive, NewCellIndex);
- RtlCopyMemory(NewCell, OldCell, (SIZE_T)-OldCellSize);
+ RtlCopyMemory(NewCell, OldCell, (SIZE_T)OldCellSize);
HvFreeCell(RegistryHive, CellIndex);
Modified: trunk/reactos/ntoskrnl/cm/cm.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/cm.h?rev=26760…
==============================================================================
--- trunk/reactos/ntoskrnl/cm/cm.h (original)
+++ trunk/reactos/ntoskrnl/cm/cm.h Sun May 13 22:39:35 2007
@@ -261,14 +261,6 @@
OUT PCM_KEY_VALUE *ValueCell);
NTSTATUS
-CmiAddValueToKey(IN PEREGISTRY_HIVE RegistryHive,
- IN PCM_KEY_NODE KeyCell,
- IN HCELL_INDEX KeyCellOffset,
- IN PUNICODE_STRING ValueName,
- OUT PCM_KEY_VALUE *pValueCell,
- OUT HCELL_INDEX *pValueCellOffset);
-
-NTSTATUS
CmiDeleteValueFromKey(IN PEREGISTRY_HIVE RegistryHive,
IN PCM_KEY_NODE KeyCell,
IN HCELL_INDEX KeyCellOffset,
@@ -295,16 +287,17 @@
HCELL_INDEX NKBOffset);
NTSTATUS
+NTAPI
+CmSetValueKey(IN PKEY_OBJECT KeyObject,
+ IN PUNICODE_STRING ValueName,
+ IN ULONG Type,
+ IN PVOID Data,
+ IN ULONG DataSize);
+
+NTSTATUS
CmiRemoveKeyFromHashTable(PEREGISTRY_HIVE RegistryHive,
PHASH_TABLE_CELL HashBlock,
HCELL_INDEX NKBOffset);
-
-NTSTATUS
-CmiAllocateValueCell(IN PEREGISTRY_HIVE RegistryHive,
- OUT PCM_KEY_VALUE *ValueCell,
- OUT HCELL_INDEX *VBOffset,
- IN PUNICODE_STRING ValueName,
- IN HV_STORAGE_TYPE Storage);
NTSTATUS
CmiDestroyValueCell(PEREGISTRY_HIVE RegistryHive,
Modified: trunk/reactos/ntoskrnl/cm/ntfunc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/ntfunc.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/cm/ntfunc.c (original)
+++ trunk/reactos/ntoskrnl/cm/ntfunc.c Sun May 13 22:39:35 2007
@@ -1799,193 +1799,60 @@
return Status;
}
-
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
NtSetValueKey(IN HANDLE KeyHandle,
- IN PUNICODE_STRING ValueName,
- IN ULONG TitleIndex,
- IN ULONG Type,
- IN PVOID Data,
- IN ULONG DataSize)
-{
- NTSTATUS Status;
- PKEY_OBJECT KeyObject;
- PEREGISTRY_HIVE RegistryHive;
- PCM_KEY_NODE KeyCell;
- PCM_KEY_VALUE ValueCell;
- HCELL_INDEX ValueCellOffset;
- PVOID DataCell;
- ULONG DesiredAccess;
- REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo;
- REG_POST_OPERATION_INFORMATION PostOperationInfo;
- ULONG DataCellSize;
-
- PAGED_CODE();
-
- DPRINT("NtSetValueKey(KeyHandle 0x%p ValueName '%wZ' Type %d)\n",
- KeyHandle, ValueName, Type);
-
- DesiredAccess = KEY_SET_VALUE;
-
- /* Verify that the handle is valid and is a registry key */
- Status = ObReferenceObjectByHandle(KeyHandle,
- DesiredAccess,
- CmpKeyObjectType,
- ExGetPreviousMode(),
- (PVOID *)&KeyObject,
- NULL);
- if (!NT_SUCCESS(Status))
- return(Status);
-
- PostOperationInfo.Object = (PVOID)KeyObject;
- SetValueKeyInfo.Object = (PVOID)KeyObject;
- SetValueKeyInfo.ValueName = ValueName;
- SetValueKeyInfo.TitleIndex = TitleIndex;
- SetValueKeyInfo.Type = Type;
- SetValueKeyInfo.Data = Data;
- SetValueKeyInfo.DataSize = DataSize;
- Status = CmiCallRegisteredCallbacks(RegNtPreSetValueKey, &SetValueKeyInfo);
- if (!NT_SUCCESS(Status))
- {
- PostOperationInfo.Status = Status;
- CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
- ObDereferenceObject(KeyObject);
- return Status;
- }
-
- /* Acquire hive lock exclucively */
- KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
-
- VERIFY_KEY_OBJECT(KeyObject);
-
- /* Get pointer to key cell */
- KeyCell = KeyObject->KeyCell;
- RegistryHive = KeyObject->RegistryHive;
- Status = CmiScanKeyForValue(RegistryHive,
- KeyCell,
- ValueName,
- &ValueCell,
- &ValueCellOffset);
- if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
- {
- DPRINT("Allocate new value cell\n");
- Status = CmiAddValueToKey(RegistryHive,
- KeyCell,
- KeyObject->KeyCellOffset,
- ValueName,
- &ValueCell,
- &ValueCellOffset);
- }
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Cannot add value. Status 0x%X\n", Status);
-
- ExReleaseResourceLite(&CmpRegistryLock);
- KeLeaveCriticalRegion();
- PostOperationInfo.Status = Status;
- CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
- ObDereferenceObject(KeyObject);
- return Status;
- }
-
- DPRINT("DataSize %lu\n", DataSize);
- DPRINT("ValueCell %p\n", ValueCell);
- DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
-
- if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET) &&
- (ValueCell->DataSize & REG_DATA_SIZE_MASK) != 0)
- {
- DataCell = HvGetCell (&RegistryHive->Hive, ValueCell->DataOffset);
- DataCellSize = -HvGetCellSize (&RegistryHive->Hive, DataCell);
- }
- else
- {
- DataCell = NULL;
- DataCellSize = 0;
- }
-
-
- if (DataSize <= sizeof(HCELL_INDEX))
- {
- /* If data size <= sizeof(HCELL_INDEX) then store data in the data offset */
- DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
- if (DataCell)
- {
- HvFreeCell(&RegistryHive->Hive, ValueCell->DataOffset);
- }
-
- RtlCopyMemory(&ValueCell->DataOffset, Data, DataSize);
- ValueCell->DataSize = DataSize | REG_DATA_IN_OFFSET;
- ValueCell->DataType = Type;
- HvMarkCellDirty(&RegistryHive->Hive, ValueCellOffset);
- }
- else
- {
- if (DataSize > DataCellSize)
- {
- /*
- * New data size is larger than the current, destroy current
- * data block and allocate a new one.
- */
- HCELL_INDEX NewOffset;
-
- DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
-
- NewOffset = HvAllocateCell (&RegistryHive->Hive, DataSize, HvStable);
- if (NewOffset == HCELL_NULL)
- {
- DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status);
-
- ExReleaseResourceLite(&CmpRegistryLock);
- KeLeaveCriticalRegion();
- PostOperationInfo.Status = Status;
- CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
- ObDereferenceObject(KeyObject);
-
- return Status;
- }
-
- if (DataCell)
- {
- HvFreeCell(&RegistryHive->Hive, ValueCell->DataOffset);
- }
-
- ValueCell->DataOffset = NewOffset;
- DataCell = HvGetCell(&RegistryHive->Hive, NewOffset);
- }
-
- RtlCopyMemory(DataCell, Data, DataSize);
- ValueCell->DataSize = DataSize & REG_DATA_SIZE_MASK;
- ValueCell->DataType = Type;
- HvMarkCellDirty(&RegistryHive->Hive, ValueCell->DataOffset);
- HvMarkCellDirty(&RegistryHive->Hive, ValueCellOffset);
- }
-
- /* Mark link key */
- if ((Type == REG_LINK) &&
- (_wcsicmp(ValueName->Buffer, L"SymbolicLinkValue") == 0))
- {
- KeyCell->Flags |= REG_KEY_LINK_CELL;
- }
-
- KeQuerySystemTime (&KeyCell->LastWriteTime);
- HvMarkCellDirty (&RegistryHive->Hive, KeyObject->KeyCellOffset);
-
- ExReleaseResourceLite(&CmpRegistryLock);
- KeLeaveCriticalRegion();
- PostOperationInfo.Status = Status;
- CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
- ObDereferenceObject(KeyObject);
-
- CmiSyncHives();
-
- DPRINT("Return Status 0x%X\n", Status);
-
- return Status;
-}
-
+ IN PUNICODE_STRING ValueName,
+ IN ULONG TitleIndex,
+ IN ULONG Type,
+ IN PVOID Data,
+ IN ULONG DataSize)
+{
+ NTSTATUS Status;
+ PKEY_OBJECT KeyObject;
+ REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo;
+ REG_POST_OPERATION_INFORMATION PostOperationInfo;
+ PAGED_CODE();
+
+ /* Verify that the handle is valid and is a registry key */
+ Status = ObReferenceObjectByHandle(KeyHandle,
+ KEY_SET_VALUE,
+ CmpKeyObjectType,
+ ExGetPreviousMode(),
+ (PVOID *)&KeyObject,
+ NULL);
+ if (!NT_SUCCESS(Status)) return(Status);
+
+ /* Setup callback */
+ PostOperationInfo.Object = (PVOID)KeyObject;
+ SetValueKeyInfo.Object = (PVOID)KeyObject;
+ SetValueKeyInfo.ValueName = ValueName;
+ SetValueKeyInfo.TitleIndex = TitleIndex;
+ SetValueKeyInfo.Type = Type;
+ SetValueKeyInfo.Data = Data;
+ SetValueKeyInfo.DataSize = DataSize;
+
+ /* Do the callback */
+ Status = CmiCallRegisteredCallbacks(RegNtPreSetValueKey, &SetValueKeyInfo);
+ if (NT_SUCCESS(Status))
+ {
+ /* Call the internal API */
+ Status = CmSetValueKey(KeyObject,
+ ValueName,
+ Type,
+ Data,
+ DataSize);
+ }
+
+ /* Do the post-callback and de-reference the key object */
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
+ ObDereferenceObject(KeyObject);
+
+ /* Synchronize the hives and return */
+ CmiSyncHives();
+ return Status;
+}
NTSTATUS STDCALL
NtDeleteValueKey (IN HANDLE KeyHandle,
Modified: trunk/reactos/ntoskrnl/cm/regfile.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/regfile.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/cm/regfile.c (original)
+++ trunk/reactos/ntoskrnl/cm/regfile.c Sun May 13 22:39:35 2007
@@ -57,22 +57,6 @@
DPRINT ("CmiLoadHive() done\n");
return Status;
-}
-
-
-NTSTATUS
-CmiRemoveRegistaryHive(PEREGISTRY_HIVE RegistryHive)
-{
- /* Remove hive from hive list */
- RemoveEntryList (&RegistryHive->HiveList);
-
- /* Release file names */
- RtlFreeUnicodeString (&RegistryHive->HiveFileName);
-
- /* Release hive */
- HvFree (&RegistryHive->Hive);
-
- return STATUS_SUCCESS;
}
VOID
@@ -680,93 +664,6 @@
return STATUS_SUCCESS;
}
-
-NTSTATUS
-CmiAddValueToKey(IN PEREGISTRY_HIVE RegistryHive,
- IN PCM_KEY_NODE KeyCell,
- IN HCELL_INDEX KeyCellOffset,
- IN PUNICODE_STRING ValueName,
- OUT PCM_KEY_VALUE *pValueCell,
- OUT HCELL_INDEX *pValueCellOffset)
-{
- PVALUE_LIST_CELL ValueListCell;
- PCM_KEY_VALUE NewValueCell;
- HCELL_INDEX ValueListCellOffset;
- HCELL_INDEX NewValueCellOffset;
- ULONG CellSize;
- HV_STORAGE_TYPE Storage;
- NTSTATUS Status;
-
- DPRINT("KeyCell->ValuesOffset %lu\n", (ULONG)KeyCell->ValueList.List);
-
- Storage = (KeyCell->Flags & REG_KEY_VOLATILE_CELL) ? HvVolatile : HvStable;
- if (KeyCell->ValueList.List == HCELL_NULL)
- {
- CellSize = sizeof(VALUE_LIST_CELL) +
- (3 * sizeof(HCELL_INDEX));
- ValueListCellOffset = HvAllocateCell (&RegistryHive->Hive, CellSize,
Storage);
- if (ValueListCellOffset == HCELL_NULL)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- ValueListCell = HvGetCell (&RegistryHive->Hive, ValueListCellOffset);
- KeyCell->ValueList.List = ValueListCellOffset;
- HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset);
- }
- else
- {
- ValueListCell = (PVALUE_LIST_CELL) HvGetCell (&RegistryHive->Hive,
KeyCell->ValueList.List);
- CellSize = ABS_VALUE(HvGetCellSize(&RegistryHive->Hive, ValueListCell));
-
- if (KeyCell->ValueList.Count >=
- (CellSize / sizeof(HCELL_INDEX)))
- {
- CellSize *= 2;
- ValueListCellOffset = HvReallocateCell (&RegistryHive->Hive,
KeyCell->ValueList.List, CellSize);
- if (ValueListCellOffset == HCELL_NULL)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- ValueListCell = HvGetCell (&RegistryHive->Hive, ValueListCellOffset);
- KeyCell->ValueList.List = ValueListCellOffset;
- HvMarkCellDirty (&RegistryHive->Hive, KeyCellOffset);
- }
- }
-
-#if 0
- DPRINT("KeyCell->ValueList.Count %lu, ValueListCell->Size %lu (%lu
%lx)\n",
- KeyCell->ValueList.Count,
- (ULONG)ABS_VALUE(ValueListCell->Size),
- ((ULONG)ABS_VALUE(ValueListCell->Size) - sizeof(HCELL)) / sizeof(HCELL_INDEX),
- ((ULONG)ABS_VALUE(ValueListCell->Size) - sizeof(HCELL)) / sizeof(HCELL_INDEX));
-#endif
-
- Status = CmiAllocateValueCell(RegistryHive,
- &NewValueCell,
- &NewValueCellOffset,
- ValueName,
- Storage);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- ValueListCell->ValueOffset[KeyCell->ValueList.Count] = NewValueCellOffset;
- KeyCell->ValueList.Count++;
-
- HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset);
- HvMarkCellDirty(&RegistryHive->Hive, KeyCell->ValueList.List);
- HvMarkCellDirty(&RegistryHive->Hive, NewValueCellOffset);
-
- *pValueCell = NewValueCell;
- *pValueCellOffset = NewValueCellOffset;
-
- return STATUS_SUCCESS;
-}
-
-
NTSTATUS
CmiDeleteValueFromKey(IN PEREGISTRY_HIVE RegistryHive,
IN PCM_KEY_NODE KeyCell,
@@ -934,63 +831,6 @@
return STATUS_UNSUCCESSFUL;
}
-
-NTSTATUS
-CmiAllocateValueCell(PEREGISTRY_HIVE RegistryHive,
- PCM_KEY_VALUE *ValueCell,
- HCELL_INDEX *VBOffset,
- IN PUNICODE_STRING ValueName,
- IN HV_STORAGE_TYPE Storage)
-{
- PCM_KEY_VALUE NewValueCell;
- NTSTATUS Status;
- BOOLEAN Packable;
- ULONG NameSize;
- ULONG i;
-
- Status = STATUS_SUCCESS;
-
- NameSize = CmiGetPackedNameLength(ValueName,
- &Packable);
-
- DPRINT("ValueName->Length %lu NameSize %lu\n", ValueName->Length,
NameSize);
-
- *VBOffset = HvAllocateCell (&RegistryHive->Hive, sizeof(CM_KEY_VALUE) +
NameSize, Storage);
- if (*VBOffset == HCELL_NULL)
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
- else
- {
- ASSERT(NameSize <= 0xffff); /* should really be USHORT_MAX or similar */
- NewValueCell = HvGetCell (&RegistryHive->Hive, *VBOffset);
- NewValueCell->Id = REG_VALUE_CELL_ID;
- NewValueCell->NameSize = (USHORT)NameSize;
- if (Packable)
- {
- /* Pack the value name */
- for (i = 0; i < NameSize; i++)
- NewValueCell->Name[i] = (CHAR)ValueName->Buffer[i];
- NewValueCell->Flags |= REG_VALUE_NAME_PACKED;
- }
- else
- {
- /* Copy the value name */
- RtlCopyMemory(NewValueCell->Name,
- ValueName->Buffer,
- NameSize);
- NewValueCell->Flags = 0;
- }
- NewValueCell->DataType = 0;
- NewValueCell->DataSize = 0;
- NewValueCell->DataOffset = (HCELL_INDEX)-1;
- *ValueCell = NewValueCell;
- }
-
- return Status;
-}
-
-
NTSTATUS
CmiDestroyValueCell(PEREGISTRY_HIVE RegistryHive,
PCM_KEY_VALUE ValueCell,
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 22:39:35 2007
@@ -1049,6 +1049,21 @@
IN HCELL_INDEX Cell
);
+BOOLEAN
+NTAPI
+CmpMarkValueDataDirty(
+ IN PHHIVE Hive,
+ IN PCM_KEY_VALUE Value
+);
+
+BOOLEAN
+NTAPI
+CmpFreeValueData(
+ IN PHHIVE Hive,
+ IN HCELL_INDEX DataCell,
+ IN ULONG DataLength
+);
+
//
// Boot Routines
//
Added: trunk/reactos/ntoskrnl/config/cmapi.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmapi.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmapi.c (added)
+++ trunk/reactos/ntoskrnl/config/cmapi.c Sun May 13 22:39:35 2007
@@ -1,0 +1,342 @@
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: ntoskrnl/config/cmapi.c
+ * PURPOSE: Configuration Manager - Internal Registry APIs
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu(a)reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include "ntoskrnl.h"
+#include "cm.h"
+#define NDEBUG
+#include "debug.h"
+
+/* FUNCTIONS *****************************************************************/
+
+NTSTATUS
+NTAPI
+CmpSetValueKeyNew(IN PHHIVE Hive,
+ IN PCM_KEY_NODE Parent,
+ IN PUNICODE_STRING ValueName,
+ IN ULONG Index,
+ IN ULONG Type,
+ IN PVOID Data,
+ IN ULONG DataSize,
+ IN ULONG StorageType,
+ IN ULONG SmallData)
+{
+ PCELL_DATA CellData;
+ HCELL_INDEX ValueCell;
+ NTSTATUS Status;
+
+ /* Check if we already have a value list */
+ if (Parent->ValueList.Count)
+ {
+ /* Then make sure it's valid and dirty it */
+ ASSERT(Parent->ValueList.List != HCELL_NIL);
+ HvMarkCellDirty(Hive, Parent->ValueList.List);
+ }
+
+ /* Allocate avalue cell */
+ ValueCell = HvAllocateCell(Hive,
+ FIELD_OFFSET(CM_KEY_VALUE, Name) +
+ CmpNameSize(Hive, ValueName),
+ StorageType);
+ if (ValueCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Get the actual data for it */
+ CellData = HvGetCell(Hive, ValueCell);
+ if (!CellData) ASSERT(FALSE);
+
+ /* Now we can release it, make sure it's also dirty */
+ HvReleaseCell(Hive, ValueCell);
+ ASSERT(HvIsCellDirty(Hive, ValueCell));
+
+ /* Set it up and copy the name */
+ CellData->u.KeyValue.Signature = CM_KEY_VALUE_SIGNATURE;
+ CellData->u.KeyValue.Flags = 0;
+ CellData->u.KeyValue.Type = Type;
+ CellData->u.KeyValue.NameLength = CmpCopyName(Hive,
+ CellData->u.KeyValue.Name,
+ ValueName);
+ if (CellData->u.KeyValue.NameLength < ValueName->Length)
+ {
+ /* This is a compressed name */
+ CellData->u.KeyValue.Flags = VALUE_COMP_NAME;
+ }
+
+ /* Check if this is a normal key */
+ if (DataSize > CM_KEY_VALUE_SMALL)
+ {
+ /* Build a data cell for it */
+ Status = CmpSetValueDataNew(Hive,
+ Data,
+ DataSize,
+ StorageType,
+ ValueCell,
+ &CellData->u.KeyValue.Data);
+ if (!NT_SUCCESS(Status))
+ {
+ /* We failed, free the cell */
+ HvFreeCell(Hive, ValueCell);
+ return Status;
+ }
+
+ /* Otherwise, set the data length, and make sure the data is dirty */
+ CellData->u.KeyValue.DataLength = DataSize;
+ ASSERT(HvIsCellDirty(Hive,CellData->u.KeyValue.Data));
+ }
+ else
+ {
+ /* This is a small key, set the data directly inside */
+ CellData->u.KeyValue.DataLength = DataSize + CM_KEY_VALUE_SPECIAL_SIZE;
+ CellData->u.KeyValue.Data = SmallData;
+ }
+
+ /* Add this value cell to the child list */
+ Status = CmpAddValueToList(Hive,
+ ValueCell,
+ Index,
+ StorageType,
+ &Parent->ValueList);
+
+ /* If we failed, free the entire cell, including the data */
+ if (!NT_SUCCESS(Status)) CmpFreeValue(Hive, ValueCell);
+
+ /* Return status */
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+CmpSetValueKeyExisting(IN PHHIVE Hive,
+ IN HCELL_INDEX OldChild,
+ IN PCM_KEY_VALUE Value,
+ IN ULONG Type,
+ IN PVOID Data,
+ IN ULONG DataSize,
+ IN ULONG StorageType,
+ IN ULONG TempData)
+{
+ HCELL_INDEX DataCell, NewCell;
+ PCELL_DATA CellData;
+ ULONG Length;
+ BOOLEAN WasSmall, IsSmall;
+
+ /* Mark the old child cell dirty */
+ HvMarkCellDirty(Hive, OldChild);
+
+ /* See if this is a small or normal key */
+ WasSmall = CmpIsKeyValueSmall(&Length, Value->DataLength);
+
+ /* See if our new data can fit in a small key */
+ IsSmall = (DataSize <= CM_KEY_VALUE_SMALL) ? TRUE: FALSE;
+
+ /* Big keys are unsupported */
+ ASSERT_VALUE_BIG(Hive, Length);
+ ASSERT_VALUE_BIG(Hive, DataSize);
+
+ /* Mark the old value dirty */
+ CmpMarkValueDataDirty(Hive, Value);
+
+ /* Check if we have a small key */
+ if (IsSmall)
+ {
+ /* Check if we had a normal key with some data in it */
+ if (!(WasSmall) && (Length > 0))
+ {
+ /* Free the previous data */
+ CmpFreeValueData(Hive, Value->Data, Length);
+ }
+
+ /* Write our data directly */
+ Value->DataLength = DataSize + CM_KEY_VALUE_SPECIAL_SIZE;
+ Value->Data = TempData;
+ Value->Type = Type;
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ /* We have a normal key. Was the old cell also normal and had data? */
+ if (!(WasSmall) && (Length > 0))
+ {
+ /* Get the current data cell and actual data inside it */
+ DataCell = Value->Data;
+ ASSERT(DataCell != HCELL_NIL);
+ CellData = HvGetCell(Hive, DataCell);
+ if (!CellData) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Immediately release the cell */
+ HvReleaseCell(Hive, DataCell);
+
+ /* Make sure that the data cell actually has a size */
+ ASSERT(HvGetCellSize(Hive, CellData) > 0);
+
+ /* Check if the previous data cell could fit our new data */
+ if (DataSize <= (ULONG)(HvGetCellSize(Hive, CellData)))
+ {
+ /* Re-use it then */
+ NewCell = DataCell;
+ }
+ else
+ {
+ /* Otherwise, re-allocate the current data cell */
+ NewCell = HvReallocateCell(Hive, DataCell, DataSize);
+ if (NewCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ else
+ {
+ /* This was a small key, or a key with no data, allocate a cell */
+ NewCell = HvAllocateCell(Hive, DataSize, StorageType);
+ if (NewCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Now get the actual data for our data cell */
+ CellData = HvGetCell(Hive, NewCell);
+ if (!CellData) ASSERT(FALSE);
+
+ /* Release it immediately */
+ HvReleaseCell(Hive, NewCell);
+
+ /* Copy our data into the data cell's buffer, and set up the value */
+ RtlCopyMemory(CellData, Data, DataSize);
+ Value->Data = NewCell;
+ Value->DataLength = DataSize;
+ Value->Type = Type;
+
+ /* Return success */
+ ASSERT(HvIsCellDirty(Hive, NewCell));
+ return STATUS_SUCCESS;
+ }
+}
+
+NTSTATUS
+NTAPI
+CmSetValueKey(IN PKEY_OBJECT KeyObject,
+ IN PUNICODE_STRING ValueName,
+ IN ULONG Type,
+ IN PVOID Data,
+ IN ULONG DataLength)
+{
+ PHHIVE Hive;
+ PCM_KEY_NODE Parent;
+ PCM_KEY_VALUE Value = NULL;
+ HCELL_INDEX CurrentChild, Cell;
+ NTSTATUS Status;
+ BOOLEAN Found, Result;
+ ULONG Count, ChildIndex, SmallData, Storage;
+
+ /* Acquire hive lock exclusively */
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
+
+ /* Get pointer to key cell */
+ Parent = KeyObject->KeyCell;
+ Hive = &KeyObject->RegistryHive->Hive;
+ Cell = KeyObject->KeyCellOffset;
+
+ /* Prepare to scan the key node */
+ Count = Parent->ValueList.Count;
+ Found = FALSE;
+ if (Count > 0)
+ {
+ /* Try to find the existing name */
+ Result = CmpFindNameInList(Hive,
+ &Parent->ValueList,
+ ValueName,
+ &ChildIndex,
+ &CurrentChild);
+ if (!Result)
+ {
+ /* Fail */
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Quickie;
+ }
+
+ /* Check if we found something */
+ if (CurrentChild != HCELL_NIL)
+ {
+ /* Get its value */
+ Value = (PCM_KEY_VALUE)HvGetCell(Hive, CurrentChild);
+ if (!Value)
+ {
+ /* Fail */
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Quickie;
+ }
+
+ /* Remember that we found it */
+ Found = TRUE;
+ }
+ }
+ else
+ {
+ /* No child list, we'll need to add it */
+ ChildIndex = 0;
+ }
+
+ /* Mark the cell dirty */
+ HvMarkCellDirty(Hive, Cell);
+
+ /* Get the storage type */
+ Storage = HvGetCellType(Cell);
+
+ /* Check if this is small data */
+ SmallData = 0;
+ if ((DataLength <= CM_KEY_VALUE_SMALL) && (DataLength > 0))
+ {
+ /* Copy it */
+ RtlCopyMemory(&SmallData, Data, DataLength);
+ }
+
+ /* Check if we didn't find a matching key */
+ if (!Found)
+ {
+ /* Call the internal routine */
+ Status = CmpSetValueKeyNew(Hive,
+ Parent,
+ ValueName,
+ ChildIndex,
+ Type,
+ Data,
+ DataLength,
+ Storage,
+ SmallData);
+ }
+ else
+ {
+ /* Call the internal routine */
+ Status = CmpSetValueKeyExisting(Hive,
+ CurrentChild,
+ Value,
+ Type,
+ Data,
+ DataLength,
+ Storage,
+ SmallData);
+ }
+
+ /* Mark link key */
+ if ((Type == REG_LINK) &&
+ (_wcsicmp(ValueName->Buffer, L"SymbolicLinkValue") == 0))
+ {
+ Parent->Flags |= KEY_SYM_LINK;
+ }
+
+ /* Check for success */
+Quickie:
+ if (NT_SUCCESS(Status))
+ {
+ /* Save the write time */
+ KeQuerySystemTime(&Parent->LastWriteTime);
+ }
+
+ /* Release the lock */
+ ExReleaseResourceLite(&CmpRegistryLock);
+ KeLeaveCriticalRegion();
+ return Status;
+}
+
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 22:39:35 2007
@@ -56,7 +56,7 @@
if (DataCell == HCELL_NIL) return TRUE;
/* Make sure the data cell is allocated */
- ASSERT(HvIsCellAllocated(Hive, DataCell));
+ //ASSERT(HvIsCellAllocated(Hive, DataCell));
/* Unsupported value type */
ASSERT_VALUE_BIG(Hive, KeySize);
Modified: trunk/reactos/ntoskrnl/ntoskrnl.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl.rbuild?r…
==============================================================================
--- trunk/reactos/ntoskrnl/ntoskrnl.rbuild (original)
+++ trunk/reactos/ntoskrnl/ntoskrnl.rbuild Sun May 13 22:39:35 2007
@@ -89,6 +89,7 @@
<file>cmhardwr.c</file>
</directory>
</if>
+ <file>cmapi.c</file>
<file>cmboot.c</file>
<file>cmcheck.c</file>
<file>cmcontrl.c</file>