Author: aandrejevic Date: Mon Apr 27 03:37:24 2015 New Revision: 67457
URL: http://svn.reactos.org/svn/reactos?rev=67457&view=rev Log: [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.
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c [iso-8859-1] Mon Apr 27 03:37:24 2015 @@ -1036,7 +1036,6 @@ { /* 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 @@ }
if (Character == '\r') break; + Count++; /* Carriage returns are NOT counted */ }
/* Update the length */ - InputBuffer->Length = Count; + InputBuffer->Length = Count - 1;
break; }
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- 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] Mon Apr 27 03:37:24 2015 @@ -25,6 +25,15 @@
/* BOP Identifiers */ #define BOP_XMS 0x52 + +ULONG +NTAPI +RtlFindLastBackwardRunClear +( + IN PRTL_BITMAP BitMapHeader, + IN ULONG FromIndex, + OUT PULONG StartingRunIndex +);
/* PRIVATE VARIABLES **********************************************************/
@@ -180,6 +189,9 @@ { 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 @@
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; - - HandleEntry->Handle = 0; - FreeBlocks += HandleEntry->Size; - - return XMS_STATUS_SUCCESS; -} - -static CHAR XmsLock(WORD Handle, PDWORD Address) -{ - DWORD CurrentIndex = 0; - PXMS_HANDLE HandleEntry = GetHandleRecord(Handle); - - if (HandleEntry == NULL) return XMS_STATUS_INVALID_HANDLE; - if (HandleEntry->LockCount == 0xFF) return XMS_STATUS_LOCK_OVERFLOW; - - if (HandleEntry->LockCount) + /* Optimize blocks */ + for (i = 0; i < XMS_MAX_HANDLES; i++) { - /* Just increment the lock count */ - HandleEntry->LockCount++; - return XMS_STATUS_SUCCESS; + /* Skip free and locked blocks */ + if (HandleEntry->Handle == 0 || HandleEntry->LockCount > 0) continue; + + CurrentIndex = (HandleEntry->Address - XMS_ADDRESS) / XMS_BLOCK_SIZE; + + /* Check if there is any free space before this block */ + RunSize = RtlFindLastBackwardRunClear(&AllocBitmap, CurrentIndex, &RunStart); + if (RunSize == 0) break; + + /* 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); + + /* 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,23 +251,49 @@ CurrentIndex = RunStart + RunSize; }
- /* Can't find any suitable range */ - return XMS_STATUS_CANNOT_LOCK; -} - -static CHAR XmsUnlock(WORD Handle) + return XMS_STATUS_OUT_OF_MEMORY; +} + +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 @@ 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: {
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h [iso-8859-1] Mon Apr 27 03:37:24 2015 @@ -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 @@ 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);