|
|
/*++
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"
#include "dbgsvc.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 EventVdmHandShakeAck( VOID );
VOID CreateProfile( VOID );
VOID StartProfile( VOID );
VOID StopProfile( VOID );
VOID AnalyzeProfile( VOID );
VOID CheckScreenSwitchRequest( HANDLE handle );
// [LATER] how do you prevent a struct from straddling a page boundary?
ULONG IntelBase; // base memory address
ULONG VdmSize; // Size of memory in VDM
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 = INITIAL_VDM_TIB_FLAGS; // VdmTib flags picked up from here
CONTEXT InitialContext; // Initial context for all threads
BOOLEAN DebugContextActive = FALSE; ULONG VdmFeatureBits = 0; // bit to indicate special features
BOOLEAN MainThreadInMonitor = TRUE;
extern PVOID NTVDMpLockPrefixTable; extern BOOL HandshakeInProgress; extern HANDLE hSuspend; extern HANDLE hResume; extern HANDLE hMainThreadSuspended;
extern PVOID __safe_se_handler_table[]; /* base of safe handler entry table */ extern BYTE __safe_se_handler_count; /* absolute symbol whose address is
the count of table entries */
IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = { sizeof(_load_config_used), // Reserved
0, // Reserved
0, // Reserved
0, // Reserved
0, // GlobalFlagsClear
0, // GlobalFlagsSet
0, // CriticalSectionTimeout (milliseconds)
0, // DeCommitFreeBlockThreshold
0, // DeCommitTotalFreeThreshold
(ULONG)&NTVDMpLockPrefixTable, // LockPrefixTable, defined in FASTPM.ASM
0, 0, 0, 0, 0, 0, 0, // Reserved
0, // & security_cookie
(ULONG)__safe_se_handler_table, (ULONG)&__safe_se_handler_count };
// Bop dispatch table
extern void (*BIOS[])();
//
// Event Dispatch table
//
VOID (*EventDispatch[VdmMaxEvent])(VOID) = { EventVdmIo, EventVdmStringIo, EventVdmMemAccess, EventVdmIntAck, EventVdmBop, EventVdmError, EventVdmIrq13, EventVdmHandShakeAck };
#if DBG
BOOLEAN fBreakInDebugger = FALSE; #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;
InitialVdmTibFlags |= RM_BIT_MASK;
//
// 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(), NULL );
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; PVDM_TIB VdmTib; ULONG oldIntState = VDM_VIRTUAL_INTERRUPTS;
DBGTRACE(VDMTR_TYPE_MONITOR | MONITOR_CPU_SIMULATE, 0, 0);
CurrentMonitorTeb = NtCurrentTeb(); VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm;
VdmTib->ContinueExecution = TRUE;
VdmTib->VdmContext.ContextFlags = CONTEXT_FULL;
while (VdmTib->ContinueExecution) {
//ASSERT(CurrentMonitorTeb == NtCurrentTeb());
ASSERT(InterlockedIncrement(&VdmTib->NumTasks) == 0);
if (*pNtVDMState & VDM_INTERRUPT_PENDING) { DispatchInterrupts(); }
// translate MSW bits into EFLAGS
if ( getMSW() & MSW_PE ) { if (!VDMForWOW && !getIF() && oldIntState == VDM_VIRTUAL_INTERRUPTS) {
//
// For PM apps, we need to set Cli time stamp if interrupts
// are disabled and the time stamp was not set already.
// This is because apps may use int31 to change interrupt
// state instead of using cli.
//
VDM_PM_CLI_DATA cliData;
cliData.Control = PM_CLI_CONTROL_SET; NtVdmControl(VdmPMCliControl, &cliData); }
VdmTib->VdmContext.EFlags &= ~EFLAGS_V86_MASK; if (HandshakeInProgress) { CheckScreenSwitchRequest(hMainThreadSuspended); } MainThreadInMonitor = FALSE;
Status = FastEnterPm(); } else { VdmTib->VdmContext.EFlags |= EFLAGS_V86_MASK; if (HandshakeInProgress) { CheckScreenSwitchRequest(hMainThreadSuspended); } MainThreadInMonitor = FALSE;
Status = NtVdmControl(VdmStartExecution,NULL); }
MainThreadInMonitor = TRUE; if (HandshakeInProgress) { CheckScreenSwitchRequest(hMainThreadSuspended); } if (!NT_SUCCESS(Status)) { #if DBG
DbgPrint("NTVDM: Could not start execution\n"); #endif
return; }
//
// Refresh VdmTib for the fact that wow32 thread never enters cpu_simulate
// but returns here to handle BOP
// Note, I think this needs only in FREE build.
//
CurrentMonitorTeb = NtCurrentTeb(); VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; if (!VDMForWOW) { oldIntState = getIF() ? VDM_VIRTUAL_INTERRUPTS : 0; }
ASSERT(InterlockedDecrement(&VdmTib->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
VdmTib->ContinueExecution = FALSE; continue; } (*EventDispatch[VdmTib->EventInfo.Event])(); }
// set this back to true incase we are nested
VdmTib->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
//
DBGTRACE(VDMTR_TYPE_MONITOR | MONITOR_CPU_UNSIMULATE, 0, 0); }
VOID host_unsimulate( )
/*++
Routine Description:
This routine causes execution of instructions in a VDM to stop.
Arguments:
Return Value:
None.
--*/
{ PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->ContinueExecution = FALSE;
}
VOID EventVdmIo( VOID ) /*++
Routine Description:
This function calls the appropriate io simulation routine.
Arguments:
Return Value:
None.
--*/ { PVDM_TIB VdmTib;
EnableScreenSwitch(TRUE, hMainThreadSuspended); // only in FULLSCREEN
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; 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
DisableScreenSwitch(hMainThreadSuspended); }
VOID EventVdmStringIo( VOID ) /*++
Routine Description:
This function calls the appropriate io simulation routine.
Arguments:
Return Value:
None.
--*/ { PVDMSTRINGIOINFO pvsio; PUSHORT pIndexRegister; USHORT Index; PVDM_TIB VdmTib;
EnableScreenSwitch(TRUE, hMainThreadSuspended); VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm;
// 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
DisableScreenSwitch(hMainThreadSuspended); 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; }
DisableScreenSwitch(hMainThreadSuspended); }
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; PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm;
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.
--*/ { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; if (VdmTib->EventInfo.BopNumber > MAX_BOP) { #if DBG
DbgPrint( "NtVdm: Invalid BOP %lx\n", VdmTib->EventInfo.BopNumber ); #endif
VdmTib->ContinueExecution = FALSE; } else {
DBGTRACE(VDMTR_TYPE_MONITOR | MONITOR_EVENT_BOP, (USHORT)VdmTib->EventInfo.BopNumber, (ULONG)(*((UCHAR *)Sim32GetVDMPointer( (VdmTib->VdmContext.SegCs << 16) | VdmTib->VdmContext.Eip, 1, ISPESET))) );
(*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.
--*/ { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; #if DBG
DbgPrint( "NtVdm: Error code %lx\n", VdmTib->EventInfo.ErrorStatus ); DbgBreakPoint(); #endif
TerminateVDM(); VdmTib->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 EventVdmHandShakeAck( VOID ) /*++
Routine Description:
This routine does nothing.
Arguments:
Return Value:
None.
--*/ { }
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.
--*/ {
PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm;
// 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) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return (VdmTib->VdmContext.Eax); } USHORT getAX (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((USHORT)(VdmTib->VdmContext.Eax)); } UCHAR getAL (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((BYTE)(VdmTib->VdmContext.Eax)); } UCHAR getAH (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((BYTE)(VdmTib->VdmContext.Eax >> 8)); } ULONG getEBX (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return (VdmTib->VdmContext.Ebx); } USHORT getBX (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((USHORT)(VdmTib->VdmContext.Ebx)); } UCHAR getBL (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((BYTE)(VdmTib->VdmContext.Ebx)); } UCHAR getBH (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((BYTE)(VdmTib->VdmContext.Ebx >> 8)); } ULONG getECX (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return (VdmTib->VdmContext.Ecx); } USHORT getCX (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((USHORT)(VdmTib->VdmContext.Ecx)); } UCHAR getCL (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((BYTE)(VdmTib->VdmContext.Ecx)); } UCHAR getCH (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((BYTE)(VdmTib->VdmContext.Ecx >> 8)); } ULONG getEDX (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return (VdmTib->VdmContext.Edx); } USHORT getDX (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((USHORT)(VdmTib->VdmContext.Edx)); } UCHAR getDL (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((BYTE)(VdmTib->VdmContext.Edx)); } UCHAR getDH (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((BYTE)(VdmTib->VdmContext.Edx >> 8)); } ULONG getESP (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return (VdmTib->VdmContext.Esp); } USHORT getSP (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((USHORT)VdmTib->VdmContext.Esp); } ULONG getEBP (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return (VdmTib->VdmContext.Ebp); } USHORT getBP (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((USHORT)VdmTib->VdmContext.Ebp); } ULONG getESI (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return (VdmTib->VdmContext.Esi); } USHORT getSI (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((USHORT)VdmTib->VdmContext.Esi); } ULONG getEDI (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return (VdmTib->VdmContext.Edi); } USHORT getDI (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((USHORT)VdmTib->VdmContext.Edi); } ULONG getEIP (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return (VdmTib->VdmContext.Eip); } USHORT getIP (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((USHORT)VdmTib->VdmContext.Eip); } USHORT getCS (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((USHORT)VdmTib->VdmContext.SegCs); } USHORT getSS (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((USHORT)VdmTib->VdmContext.SegSs); } USHORT getDS (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((USHORT)VdmTib->VdmContext.SegDs); } USHORT getES (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((USHORT)VdmTib->VdmContext.SegEs); } USHORT getFS (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((USHORT)VdmTib->VdmContext.SegFs); } USHORT getGS (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((USHORT)VdmTib->VdmContext.SegGs); } ULONG getCF (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((VdmTib->VdmContext.EFlags & FLG_CARRY) ? 1 : 0); } ULONG getPF (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((VdmTib->VdmContext.EFlags & FLG_PARITY) ? 1 : 0); } ULONG getAF (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((VdmTib->VdmContext.EFlags & FLG_AUXILIARY) ? 1 : 0); } ULONG getZF (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((VdmTib->VdmContext.EFlags & FLG_ZERO) ? 1 : 0); } ULONG getSF (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((VdmTib->VdmContext.EFlags & FLG_SIGN) ? 1 : 0); } ULONG getTF (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((VdmTib->VdmContext.EFlags & FLG_TRAP) ? 1 : 0); } ULONG getIF (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((VdmTib->VdmContext.EFlags & FLG_INTERRUPT) ? 1 : 0); } ULONG getDF (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((VdmTib->VdmContext.EFlags & FLG_DIRECTION) ? 1 : 0); } ULONG getOF (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((VdmTib->VdmContext.EFlags & FLG_OVERFLOW) ? 1 : 0); } USHORT getMSW (VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return ((USHORT)VdmTib->IntelMSW); } USHORT getSTATUS(VOID){ PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return (USHORT)VdmTib->VdmContext.EFlags; } ULONG getEFLAGS(VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return VdmTib->VdmContext.EFlags; } USHORT getFLAGS(VOID) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return (USHORT)VdmTib->VdmContext.EFlags; }
VOID setEAX (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Eax = val; }
VOID setAX (USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Eax = (VdmTib->VdmContext.Eax & 0xFFFF0000) | ((ULONG)val & 0x0000FFFF); }
VOID setAH (UCHAR val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Eax = (VdmTib->VdmContext.Eax & 0xFFFF00FF) | ((ULONG)(val << 8) & 0x0000FF00); }
VOID setAL (UCHAR val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Eax = (VdmTib->VdmContext.Eax & 0xFFFFFF00) | ((ULONG)val & 0x000000FF); }
VOID setEBX (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Ebx = val ; }
VOID setBX (USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Ebx = (VdmTib->VdmContext.Ebx & 0xFFFF0000) | ((ULONG)val & 0x0000FFFF); }
VOID setBH (UCHAR val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Ebx = (VdmTib->VdmContext.Ebx & 0xFFFF00FF) | ((ULONG)(val << 8) & 0x0000FF00); }
VOID setBL (UCHAR val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Ebx = (VdmTib->VdmContext.Ebx & 0xFFFFFF00) | ((ULONG)val & 0x000000FF); }
VOID setECX (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Ecx = val ; }
VOID setCX (USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Ecx = (VdmTib->VdmContext.Ecx & 0xFFFF0000) | ((ULONG)val & 0x0000FFFF); }
VOID setCH (UCHAR val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Ecx = (VdmTib->VdmContext.Ecx & 0xFFFF00FF) | ((ULONG)(val << 8) & 0x0000FF00); }
VOID setCL (UCHAR val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Ecx = (VdmTib->VdmContext.Ecx & 0xFFFFFF00) | ((ULONG)val & 0x000000FF); }
VOID setEDX (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Edx = val ; }
VOID setDX (USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Edx = (VdmTib->VdmContext.Edx & 0xFFFF0000) | ((ULONG)val & 0x0000FFFF); }
VOID setDH (UCHAR val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Edx = (VdmTib->VdmContext.Edx & 0xFFFF00FF) | ((ULONG)(val << 8) & 0x0000FF00); }
VOID setDL (UCHAR val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Edx = (VdmTib->VdmContext.Edx & 0xFFFFFF00) | ((ULONG)val & 0x000000FF); }
VOID setESP (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Esp = val ; }
VOID setSP (USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Esp = (VdmTib->VdmContext.Esp & 0xFFFF0000) | ((ULONG)val & 0x0000FFFF); }
VOID setEBP (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Ebp = val; }
VOID setBP (USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Ebp = (VdmTib->VdmContext.Ebp & 0xFFFF0000) | ((ULONG)val & 0x0000FFFF); }
VOID setESI (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Esi = val ; }
VOID setSI (USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Esi = (VdmTib->VdmContext.Esi & 0xFFFF0000) | ((ULONG)val & 0x0000FFFF); } VOID setEDI (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Edi = val ; }
VOID setDI (USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Edi = (VdmTib->VdmContext.Edi & 0xFFFF0000) | ((ULONG)val & 0x0000FFFF); }
VOID setEIP (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Eip = val ; }
VOID setIP (USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.Eip = (VdmTib->VdmContext.Eip & 0xFFFF0000) | ((ULONG)val & 0x0000FFFF); }
VOID setCS (USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.SegCs = (ULONG) val & 0x0000FFFF ; }
VOID setSS (USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.SegSs = (ULONG) val & 0x0000FFFF ; }
VOID setDS (USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.SegDs = (ULONG) val & 0x0000FFFF ; }
VOID setES (USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.SegEs = (ULONG) val & 0x0000FFFF ; }
VOID setFS (USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.SegFs = (ULONG) val & 0x0000FFFF ; }
VOID setGS (USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.SegGs = (ULONG) val & 0x0000FFFF ; }
VOID setCF (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.EFlags = (VdmTib->VdmContext.EFlags & ~FLG_CARRY) | (((ULONG)val << FLG_CARRY_BIT) & FLG_CARRY); }
VOID setPF (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.EFlags = (VdmTib->VdmContext.EFlags & ~FLG_PARITY) | (((ULONG)val << FLG_PARITY_BIT) & FLG_PARITY); }
VOID setAF (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.EFlags = (VdmTib->VdmContext.EFlags & ~FLG_AUXILIARY) | (((ULONG)val << FLG_AUXILIARY_BIT) & FLG_AUXILIARY); }
VOID setZF (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.EFlags = (VdmTib->VdmContext.EFlags & ~FLG_ZERO) | (((ULONG)val << FLG_ZERO_BIT) & FLG_ZERO); }
VOID setSF (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.EFlags = (VdmTib->VdmContext.EFlags & ~FLG_SIGN) | (((ULONG)val << FLG_SIGN_BIT) & FLG_SIGN); }
VOID setIF (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.EFlags = (VdmTib->VdmContext.EFlags & ~FLG_INTERRUPT) | (((ULONG)val << FLG_INTERRUPT_BIT) & FLG_INTERRUPT); }
VOID setDF (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.EFlags = (VdmTib->VdmContext.EFlags & ~FLG_DIRECTION) | (((ULONG)val << FLG_DIRECTION_BIT) & FLG_DIRECTION); }
VOID setOF (ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.EFlags = (VdmTib->VdmContext.EFlags & ~FLG_OVERFLOW) | (((ULONG)val << FLG_OVERFLOW_BIT) & FLG_OVERFLOW); }
VOID setMSW (USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->IntelMSW = val ; }
VOID setSTATUS(USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.EFlags = (VdmTib->VdmContext.EFlags & 0xFFFF0000) | val; }
VOID setEFLAGS(ULONG val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.EFlags = val; }
VOID setFLAGS(USHORT val) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; VdmTib->VdmContext.EFlags = (VdmTib->VdmContext.EFlags & 0xFFFF0000) | val; } //
// The following is a private register function
//
ULONG getPE(){ PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return((VdmTib->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
--*/ { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; return &(VdmTib->VdmContext); }
BOOLEAN MonitorInitializePrinterInfo( WORD Ports, PWORD PortTable, PUCHAR State, PUCHAR Control, PUCHAR Status, PUCHAR HostState) { UCHAR adapter; PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm;
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;
// default mode is kernel simulating status port read
// mode will be changed if
// (1). A vdd is hooking printer ports.
// (2). Dongle mode is detected
VdmTib->PrinterInfo.prt_Mode[0] = VdmTib->PrinterInfo.prt_Mode[1] = VdmTib->PrinterInfo.prt_Mode[2] = PRT_MODE_SIMULATE_STATUS_PORT;
// 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;
//
// Give the kernel printer emulation an opportunity to cache the
// pointers
//
if (!NT_SUCCESS(NtVdmControl(VdmPrinterInitialize,NULL))) { return FALSE; }
return TRUE; } else { return FALSE; } }
BOOLEAN MonitorEnablePrinterDirectAccess(WORD adapter, HANDLE handle, BOOLEAN Enable) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; 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) { PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm; 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; PVDM_TIB VdmTib;
VdmTib = (PVDM_TIB)NtCurrentTeb()->Vdm;
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; }
/* CheckScreenSwitchRequest -
* * This function checks if timer thread has asked us to stop such that it * can handle the fullscreen and windowed switch. * If yes, we will signal that we are stopped and wait for resume event. * */ VOID CheckScreenSwitchRequest(HANDLE handle) { DWORD status;
//
// Check if Suspen is requested. If yes, we will signal that we are going to
// the wait state and wait for the resume event
// Since 'handle' event is a manual event, it is important that
// we check-and-wait in a loop such that timer thread will not pick up the
// 'handle' event between the wait-for-resume and the ResetEvent(handle).
//
while (TRUE) { status = WaitForSingleObject(hSuspend, 0); if (status == 0) { SetEvent(handle); WaitForSingleObject(hResume, INFINITE); ResetEvent(handle); } else {
//
// Make sure event is reset before leaving this function
//
ResetEvent(handle); return; } } }
|