Implement the EMS memory handlers.
Make memory hooks expandable.


svn path=/trunk/; revision=66673
This commit is contained in:
Aleksandar Andrejevic 2015-03-14 01:54:35 +00:00
parent a0ee24eb0b
commit d2d2431614
2 changed files with 92 additions and 24 deletions

View 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;
}

View 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);
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;
}