From 68285022692160e5e429c0750d9b4732a694eade Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Sat, 1 Aug 2015 21:48:06 +0000 Subject: [PATCH] [NTVDM] Implement XMS function 0Fh (Reallocate Extended Memory Block). svn path=/trunk/; revision=68592 --- .../mvdm/ntvdm/dos/dos32krnl/himem.c | 127 +++++++++++++----- 1 file changed, 90 insertions(+), 37 deletions(-) diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c index dce3da29a5b..998244c6407 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c @@ -272,6 +272,89 @@ static UCHAR XmsAlloc(WORD Size, PWORD Handle) 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 @@ static VOID WINAPI XmsBopProcedure(LPWORD Stack) WORD Handle; UCHAR Result = XmsAlloc(getDX(), &Handle); - if (Result >= 0) + if (Result == XMS_STATUS_SUCCESS) { setAX(1); setDX(Handle); @@ -497,7 +580,7 @@ static VOID WINAPI XmsBopProcedure(LPWORD Stack) { UCHAR Result = XmsFree(getDX()); - setAX(Result >= 0); + setAX(Result == XMS_STATUS_SUCCESS); setBL(Result); break; } @@ -571,7 +654,7 @@ static VOID WINAPI XmsBopProcedure(LPWORD Stack) DWORD Address; UCHAR Result = XmsLock(getDX(), &Address); - if (Result >= 0) + if (Result == XMS_STATUS_SUCCESS) { setAX(1); @@ -593,7 +676,7 @@ static VOID WINAPI XmsBopProcedure(LPWORD Stack) { UCHAR Result = XmsUnlock(getDX()); - setAX(Result >= 0); + setAX(Result == XMS_STATUS_SUCCESS); setBL(Result); break; } @@ -627,40 +710,10 @@ static VOID WINAPI XmsBopProcedure(LPWORD Stack) /* Reallocate Extended Memory Block */ case 0x0F: { - PXMS_HANDLE HandleEntry = GetHandleRecord(getDX()); - WORD NewSize = getBX(); + UCHAR Result = XmsRealloc(getDX(), 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); + setAX(Result == XMS_STATUS_SUCCESS); + setBL(Result); break; }