From a8c3b4f1d93fab45774a14950f4d35e4f91bca9d Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Mon, 27 Apr 2015 03:37:24 +0000 Subject: [PATCH] [NTVDM] - In INT 21h, AH = 0Ah, the final carriage return is not counted. - Implement XMS function 0Bh (Move Extended Memory Block). - The driver must preserve the contents of unlocked Extended Memory Blocks (EMBs), so move the bitmap setting/clearing code into XmsAlloc and XmsFree. - Make XmsAlloc optimize memory blocks by moving them around, except it can't move locked blocks. svn path=/trunk/; revision=67457 --- .../subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c | 4 +- .../mvdm/ntvdm/dos/dos32krnl/himem.c | 170 +++++++++++++----- .../mvdm/ntvdm/dos/dos32krnl/himem.h | 15 ++ 3 files changed, 146 insertions(+), 43 deletions(-) diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c index ae904a20c89..9f49650ef34 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c @@ -1036,7 +1036,6 @@ VOID WINAPI DosInt21h(LPWORD Stack) { /* Append it to the buffer */ InputBuffer->Buffer[Count] = Character; - Count++; /* Carriage returns are also counted */ /* Check if this is a special character */ if (Character < 0x20 && Character != 0x0A && Character != 0x0D) @@ -1051,10 +1050,11 @@ VOID WINAPI DosInt21h(LPWORD Stack) } if (Character == '\r') break; + Count++; /* Carriage returns are NOT counted */ } /* Update the length */ - InputBuffer->Length = Count; + InputBuffer->Length = Count - 1; break; } diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c index 816141abf28..4da96bbf5f8 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c @@ -26,6 +26,15 @@ /* BOP Identifiers */ #define BOP_XMS 0x52 +ULONG +NTAPI +RtlFindLastBackwardRunClear +( + IN PRTL_BITMAP BitMapHeader, + IN ULONG FromIndex, + OUT PULONG StartingRunIndex +); + /* PRIVATE VARIABLES **********************************************************/ static const BYTE EntryProcedure[] = { @@ -180,6 +189,9 @@ static CHAR XmsAlloc(WORD Size, PWORD Handle) { BYTE i; PXMS_HANDLE HandleEntry; + DWORD CurrentIndex = 0; + ULONG RunStart; + ULONG RunSize; if (Size > FreeBlocks) return XMS_STATUS_OUT_OF_MEMORY; @@ -195,55 +207,43 @@ static CHAR XmsAlloc(WORD Size, PWORD Handle) if (i == XMS_MAX_HANDLES) return XMS_STATUS_OUT_OF_HANDLES; - HandleEntry->Handle = i + 1; - HandleEntry->LockCount = 0; - HandleEntry->Size = Size; - FreeBlocks -= Size; - - return XMS_STATUS_SUCCESS; -} - -static CHAR XmsFree(WORD Handle) -{ - PXMS_HANDLE HandleEntry = GetHandleRecord(Handle); - if (HandleEntry == NULL) return XMS_STATUS_INVALID_HANDLE; - if (HandleEntry->LockCount) return XMS_STATUS_LOCKED; + /* Optimize blocks */ + for (i = 0; i < XMS_MAX_HANDLES; i++) + { + /* Skip free and locked blocks */ + if (HandleEntry->Handle == 0 || HandleEntry->LockCount > 0) continue; - HandleEntry->Handle = 0; - FreeBlocks += HandleEntry->Size; + CurrentIndex = (HandleEntry->Address - XMS_ADDRESS) / XMS_BLOCK_SIZE; - return XMS_STATUS_SUCCESS; -} + /* Check if there is any free space before this block */ + RunSize = RtlFindLastBackwardRunClear(&AllocBitmap, CurrentIndex, &RunStart); + if (RunSize == 0) break; -static CHAR XmsLock(WORD Handle, PDWORD Address) -{ - DWORD CurrentIndex = 0; - PXMS_HANDLE HandleEntry = GetHandleRecord(Handle); + /* Move this block back */ + RtlMoveMemory((PVOID)REAL_TO_PHYS(HandleEntry->Address - RunSize * XMS_BLOCK_SIZE), + (PVOID)REAL_TO_PHYS(HandleEntry->Address), + RunSize * XMS_BLOCK_SIZE); - if (HandleEntry == NULL) return XMS_STATUS_INVALID_HANDLE; - if (HandleEntry->LockCount == 0xFF) return XMS_STATUS_LOCK_OVERFLOW; - - if (HandleEntry->LockCount) - { - /* Just increment the lock count */ - HandleEntry->LockCount++; - return XMS_STATUS_SUCCESS; + /* Update the address */ + HandleEntry->Address -= RunSize * XMS_BLOCK_SIZE; } while (CurrentIndex < XMS_BLOCKS) { - ULONG RunStart; - ULONG RunSize = RtlFindNextForwardRunClear(&AllocBitmap, CurrentIndex, &RunStart); + RunSize = RtlFindNextForwardRunClear(&AllocBitmap, CurrentIndex, &RunStart); if (RunSize == 0) break; if (RunSize >= HandleEntry->Size) { - /* Lock it here */ - HandleEntry->LockCount++; + /* Allocate it here */ + HandleEntry->Handle = i + 1; + HandleEntry->LockCount = 0; + HandleEntry->Size = Size; HandleEntry->Address = XMS_ADDRESS + RunStart * XMS_BLOCK_SIZE; + FreeBlocks -= Size; RtlSetBits(&AllocBitmap, RunStart, RunSize); - *Address = HandleEntry->Address; + return XMS_STATUS_SUCCESS; } @@ -251,24 +251,50 @@ static CHAR XmsLock(WORD Handle, PDWORD Address) CurrentIndex = RunStart + RunSize; } - /* Can't find any suitable range */ - return XMS_STATUS_CANNOT_LOCK; + return XMS_STATUS_OUT_OF_MEMORY; } -static CHAR XmsUnlock(WORD Handle) +static CHAR XmsFree(WORD Handle) { DWORD BlockNumber; PXMS_HANDLE HandleEntry = GetHandleRecord(Handle); if (HandleEntry == NULL) return XMS_STATUS_INVALID_HANDLE; - if (!HandleEntry->LockCount) return XMS_STATUS_NOT_LOCKED; - - /* Decrement the lock count and exit early if it's still locked */ - if (--HandleEntry->LockCount) return XMS_STATUS_SUCCESS; + if (HandleEntry->LockCount) return XMS_STATUS_LOCKED; BlockNumber = (HandleEntry->Address - XMS_ADDRESS) / XMS_BLOCK_SIZE; RtlClearBits(&AllocBitmap, BlockNumber, HandleEntry->Size); + HandleEntry->Handle = 0; + FreeBlocks += HandleEntry->Size; + + return XMS_STATUS_SUCCESS; +} + +static CHAR XmsLock(WORD Handle, PDWORD Address) +{ + PXMS_HANDLE HandleEntry = GetHandleRecord(Handle); + + if (HandleEntry == NULL) return XMS_STATUS_INVALID_HANDLE; + if (HandleEntry->LockCount == 0xFF) return XMS_STATUS_LOCK_OVERFLOW; + + /* Increment the lock count */ + HandleEntry->LockCount++; + *Address = HandleEntry->Address; + + return XMS_STATUS_SUCCESS; +} + +static CHAR XmsUnlock(WORD Handle) +{ + PXMS_HANDLE HandleEntry = GetHandleRecord(Handle); + + if (HandleEntry == NULL) return XMS_STATUS_INVALID_HANDLE; + if (!HandleEntry->LockCount) return XMS_STATUS_NOT_LOCKED; + + /* Decrement the lock count */ + HandleEntry->LockCount--; + return XMS_STATUS_SUCCESS; } @@ -391,6 +417,68 @@ static VOID WINAPI XmsBopProcedure(LPWORD Stack) break; } + /* Move Extended Memory Block */ + case 0x0B: + { + PVOID SourceAddress, DestAddress; + PXMS_COPY_DATA CopyData = (PXMS_COPY_DATA)SEG_OFF_TO_PTR(getDS(), getSI()); + + if (CopyData->SourceHandle) + { + PXMS_HANDLE Entry = GetHandleRecord(CopyData->SourceHandle); + if (!Entry) + { + setAX(0); + setBL(XMS_STATUS_BAD_SRC_HANDLE); + break; + } + + if (CopyData->SourceOffset >= Entry->Size * XMS_BLOCK_SIZE) + { + setAX(0); + setBL(XMS_STATUS_BAD_SRC_OFFSET); + } + + SourceAddress = (PVOID)REAL_TO_PHYS(Entry->Address + CopyData->SourceOffset); + } + else + { + /* The offset is actually a 16-bit segment:offset pointer */ + SourceAddress = SEG_OFF_TO_PTR(HIWORD(CopyData->SourceOffset), + LOWORD(CopyData->SourceOffset)); + } + + if (CopyData->DestHandle) + { + PXMS_HANDLE Entry = GetHandleRecord(CopyData->DestHandle); + if (!Entry) + { + setAX(0); + setBL(XMS_STATUS_BAD_DEST_HANDLE); + break; + } + + if (CopyData->DestOffset >= Entry->Size * XMS_BLOCK_SIZE) + { + setAX(0); + setBL(XMS_STATUS_BAD_DEST_OFFSET); + } + + DestAddress = (PVOID)REAL_TO_PHYS(Entry->Address + CopyData->DestOffset); + } + else + { + /* The offset is actually a 16-bit segment:offset pointer */ + DestAddress = SEG_OFF_TO_PTR(HIWORD(CopyData->DestOffset), + LOWORD(CopyData->DestOffset)); + } + + setAX(1); + setBL(XMS_STATUS_SUCCESS); + RtlMoveMemory(DestAddress, SourceAddress, CopyData->Count); + break; + } + /* Lock Extended Memory Block */ case 0x0C: { diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h index 142de4afdf6..fb661354d3d 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h @@ -20,6 +20,10 @@ #define XMS_STATUS_OUT_OF_MEMORY 0xA0 #define XMS_STATUS_OUT_OF_HANDLES 0xA1 #define XMS_STATUS_INVALID_HANDLE 0xA2 +#define XMS_STATUS_BAD_SRC_HANDLE 0xA3 +#define XMS_STATUS_BAD_DEST_HANDLE 0xA4 +#define XMS_STATUS_BAD_SRC_OFFSET 0xA5 +#define XMS_STATUS_BAD_DEST_OFFSET 0xA6 #define XMS_STATUS_NOT_LOCKED 0xAA #define XMS_STATUS_LOCKED 0xAB #define XMS_STATUS_LOCK_OVERFLOW 0xAC @@ -33,6 +37,17 @@ typedef struct _XMS_HANDLE DWORD Address; } XMS_HANDLE, *PXMS_HANDLE; +#pragma pack(push, 1) +typedef struct _XMS_COPY_DATA +{ + DWORD Count; + WORD SourceHandle; + DWORD SourceOffset; + WORD DestHandle; + DWORD DestOffset; +} XMS_COPY_DATA, *PXMS_COPY_DATA; +#pragma pack(pop) + /* FUNCTIONS ******************************************************************/ BOOLEAN XmsGetDriverEntry(PDWORD Pointer); -- 2.17.1