From d2d24316141ad10a42f9ffab07bdc29d26f5621c Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Sat, 14 Mar 2015 01:54:35 +0000 Subject: [PATCH] [NTVDM] Implement the EMS memory handlers. Make memory hooks expandable. svn path=/trunk/; revision=66673 --- reactos/subsystems/mvdm/ntvdm/ems.c | 37 ++++++++++-- reactos/subsystems/mvdm/ntvdm/memory.c | 79 +++++++++++++++++++------- 2 files changed, 92 insertions(+), 24 deletions(-) diff --git a/reactos/subsystems/mvdm/ntvdm/ems.c b/reactos/subsystems/mvdm/ntvdm/ems.c index 01deace29fd..09919a2e1ff 100644 --- a/reactos/subsystems/mvdm/ntvdm/ems.c +++ b/reactos/subsystems/mvdm/ntvdm/ems.c @@ -297,14 +297,43 @@ static VOID WINAPI EmsIntHandler(LPWORD Stack) static VOID NTAPI EmsReadMemory(ULONG Address, PVOID Buffer, ULONG Size) { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + ULONG i; + ULONG RelativeAddress = Address - TO_LINEAR(EMS_SEGMENT, 0); + ULONG FirstPage = RelativeAddress / EMS_PAGE_SIZE; + ULONG LastPage = (RelativeAddress + Size - 1) / EMS_PAGE_SIZE; + ULONG Offset, Length; + + for (i = FirstPage; i <= LastPage; i++) + { + Offset = (i == FirstPage) ? Address & (EMS_PAGE_SIZE - 1) : 0; + Length = ((i == LastPage) + ? (Address + Size - (LastPage << EMS_PAGE_BITS)) + : EMS_PAGE_SIZE) - Offset; + + if (Mapping[i]) RtlCopyMemory(Buffer, (PVOID)((ULONG_PTR)Mapping[i] + Offset), Length); + Buffer = (PVOID)((ULONG_PTR)Buffer + Length); + } } static BOOLEAN NTAPI EmsWriteMemory(ULONG Address, PVOID Buffer, ULONG Size) { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + ULONG i; + ULONG RelativeAddress = Address - TO_LINEAR(EMS_SEGMENT, 0); + ULONG FirstPage = RelativeAddress / EMS_PAGE_SIZE; + ULONG LastPage = (RelativeAddress + Size - 1) / EMS_PAGE_SIZE; + ULONG Offset, Length; + + for (i = FirstPage; i <= LastPage; i++) + { + Offset = (i == FirstPage) ? Address & (EMS_PAGE_SIZE - 1) : 0; + Length = ((i == LastPage) + ? (Address + Size - (LastPage << EMS_PAGE_BITS)) + : EMS_PAGE_SIZE) - Offset; + + if (Mapping[i]) RtlCopyMemory((PVOID)((ULONG_PTR)Mapping[i] + Offset), Buffer, Length); + Buffer = (PVOID)((ULONG_PTR)Buffer + Length); + } + return TRUE; } diff --git a/reactos/subsystems/mvdm/ntvdm/memory.c b/reactos/subsystems/mvdm/ntvdm/memory.c index 151a0fabe03..a20499dc447 100644 --- a/reactos/subsystems/mvdm/ntvdm/memory.c +++ b/reactos/subsystems/mvdm/ntvdm/memory.c @@ -209,6 +209,7 @@ MemInstallFastMemoryHook(PVOID Address, ULONG i; ULONG FirstPage = (ULONG_PTR)Address >> 12; ULONG LastPage = ((ULONG_PTR)Address + Size - 1) >> 12; + PLIST_ENTRY Pointer; /* Make sure none of these pages are already allocated */ for (i = FirstPage; i <= LastPage; i++) @@ -216,20 +217,39 @@ MemInstallFastMemoryHook(PVOID Address, if (PageTable[i] != NULL) return FALSE; } - /* Create and initialize a new hook entry */ - Hook = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*Hook)); - if (Hook == NULL) return FALSE; + for (Pointer = HookList.Flink; Pointer != &HookList; Pointer = Pointer->Flink) + { + Hook = CONTAINING_RECORD(Pointer, MEM_HOOK, Entry); - Hook->hVdd = NULL; - Hook->Count = LastPage - FirstPage + 1; - Hook->FastReadHandler = ReadHandler; - Hook->FastWriteHandler = WriteHandler; + if (Hook->hVdd == NULL + && Hook->FastReadHandler == ReadHandler + && Hook->FastWriteHandler == WriteHandler) + { + break; + } + } - /* Add the hook entry to the page table... */ + if (Pointer == &HookList) + { + /* Create and initialize a new hook entry... */ + Hook = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*Hook)); + if (Hook == NULL) return FALSE; + + Hook->hVdd = NULL; + Hook->Count = 0; + Hook->FastReadHandler = ReadHandler; + Hook->FastWriteHandler = WriteHandler; + + /* ... and add it to the list of hooks */ + InsertTailList(&HookList, &Hook->Entry); + } + + /* Increase the number of pages this hook has */ + Hook->Count += LastPage - FirstPage + 1; + + /* Add the hook entry to the page table */ for (i = FirstPage; i <= LastPage; i++) PageTable[i] = Hook; - /* ... and to the list of hooks */ - InsertTailList(&HookList, &Hook->Entry); return TRUE; } @@ -339,6 +359,7 @@ VDDInstallMemoryHook(IN HANDLE hVdd, ULONG LastPage = ((ULONG_PTR)pStart + dwCount - 1) >> 12; PVOID Address = (PVOID)(FirstPage * PAGE_SIZE); SIZE_T Size = (LastPage - FirstPage + 1) * PAGE_SIZE; + PLIST_ENTRY Pointer; /* Check validity of the VDD handle */ if (hVdd == NULL || hVdd == INVALID_HANDLE_VALUE) return FALSE; @@ -350,27 +371,45 @@ VDDInstallMemoryHook(IN HANDLE hVdd, if (PageTable[i] != NULL) return FALSE; } - /* Create and initialize a new hook entry */ - Hook = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*Hook)); - if (Hook == NULL) return FALSE; + for (Pointer = HookList.Flink; Pointer != &HookList; Pointer = Pointer->Flink) + { + Hook = CONTAINING_RECORD(Pointer, MEM_HOOK, Entry); + if (Hook->hVdd == hVdd && Hook->VddHandler == MemoryHandler) break; + } - Hook->hVdd = hVdd; - Hook->Count = LastPage - FirstPage + 1; - Hook->VddHandler = MemoryHandler; + if (Pointer == &HookList) + { + /* Create and initialize a new hook entry... */ + Hook = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*Hook)); + if (Hook == NULL) return FALSE; + + Hook->hVdd = hVdd; + Hook->Count = 0; + Hook->VddHandler = MemoryHandler; + + /* ... and add it to the list of hooks */ + InsertTailList(&HookList, &Hook->Entry); + } /* Decommit the pages */ Status = NtFreeVirtualMemory(NtCurrentProcess(), &Address, &Size, MEM_DECOMMIT); if (!NT_SUCCESS(Status)) { - RtlFreeHeap(RtlGetProcessHeap(), 0, Hook); + if (Pointer == &HookList) + { + RemoveEntryList(&Hook->Entry); + RtlFreeHeap(RtlGetProcessHeap(), 0, Hook); + } + return FALSE; } - /* Add the hook entry to the page table... */ + /* Increase the number of pages this hook has */ + Hook->Count += LastPage - FirstPage + 1; + + /* Add the hook entry to the page table */ for (i = FirstPage; i <= LastPage; i++) PageTable[i] = Hook; - /* ... and to the list of hooks */ - InsertTailList(&HookList, &Hook->Entry); return TRUE; }