Used the size of the data cell instead of the previous data length to check if enough...
[reactos.git] / reactos / ntoskrnl / cm / ntfunc.c
index 57d5761..612d716 100644 (file)
@@ -202,7 +202,7 @@ NtCreateKey(OUT PHANDLE KeyHandle,
 
   PAGED_CODE();
 
-  PreviousMode = KeGetPreviousMode();
+  PreviousMode = ExGetPreviousMode();
 
   if (PreviousMode != KernelMode)
   {
@@ -982,7 +982,7 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
   Status = ObReferenceObjectByHandle(KeyHandle,
                KEY_QUERY_VALUE,
                CmiKeyType,
-               UserMode,
+               ExGetPreviousMode(),
                (PVOID *) &KeyObject,
                NULL);
 
@@ -1429,7 +1429,7 @@ NtQueryKey(IN HANDLE KeyHandle,
   Status = ObReferenceObjectByHandle(KeyHandle,
                (KeyInformationClass != KeyNameInformation ? KEY_QUERY_VALUE : 0),
                CmiKeyType,
-               UserMode,
+               ExGetPreviousMode(),
                (PVOID *) &KeyObject,
                NULL);
   if (!NT_SUCCESS(Status))
@@ -1655,7 +1655,7 @@ NtQueryValueKey(IN HANDLE KeyHandle,
   Status = ObReferenceObjectByHandle(KeyHandle,
                KEY_QUERY_VALUE,
                CmiKeyType,
-               UserMode,
+               ExGetPreviousMode(),
                (PVOID *)&KeyObject,
                NULL);
 
@@ -1902,10 +1902,10 @@ NtSetValueKey(IN HANDLE KeyHandle,
   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,74 +1979,74 @@ NtSetValueKey(IN HANDLE KeyHandle,
   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);
        }
 
       RtlCopyMemory(&ValueCell->DataOffset, Data, DataSize);
       ValueCell->DataSize = DataSize | REG_DATA_IN_OFFSET;
       ValueCell->DataType = Type;
-      RtlMoveMemory(&ValueCell->DataOffset, Data, DataSize);
       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;
-    }
-  else
-    {
-      /*
-       * 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);
+      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);
+
+          Status = CmiAllocateCell (RegistryHive,
+                                   sizeof(CELL_HEADER) + DataSize,
+                                   (PVOID *)&NewDataCell,
+                                   &NewOffset);
+          if (!NT_SUCCESS(Status))
+           {
+             DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status);
 
-      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;
-       }
+             ExReleaseResourceLite(&CmiRegistryLock);
+             KeLeaveCriticalRegion();
+              PostOperationInfo.Status = Status;
+              CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
+             ObDereferenceObject(KeyObject);
 
-      Status = CmiAllocateCell (RegistryHive,
-                               sizeof(CELL_HEADER) + DataSize,
-                               (PVOID *)&NewDataCell,
-                               &NewOffset);
-      if (!NT_SUCCESS(Status))
-       {
-         DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status);
+             return Status;
+           }
 
-         ExReleaseResourceLite(&CmiRegistryLock);
-         KeLeaveCriticalRegion();
-          PostOperationInfo.Status = Status;
-          CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
-         ObDereferenceObject(KeyObject);
+          if (DataCell)
+           {
+             CmiDestroyCell(RegistryHive, DataCell, ValueCell->DataOffset);
+           }
 
-         return Status;
-       }
+          ValueCell->DataOffset = NewOffset;
+          DataCell = NewDataCell;
+        }
 
-      RtlCopyMemory(&NewDataCell->Data[0], Data, DataSize);
+      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);
     }
@@ -2088,7 +2088,7 @@ NtDeleteValueKey (IN HANDLE KeyHandle,
 
   PAGED_CODE();
   
-  PreviousMode = KeGetPreviousMode();
+  PreviousMode = ExGetPreviousMode();
 
   /* Verify that the handle is valid and is a registry key */
   Status = ObReferenceObjectByHandle(KeyHandle,
@@ -2195,7 +2195,7 @@ NtLoadKey2 (IN POBJECT_ATTRIBUTES KeyObjectAttributes,
   DPRINT ("NtLoadKey2() called\n");
 
 #if 0
-  if (!SeSinglePrivilegeCheck (SeRestorePrivilege, KeGetPreviousMode ()))
+  if (!SeSinglePrivilegeCheck (SeRestorePrivilege, ExGetPreviousMode ()))
     return STATUS_PRIVILEGE_NOT_HELD;
 #endif
 
@@ -2366,7 +2366,7 @@ NtQueryMultipleValueKey (IN HANDLE KeyHandle,
   Status = ObReferenceObjectByHandle(KeyHandle,
                                     KEY_QUERY_VALUE,
                                     CmiKeyType,
-                                    UserMode,
+                                    ExGetPreviousMode(),
                                     (PVOID *) &KeyObject,
                                     NULL);
   if (!NT_SUCCESS(Status))
@@ -2513,14 +2513,14 @@ NtSaveKey (IN HANDLE KeyHandle,
   DPRINT ("NtSaveKey() called\n");
 
 #if 0
-  if (!SeSinglePrivilegeCheck (SeBackupPrivilege, KeGetPreviousMode ()))
+  if (!SeSinglePrivilegeCheck (SeBackupPrivilege, ExGetPreviousMode ()))
     return STATUS_PRIVILEGE_NOT_HELD;
 #endif
 
   Status = ObReferenceObjectByHandle (KeyHandle,
                                      0,
                                      CmiKeyType,
-                                     KeGetPreviousMode(),
+                                     ExGetPreviousMode(),
                                      (PVOID *)&KeyObject,
                                      NULL);
   if (!NT_SUCCESS(Status))
@@ -2620,7 +2620,7 @@ NtSetInformationKey (IN HANDLE KeyHandle,
   Status = ObReferenceObjectByHandle (KeyHandle,
                                      KEY_SET_VALUE,
                                      CmiKeyType,
-                                     UserMode,
+                                     ExGetPreviousMode(),
                                      (PVOID *)&KeyObject,
                                      NULL);
   if (!NT_SUCCESS (Status))
@@ -2702,7 +2702,7 @@ NtUnloadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes)
   DPRINT ("NtUnloadKey() called\n");
 
 #if 0
-  if (!SeSinglePrivilegeCheck (SeRestorePrivilege, KeGetPreviousMode ()))
+  if (!SeSinglePrivilegeCheck (SeRestorePrivilege, ExGetPreviousMode ()))
     return STATUS_PRIVILEGE_NOT_HELD;
 #endif