2020-09-30 17:12:29 +02:00

1136 lines
26 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
Monitor.c
Abstract:
This module is the user mode portion of the x86 monitor
Author:
Dave Hastings (daveh) 16 Mar 1991
Environment:
User mode only
Revision History:
Sudeep Bharati (sudeepb) 31-Dec-1991
Converted all register manipulation interfaces to functions
from macros. This is to make ntvdm an exe as well as a dll,
and these register oriented routines are exported from ntvdm
for WOW32 and other installable VDDs.
Dave Hastings (daveh) 18-Apr-1992
Split into multiple files. Track current monitor thread by
Teb pointer. Register initial thread.
Sudeep Bharati (sudeepb) 22-Sep-1992
Added Page Fault Handling For installable VDD support
--*/
#include "monitorp.h"
//
// Internal functions
//
VOID
EventVdmIo(
VOID
);
VOID
EventVdmStringIo(
VOID
);
VOID
EventVdmMemAccess(
VOID
);
VOID
EventVdmIntAck(
VOID
);
VOID
EventVdmBop(
VOID
);
VOID
EventVdmError(
VOID
);
VOID
EventVdmIrq13(
VOID
);
VOID
CreateProfile(
VOID
);
VOID
StartProfile(
VOID
);
VOID
StopProfile(
VOID
);
VOID
AnalyzeProfile(
VOID
);
// [LATER] how do you prevent a struct from straddling a page boundary?
VDM_TIB VdmTib;
ULONG IntelBase; // base memory address
ULONG VdmSize; // Size of memory in VDM
ULONG IntelMSW; // Msw value (no msw in context)
ULONG VdmDebugLevel; // used to control debugging
PVOID CurrentMonitorTeb; // thread that is currently executing instructions.
ULONG InitialBreakpoint = FALSE; // if set, breakpoint at end of cpu_init
ULONG InitialVdmTibFlags = 0; // VdmTib flags picked up from here
CONTEXT InitialContext; // Initial context for all threads
BOOLEAN DebugContextActive = FALSE;
ULONG VdmFeatureBits = 0; // bit to indicate special features
extern PVOID NTVDMpLockPrefixTable;
IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = {
0, // Reserved
0, // Reserved
0, // Reserved
0, // Reserved
0, // GlobalFlagsClear
0, // GlobalFlagsSet
0, // CriticalSectionTimeout (milliseconds)
0, // DeCommitFreeBlockThreshold
0, // DeCommitTotalFreeThreshold
&NTVDMpLockPrefixTable, // LockPrefixTable, defined in FASTPM.ASM
0, 0, 0, 0, 0, 0, 0 // Reserved
};
// Bop dispatch table
extern void (*BIOS[])();
BOOLEAN ContinueExecution;
//
// Event Dispatch table
//
VOID (*EventDispatch[VdmMaxEvent])(VOID) = {
EventVdmIo,
EventVdmStringIo,
EventVdmMemAccess,
EventVdmIntAck,
EventVdmBop,
EventVdmError,
EventVdmIrq13
};
// Debug control flags
BOOLEAN fShowBop = FALSE;
#if DBG
BOOLEAN fBreakInDebugger = FALSE;
LONG NumTasks = -1;
#endif
EXPORT
VOID
cpu_init(
)
/*++
Routine Description:
This routine is used to prepare the IEU for instruction simulation.
It will set the Intel registers to thier initial value, and perform
any implementation specific initialization necessary.
Arguments:
Return Value:
None.
--*/
{
NTSTATUS Status;
IntelMSW = 0x0; // bugbug use correct value for ET and MP
InitialVdmTibFlags |= RM_BIT_MASK;
VdmTib.VdmContext.SegGs = 0;
VdmTib.VdmContext.SegFs = 0;
VdmTib.VdmContext.SegEs = 0;
VdmTib.VdmContext.SegDs = 0;
VdmTib.VdmContext.SegCs = 0;
VdmTib.VdmContext.Eip = 0xFFF0L;
VdmTib.VdmContext.EFlags = 0x02L | EFLAGS_INTERRUPT_MASK;
VdmTib.MonitorContext.SegDs = KGDT_R3_DATA | RPL_MASK;
VdmTib.MonitorContext.SegEs = KGDT_R3_DATA | RPL_MASK;
VdmTib.MonitorContext.SegGs = 0;
VdmTib.MonitorContext.SegFs = KGDT_R3_TEB | RPL_MASK;
VdmTib.PrinterInfo.prt_State = NULL;
VdmTib.PrinterInfo.prt_Control = NULL;
VdmTib.PrinterInfo.prt_Status = NULL;
VdmTib.PrinterInfo.prt_HostState = NULL;
ASSERT(VDM_NUMBER_OF_LPT == 3);
VdmTib.PrinterInfo.prt_Mode[0] =
VdmTib.PrinterInfo.prt_Mode[1] =
VdmTib.PrinterInfo.prt_Mode[2] = PRT_MODE_NO_SIMULATION;
VdmTib.Size = sizeof(VDM_TIB);
//
// Find out if we are running with IOPL. We call the kernel
// rather than checking the registry ourselves, so that we can
// insure that both the kernel and ntvdm.exe agree. If they didn't,
// it would result in unnecssary trapping instructions. Whether or
// not Vdms run with IOPL only changes on reboot
//
Status = NtVdmControl(VdmFeatures, &VdmFeatureBits);
#if DBG
if (!NT_SUCCESS(Status)) {
DbgPrint(
"NTVDM: Could not find out whether to use IOPL, %lx\n",
Status
);
}
#endif
//
// If we have fast v86 mode IF emulation set the bit that tells
// the 16 bit IF macros they know.
//
if (VdmFeatureBits & V86_VIRTUAL_INT_EXTENSIONS) {
InitialVdmTibFlags |= RI_BIT_MASK;
}
*pNtVDMState = InitialVdmTibFlags;
// Switch the npx back to 80 bit mode. Win32 apps start with
// 64-bit precision for compatibility across platforms, but
// DOS and Win16 apps expect 80 bit precision.
//
_asm fninit;
//
// We setup the InitialContext structure with the correct floating
// point and debug register configuration, and cpu_createthread
// uses this context to configure each 16-bit thread's floating
// point and debug registers.
//
InitialContext.ContextFlags = CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS;
Status = NtGetContextThread(
NtCurrentThread(),
&InitialContext
);
if (!NT_SUCCESS(Status)) {
#if DBG
DbgPrint("NtVdm terminating : Could not get float/debug context for\n"
" initial thread, status %lx\n", Status);
DbgBreakPoint();
#endif
TerminateVDM();
}
//
//
// Turn OFF em bit so that dos apps will work correctly.
//
// On machines without 387's the floating point flag will have been
// cleared.
//
InitialContext.ContextFlags = CONTEXT_FLOATING_POINT;
InitialContext.FloatSave.Cr0NpxState &= ~0x6; // CR0_EM | CR0_MP
//
// Do the rest of thread initialization
//
cpu_createthread( NtCurrentThread() );
InterruptInit();
if (InitialBreakpoint) {
DbgBreakPoint();
}
}
EXPORT
VOID
cpu_terminate(
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
InterruptTerminate();
}
EXPORT
VOID
cpu_simulate(
)
/*++
Routine Description:
This routine causes the simulation of intel instructions to start.
Arguments:
Return Value:
None.
--*/
{
NTSTATUS Status;
VDMEVENTINFO OldEventInfo;
CONTEXT OldMonitorContext;
OldEventInfo = VdmTib.EventInfo;
OldMonitorContext = VdmTib.MonitorContext;
ContinueExecution = TRUE;
CurrentMonitorTeb = NtCurrentTeb();
VdmTib.VdmContext.ContextFlags = CONTEXT_FULL;
while (ContinueExecution) {
ASSERT(CurrentMonitorTeb == NtCurrentTeb());
ASSERT(InterlockedIncrement(&NumTasks) == 0);
if (*pNtVDMState & VDM_INTERRUPT_PENDING) {
DispatchInterrupts();
}
// translate MSW bits into EFLAGS
if ( getMSW() & MSW_PE ) {
VdmTib.VdmContext.EFlags &= ~EFLAGS_V86_MASK;
Status = FastEnterPm();
} else {
VdmTib.VdmContext.EFlags |= EFLAGS_V86_MASK;
Status = NtVdmControl(VdmStartExecution,NULL);
}
if (!NT_SUCCESS(Status)) {
#if DBG
DbgPrint("NTVDM: Could not start execution\n");
#endif
return;
}
ASSERT(InterlockedDecrement(&NumTasks) < 0);
#if DBG
if (fBreakInDebugger) {
fBreakInDebugger = 0;
DbgBreakPoint();
}
#endif
// Translate Eflags value
ASSERT ((!((VdmTib.VdmContext.EFlags & EFLAGS_V86_MASK) &&
(getMSW() & MSW_PE))));
if ( VdmTib.VdmContext.EFlags & EFLAGS_V86_MASK ) {
VdmTib.VdmContext.EFlags &= ~EFLAGS_V86_MASK;
}
// bugbug does cs:eip wrap cause some kind of fault?
VdmTib.VdmContext.Eip += VdmTib.EventInfo.InstructionSize;
if (VdmTib.EventInfo.Event >= VdmMaxEvent) {
#if DBG
DbgPrint("NTVDM: Unknown event type\n");
DbgBreakPoint();
#endif
ContinueExecution = FALSE;
continue;
}
(*EventDispatch[VdmTib.EventInfo.Event])();
}
// set this back to true incase we are nested
ContinueExecution = TRUE;
//
// Restore the old Vdm tib info. This is necessary for the for the
// case where the application thread is suspended, and a host simulate is
// performed from another thread
//
VdmTib.EventInfo = OldEventInfo;
VdmTib.MonitorContext = OldMonitorContext;
}
VOID
host_unsimulate(
)
/*++
Routine Description:
This routine causes execution of instructions in a VDM to stop.
Arguments:
Return Value:
None.
--*/
{
ContinueExecution = FALSE;
}
VOID
EventVdmIo(
VOID
)
/*++
Routine Description:
This function calls the appropriate io simulation routine.
Arguments:
Return Value:
None.
--*/
{
if (VdmTib.EventInfo.IoInfo.Size == 1) {
if (VdmTib.EventInfo.IoInfo.Read) {
inb(VdmTib.EventInfo.IoInfo.PortNumber,(half_word *)&(VdmTib.VdmContext.Eax));
} else {
outb(VdmTib.EventInfo.IoInfo.PortNumber,getAL());
}
} else if (VdmTib.EventInfo.IoInfo.Size == 2) {
if (VdmTib.EventInfo.IoInfo.Read) {
inw(VdmTib.EventInfo.IoInfo.PortNumber,(word *)&(VdmTib.VdmContext.Eax));
} else {
outw(VdmTib.EventInfo.IoInfo.PortNumber,getAX());
}
}
#if DBG
else {
DbgPrint(
"NtVdm: Unimplemented IO size %d\n",
VdmTib.EventInfo.IoInfo.Size
);
DbgBreakPoint();
}
#endif
}
VOID
EventVdmStringIo(
VOID
)
/*++
Routine Description:
This function calls the appropriate io simulation routine.
Arguments:
Return Value:
None.
--*/
{
PVDMSTRINGIOINFO pvsio;
PUSHORT pIndexRegister;
USHORT Index;
// WARNING no 32 bit address support
pvsio = &VdmTib.EventInfo.StringIoInfo;
if (pvsio->Size == 1) {
if (pvsio->Read) {
insb((io_addr)pvsio->PortNumber,
(half_word *)Sim32GetVDMPointer(pvsio->Address, 1, ISPESET),
(word)pvsio->Count
);
pIndexRegister = (PUSHORT)&VdmTib.VdmContext.Edi;
} else {
outsb((io_addr)pvsio->PortNumber,
(half_word *)Sim32GetVDMPointer(pvsio->Address,1,ISPESET),
(word)pvsio->Count
);
pIndexRegister = (PUSHORT)&VdmTib.VdmContext.Esi;
}
} else if (pvsio->Size == 2) {
if (pvsio->Read) {
insw((io_addr)pvsio->PortNumber,
(word *)Sim32GetVDMPointer(pvsio->Address,1,ISPESET),
(word)pvsio->Count
);
pIndexRegister = (PUSHORT)&VdmTib.VdmContext.Edi;
} else {
outsw((io_addr)pvsio->PortNumber,
(word *)Sim32GetVDMPointer(pvsio->Address,1,ISPESET),
(word)pvsio->Count
);
pIndexRegister = (PUSHORT)&VdmTib.VdmContext.Esi;
}
} else {
#if DBG
DbgPrint(
"NtVdm: Unimplemented IO size %d\n",
VdmTib.EventInfo.IoInfo.Size
);
DbgBreakPoint();
#endif
return;
}
if (getDF()) {
Index = *pIndexRegister - (USHORT)(pvsio->Count * pvsio->Size);
}
else {
Index = *pIndexRegister + (USHORT)(pvsio->Count * pvsio->Size);
}
*pIndexRegister = Index;
if (pvsio->Rep) {
(USHORT)VdmTib.VdmContext.Ecx = 0;
}
}
VOID
EventVdmIntAck(
VOID
)
/*++
Routine Description:
This routine is called each time we have returned to monitor context
to dispatch interrupts. Its function is to check for AutoEoi and call
the ica to do a nonspecific eoi, when the ica adapter is in AEOI mode.
Arguments:
Return Value:
None.
--*/
{
int line;
int adapter;
if (VdmTib.EventInfo.IntAckInfo) {
if (VdmTib.EventInfo.IntAckInfo & VDMINTACK_SLAVE)
adapter = 1;
else
adapter = 0;
line = -1;
host_ica_lock();
ica_eoi(adapter,
&line,
(int)(VdmTib.EventInfo.IntAckInfo & VDMINTACK_RAEOIMASK)
);
host_ica_unlock();
}
}
VOID
EventVdmBop(
VOID
)
/*++
Routine Description:
This routine dispatches to the appropriate bop handler
Arguments:
Return Value:
None.
--*/
{
if (VdmTib.EventInfo.BopNumber > MAX_BOP) {
#if DBG
DbgPrint(
"NtVdm: Invalid BOP %lx\n",
VdmTib.EventInfo.BopNumber
);
#endif
ContinueExecution = FALSE;
} else {
#if DBG
if (fShowBop) {
DbgPrint("Ntvdm cpu_simulate : bop dispatch %x,%x\n",
VdmTib.EventInfo.BopNumber,
(ULONG)(*((UCHAR *)Sim32GetVDMPointer(
(VdmTib.VdmContext.SegCs << 16) | VdmTib.VdmContext.Eip,
1,
ISPESET)))
);
}
#endif
(*BIOS[VdmTib.EventInfo.BopNumber])();
CurrentMonitorTeb = NtCurrentTeb();
}
}
VOID
EventVdmError(
VOID
)
/*++
Routine Description:
This routine prints a message(debug only), and exits the vdm
Arguments:
Return Value:
None.
--*/
{
#if DBG
DbgPrint(
"NtVdm: Error code %lx\n",
VdmTib.EventInfo.ErrorStatus
);
DbgBreakPoint();
#endif
TerminateVDM();
ContinueExecution = FALSE;
}
VOID
EventVdmIrq13(
VOID
)
/*++
Routine Description:
This routine simulates an IRQ 13 to the vdm
Arguments:
Return Value:
None.
--*/
{
if (!IRQ13BeingHandled) {
IRQ13BeingHandled = TRUE;
ica_hw_interrupt(
ICA_SLAVE,
5,
1
);
}
}
VOID
EventVdmMemAccess(
VOID
)
/*++
Routine Description:
This routine will call the page fault handler routine which
is common to both x86 and mips.
Arguments:
Return Value:
None.
--*/
{
// RWMode is 0 if read fault or 1 if write fault.
DispatchPageFault(
VdmTib.EventInfo.FaultInfo.FaultAddr,
VdmTib.EventInfo.FaultInfo.RWMode
);
CurrentMonitorTeb = NtCurrentTeb();
}
// Get and Set routines for intel registers.
ULONG getEAX (VOID) { return (VdmTib.VdmContext.Eax); }
USHORT getAX (VOID) { return ((USHORT)(VdmTib.VdmContext.Eax)); }
UCHAR getAL (VOID) { return ((BYTE)(VdmTib.VdmContext.Eax)); }
UCHAR getAH (VOID) { return ((BYTE)(VdmTib.VdmContext.Eax >> 8)); }
ULONG getEBX (VOID) { return (VdmTib.VdmContext.Ebx); }
USHORT getBX (VOID) { return ((USHORT)(VdmTib.VdmContext.Ebx)); }
UCHAR getBL (VOID) { return ((BYTE)(VdmTib.VdmContext.Ebx)); }
UCHAR getBH (VOID) { return ((BYTE)(VdmTib.VdmContext.Ebx >> 8)); }
ULONG getECX (VOID) { return (VdmTib.VdmContext.Ecx); }
USHORT getCX (VOID) { return ((USHORT)(VdmTib.VdmContext.Ecx)); }
UCHAR getCL (VOID) { return ((BYTE)(VdmTib.VdmContext.Ecx)); }
UCHAR getCH (VOID) { return ((BYTE)(VdmTib.VdmContext.Ecx >> 8)); }
ULONG getEDX (VOID) { return (VdmTib.VdmContext.Edx); }
USHORT getDX (VOID) { return ((USHORT)(VdmTib.VdmContext.Edx)); }
UCHAR getDL (VOID) { return ((BYTE)(VdmTib.VdmContext.Edx)); }
UCHAR getDH (VOID) { return ((BYTE)(VdmTib.VdmContext.Edx >> 8)); }
ULONG getESP (VOID) { return (VdmTib.VdmContext.Esp); }
USHORT getSP (VOID) { return ((USHORT)VdmTib.VdmContext.Esp); }
ULONG getEBP (VOID) { return (VdmTib.VdmContext.Ebp); }
USHORT getBP (VOID) { return ((USHORT)VdmTib.VdmContext.Ebp); }
ULONG getESI (VOID) { return (VdmTib.VdmContext.Esi); }
USHORT getSI (VOID) { return ((USHORT)VdmTib.VdmContext.Esi); }
ULONG getEDI (VOID) { return (VdmTib.VdmContext.Edi); }
USHORT getDI (VOID) { return ((USHORT)VdmTib.VdmContext.Edi); }
ULONG getEIP (VOID) { return (VdmTib.VdmContext.Eip); }
USHORT getIP (VOID) { return ((USHORT)VdmTib.VdmContext.Eip); }
USHORT getCS (VOID) { return ((USHORT)VdmTib.VdmContext.SegCs); }
USHORT getSS (VOID) { return ((USHORT)VdmTib.VdmContext.SegSs); }
USHORT getDS (VOID) { return ((USHORT)VdmTib.VdmContext.SegDs); }
USHORT getES (VOID) { return ((USHORT)VdmTib.VdmContext.SegEs); }
USHORT getFS (VOID) { return ((USHORT)VdmTib.VdmContext.SegFs); }
USHORT getGS (VOID) { return ((USHORT)VdmTib.VdmContext.SegGs); }
ULONG getCF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_CARRY) ? 1 : 0); }
ULONG getPF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_PARITY) ? 1 : 0); }
ULONG getAF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_AUXILIARY) ? 1 : 0); }
ULONG getZF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_ZERO) ? 1 : 0); }
ULONG getSF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_SIGN) ? 1 : 0); }
ULONG getTF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_TRAP) ? 1 : 0); }
ULONG getIF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_INTERRUPT) ? 1 : 0); }
ULONG getDF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_DIRECTION) ? 1 : 0); }
ULONG getOF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_OVERFLOW) ? 1 : 0); }
USHORT getMSW (VOID) { return ((USHORT)IntelMSW); }
USHORT getSTATUS(VOID){ return (USHORT)VdmTib.VdmContext.EFlags; }
ULONG getEFLAGS(VOID) { return VdmTib.VdmContext.EFlags; }
USHORT getFLAGS(VOID) { return (USHORT)VdmTib.VdmContext.EFlags; }
VOID setEAX (ULONG val) {
VdmTib.VdmContext.Eax = val;
}
VOID setAX (USHORT val) {
VdmTib.VdmContext.Eax = (VdmTib.VdmContext.Eax & 0xFFFF0000) |
((ULONG)val & 0x0000FFFF);
}
VOID setAH (UCHAR val) {
VdmTib.VdmContext.Eax = (VdmTib.VdmContext.Eax & 0xFFFF00FF) |
((ULONG)(val << 8) & 0x0000FF00);
}
VOID setAL (UCHAR val) {
VdmTib.VdmContext.Eax = (VdmTib.VdmContext.Eax & 0xFFFFFF00) |
((ULONG)val & 0x000000FF);
}
VOID setEBX (ULONG val) {
VdmTib.VdmContext.Ebx = val ;
}
VOID setBX (USHORT val) {
VdmTib.VdmContext.Ebx = (VdmTib.VdmContext.Ebx & 0xFFFF0000) |
((ULONG)val & 0x0000FFFF);
}
VOID setBH (UCHAR val) {
VdmTib.VdmContext.Ebx = (VdmTib.VdmContext.Ebx & 0xFFFF00FF) |
((ULONG)(val << 8) & 0x0000FF00);
}
VOID setBL (UCHAR val) {
VdmTib.VdmContext.Ebx = (VdmTib.VdmContext.Ebx & 0xFFFFFF00) |
((ULONG)val & 0x000000FF);
}
VOID setECX (ULONG val) {
VdmTib.VdmContext.Ecx = val ;
}
VOID setCX (USHORT val) {
VdmTib.VdmContext.Ecx = (VdmTib.VdmContext.Ecx & 0xFFFF0000) |
((ULONG)val & 0x0000FFFF);
}
VOID setCH (UCHAR val) {
VdmTib.VdmContext.Ecx = (VdmTib.VdmContext.Ecx & 0xFFFF00FF) |
((ULONG)(val << 8) & 0x0000FF00);
}
VOID setCL (UCHAR val) {
VdmTib.VdmContext.Ecx = (VdmTib.VdmContext.Ecx & 0xFFFFFF00) |
((ULONG)val & 0x000000FF);
}
VOID setEDX (ULONG val) {
VdmTib.VdmContext.Edx = val ;
}
VOID setDX (USHORT val) {
VdmTib.VdmContext.Edx = (VdmTib.VdmContext.Edx & 0xFFFF0000) |
((ULONG)val & 0x0000FFFF);
}
VOID setDH (UCHAR val) {
VdmTib.VdmContext.Edx = (VdmTib.VdmContext.Edx & 0xFFFF00FF) |
((ULONG)(val << 8) & 0x0000FF00);
}
VOID setDL (UCHAR val) {
VdmTib.VdmContext.Edx = (VdmTib.VdmContext.Edx & 0xFFFFFF00) |
((ULONG)val & 0x000000FF);
}
VOID setESP (ULONG val) {
VdmTib.VdmContext.Esp = val ;
}
VOID setSP (USHORT val) {
VdmTib.VdmContext.Esp = (VdmTib.VdmContext.Esp & 0xFFFF0000) |
((ULONG)val & 0x0000FFFF);
}
VOID setEBP (ULONG val) {
VdmTib.VdmContext.Ebp = val;
}
VOID setBP (USHORT val) {
VdmTib.VdmContext.Ebp = (VdmTib.VdmContext.Ebp & 0xFFFF0000) |
((ULONG)val & 0x0000FFFF);
}
VOID setESI (ULONG val) {
VdmTib.VdmContext.Esi = val ;
}
VOID setSI (USHORT val) {
VdmTib.VdmContext.Esi = (VdmTib.VdmContext.Esi & 0xFFFF0000) |
((ULONG)val & 0x0000FFFF);
}
VOID setEDI (ULONG val) {
VdmTib.VdmContext.Edi = val ;
}
VOID setDI (USHORT val) {
VdmTib.VdmContext.Edi = (VdmTib.VdmContext.Edi & 0xFFFF0000) |
((ULONG)val & 0x0000FFFF);
}
VOID setEIP (ULONG val) {
VdmTib.VdmContext.Eip = val ;
}
VOID setIP (USHORT val) {
VdmTib.VdmContext.Eip = (VdmTib.VdmContext.Eip & 0xFFFF0000) |
((ULONG)val & 0x0000FFFF);
}
VOID setCS (USHORT val) {
VdmTib.VdmContext.SegCs = (ULONG) val & 0x0000FFFF ;
}
VOID setSS (USHORT val) {
VdmTib.VdmContext.SegSs = (ULONG) val & 0x0000FFFF ;
}
VOID setDS (USHORT val) {
VdmTib.VdmContext.SegDs = (ULONG) val & 0x0000FFFF ;
}
VOID setES (USHORT val) {
VdmTib.VdmContext.SegEs = (ULONG) val & 0x0000FFFF ;
}
VOID setFS (USHORT val) {
VdmTib.VdmContext.SegFs = (ULONG) val & 0x0000FFFF ;
}
VOID setGS (USHORT val) {
VdmTib.VdmContext.SegGs = (ULONG) val & 0x0000FFFF ;
}
VOID setCF (ULONG val) {
VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_CARRY) |
(((ULONG)val << FLG_CARRY_BIT) & FLG_CARRY);
}
VOID setPF (ULONG val) {
VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_PARITY) |
(((ULONG)val << FLG_PARITY_BIT) & FLG_PARITY);
}
VOID setAF (ULONG val) {
VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_AUXILIARY) |
(((ULONG)val << FLG_AUXILIARY_BIT) & FLG_AUXILIARY);
}
VOID setZF (ULONG val) {
VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_ZERO) |
(((ULONG)val << FLG_ZERO_BIT) & FLG_ZERO);
}
VOID setSF (ULONG val) {
VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_SIGN) |
(((ULONG)val << FLG_SIGN_BIT) & FLG_SIGN);
}
VOID setIF (ULONG val) {
VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_INTERRUPT) |
(((ULONG)val << FLG_INTERRUPT_BIT) & FLG_INTERRUPT);
}
VOID setDF (ULONG val) {
VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_DIRECTION) |
(((ULONG)val << FLG_DIRECTION_BIT) & FLG_DIRECTION);
}
VOID setOF (ULONG val) {
VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_OVERFLOW) |
(((ULONG)val << FLG_OVERFLOW_BIT) & FLG_OVERFLOW);
}
VOID setMSW (USHORT val) {
IntelMSW = val ;
}
VOID setSTATUS(USHORT val) {
VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & 0xFFFF0000) | val;
}
//
// The following is a private register function
//
ULONG getPE(){
return((IntelMSW & MSW_PE) ? 1 : 0);
}
PX86CONTEXT
getIntelRegistersPointer(
VOID
)
/*++
Routine Description:
Return Address on Intel Registers for WOW Fast Access
Arguments:
None
Return Value:
Pointer to Intel Registers x86 Context Record
--*/
{
return &(VdmTib.VdmContext);
}
BOOLEAN MonitorInitializePrinterInfo(
WORD Ports,
PWORD PortTable,
PUCHAR State,
PUCHAR Control,
PUCHAR Status,
PUCHAR HostState)
{
int i;
ASSERT (Ports == 3);
ASSERT (Status != NULL);
// only do this if the structure has not been initialized -- meaning
// the pointers can be set once.
if (NULL == VdmTib.PrinterInfo.prt_Status) {
VdmTib.PrinterInfo.prt_PortAddr[0] = PortTable[0];
VdmTib.PrinterInfo.prt_PortAddr[1] = PortTable[1];
VdmTib.PrinterInfo.prt_PortAddr[2] = PortTable[2];
VdmTib.PrinterInfo.prt_Handle[0] =
VdmTib.PrinterInfo.prt_Handle[1] =
VdmTib.PrinterInfo.prt_Handle[2] = NULL;
// primarily for dongle
VdmTib.PrinterInfo.prt_BytesInBuffer[0] =
VdmTib.PrinterInfo.prt_BytesInBuffer[1] =
VdmTib.PrinterInfo.prt_BytesInBuffer[2] = 0;
// primarily for simulating printer status read in kernel
VdmTib.PrinterInfo.prt_State = State;
VdmTib.PrinterInfo.prt_Control = Control;
VdmTib.PrinterInfo.prt_Status = Status;
VdmTib.PrinterInfo.prt_HostState = HostState;
// deal with mode carefully. VDD may have hooked printer ports
// before we get here. If the mode is undefined, we can
// safely initialize it to our default, otherwise, just leave
// it alone.
for (i = 0; i < 3; i++) {
if (PRT_MODE_NO_SIMULATION == VdmTib.PrinterInfo.prt_Mode[i])
VdmTib.PrinterInfo.prt_Mode[i] = PRT_MODE_SIMULATE_STATUS_PORT;
}
return TRUE;
}
else
return FALSE;
}
BOOLEAN MonitorEnablePrinterDirectAccess(WORD adapter, HANDLE handle, BOOLEAN Enable)
{
ASSERT(VDM_NUMBER_OF_LPT > adapter);
if (Enable) {
// if the adapter has been allocated by a third party VDD,
// can't do direct io.
if (PRT_MODE_VDD_CONNECTED != VdmTib.PrinterInfo.prt_Mode[adapter]) {
VdmTib.PrinterInfo.prt_Mode[adapter] = PRT_MODE_DIRECT_IO;
VdmTib.PrinterInfo.prt_Handle[adapter] = handle;
// NtVdmControl(VdmPrinterDirectIoOpen, &adapter);
return TRUE;
}
else
return FALSE;
}
else {
// disabling direct i/o. reset it back to status port simulation
if (VdmTib.PrinterInfo.prt_Handle[adapter] == handle) {
NtVdmControl(VdmPrinterDirectIoClose, &adapter);
VdmTib.PrinterInfo.prt_Mode[adapter] = PRT_MODE_SIMULATE_STATUS_PORT;
VdmTib.PrinterInfo.prt_Handle[adapter] = NULL;
VdmTib.PrinterInfo.prt_BytesInBuffer[adapter] = 0;
return TRUE;
}
else
return FALSE;
}
}
BOOLEAN MonitorVddConnectPrinter(WORD Adapter, HANDLE hVdd, BOOLEAN Connect)
{
if (VDM_NUMBER_OF_LPT <= Adapter)
return FALSE;
if (Connect) {
VdmTib.PrinterInfo.prt_Mode[Adapter] = PRT_MODE_VDD_CONNECTED;
VdmTib.PrinterInfo.prt_Handle[Adapter] = hVdd;
return TRUE;
}
else {
if (hVdd == VdmTib.PrinterInfo.prt_Handle[Adapter]) {
VdmTib.PrinterInfo.prt_Mode[Adapter] = PRT_MODE_SIMULATE_STATUS_PORT;
VdmTib.PrinterInfo.prt_Handle[Adapter] = NULL;
return TRUE;
}
else return FALSE;
}
}
BOOLEAN MonitorPrinterWriteData(WORD Adapter, BYTE Value)
{
USHORT BytesInBuffer;
ASSERT(VDM_NUMBER_OF_LPT > Adapter);
BytesInBuffer = VdmTib.PrinterInfo.prt_BytesInBuffer[Adapter];
VdmTib.PrinterInfo.prt_Buffer[Adapter][BytesInBuffer] = Value;
VdmTib.PrinterInfo.prt_BytesInBuffer[Adapter]++;
return TRUE;
}