Used the size of the data cell instead of the previous data length to check if enough space is available (in NtSetValueKey).
Modified: trunk/reactos/ntoskrnl/cm/ntfunc.c

Modified: trunk/reactos/ntoskrnl/cm/ntfunc.c
--- trunk/reactos/ntoskrnl/cm/ntfunc.c	2005-11-23 22:10:30 UTC (rev 19506)
+++ trunk/reactos/ntoskrnl/cm/ntfunc.c	2005-11-23 22:16:21 UTC (rev 19507)
@@ -1902,10 +1902,10 @@
   BLOCK_OFFSET ValueCellOffset;
   PDATA_CELL DataCell;
   PDATA_CELL NewDataCell;
-  PHBIN pBin;
   ULONG DesiredAccess;
   REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo;
   REG_POST_OPERATION_INFORMATION PostOperationInfo;
+  ULONG DataCellSize;
 
   PAGED_CODE();
 
@@ -1979,14 +1979,25 @@
   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 = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
+      DataCellSize = (DataCell->CellSize < 0 ? -DataCell->CellSize : DataCell->CellSize) - sizeof(CELL_HEADER);
+    }
+  else
+    {
+      DataCell = NULL;
+      DataCellSize = 0;
+    }
+
+
   if (DataSize <= sizeof(BLOCK_OFFSET))
     {
       /* If data size <= sizeof(BLOCK_OFFSET) then store data in the data offset */
       DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
-      if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET) &&
-	  (ValueCell->DataSize & REG_DATA_SIZE_MASK) != 0)
+      if (DataCell)
 	{
-	  DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
 	  CmiDestroyCell(RegistryHive, DataCell, ValueCell->DataOffset);
 	}
 
@@ -1995,59 +2006,47 @@
       ValueCell->DataType = Type;
       CmiMarkBlockDirty(RegistryHive, ValueCellOffset);
     }
-  else if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET) &&
-	   (DataSize <= (ValueCell->DataSize & REG_DATA_SIZE_MASK)))
+  else 
     {
-      /* If new data size is <= current then overwrite current data */
-      DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset,&pBin);
-      RtlZeroMemory(DataCell->Data, ValueCell->DataSize);
-      RtlCopyMemory(DataCell->Data, Data, DataSize);
-      ValueCell->DataSize = DataSize;
-      ValueCell->DataType = Type;
-      CmiMarkBlockDirty(RegistryHive, ValueCell->DataOffset);
-      CmiMarkBlockDirty(RegistryHive, ValueCellOffset);
-    }
-  else
-    {
-      /*
-       * New data size is larger than the current, destroy current
-       * data block and allocate a new one.
-       */
-      BLOCK_OFFSET NewOffset;
+      if (DataSize > DataCellSize)
+        {
+         /*
+          * New data size is larger than the current, destroy current
+          * data block and allocate a new one.
+          */
+          BLOCK_OFFSET NewOffset;
 
-      DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
+          DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
 
-      if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET) &&
-	  (ValueCell->DataSize & REG_DATA_SIZE_MASK) != 0)
-	{
-	  DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
-	  CmiDestroyCell(RegistryHive, DataCell, ValueCell->DataOffset);
-	  ValueCell->DataSize = 0;
-	  ValueCell->DataType = 0;
-	  ValueCell->DataOffset = (BLOCK_OFFSET)-1;
-	}
+          Status = CmiAllocateCell (RegistryHive,
+				    sizeof(CELL_HEADER) + DataSize,
+				    (PVOID *)&NewDataCell,
+				    &NewOffset);
+          if (!NT_SUCCESS(Status))
+	    {
+	      DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status);
 
-      Status = CmiAllocateCell (RegistryHive,
-				sizeof(CELL_HEADER) + DataSize,
-				(PVOID *)&NewDataCell,
-				&NewOffset);
-      if (!NT_SUCCESS(Status))
-	{
-	  DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status);
+	      ExReleaseResourceLite(&CmiRegistryLock);
+	      KeLeaveCriticalRegion();
+              PostOperationInfo.Status = Status;
+              CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
+	      ObDereferenceObject(KeyObject);
 
-	  ExReleaseResourceLite(&CmiRegistryLock);
-	  KeLeaveCriticalRegion();
-          PostOperationInfo.Status = Status;
-          CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
-	  ObDereferenceObject(KeyObject);
+	      return Status;
+	    }
 
-	  return Status;
-	}
+          if (DataCell)
+	    {
+	      CmiDestroyCell(RegistryHive, DataCell, ValueCell->DataOffset);
+	    }
 
-      RtlCopyMemory(&NewDataCell->Data[0], Data, DataSize);
+          ValueCell->DataOffset = NewOffset;
+          DataCell = NewDataCell;
+        }
+
+      RtlCopyMemory(DataCell->Data, Data, DataSize);
       ValueCell->DataSize = DataSize & REG_DATA_SIZE_MASK;
       ValueCell->DataType = Type;
-      ValueCell->DataOffset = NewOffset;
       CmiMarkBlockDirty(RegistryHive, ValueCell->DataOffset);
       CmiMarkBlockDirty(RegistryHive, ValueCellOffset);
     }