Author: aandrejevic
Date: Sat Aug  1 21:48:06 2015
New Revision: 68592
URL: 
http://svn.reactos.org/svn/reactos?rev=68592&view=rev
Log:
[NTVDM]
Implement XMS function 0Fh (Reallocate Extended Memory Block).
Modified:
    trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c   [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c   [iso-8859-1] Sat Aug  1
21:48:06 2015
@@ -272,6 +272,89 @@
     return XMS_STATUS_OUT_OF_MEMORY;
 }
+static UCHAR XmsRealloc(WORD Handle, WORD NewSize)
+{
+    DWORD BlockNumber;
+    PXMS_HANDLE HandleEntry = GetHandleRecord(Handle);
+    DWORD CurrentIndex = 0;
+    ULONG RunStart;
+    ULONG RunSize;
+
+    if (!ValidateHandle(HandleEntry))
+        return XMS_STATUS_INVALID_HANDLE;
+
+    if (HandleEntry->LockCount)
+        return XMS_STATUS_LOCKED;
+
+    /* Get the block number */
+    BlockNumber = (HandleEntry->Address - XMS_ADDRESS) / XMS_BLOCK_SIZE;
+
+    if (NewSize < HandleEntry->Size)
+    {
+        /* Just reduce the size of this block */
+        RtlClearBits(&AllocBitmap, BlockNumber + NewSize, HandleEntry->Size -
NewSize);
+        FreeBlocks += HandleEntry->Size - NewSize;
+        HandleEntry->Size = NewSize;
+    }
+    else if (NewSize > HandleEntry->Size)
+    {
+        /* Check if we can expand in-place */
+        if (RtlAreBitsClear(&AllocBitmap,
+                            BlockNumber + HandleEntry->Size,
+                            NewSize - HandleEntry->Size))
+        {
+            /* Just increase the size of this block */
+            RtlSetBits(&AllocBitmap,
+                       BlockNumber + HandleEntry->Size,
+                       NewSize - HandleEntry->Size);
+            FreeBlocks -= NewSize - HandleEntry->Size;
+            HandleEntry->Size = NewSize;
+
+            /* We're done */
+            return XMS_STATUS_SUCCESS;
+        }
+
+        /* Deallocate the current block range */
+        RtlClearBits(&AllocBitmap, BlockNumber, HandleEntry->Size);
+
+        /* Find a new place for this block */
+        while (CurrentIndex < XMS_BLOCKS)
+        {
+            RunSize = RtlFindNextForwardRunClear(&AllocBitmap, CurrentIndex,
&RunStart);
+            if (RunSize == 0) break;
+
+            if (RunSize >= NewSize)
+            {
+                /* Allocate the new range */
+                RtlSetBits(&AllocBitmap, RunStart, NewSize);
+
+                /* Move the data to the new location */
+                RtlMoveMemory((PVOID)REAL_TO_PHYS(XMS_ADDRESS + RunStart *
XMS_BLOCK_SIZE),
+                              (PVOID)REAL_TO_PHYS(HandleEntry->Address),
+                              HandleEntry->Size * XMS_BLOCK_SIZE);
+
+                /* Update the handle entry */
+                HandleEntry->Address = XMS_ADDRESS + RunStart * XMS_BLOCK_SIZE;
+                HandleEntry->Size = NewSize;
+
+                /* Update the free block counter */
+                FreeBlocks -= NewSize - HandleEntry->Size;
+
+                return XMS_STATUS_SUCCESS;
+            }
+
+            /* Keep searching */
+            CurrentIndex = RunStart + RunSize;
+        }
+
+        /* Restore the old block range */
+        RtlSetBits(&AllocBitmap, BlockNumber, HandleEntry->Size);
+        return XMS_STATUS_OUT_OF_MEMORY;
+    }
+
+    return XMS_STATUS_SUCCESS;
+}
+
 static UCHAR XmsFree(WORD Handle)
 {
     DWORD BlockNumber;
@@ -478,7 +561,7 @@
             WORD Handle;
             UCHAR Result = XmsAlloc(getDX(), &Handle);
-            if (Result >= 0)
+            if (Result == XMS_STATUS_SUCCESS)
             {
                 setAX(1);
                 setDX(Handle);
@@ -497,7 +580,7 @@
         {
             UCHAR Result = XmsFree(getDX());
-            setAX(Result >= 0);
+            setAX(Result == XMS_STATUS_SUCCESS);
             setBL(Result);
             break;
         }
@@ -571,7 +654,7 @@
             DWORD Address;
             UCHAR Result = XmsLock(getDX(), &Address);
-            if (Result >= 0)
+            if (Result == XMS_STATUS_SUCCESS)
             {
                 setAX(1);
@@ -593,7 +676,7 @@
         {
             UCHAR Result = XmsUnlock(getDX());
-            setAX(Result >= 0);
+            setAX(Result == XMS_STATUS_SUCCESS);
             setBL(Result);
             break;
         }
@@ -627,40 +710,10 @@
         /* Reallocate Extended Memory Block */
         case 0x0F:
         {
-            PXMS_HANDLE HandleEntry = GetHandleRecord(getDX());
-            WORD NewSize = getBX();
-
-            if (!ValidateHandle(HandleEntry))
-            {
-                setAX(0);
-                setBL(XMS_STATUS_INVALID_HANDLE);
-                break;
-            }
-
-            if (HandleEntry->LockCount)
-            {
-                setAX(0);
-                setBL(XMS_STATUS_LOCKED);
-                break;
-            }
-
-            /* Check for reduction or enlargement */
-            if (NewSize < HandleEntry->Size)
-            {
-                /* Reduction, the easy case: just update the size */
-                HandleEntry->Size = NewSize;
-            }
-            else
-            {
-                /* Enlargement: we need to reallocate elsewhere */
-                UNIMPLEMENTED;
-                setAX(0);
-                setBL(XMS_STATUS_NOT_IMPLEMENTED);
-                break;
-            }
-
-            setAX(1);
-            setBL(XMS_STATUS_SUCCESS);
+            UCHAR Result = XmsRealloc(getDX(), getBX());
+
+            setAX(Result == XMS_STATUS_SUCCESS);
+            setBL(Result);
             break;
         }