[NTVDM]
authorAleksandar Andrejevic <aandrejevic@reactos.org>
Sat, 14 Mar 2015 01:54:35 +0000 (01:54 +0000)
committerAleksandar Andrejevic <aandrejevic@reactos.org>
Sat, 14 Mar 2015 01:54:35 +0000 (01:54 +0000)
Implement the EMS memory handlers.
Make memory hooks expandable.

svn path=/trunk/; revision=66673

reactos/subsystems/mvdm/ntvdm/ems.c
reactos/subsystems/mvdm/ntvdm/memory.c

index 01deace..09919a2 100644 (file)
@@ -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;
 }
 
index 151a0fa..a20499d 100644 (file)
@@ -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);
+
+        if (Hook->hVdd == NULL
+            && Hook->FastReadHandler == ReadHandler
+            && Hook->FastWriteHandler == WriteHandler)
+        {
+            break;
+        }
+    }
+
+    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;
 
-    Hook->hVdd = NULL;
-    Hook->Count = LastPage - FirstPage + 1;
-    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... */
+    /* 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;
+    }
+
+    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;
 
-    Hook->hVdd = hVdd;
-    Hook->Count = LastPage - FirstPage + 1;
-    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;
 }