mirror of
https://github.com/reactos/reactos.git
synced 2024-07-04 03:34:16 +00:00
[NTVDM][FAST486]
- Implement VDDInstallMemoryHook and VDDDeInstallMemoryHook using page guards. - Implement another API for memory hooks that should be faster than page guards (for NTVDM only). - Adjust the VGA and EMS memory handlers to use this method. - In Fast486, implement a method that will allow us to "rewind" the current instruction, in case it was interrupted by a memory hook page fault. - Use a memory hook to protect the BIOS ROM from being written to. svn path=/trunk/; revision=66666
This commit is contained in:
parent
027720cd57
commit
888e1c450b
|
@ -576,6 +576,10 @@ Fast486SetSegment
|
|||
USHORT Selector
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
Fast486Rewind(PFAST486_STATE State);
|
||||
|
||||
#endif // _FAST486_H_
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -333,4 +333,14 @@ Fast486SetSegment(PFAST486_STATE State,
|
|||
Fast486LoadSegment(State, Segment, Selector);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
Fast486Rewind(PFAST486_STATE State)
|
||||
{
|
||||
/* This function is used when an instruction has been interrupted remotely */
|
||||
State->PrefixFlags = 0;
|
||||
State->InstPtr.Long = State->SavedInstPtr.Long;
|
||||
State->PrefetchValid = FALSE;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -37,6 +37,7 @@ list(APPEND SOURCE
|
|||
emulator.c
|
||||
int32.c
|
||||
io.c
|
||||
memory.c
|
||||
utils.c
|
||||
vddsup.c
|
||||
ntvdm.c
|
||||
|
@ -45,6 +46,6 @@ list(APPEND SOURCE
|
|||
|
||||
add_executable(ntvdm ${SOURCE})
|
||||
set_module_type(ntvdm win32cui UNICODE IMAGEBASE 0x0F000000)
|
||||
target_link_libraries(ntvdm fast486)
|
||||
target_link_libraries(ntvdm fast486 ${PSEH_LIB})
|
||||
add_importlibs(ntvdm user32 gdi32 advapi32 msvcrt kernel32 ntdll)
|
||||
add_cd_file(TARGET ntvdm DESTINATION reactos/system32 FOR all)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define NDEBUG
|
||||
|
||||
#include "emulator.h"
|
||||
#include "memory.h"
|
||||
#include "cpu/callback.h"
|
||||
#include "cpu/bop.h"
|
||||
|
||||
|
@ -40,6 +41,12 @@ PBIOS_CONFIG_TABLE Bct;
|
|||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
static BOOLEAN NTAPI BiosRomWrite(ULONG Address, PVOID Buffer, ULONG Size)
|
||||
{
|
||||
/* Prevent writing to ROM */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
||||
VOID WINAPI BiosEquipmentService(LPWORD Stack)
|
||||
|
@ -74,6 +81,11 @@ BiosInitialize(IN LPCSTR BiosFileName)
|
|||
// RegisterBop(BOP_EQUIPLIST , BiosEquipmentService);
|
||||
// RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize);
|
||||
|
||||
MemInstallFastMemoryHook((PVOID)ROM_AREA_START,
|
||||
ROM_AREA_END - ROM_AREA_START + 1,
|
||||
NULL,
|
||||
BiosRomWrite);
|
||||
|
||||
if (BiosFileName && BiosFileName[0] != '\0')
|
||||
{
|
||||
PVOID BiosLocation = NULL;
|
||||
|
|
|
@ -13,9 +13,11 @@
|
|||
#include "cpu.h"
|
||||
|
||||
#include "emulator.h"
|
||||
#include "memory.h"
|
||||
#include "callback.h"
|
||||
#include "bop.h"
|
||||
#include <isvbop.h>
|
||||
#include <pseh/pseh2.h>
|
||||
|
||||
#include "clock.h"
|
||||
#include "bios/rom.h"
|
||||
|
@ -112,6 +114,8 @@ VOID CpuStep(VOID)
|
|||
|
||||
VOID CpuSimulate(VOID)
|
||||
{
|
||||
EXCEPTION_RECORD LocalExceptionRecord;
|
||||
|
||||
if (CpuCallLevel > MaxCpuCallLevel)
|
||||
{
|
||||
DisplayMessage(L"Too many CPU levels of recursion (%d, expected maximum %d)",
|
||||
|
@ -125,7 +129,29 @@ VOID CpuSimulate(VOID)
|
|||
DPRINT("CpuSimulate --> Level %d\n", CpuCallLevel);
|
||||
|
||||
CpuRunning = TRUE;
|
||||
while (VdmRunning && CpuRunning) ClockUpdate();
|
||||
while (VdmRunning && CpuRunning)
|
||||
{
|
||||
_SEH2_TRY
|
||||
{
|
||||
while (VdmRunning && CpuRunning) ClockUpdate();
|
||||
}
|
||||
_SEH2_EXCEPT(LocalExceptionRecord = *_SEH2_GetExceptionInformation()->ExceptionRecord,
|
||||
EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
BOOLEAN Writing = (LocalExceptionRecord.ExceptionInformation[0] == 1);
|
||||
DWORD FaultingAddress = (DWORD)LocalExceptionRecord.ExceptionInformation[1];
|
||||
|
||||
/* Make sure this was an access violation */
|
||||
ASSERT(LocalExceptionRecord.ExceptionCode == EXCEPTION_ACCESS_VIOLATION);
|
||||
|
||||
/* Fix the CPU state */
|
||||
Fast486Rewind(&EmulatorContext);
|
||||
|
||||
/* Call the handler */
|
||||
MemExceptionHandler(FaultingAddress, Writing);
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
||||
DPRINT("CpuSimulate <-- Level %d\n", CpuCallLevel);
|
||||
CpuCallLevel--;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <ndk/rtltypes.h>
|
||||
#include <ndk/rtlfuncs.h>
|
||||
#include "ems.h"
|
||||
#include "memory.h"
|
||||
|
||||
/* PRIVATE VARIABLES **********************************************************/
|
||||
|
||||
|
@ -294,23 +295,26 @@ static VOID WINAPI EmsIntHandler(LPWORD Stack)
|
|||
}
|
||||
}
|
||||
|
||||
static VOID NTAPI EmsReadMemory(ULONG Address, PVOID Buffer, ULONG Size)
|
||||
{
|
||||
// TODO: NOT IMPLEMENTED
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
static BOOLEAN NTAPI EmsWriteMemory(ULONG Address, PVOID Buffer, ULONG Size)
|
||||
{
|
||||
// TODO: NOT IMPLEMENTED
|
||||
UNIMPLEMENTED;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
||||
VOID EmsReadMemory(ULONG Address, PVOID Buffer, ULONG Size)
|
||||
{
|
||||
// TODO: NOT IMPLEMENTED
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
VOID EmsWriteMemory(ULONG Address, PVOID Buffer, ULONG Size)
|
||||
{
|
||||
// TODO: NOT IMPLEMENTED
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
VOID EmsInitialize(VOID)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
RtlZeroMemory(BitmapBuffer, sizeof(BitmapBuffer));
|
||||
RtlInitializeBitMap(&AllocBitmap, BitmapBuffer, EMS_TOTAL_PAGES);
|
||||
|
||||
for (i = 0; i < EMS_MAX_HANDLES; i++)
|
||||
|
@ -320,5 +324,16 @@ VOID EmsInitialize(VOID)
|
|||
InitializeListHead(&HandleTable[i].PageList);
|
||||
}
|
||||
|
||||
MemInstallFastMemoryHook(SEG_OFF_TO_PTR(EMS_SEGMENT, 0),
|
||||
EMS_PHYSICAL_PAGES * EMS_PAGE_SIZE,
|
||||
EmsReadMemory,
|
||||
EmsWriteMemory);
|
||||
|
||||
RegisterBiosInt32(EMS_INTERRUPT_NUM, EmsIntHandler);
|
||||
}
|
||||
|
||||
VOID EmsCleanup(VOID)
|
||||
{
|
||||
MemRemoveFastMemoryHook(SEG_OFF_TO_PTR(EMS_SEGMENT, 0),
|
||||
EMS_PHYSICAL_PAGES * EMS_PAGE_SIZE);
|
||||
}
|
||||
|
|
|
@ -12,15 +12,13 @@
|
|||
/* DEFINITIONS ****************************************************************/
|
||||
|
||||
#define EMS_INTERRUPT_NUM 0x67
|
||||
#define EMS_SEGMENT 0xE000
|
||||
#define EMS_SEGMENT 0xD000
|
||||
#define EMS_MAX_HANDLES 16
|
||||
#define EMS_TOTAL_PAGES 256
|
||||
#define EMS_PAGE_BITS 14
|
||||
#define EMS_PAGE_SIZE (1 << EMS_PAGE_BITS)
|
||||
#define EMS_ADDRESS 0xA00000
|
||||
#define EMS_PHYSICAL_PAGES 4
|
||||
#define EMS_START_ADDRESS (EMS_SEGMENT << 4)
|
||||
#define EMS_END_ADDRESS (EMS_START_ADDRESS + EMS_PHYSICAL_PAGES * EMS_PAGE_SIZE)
|
||||
|
||||
#define EMS_STATUS_OK 0x00
|
||||
#define EMS_STATUS_INTERNAL_ERROR 0x80
|
||||
|
@ -66,9 +64,8 @@ typedef struct _EMS_COPY_DATA
|
|||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
VOID EmsReadMemory(ULONG Address, PVOID Buffer, ULONG Size);
|
||||
VOID EmsWriteMemory(ULONG Address, PVOID Buffer, ULONG Size);
|
||||
VOID EmsInitialize(VOID);
|
||||
VOID EmsCleanup(VOID);
|
||||
|
||||
#endif // _EMS_H_
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define NDEBUG
|
||||
|
||||
#include "emulator.h"
|
||||
#include "memory.h"
|
||||
|
||||
#include "cpu/callback.h"
|
||||
#include "cpu/cpu.h"
|
||||
|
@ -66,143 +67,35 @@ LPCWSTR ExceptionName[] =
|
|||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
static inline VOID
|
||||
EmulatorMoveMemory(OUT VOID UNALIGNED *Destination,
|
||||
IN const VOID UNALIGNED *Source,
|
||||
IN SIZE_T Length)
|
||||
{
|
||||
#if 1
|
||||
/*
|
||||
* We use a switch here to detect small moves of memory, as these
|
||||
* constitute the bulk of our moves.
|
||||
* Using RtlMoveMemory for all these small moves would be slow otherwise.
|
||||
*/
|
||||
switch (Length)
|
||||
{
|
||||
case 0:
|
||||
return;
|
||||
|
||||
case sizeof(UCHAR):
|
||||
*(PUCHAR)Destination = *(PUCHAR)Source;
|
||||
return;
|
||||
|
||||
case sizeof(USHORT):
|
||||
*(PUSHORT)Destination = *(PUSHORT)Source;
|
||||
return;
|
||||
|
||||
case sizeof(ULONG):
|
||||
*(PULONG)Destination = *(PULONG)Source;
|
||||
return;
|
||||
|
||||
case sizeof(ULONGLONG):
|
||||
*(PULONGLONG)Destination = *(PULONGLONG)Source;
|
||||
return;
|
||||
|
||||
default:
|
||||
#if defined(__GNUC__)
|
||||
__builtin_memmove(Destination, Source, Length);
|
||||
#else
|
||||
RtlMoveMemory(Destination, Source, Length);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else // defined(_MSC_VER)
|
||||
|
||||
PUCHAR Dest = (PUCHAR)Destination;
|
||||
PUCHAR Src = (PUCHAR)Source;
|
||||
|
||||
SIZE_T Count, NewSize = Length;
|
||||
|
||||
/* Move dword */
|
||||
Count = NewSize >> 2; // NewSize / sizeof(ULONG);
|
||||
NewSize = NewSize & 3; // NewSize % sizeof(ULONG);
|
||||
__movsd(Dest, Src, Count);
|
||||
Dest += Count << 2; // Count * sizeof(ULONG);
|
||||
Src += Count << 2;
|
||||
|
||||
/* Move word */
|
||||
Count = NewSize >> 1; // NewSize / sizeof(USHORT);
|
||||
NewSize = NewSize & 1; // NewSize % sizeof(USHORT);
|
||||
__movsw(Dest, Src, Count);
|
||||
Dest += Count << 1; // Count * sizeof(USHORT);
|
||||
Src += Count << 1;
|
||||
|
||||
/* Move byte */
|
||||
Count = NewSize; // NewSize / sizeof(UCHAR);
|
||||
// NewSize = NewSize; // NewSize % sizeof(UCHAR);
|
||||
__movsb(Dest, Src, Count);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID WINAPI EmulatorReadMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(State);
|
||||
|
||||
// BIG HACK!!!! To make BIOS images working correctly,
|
||||
// until Aleksander rewrites memory management!!
|
||||
/* Mirror 0x000FFFF0 at 0xFFFFFFF0 */
|
||||
if (Address >= 0xFFFFFFF0) Address -= 0xFFF00000;
|
||||
|
||||
/* If the A20 line is disabled, mask bit 20 */
|
||||
if (!A20Line) Address &= ~(1 << 20);
|
||||
if (!A20Line) Address &= ~(1 << 20);
|
||||
|
||||
/* Make sure the requested address is valid */
|
||||
if ((Address + Size) >= MAX_ADDRESS) return;
|
||||
if (Address >= MAX_ADDRESS) return;
|
||||
Size = min(Size, MAX_ADDRESS - Address);
|
||||
|
||||
/*
|
||||
* Check if we are going to read the VGA memory and
|
||||
* copy it into the virtual address space if needed.
|
||||
*/
|
||||
if (((Address + Size) >= VgaGetVideoBaseAddress())
|
||||
&& (Address < VgaGetVideoLimitAddress()))
|
||||
{
|
||||
DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress());
|
||||
DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress())
|
||||
- VgaAddress + 1;
|
||||
LPBYTE DestBuffer = (LPBYTE)REAL_TO_PHYS(VgaAddress);
|
||||
|
||||
/* Read from the VGA memory */
|
||||
VgaReadMemory(VgaAddress, DestBuffer, ActualSize);
|
||||
}
|
||||
|
||||
/* Read the data from the virtual address space and store it in the buffer */
|
||||
EmulatorMoveMemory(Buffer, REAL_TO_PHYS(Address), Size);
|
||||
/* Read while calling fast memory hooks */
|
||||
MemRead(Address, Buffer, Size);
|
||||
}
|
||||
|
||||
VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(State);
|
||||
|
||||
// BIG HACK!!!! To make BIOS images working correctly,
|
||||
// until Aleksander rewrites memory management!!
|
||||
if (Address >= 0xFFFFFFF0) Address -= 0xFFF00000;
|
||||
|
||||
/* If the A20 line is disabled, mask bit 20 */
|
||||
if (!A20Line) Address &= ~(1 << 20);
|
||||
if (!A20Line) Address &= ~(1 << 20);
|
||||
|
||||
/* Make sure the requested address is valid */
|
||||
if ((Address + Size) >= MAX_ADDRESS) return;
|
||||
if (Address >= MAX_ADDRESS) return;
|
||||
Size = min(Size, MAX_ADDRESS - Address);
|
||||
|
||||
/* Make sure we don't write to the ROM area */
|
||||
if ((Address + Size) >= ROM_AREA_START && (Address < ROM_AREA_END)) return;
|
||||
|
||||
/* Read the data from the buffer and store it in the virtual address space */
|
||||
EmulatorMoveMemory(REAL_TO_PHYS(Address), Buffer, Size);
|
||||
|
||||
/*
|
||||
* Check if we modified the VGA memory.
|
||||
*/
|
||||
if (((Address + Size) >= VgaGetVideoBaseAddress())
|
||||
&& (Address < VgaGetVideoLimitAddress()))
|
||||
{
|
||||
DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress());
|
||||
DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress())
|
||||
- VgaAddress + 1;
|
||||
LPBYTE SrcBuffer = (LPBYTE)REAL_TO_PHYS(VgaAddress);
|
||||
|
||||
/* Write to the VGA memory */
|
||||
VgaWriteMemory(VgaAddress, SrcBuffer, ActualSize);
|
||||
}
|
||||
/* Write while calling fast memory hooks */
|
||||
MemWrite(Address, Buffer, Size);
|
||||
}
|
||||
|
||||
UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State)
|
||||
|
@ -566,57 +459,13 @@ VOID DumpMemory(BOOLEAN TextFormat)
|
|||
|
||||
BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
|
||||
{
|
||||
#ifdef STANDALONE
|
||||
|
||||
/* Allocate 16 MB memory for the 16-bit address space */
|
||||
BaseAddress = HeapAlloc(GetProcessHeap(), /*HEAP_ZERO_MEMORY*/ 0, MAX_ADDRESS);
|
||||
if (BaseAddress == NULL)
|
||||
/* Initialize memory */
|
||||
if (!MemInitialize())
|
||||
{
|
||||
wprintf(L"FATAL: Failed to allocate VDM memory.\n");
|
||||
wprintf(L"Memory initialization failed.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
NTSTATUS Status;
|
||||
SIZE_T MemorySize = MAX_ADDRESS; // See: kernel32/client/vdm.c!BaseGetVdmConfigInfo
|
||||
|
||||
/*
|
||||
* The reserved region starts from the very first page.
|
||||
* We need to commit the reserved first 16 MB virtual address.
|
||||
*/
|
||||
BaseAddress = (PVOID)1; // NULL has another signification for NtAllocateVirtualMemory
|
||||
|
||||
/*
|
||||
* Since to get NULL, we allocated from 0x1, account for this.
|
||||
* See also: kernel32/client/proc.c!CreateProcessInternalW
|
||||
*/
|
||||
MemorySize -= 1;
|
||||
|
||||
/* Commit the reserved memory */
|
||||
Status = NtAllocateVirtualMemory(NtCurrentProcess(),
|
||||
&BaseAddress,
|
||||
0,
|
||||
&MemorySize,
|
||||
MEM_COMMIT,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
wprintf(L"FATAL: Failed to commit VDM memory, Status 0x%08lx\n", Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ASSERT(BaseAddress == NULL);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For diagnostics purposes, we fill the memory with INT 0x03 codes
|
||||
* so that if a program wants to execute random code in memory, we can
|
||||
* retrieve the exact CS:IP where the problem happens.
|
||||
*/
|
||||
RtlFillMemory(BaseAddress, MAX_ADDRESS, 0xCC);
|
||||
|
||||
/* Initialize I/O ports */
|
||||
/* Initialize RAM */
|
||||
|
||||
|
@ -700,11 +549,6 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
|
|||
|
||||
VOID EmulatorCleanup(VOID)
|
||||
{
|
||||
#ifndef STANDALONE
|
||||
NTSTATUS Status;
|
||||
SIZE_T MemorySize = MAX_ADDRESS;
|
||||
#endif
|
||||
|
||||
VgaCleanup();
|
||||
|
||||
/* Close the input thread handle */
|
||||
|
@ -713,6 +557,7 @@ VOID EmulatorCleanup(VOID)
|
|||
|
||||
PS2Cleanup();
|
||||
|
||||
EmsCleanup();
|
||||
SpeakerCleanup();
|
||||
CmosCleanup();
|
||||
// PitCleanup();
|
||||
|
@ -721,29 +566,7 @@ VOID EmulatorCleanup(VOID)
|
|||
// DmaCleanup();
|
||||
|
||||
CpuCleanup();
|
||||
|
||||
#ifdef STANDALONE
|
||||
|
||||
/* Free the memory allocated for the 16-bit address space */
|
||||
if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress);
|
||||
|
||||
#else
|
||||
|
||||
/* The reserved region starts from the very first page */
|
||||
// BaseAddress = (PVOID)1;
|
||||
|
||||
/* Since to get NULL, we allocated from 0x1, account for this */
|
||||
MemorySize -= 1;
|
||||
|
||||
Status = NtFreeVirtualMemory(NtCurrentProcess(),
|
||||
&BaseAddress,
|
||||
&MemorySize,
|
||||
MEM_DECOMMIT);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NTVDM: Failed to decommit VDM memory, Status 0x%08lx\n", Status);
|
||||
}
|
||||
#endif
|
||||
MemCleanup();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "vga.h"
|
||||
#include <bios/vidbios.h>
|
||||
|
||||
#include "memory.h"
|
||||
#include "io.h"
|
||||
|
||||
/* PRIVATE VARIABLES **********************************************************/
|
||||
|
@ -418,6 +419,16 @@ __InvalidateConsoleDIBits(IN HANDLE hConsoleOutput,
|
|||
static inline DWORD VgaGetAddressSize(VOID);
|
||||
static VOID VgaUpdateTextCursor(VOID);
|
||||
|
||||
static inline DWORD VgaGetVideoBaseAddress(VOID)
|
||||
{
|
||||
return MemoryBase[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03];
|
||||
}
|
||||
|
||||
static inline DWORD VgaGetVideoLimitAddress(VOID)
|
||||
{
|
||||
return MemoryLimit[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03];
|
||||
}
|
||||
|
||||
static VOID VgaUpdateCursorPosition(VOID)
|
||||
{
|
||||
/*
|
||||
|
@ -1745,16 +1756,6 @@ static VOID WINAPI VgaWritePort(USHORT Port, BYTE Data)
|
|||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
||||
DWORD VgaGetVideoBaseAddress(VOID)
|
||||
{
|
||||
return MemoryBase[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03];
|
||||
}
|
||||
|
||||
DWORD VgaGetVideoLimitAddress(VOID)
|
||||
{
|
||||
return MemoryLimit[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03];
|
||||
}
|
||||
|
||||
COORD VgaGetDisplayResolution(VOID)
|
||||
{
|
||||
COORD Resolution;
|
||||
|
@ -1881,12 +1882,15 @@ VOID VgaHorizontalRetrace(VOID)
|
|||
InHorizontalRetrace = TRUE;
|
||||
}
|
||||
|
||||
VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size)
|
||||
VOID NTAPI VgaReadMemory(ULONG Address, PVOID Buffer, ULONG Size)
|
||||
{
|
||||
DWORD i;
|
||||
DWORD VideoAddress;
|
||||
PUCHAR BufPtr = (PUCHAR)Buffer;
|
||||
|
||||
DPRINT("VgaReadMemory: Address 0x%08X, Size %lu\n", Address, Size);
|
||||
Address = max(min(Address, VgaGetVideoLimitAddress() - 1), VgaGetVideoBaseAddress());
|
||||
Size = min(Size, VgaGetVideoLimitAddress() - Address + 1);
|
||||
|
||||
/* Ignore if video RAM access is disabled */
|
||||
if ((VgaMiscRegister & VGA_MISC_RAM_ENABLED) == 0) return;
|
||||
|
@ -1897,7 +1901,7 @@ VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size)
|
|||
VideoAddress = VgaTranslateReadAddress(Address + i);
|
||||
|
||||
/* Copy the value to the buffer */
|
||||
Buffer[i] = VgaMemory[VideoAddress];
|
||||
BufPtr[i] = VgaMemory[VideoAddress];
|
||||
}
|
||||
|
||||
/* Load the latch registers */
|
||||
|
@ -1907,18 +1911,21 @@ VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size)
|
|||
VgaLatchRegisters[3] = VgaMemory[(3 * VGA_BANK_SIZE) + LOWORD(VideoAddress)];
|
||||
}
|
||||
|
||||
VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size)
|
||||
BOOLEAN NTAPI VgaWriteMemory(ULONG Address, PVOID Buffer, ULONG Size)
|
||||
{
|
||||
DWORD i, j;
|
||||
DWORD VideoAddress;
|
||||
PUCHAR BufPtr = (PUCHAR)Buffer;
|
||||
|
||||
DPRINT("VgaWriteMemory: Address 0x%08X, Size %lu\n", Address, Size);
|
||||
Address = max(min(Address, VgaGetVideoLimitAddress() - 1), VgaGetVideoBaseAddress());
|
||||
Size = min(Size, VgaGetVideoLimitAddress() - Address + 1);
|
||||
|
||||
/* Ignore if video RAM access is disabled */
|
||||
if ((VgaMiscRegister & VGA_MISC_RAM_ENABLED) == 0) return;
|
||||
if ((VgaMiscRegister & VGA_MISC_RAM_ENABLED) == 0) return TRUE;
|
||||
|
||||
/* Also ignore if write access to all planes is disabled */
|
||||
if ((VgaSeqRegisters[VGA_SEQ_MASK_REG] & 0x0F) == 0x00) return;
|
||||
if ((VgaSeqRegisters[VGA_SEQ_MASK_REG] & 0x0F) == 0x00) return TRUE;
|
||||
|
||||
/* Loop through each byte */
|
||||
for (i = 0; i < Size; i++)
|
||||
|
@ -1951,9 +1958,11 @@ VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size)
|
|||
}
|
||||
|
||||
/* Copy the value to the VGA memory */
|
||||
VgaMemory[VideoAddress + j * VGA_BANK_SIZE] = VgaTranslateByteForWriting(Buffer[i], j);
|
||||
VgaMemory[VideoAddress + j * VGA_BANK_SIZE] = VgaTranslateByteForWriting(BufPtr[i], j);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID VgaClearMemory(VOID)
|
||||
|
@ -2074,6 +2083,9 @@ BOOLEAN VgaInitialize(HANDLE TextHandle)
|
|||
|
||||
/* Clear the VGA memory */
|
||||
VgaClearMemory();
|
||||
|
||||
/* Register the memory hook */
|
||||
MemInstallFastMemoryHook((PVOID)0xA0000, 0x20000, VgaReadMemory, VgaWriteMemory);
|
||||
|
||||
/* Register the I/O Ports */
|
||||
RegisterIoPort(0x3CC, VgaReadPort, NULL); // VGA_MISC_READ
|
||||
|
@ -2112,6 +2124,7 @@ VOID VgaCleanup(VOID)
|
|||
}
|
||||
|
||||
VgaDetachFromConsole(FALSE);
|
||||
MemRemoveFastMemoryHook((PVOID)0xA0000, 0x20000);
|
||||
|
||||
CloseHandle(AnotherEvent);
|
||||
CloseHandle(EndEvent);
|
||||
|
|
|
@ -258,14 +258,10 @@ VOID ScreenEventHandler(PWINDOW_BUFFER_SIZE_RECORD ScreenEvent);
|
|||
BOOL VgaAttachToConsole(VOID);
|
||||
VOID VgaDetachFromConsole(BOOL ChangeMode);
|
||||
|
||||
DWORD VgaGetVideoBaseAddress(VOID);
|
||||
DWORD VgaGetVideoLimitAddress(VOID);
|
||||
COORD VgaGetDisplayResolution(VOID);
|
||||
VOID VgaRefreshDisplay(VOID);
|
||||
VOID VgaHorizontalRetrace(VOID);
|
||||
VOID VgaWriteFont(UINT FontNumber, CONST UCHAR *FontData, UINT Height);
|
||||
VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size);
|
||||
VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size);
|
||||
VOID VgaClearMemory(VOID);
|
||||
|
||||
BOOLEAN VgaInitialize(HANDLE TextHandle);
|
||||
|
|
422
reactos/subsystems/mvdm/ntvdm/memory.c
Normal file
422
reactos/subsystems/mvdm/ntvdm/memory.c
Normal file
|
@ -0,0 +1,422 @@
|
|||
/*
|
||||
* COPYRIGHT: GPLv2+ - See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Virtual DOS Machine
|
||||
* FILE: memory.c
|
||||
* PURPOSE: Expanded Memory Support
|
||||
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#define NDEBUG
|
||||
|
||||
#include "emulator.h"
|
||||
#include <ndk/mmfuncs.h>
|
||||
#include <ndk/rtlfuncs.h>
|
||||
#include "memory.h"
|
||||
|
||||
/* PRIVATE VARIABLES **********************************************************/
|
||||
|
||||
static LIST_ENTRY HookList;
|
||||
static PMEM_HOOK PageTable[TOTAL_PAGES];
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
static inline VOID
|
||||
MemFastMoveMemory(OUT VOID UNALIGNED *Destination,
|
||||
IN const VOID UNALIGNED *Source,
|
||||
IN SIZE_T Length)
|
||||
{
|
||||
#if 1
|
||||
/*
|
||||
* We use a switch here to detect small moves of memory, as these
|
||||
* constitute the bulk of our moves.
|
||||
* Using RtlMoveMemory for all these small moves would be slow otherwise.
|
||||
*/
|
||||
switch (Length)
|
||||
{
|
||||
case 0:
|
||||
return;
|
||||
|
||||
case sizeof(UCHAR):
|
||||
*(PUCHAR)Destination = *(PUCHAR)Source;
|
||||
return;
|
||||
|
||||
case sizeof(USHORT):
|
||||
*(PUSHORT)Destination = *(PUSHORT)Source;
|
||||
return;
|
||||
|
||||
case sizeof(ULONG):
|
||||
*(PULONG)Destination = *(PULONG)Source;
|
||||
return;
|
||||
|
||||
case sizeof(ULONGLONG):
|
||||
*(PULONGLONG)Destination = *(PULONGLONG)Source;
|
||||
return;
|
||||
|
||||
default:
|
||||
#if defined(__GNUC__)
|
||||
__builtin_memmove(Destination, Source, Length);
|
||||
#else
|
||||
RtlMoveMemory(Destination, Source, Length);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else // defined(_MSC_VER)
|
||||
|
||||
PUCHAR Dest = (PUCHAR)Destination;
|
||||
PUCHAR Src = (PUCHAR)Source;
|
||||
|
||||
SIZE_T Count, NewSize = Length;
|
||||
|
||||
/* Move dword */
|
||||
Count = NewSize >> 2; // NewSize / sizeof(ULONG);
|
||||
NewSize = NewSize & 3; // NewSize % sizeof(ULONG);
|
||||
__movsd(Dest, Src, Count);
|
||||
Dest += Count << 2; // Count * sizeof(ULONG);
|
||||
Src += Count << 2;
|
||||
|
||||
/* Move word */
|
||||
Count = NewSize >> 1; // NewSize / sizeof(USHORT);
|
||||
NewSize = NewSize & 1; // NewSize % sizeof(USHORT);
|
||||
__movsw(Dest, Src, Count);
|
||||
Dest += Count << 1; // Count * sizeof(USHORT);
|
||||
Src += Count << 1;
|
||||
|
||||
/* Move byte */
|
||||
Count = NewSize; // NewSize / sizeof(UCHAR);
|
||||
// NewSize = NewSize; // NewSize % sizeof(UCHAR);
|
||||
__movsb(Dest, Src, Count);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static
|
||||
inline
|
||||
VOID
|
||||
ReadPage(PMEM_HOOK Hook, ULONG Address, PVOID Buffer, ULONG Size)
|
||||
{
|
||||
if (Hook && !Hook->hVdd && Hook->FastReadHandler)
|
||||
{
|
||||
Hook->FastReadHandler(Address, REAL_TO_PHYS(Address), Size);
|
||||
}
|
||||
|
||||
MemFastMoveMemory(Buffer, REAL_TO_PHYS(Address), Size);
|
||||
}
|
||||
|
||||
static
|
||||
inline
|
||||
VOID
|
||||
WritePage(PMEM_HOOK Hook, ULONG Address, PVOID Buffer, ULONG Size)
|
||||
{
|
||||
if (!Hook
|
||||
|| Hook->hVdd
|
||||
|| !Hook->FastWriteHandler
|
||||
|| Hook->FastWriteHandler(Address, Buffer, Size))
|
||||
{
|
||||
MemFastMoveMemory(REAL_TO_PHYS(Address), Buffer, Size);
|
||||
}
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
||||
VOID
|
||||
MemRead(ULONG Address, PVOID Buffer, ULONG Size)
|
||||
{
|
||||
ULONG i, Offset, Length;
|
||||
ULONG FirstPage = Address >> 12;
|
||||
ULONG LastPage = (Address + Size - 1) >> 12;
|
||||
|
||||
MemFastMoveMemory(Buffer, REAL_TO_PHYS(Address), Size);
|
||||
|
||||
if (FirstPage == LastPage)
|
||||
{
|
||||
ReadPage(PageTable[FirstPage], Address, Buffer, Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = FirstPage; i <= LastPage; i++)
|
||||
{
|
||||
Offset = (i == FirstPage) ? (Address & (PAGE_SIZE - 1)) : 0;
|
||||
Length = ((i == LastPage) ? (Address + Size - (LastPage << 12)) : PAGE_SIZE) - Offset;
|
||||
|
||||
ReadPage(PageTable[i], (i << 12) + Offset, Buffer, Length);
|
||||
Buffer = (PVOID)((ULONG_PTR)Buffer + Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
MemWrite(ULONG Address, PVOID Buffer, ULONG Size)
|
||||
{
|
||||
ULONG i, Offset, Length;
|
||||
ULONG FirstPage = Address >> 12;
|
||||
ULONG LastPage = (Address + Size - 1) >> 12;
|
||||
|
||||
if (FirstPage == LastPage)
|
||||
{
|
||||
WritePage(PageTable[FirstPage], Address, Buffer, Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = FirstPage; i <= LastPage; i++)
|
||||
{
|
||||
Offset = (i == FirstPage) ? (Address & (PAGE_SIZE - 1)) : 0;
|
||||
Length = ((i == LastPage) ? (Address + Size - (LastPage << 12)) : PAGE_SIZE) - Offset;
|
||||
|
||||
WritePage(PageTable[i], (i << 12) + Offset, Buffer, Length);
|
||||
Buffer = (PVOID)((ULONG_PTR)Buffer + Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
MemExceptionHandler(DWORD Address, BOOLEAN Writing)
|
||||
{
|
||||
PMEM_HOOK Hook = PageTable[Address >> 12];
|
||||
DPRINT("The memory at 0x%08X could not be %s.\n", Address, Writing ? "written" : "read");
|
||||
|
||||
/* Exceptions are only supposed to happen when using VDD-style memory hooks */
|
||||
ASSERT(Address < MAX_ADDRESS && Hook != NULL && Hook->hVdd != NULL);
|
||||
|
||||
/* Call the VDD handler */
|
||||
Hook->VddHandler(Address, Writing);
|
||||
}
|
||||
|
||||
BOOL
|
||||
MemInstallFastMemoryHook(PVOID Address,
|
||||
ULONG Size,
|
||||
PMEMORY_READ_HANDLER ReadHandler,
|
||||
PMEMORY_WRITE_HANDLER WriteHandler)
|
||||
{
|
||||
PMEM_HOOK Hook;
|
||||
ULONG i;
|
||||
ULONG FirstPage = (ULONG)Address >> 12;
|
||||
ULONG LastPage = ((ULONG)Address + Size - 1) >> 12;
|
||||
|
||||
/* Make sure none of these pages are already allocated */
|
||||
for (i = FirstPage; i <= LastPage; i++)
|
||||
{
|
||||
if (PageTable[i] != NULL) return FALSE;
|
||||
}
|
||||
|
||||
Hook = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(MEM_HOOK));
|
||||
if (Hook == NULL) return FALSE;
|
||||
|
||||
Hook->hVdd = NULL;
|
||||
Hook->Count = LastPage - FirstPage + 1;
|
||||
Hook->FastReadHandler = ReadHandler;
|
||||
Hook->FastWriteHandler = WriteHandler;
|
||||
|
||||
for (i = FirstPage; i <= LastPage; i++) PageTable[i] = Hook;
|
||||
|
||||
InsertTailList(&HookList, &Hook->Entry);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
MemRemoveFastMemoryHook(PVOID Address, ULONG Size)
|
||||
{
|
||||
ULONG i;
|
||||
ULONG FirstPage = (ULONG)Address >> 12;
|
||||
ULONG LastPage = ((ULONG)Address + Size - 1) >> 12;
|
||||
|
||||
if (Size == 0) return FALSE;
|
||||
|
||||
for (i = FirstPage; i <= LastPage; i++)
|
||||
{
|
||||
PMEM_HOOK Hook = PageTable[i];
|
||||
if (Hook == NULL || Hook->hVdd != NULL) continue;
|
||||
|
||||
if (--Hook->Count == 0)
|
||||
{
|
||||
/* This hook has no more pages */
|
||||
RemoveEntryList(&Hook->Entry);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, Hook);
|
||||
}
|
||||
|
||||
PageTable[i] = NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
WINAPI
|
||||
VDDInstallMemoryHook(HANDLE hVdd,
|
||||
PVOID pStart,
|
||||
DWORD dwCount,
|
||||
PVDD_MEMORY_HANDLER pHandler)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PMEM_HOOK Hook;
|
||||
ULONG i;
|
||||
ULONG FirstPage = (ULONG)pStart >> 12;
|
||||
ULONG LastPage = ((ULONG)pStart + dwCount - 1) >> 12;
|
||||
PVOID Address = (PVOID)(FirstPage * PAGE_SIZE);
|
||||
SIZE_T Size = (LastPage - FirstPage + 1) * PAGE_SIZE;
|
||||
|
||||
/* Check validity of the VDD handle */
|
||||
if (hVdd == NULL || hVdd == INVALID_HANDLE_VALUE) return FALSE;
|
||||
if (dwCount == 0) return FALSE;
|
||||
|
||||
/* Make sure none of these pages are already allocated */
|
||||
for (i = FirstPage; i <= LastPage; i++)
|
||||
{
|
||||
if (PageTable[i] != NULL) return FALSE;
|
||||
}
|
||||
|
||||
Hook = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(MEM_HOOK));
|
||||
if (Hook == NULL) return FALSE;
|
||||
|
||||
Hook->hVdd = hVdd;
|
||||
Hook->Count = LastPage - FirstPage + 1;
|
||||
Hook->VddHandler = pHandler;
|
||||
|
||||
/* Decommit the pages */
|
||||
Status = NtFreeVirtualMemory(NtCurrentProcess(), &Address, &Size, MEM_DECOMMIT);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, Hook);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = FirstPage; i <= LastPage; i++) PageTable[i] = Hook;
|
||||
|
||||
InsertTailList(&HookList, &Hook->Entry);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
WINAPI
|
||||
VDDDeInstallMemoryHook(HANDLE hVdd,
|
||||
PVOID pStart,
|
||||
DWORD dwCount)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG i;
|
||||
ULONG FirstPage = (ULONG)pStart >> 12;
|
||||
ULONG LastPage = ((ULONG)pStart + dwCount - 1) >> 12;
|
||||
PVOID Address = (PVOID)(FirstPage * PAGE_SIZE);
|
||||
SIZE_T Size = (LastPage - FirstPage + 1) * PAGE_SIZE;
|
||||
|
||||
if (dwCount == 0) return FALSE;
|
||||
|
||||
/* Commit the pages */
|
||||
Status = NtAllocateVirtualMemory(NtCurrentProcess(),
|
||||
&Address,
|
||||
0,
|
||||
&Size,
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(Status)) return FALSE;
|
||||
|
||||
for (i = FirstPage; i <= LastPage; i++)
|
||||
{
|
||||
PMEM_HOOK Hook = PageTable[i];
|
||||
if (Hook == NULL) continue;
|
||||
|
||||
if (Hook->hVdd != hVdd)
|
||||
{
|
||||
DPRINT1("VDDDeInstallMemoryHook: Page %u owned by someone else.\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (--Hook->Count == 0)
|
||||
{
|
||||
/* This hook has no more pages */
|
||||
RemoveEntryList(&Hook->Entry);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, Hook);
|
||||
}
|
||||
|
||||
PageTable[i] = NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
MemInitialize(VOID)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
SIZE_T MemorySize = MAX_ADDRESS; // See: kernel32/client/vdm.c!BaseGetVdmConfigInfo
|
||||
|
||||
#ifndef STANDALONE
|
||||
|
||||
/*
|
||||
* The reserved region starts from the very first page.
|
||||
* We need to commit the reserved first 16 MB virtual address.
|
||||
*/
|
||||
BaseAddress = (PVOID)1;
|
||||
|
||||
/*
|
||||
* Since to get NULL, we allocated from 0x1, account for this.
|
||||
* See also: kernel32/client/proc.c!CreateProcessInternalW
|
||||
*/
|
||||
MemorySize -= 1;
|
||||
|
||||
#else
|
||||
|
||||
/* Allocate it anywhere */
|
||||
BaseAddress = NULL;
|
||||
|
||||
#endif
|
||||
|
||||
Status = NtAllocateVirtualMemory(NtCurrentProcess(),
|
||||
&BaseAddress,
|
||||
0,
|
||||
&MemorySize,
|
||||
#ifndef STANDALONE
|
||||
MEM_COMMIT,
|
||||
#else
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
#endif
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
wprintf(L"FATAL: Failed to commit VDM memory, Status 0x%08lx\n", Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifndef STANDALONE
|
||||
ASSERT(BaseAddress == NULL);
|
||||
#endif
|
||||
|
||||
InitializeListHead(&HookList);
|
||||
|
||||
/*
|
||||
* For diagnostics purposes, we fill the memory with INT 0x03 codes
|
||||
* so that if a program wants to execute random code in memory, we can
|
||||
* retrieve the exact CS:IP where the problem happens.
|
||||
*/
|
||||
RtlFillMemory(BaseAddress, MAX_ADDRESS, 0xCC);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
MemCleanup(VOID)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
SIZE_T MemorySize = MAX_ADDRESS;
|
||||
|
||||
while (HookList.Flink != &HookList)
|
||||
{
|
||||
PLIST_ENTRY Pointer = RemoveHeadList(&HookList);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, CONTAINING_RECORD(Pointer, MEM_HOOK, Entry));
|
||||
}
|
||||
|
||||
/* Decommit the VDM memory */
|
||||
Status = NtFreeVirtualMemory(NtCurrentProcess(),
|
||||
&BaseAddress,
|
||||
&MemorySize,
|
||||
#ifndef STANDALONE
|
||||
MEM_DECOMMIT
|
||||
#else
|
||||
MEM_RELEASE
|
||||
#endif
|
||||
);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NTVDM: Failed to decommit VDM memory, Status 0x%08lx\n", Status);
|
||||
}
|
||||
}
|
116
reactos/subsystems/mvdm/ntvdm/memory.h
Normal file
116
reactos/subsystems/mvdm/ntvdm/memory.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* COPYRIGHT: GPLv2+ - See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Virtual DOS Machine
|
||||
* FILE: memory.h
|
||||
* PURPOSE: Expanded Memory Support
|
||||
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
|
||||
*/
|
||||
|
||||
#ifndef _MEMORY_H_
|
||||
#define _MEMORY_H_
|
||||
|
||||
/* DEFINITIONS ****************************************************************/
|
||||
|
||||
#define TOTAL_PAGES (MAX_ADDRESS / PAGE_SIZE)
|
||||
|
||||
typedef VOID
|
||||
(WINAPI *PVDD_MEMORY_HANDLER)
|
||||
(
|
||||
DWORD FaultingAddress,
|
||||
BOOLEAN Writing
|
||||
);
|
||||
|
||||
typedef VOID
|
||||
(WINAPI *PMEMORY_READ_HANDLER)
|
||||
(
|
||||
ULONG Address,
|
||||
PVOID Buffer,
|
||||
ULONG Size
|
||||
);
|
||||
|
||||
typedef BOOLEAN
|
||||
(WINAPI *PMEMORY_WRITE_HANDLER)
|
||||
(
|
||||
ULONG Address,
|
||||
PVOID Buffer,
|
||||
ULONG Size
|
||||
);
|
||||
|
||||
typedef struct _MEM_HOOK
|
||||
{
|
||||
LIST_ENTRY Entry;
|
||||
HANDLE hVdd;
|
||||
ULONG Count;
|
||||
|
||||
union
|
||||
{
|
||||
PVDD_MEMORY_HANDLER VddHandler;
|
||||
|
||||
struct
|
||||
{
|
||||
PMEMORY_READ_HANDLER FastReadHandler;
|
||||
PMEMORY_WRITE_HANDLER FastWriteHandler;
|
||||
};
|
||||
};
|
||||
} MEM_HOOK, *PMEM_HOOK;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
BOOLEAN MemInitialize(VOID);
|
||||
VOID MemCleanup(VOID);
|
||||
VOID MemExceptionHandler(DWORD Address, BOOLEAN Writing);
|
||||
|
||||
VOID
|
||||
MemRead
|
||||
(
|
||||
ULONG Address,
|
||||
PVOID Buffer,
|
||||
ULONG Size
|
||||
);
|
||||
|
||||
VOID
|
||||
MemWrite
|
||||
(
|
||||
ULONG Address,
|
||||
PVOID Buffer,
|
||||
ULONG Size
|
||||
);
|
||||
|
||||
BOOL
|
||||
MemInstallFastMemoryHook
|
||||
(
|
||||
PVOID Address,
|
||||
ULONG Size,
|
||||
PMEMORY_READ_HANDLER ReadHandler,
|
||||
PMEMORY_WRITE_HANDLER WriteHandler
|
||||
);
|
||||
|
||||
BOOL
|
||||
MemRemoveFastMemoryHook
|
||||
(
|
||||
PVOID Address,
|
||||
ULONG Size
|
||||
);
|
||||
|
||||
BOOL
|
||||
WINAPI
|
||||
VDDInstallMemoryHook
|
||||
(
|
||||
HANDLE hVdd,
|
||||
PVOID pStart,
|
||||
DWORD dwCount,
|
||||
PVDD_MEMORY_HANDLER pHandler
|
||||
);
|
||||
|
||||
BOOL
|
||||
WINAPI
|
||||
VDDDeInstallMemoryHook
|
||||
(
|
||||
HANDLE hVdd,
|
||||
PVOID pStart,
|
||||
DWORD dwCount
|
||||
);
|
||||
|
||||
#endif // _MEMORY_H_
|
||||
|
||||
/* EOF */
|
Loading…
Reference in a new issue