mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1701 lines
51 KiB
1701 lines
51 KiB
/*
|
|
* dbg.c - Main Module of DBG DLL.
|
|
*
|
|
* BobDay 13-Jan-1992 Created
|
|
*
|
|
* WARNING: THIS MODULE APPEARS TO HAVE MANY FUNCTIONS THAT APPEAR IDENTICAL
|
|
* THEY ARE NOT IDENTICAL. THEY ARE NEARLY IDENTICAL. IF YOU CHOOSE
|
|
* TO COMBINE SIMILAR FUNCTIONALITY INTO SEVERAL SMALLER ROUTINES,
|
|
* BE VERY CAREFUL TO LOOK FOR THE SMALL SUBTLE DIFFERENCES.
|
|
*/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <ntdbg.h>
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <mvdm.h>
|
|
#include <bop.h>
|
|
#include <softpc.h>
|
|
#include <dbgexp.h>
|
|
#include <dbgsvc.h>
|
|
#include <vdmdbg.h>
|
|
#include <dbginfo.h>
|
|
|
|
#define MAX_MODULE 64
|
|
|
|
#define MAX_DBG_FRAME 10
|
|
|
|
ULONG ulTHHOOK = 0L; // Address registered from 16-bit world
|
|
LPVOID lpRemoteAddress = NULL; // Address registered from WOW32
|
|
DWORD lpRemoteBlock = 0; // Address registered from WOW32
|
|
BOOL f386;
|
|
|
|
typedef struct _trapframe {
|
|
WORD wCode; /* Noise from DbgDispatchBop */
|
|
WORD wAX; /* AX at time of fault */
|
|
WORD wDS; /* DS at time of fault */
|
|
WORD wRetIP; /* Noise from DPMI */
|
|
WORD wRetCS; /* Noise from DPMI */
|
|
WORD wErrCode; /* Noise from 16-bit kernel */
|
|
WORD wIP; /* IP at time of fault */
|
|
WORD wCS; /* CS at time of fault */
|
|
WORD wFlags; /* Flags at time of fault */
|
|
WORD wSP; /* SS at time of fault */
|
|
WORD wSS; /* SP at time of fault */
|
|
} TFRAME16;
|
|
typedef TFRAME16 UNALIGNED *PTFRAME16;
|
|
|
|
typedef struct _faultframe {
|
|
WORD wES; /* ES at time of fault */
|
|
WORD wDS; /* DS at time of fault */
|
|
WORD wDI; /* DI at time of fault */
|
|
WORD wSI; /* SI at time of fault */
|
|
WORD wTempBP; /* Noise from 16-bit kernel stack frame */
|
|
WORD wTempSP; /* Noise from 16-bit kernel stack frame */
|
|
WORD wBX; /* BX at time of fault */
|
|
WORD wDX; /* DX at time of fault */
|
|
WORD wCX; /* CX at time of fault */
|
|
WORD wAX; /* AX at time of fault */
|
|
WORD wBP; /* BP at time of fault */
|
|
WORD npszMsg; /* Noise from 16-bit kernel */
|
|
WORD wPrevIP; /* Noise from DPMI */
|
|
WORD wPrevCS; /* Noise from DPMI */
|
|
WORD wRetIP; /* Noise from DPMI */
|
|
WORD wRetCS; /* Noise from DPMI */
|
|
WORD wErrCode; /* Noise from 16-bit kernel */
|
|
WORD wIP; /* IP at time of fault */
|
|
WORD wCS; /* CS at time of fault */
|
|
WORD wFlags; /* Flags at time of fault */
|
|
WORD wSP; /* SS at time of fault */
|
|
WORD wSS; /* SP at time of fault */
|
|
} FFRAME16;
|
|
typedef FFRAME16 UNALIGNED *PFFRAME16;
|
|
|
|
typedef struct _newtaskframe {
|
|
DWORD dwNoise; /* Noise from InitTask */
|
|
DWORD dwModulePath; /* Module path address */
|
|
DWORD dwModuleName; /* Module name address */
|
|
WORD hModule; /* 16-bit Module handle */
|
|
WORD hTask; /* 16-bit Task handle */
|
|
WORD wFlags; /* Flags at time to task start */
|
|
WORD wDX; /* DX at time of task start */
|
|
WORD wBX; /* BX at time of task start */
|
|
WORD wES; /* ES at time of task start */
|
|
WORD wCX; /* CX at time of task start */
|
|
WORD wAX; /* AX at time of task start */
|
|
WORD wDI; /* DI at time of task start */
|
|
WORD wSI; /* SI at time of task start */
|
|
WORD wDS; /* DS at time of task start */
|
|
WORD wBP; /* BP at time of task start */
|
|
WORD wIP; /* IP for task start */
|
|
WORD wCS; /* CS for task start */
|
|
} NTFRAME16;
|
|
typedef NTFRAME16 UNALIGNED *PNTFRAME16;
|
|
|
|
#pragma pack(2)
|
|
|
|
typedef struct _stoptaskframe {
|
|
WORD wCode; /* Noise from BOP Dispatcher */
|
|
DWORD dwModulePath; /* Module path address */
|
|
DWORD dwModuleName; /* Module name address */
|
|
WORD hModule; /* 16-bit Module handle */
|
|
WORD hTask; /* 16-bit Task handle */
|
|
} STFRAME16;
|
|
typedef STFRAME16 UNALIGNED *PSTFRAME16;
|
|
|
|
typedef struct _newdllframe {
|
|
WORD wCode; /* Noise from DbgDispatchBop */
|
|
DWORD dwModulePath; /* Module path address */
|
|
DWORD dwModuleName; /* Module name address */
|
|
WORD hModule; /* 16-bit Module handle */
|
|
WORD hTask; /* 16-bit Task handle */
|
|
WORD wDS; /* DS at time of dll start */
|
|
WORD wAX; /* AX at time of dll start */
|
|
WORD wIP; /* IP at time of dll start */
|
|
WORD wCS; /* CS at time of dll start */
|
|
WORD wFlags; /* Flags at time of dll start */
|
|
} NDFRAME16;
|
|
typedef NDFRAME16 UNALIGNED *PNDFRAME16;
|
|
|
|
#pragma pack()
|
|
|
|
|
|
BOOL fDebugged = FALSE;
|
|
|
|
/* DBGInit - DBG Initialiazation routine. (This name may change when DBG is
|
|
* converted to DLL).
|
|
*
|
|
* Entry
|
|
* None
|
|
*
|
|
* Exit
|
|
* None
|
|
*/
|
|
|
|
BOOL DBGInit (int argc, char *argv[])
|
|
{
|
|
HANDLE hProcess;
|
|
HANDLE MyDebugPort;
|
|
DWORD st;
|
|
|
|
hProcess = NtCurrentProcess();
|
|
|
|
st = NtQueryInformationProcess(
|
|
hProcess,
|
|
ProcessDebugPort,
|
|
(PVOID)&MyDebugPort,
|
|
sizeof(MyDebugPort),
|
|
NULL );
|
|
if ( NT_SUCCESS(st) ) {
|
|
fDebugged = (MyDebugPort != NULL);
|
|
} else {
|
|
fDebugged = FALSE;
|
|
}
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOL SendVDMEvent(
|
|
LPDWORD lpParams
|
|
) {
|
|
BOOL fResult;
|
|
|
|
// Slimyness to determine whether the exception was handled or not.
|
|
|
|
try {
|
|
RaiseException( STATUS_VDM_EVENT,
|
|
0,
|
|
4,
|
|
lpParams );
|
|
fResult = TRUE;
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
fResult = FALSE;
|
|
}
|
|
return( fResult );
|
|
}
|
|
|
|
|
|
/* GetNormalContext() - Get the VDM's current context
|
|
*
|
|
* Most of the routines that send VDMEvents need to have a context record
|
|
* associated with them. This routine is a quick way to get most of the
|
|
* general registers. Redundant work is being done because AX for example
|
|
* is often on the stack and as such must really be pulled from the frame.
|
|
* Hopefully this is OK because it is fast.
|
|
*/
|
|
#ifdef i386
|
|
#define PX86 px86
|
|
#else
|
|
#define PX86 0
|
|
#endif
|
|
|
|
VOID GetNormalContext(
|
|
LPVDMCONTEXT lpvcContext,
|
|
LPVDMINTERNALINFO lpviInfo,
|
|
LPDWORD lpdwExceptionParams,
|
|
WORD wEventType,
|
|
#ifdef i386
|
|
PX86CONTEXT px86
|
|
#else
|
|
DWORD dw
|
|
#endif
|
|
) {
|
|
//
|
|
// Everything defaults to 0.
|
|
//
|
|
RtlFillMemory( lpvcContext, sizeof(VDMCONTEXT), (UCHAR)0 );
|
|
RtlFillMemory( lpviInfo, sizeof(VDMINTERNALINFO), (UCHAR)0 );
|
|
RtlFillMemory( lpdwExceptionParams, 4*sizeof(DWORD), (UCHAR)0 );
|
|
|
|
//
|
|
// Fill in the exception parameters
|
|
//
|
|
lpdwExceptionParams[0] = MAKELONG( wEventType, 0 );
|
|
lpdwExceptionParams[3] = (DWORD)lpviInfo;
|
|
|
|
//
|
|
// Fill in the internal info structure
|
|
//
|
|
lpviInfo->wKernelSeg = HIWORD(ulTHHOOK);
|
|
lpviInfo->dwOffsetTHHOOK = (DWORD)(LOWORD(ulTHHOOK));
|
|
lpviInfo->vdmContext = lpvcContext;
|
|
lpviInfo->lpRemoteAddress = lpRemoteAddress;
|
|
lpviInfo->lpRemoteBlock = lpRemoteBlock;
|
|
lpviInfo->f386 = f386;
|
|
|
|
//
|
|
// Fill in the context structure
|
|
//
|
|
lpvcContext->SegEs = (ULONG)getES();
|
|
lpvcContext->SegDs = (ULONG)getDS();
|
|
lpvcContext->SegCs = (ULONG)getCS();
|
|
lpvcContext->SegSs = (ULONG)getSS();
|
|
|
|
lpvcContext->EFlags = 0; // BUGBUG - We need the 16-bit's Flags
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the FS and GS
|
|
// registers. Hopefully the code path through DOSX and KERNEL don't
|
|
// modify them (I traced it and it didn't seem to). Here is where
|
|
// we attempt to recover them.
|
|
//
|
|
lpvcContext->SegGs = px86->SegGs;
|
|
lpvcContext->SegFs = px86->SegFs;
|
|
|
|
// On x86 systems, we really might have some data in the high words
|
|
// of the registers. Hopefully the code path through DOSX and KERNEL
|
|
// don't modify them (I trace it and it didn't seem to). Here is where
|
|
// we attempt to recover them.
|
|
|
|
lpvcContext->Edi = MAKELONG(getDI(), HIWORD(px86->Edi ));
|
|
lpvcContext->Esi = MAKELONG(getSI(), HIWORD(px86->Esi ));
|
|
lpvcContext->Ebx = MAKELONG(getBX(), HIWORD(px86->Ebx ));
|
|
lpvcContext->Edx = MAKELONG(getDX(), HIWORD(px86->Edx ));
|
|
lpvcContext->Ecx = MAKELONG(getCX(), HIWORD(px86->Ecx ));
|
|
lpvcContext->Eax = MAKELONG(getAX(), HIWORD(px86->Eax ));
|
|
|
|
lpvcContext->Ebp = MAKELONG(getBP(), HIWORD(px86->Ebp ));
|
|
lpvcContext->Eip = MAKELONG(getIP(), HIWORD(px86->Eip ));
|
|
lpvcContext->Esp = MAKELONG(getSP(), HIWORD(px86->Esp ));
|
|
|
|
#else
|
|
// Leave GS & FS zero.
|
|
|
|
lpvcContext->Edi = (ULONG)getDI();
|
|
lpvcContext->Esi = (ULONG)getSI();
|
|
lpvcContext->Ebx = (ULONG)getBX();
|
|
lpvcContext->Edx = (ULONG)getDX();
|
|
lpvcContext->Ecx = (ULONG)getCX();
|
|
lpvcContext->Eax = (ULONG)getAX();
|
|
|
|
lpvcContext->Ebp = (ULONG)getBP();
|
|
lpvcContext->Eip = (ULONG)getIP();
|
|
lpvcContext->Esp = (ULONG)getSP();
|
|
|
|
if ( (getMSW() & MSW_PE) == 0 ) {
|
|
lpvcContext->EFlags |= V86FLAGS_V86;
|
|
}
|
|
|
|
// BUGBUG initialize the GDT/LDT stuff for the emulator
|
|
#endif
|
|
}
|
|
|
|
void SegmentLoad(
|
|
LPSTR lpModuleName,
|
|
LPSTR lpPathName,
|
|
WORD Selector,
|
|
WORD Segment,
|
|
BOOL fData
|
|
|
|
) {
|
|
|
|
if ( fDebugged ) {
|
|
DWORD EventParams[4];
|
|
VDMCONTEXT vcContext;
|
|
VDMINTERNALINFO viInfo;
|
|
SEGMENT_NOTE se;
|
|
UINT length;
|
|
#ifdef i386
|
|
PX86CONTEXT px86;
|
|
|
|
// X86 Only, get pointer to Register Context Block
|
|
px86 = getIntelRegistersPointer();
|
|
#endif
|
|
|
|
GetNormalContext( &vcContext, &viInfo, EventParams, DBG_SEGLOAD, PX86 );
|
|
|
|
RtlFillMemory( &se, sizeof(se), (UCHAR)0 );
|
|
|
|
se.Selector1 = Selector;
|
|
se.Segment = Segment;
|
|
se.Type = fData;
|
|
|
|
length = strlen(lpPathName);
|
|
if ( length >= MAX_PATH16 ) {
|
|
length = MAX_PATH16-1;
|
|
}
|
|
strncpy( se.FileName, lpPathName, length );
|
|
se.FileName[length] = '\0';
|
|
|
|
length = strlen(lpModuleName);
|
|
if ( length >= MAX_MODULE ) {
|
|
length = MAX_MODULE-1;
|
|
}
|
|
strncpy( se.Module, lpModuleName, length );
|
|
se.Module[length] = '\0';
|
|
|
|
EventParams[2] = (DWORD)&se;
|
|
|
|
SendVDMEvent( EventParams );
|
|
}
|
|
}
|
|
|
|
void SegmentMove(
|
|
WORD OldSelector,
|
|
WORD NewSelector
|
|
) {
|
|
|
|
if ( fDebugged ) {
|
|
DWORD EventParams[4];
|
|
VDMCONTEXT vcContext;
|
|
VDMINTERNALINFO viInfo;
|
|
SEGMENT_NOTE se;
|
|
#ifdef i386
|
|
PX86CONTEXT px86;
|
|
|
|
// X86 Only, get pointer to Register Context Block
|
|
px86 = getIntelRegistersPointer();
|
|
#endif
|
|
|
|
GetNormalContext( &vcContext, &viInfo, EventParams, DBG_SEGMOVE, PX86 );
|
|
|
|
RtlFillMemory( &se, sizeof(se), (UCHAR)0 );
|
|
|
|
se.Selector1 = OldSelector;
|
|
se.Selector2 = NewSelector;
|
|
|
|
EventParams[2] = (DWORD)&se;
|
|
|
|
SendVDMEvent( EventParams );
|
|
}
|
|
}
|
|
|
|
void SegmentFree(
|
|
WORD Selector,
|
|
BOOL fBPRelease
|
|
) {
|
|
|
|
if ( fDebugged ) {
|
|
DWORD EventParams[4];
|
|
VDMCONTEXT vcContext;
|
|
VDMINTERNALINFO viInfo;
|
|
SEGMENT_NOTE se;
|
|
#ifdef i386
|
|
PX86CONTEXT px86;
|
|
|
|
// X86 Only, get pointer to Register Context Block
|
|
px86 = getIntelRegistersPointer();
|
|
#endif
|
|
|
|
GetNormalContext( &vcContext, &viInfo, EventParams, DBG_SEGFREE, PX86 );
|
|
|
|
RtlFillMemory( &se, sizeof(se), (UCHAR)0 );
|
|
|
|
se.Selector1 = Selector;
|
|
se.Type = (WORD)fBPRelease;
|
|
|
|
EventParams[2] = (DWORD)&se;
|
|
|
|
SendVDMEvent( EventParams );
|
|
}
|
|
}
|
|
|
|
void ModuleLoad(
|
|
LPSTR lpModuleName,
|
|
LPSTR lpPathName,
|
|
WORD Segment,
|
|
DWORD Length
|
|
) {
|
|
|
|
if ( fDebugged ) {
|
|
DWORD EventParams[4];
|
|
VDMCONTEXT vcContext;
|
|
VDMINTERNALINFO viInfo;
|
|
SEGMENT_NOTE se;
|
|
UINT length;
|
|
#ifdef i386
|
|
PX86CONTEXT px86;
|
|
|
|
// X86 Only, get pointer to Register Context Block
|
|
px86 = getIntelRegistersPointer();
|
|
#endif
|
|
|
|
GetNormalContext( &vcContext, &viInfo, EventParams, DBG_MODLOAD, PX86 );
|
|
|
|
RtlFillMemory( &se, sizeof(se), (UCHAR)0 );
|
|
|
|
se.Segment = Segment;
|
|
se.Length = Length;
|
|
|
|
length = strlen(lpPathName);
|
|
if ( length >= MAX_PATH16 ) {
|
|
length = MAX_PATH16-1;
|
|
}
|
|
strncpy( se.FileName, lpPathName, length );
|
|
se.FileName[length] = '\0';
|
|
|
|
length = strlen(lpModuleName);
|
|
if ( length >= MAX_MODULE ) {
|
|
length = MAX_MODULE-1;
|
|
}
|
|
strncpy( se.Module, lpModuleName, length );
|
|
se.Module[length] = '\0';
|
|
|
|
EventParams[2] = (DWORD)&se;
|
|
|
|
SendVDMEvent( EventParams );
|
|
}
|
|
}
|
|
|
|
void ModuleSegmentMove(
|
|
LPSTR lpModuleName,
|
|
LPSTR lpPathName,
|
|
WORD OldSelector,
|
|
WORD NewSelector
|
|
) {
|
|
|
|
if ( fDebugged ) {
|
|
DWORD EventParams[4];
|
|
VDMCONTEXT vcContext;
|
|
VDMINTERNALINFO viInfo;
|
|
SEGMENT_NOTE se;
|
|
UINT length;
|
|
#ifdef i386
|
|
PX86CONTEXT px86;
|
|
|
|
// X86 Only, get pointer to Register Context Block
|
|
px86 = getIntelRegistersPointer();
|
|
#endif
|
|
|
|
GetNormalContext( &vcContext, &viInfo, EventParams, DBG_SEGMOVE, PX86 );
|
|
|
|
RtlFillMemory( &se, sizeof(se), (UCHAR)0 );
|
|
|
|
se.Segment = OldSelector;
|
|
se.Selector2 = NewSelector;
|
|
length = strlen(lpPathName);
|
|
|
|
if ( length >= MAX_PATH16 ) {
|
|
length = MAX_PATH16-1;
|
|
}
|
|
strncpy( se.FileName, lpPathName, length );
|
|
se.FileName[length] = '\0';
|
|
|
|
length = strlen(lpModuleName);
|
|
if ( length >= MAX_MODULE ) {
|
|
length = MAX_MODULE-1;
|
|
}
|
|
strncpy( se.Module, lpModuleName, length );
|
|
se.Module[length] = '\0';
|
|
|
|
EventParams[2] = (DWORD)&se;
|
|
|
|
SendVDMEvent( EventParams );
|
|
}
|
|
}
|
|
|
|
void ModuleFree(
|
|
LPSTR lpModuleName,
|
|
LPSTR lpPathName
|
|
) {
|
|
|
|
if ( fDebugged ) {
|
|
DWORD EventParams[4];
|
|
VDMCONTEXT vcContext;
|
|
VDMINTERNALINFO viInfo;
|
|
SEGMENT_NOTE se;
|
|
UINT length;
|
|
#ifdef i386
|
|
PX86CONTEXT px86;
|
|
|
|
// X86 Only, get pointer to Register Context Block
|
|
px86 = getIntelRegistersPointer();
|
|
#endif
|
|
|
|
GetNormalContext( &vcContext, &viInfo, EventParams, DBG_MODFREE, PX86 );
|
|
|
|
RtlFillMemory( &se, sizeof(se), (UCHAR)0 );
|
|
|
|
length = strlen(lpPathName);
|
|
if ( length >= MAX_PATH16 ) {
|
|
length = MAX_PATH16-1;
|
|
}
|
|
strncpy( se.FileName, lpPathName, length );
|
|
se.FileName[length] = '\0';
|
|
|
|
length = strlen(lpModuleName);
|
|
if ( length >= MAX_MODULE ) {
|
|
length = MAX_MODULE-1;
|
|
}
|
|
strncpy( se.Module, lpModuleName, length );
|
|
se.Module[length] = '\0';
|
|
|
|
EventParams[2] = (DWORD)&se;
|
|
|
|
SendVDMEvent( EventParams );
|
|
}
|
|
}
|
|
|
|
BOOL SingleStep(
|
|
PTFRAME16 pTFrame
|
|
) {
|
|
BOOL fResult;
|
|
|
|
fResult = FALSE; // Default to Event not handled
|
|
|
|
if ( fDebugged ) {
|
|
DWORD EventParams[4];
|
|
VDMCONTEXT vcContext;
|
|
VDMINTERNALINFO viInfo;
|
|
#ifdef i386
|
|
PX86CONTEXT px86;
|
|
|
|
// X86 Only, get pointer to Register Context Block
|
|
px86 = getIntelRegistersPointer();
|
|
#endif
|
|
|
|
GetNormalContext( &vcContext, &viInfo, EventParams, DBG_SINGLESTEP, PX86 );
|
|
|
|
vcContext.SegDs = (ULONG)pTFrame->wDS;
|
|
vcContext.SegCs = (ULONG)pTFrame->wCS;
|
|
vcContext.SegSs = (ULONG)pTFrame->wSS;
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the high words
|
|
// of these registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to recover them.
|
|
//
|
|
vcContext.Eax = MAKELONG(pTFrame->wAX, HIWORD(px86->Eax ));
|
|
vcContext.Eip = MAKELONG(pTFrame->wIP, HIWORD(px86->Eip ));
|
|
vcContext.Esp = MAKELONG(pTFrame->wSP, HIWORD(px86->Esp ));
|
|
vcContext.EFlags = MAKELONG(pTFrame->wFlags,HIWORD(px86->EFlags));
|
|
#else
|
|
vcContext.Eax = (ULONG)pTFrame->wAX;
|
|
|
|
vcContext.Eip = (ULONG)pTFrame->wIP;
|
|
vcContext.Esp = (ULONG)pTFrame->wSP;
|
|
vcContext.EFlags = (ULONG)pTFrame->wFlags;
|
|
|
|
if ( (getMSW() & MSW_PE) == 0 ) {
|
|
vcContext.EFlags |= V86FLAGS_V86;
|
|
}
|
|
#endif
|
|
|
|
fResult = SendVDMEvent( EventParams );
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the FS and GS
|
|
// registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to restore them.
|
|
//
|
|
px86->SegGs = vcContext.SegGs;
|
|
px86->SegFs = vcContext.SegFs;
|
|
#else
|
|
// No need to set FS,GS, they don't exist
|
|
#endif
|
|
|
|
setES( (WORD)vcContext.SegEs );
|
|
pTFrame->wDS = (WORD)vcContext.SegDs;
|
|
pTFrame->wCS = (WORD)vcContext.SegCs;
|
|
pTFrame->wSS = (WORD)vcContext.SegSs;
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the high words
|
|
// of these registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to restore them.
|
|
//
|
|
setEDI( vcContext.Edi );
|
|
setESI( vcContext.Esi );
|
|
setEBX( vcContext.Ebx );
|
|
setEDX( vcContext.Edx );
|
|
setECX( vcContext.Ecx );
|
|
|
|
pTFrame->wAX = LOWORD(vcContext.Eax);
|
|
px86->Eax = MAKELONG(LOWORD(px86->Eax),HIWORD(vcContext.Eax));
|
|
|
|
setEBP( vcContext.Ebp );
|
|
|
|
pTFrame->wIP = LOWORD(vcContext.Eip);
|
|
px86->Eip = MAKELONG(LOWORD(px86->Eip),HIWORD(vcContext.Eip));
|
|
|
|
pTFrame->wFlags = LOWORD(vcContext.EFlags);
|
|
px86->EFlags = MAKELONG(LOWORD(px86->EFlags),HIWORD(vcContext.EFlags));
|
|
|
|
pTFrame->wSP = LOWORD(vcContext.Esp);
|
|
px86->Esp = MAKELONG(LOWORD(px86->Esp),HIWORD(vcContext.Esp));
|
|
#else
|
|
setDI( (WORD)vcContext.Edi );
|
|
setSI( (WORD)vcContext.Esi );
|
|
setBX( (WORD)vcContext.Ebx );
|
|
setDX( (WORD)vcContext.Edx );
|
|
setCX( (WORD)vcContext.Ecx );
|
|
pTFrame->wAX = (WORD)vcContext.Eax;
|
|
|
|
|
|
setBP( (WORD)vcContext.Ebp );
|
|
pTFrame->wIP = (WORD)vcContext.Eip;
|
|
pTFrame->wFlags = (WORD)vcContext.EFlags;
|
|
pTFrame->wSP = (WORD)vcContext.Esp;
|
|
#endif
|
|
}
|
|
return( fResult );
|
|
}
|
|
|
|
BOOL Breakpoint(
|
|
PTFRAME16 pTFrame
|
|
) {
|
|
BOOL fResult;
|
|
|
|
fResult = FALSE; // Default to Event not handled
|
|
|
|
if ( fDebugged ) {
|
|
DWORD EventParams[4];
|
|
VDMCONTEXT vcContext;
|
|
VDMINTERNALINFO viInfo;
|
|
#ifdef i386
|
|
PX86CONTEXT px86;
|
|
|
|
// X86 Only, get pointer to Register Context Block
|
|
px86 = getIntelRegistersPointer();
|
|
#endif
|
|
|
|
GetNormalContext( &vcContext, &viInfo, EventParams, DBG_BREAK, PX86 );
|
|
|
|
vcContext.SegDs = (ULONG)pTFrame->wDS;
|
|
vcContext.SegCs = (ULONG)pTFrame->wCS;
|
|
vcContext.SegSs = (ULONG)pTFrame->wSS;
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the high words
|
|
// of these registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to recover them.
|
|
//
|
|
vcContext.Eax = MAKELONG(pTFrame->wAX, HIWORD(px86->Eax ));
|
|
|
|
vcContext.Eip = MAKELONG(pTFrame->wIP, HIWORD(px86->Eip ));
|
|
vcContext.Esp = MAKELONG(pTFrame->wSP, HIWORD(px86->Esp ));
|
|
vcContext.EFlags = MAKELONG(pTFrame->wFlags,HIWORD(px86->EFlags));
|
|
#else
|
|
vcContext.Eax = (ULONG)pTFrame->wAX;
|
|
|
|
vcContext.Ebp = (ULONG)getBP();
|
|
vcContext.Eip = (ULONG)pTFrame->wIP;
|
|
vcContext.Esp = (ULONG)pTFrame->wSP;
|
|
vcContext.EFlags = (ULONG)pTFrame->wFlags;
|
|
|
|
if ( (getMSW() & MSW_PE) == 0 ) {
|
|
vcContext.EFlags |= V86FLAGS_V86;
|
|
}
|
|
#endif
|
|
|
|
fResult = SendVDMEvent( EventParams );
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the FS and GS
|
|
// registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to restore them.
|
|
//
|
|
px86->SegGs = (WORD)vcContext.SegGs;
|
|
px86->SegFs = (WORD)vcContext.SegFs;
|
|
#else
|
|
// No need to set FS,GS, they don't exist
|
|
#endif
|
|
|
|
setES( (WORD)vcContext.SegEs );
|
|
pTFrame->wDS = (WORD)vcContext.SegDs;
|
|
pTFrame->wCS = (WORD)vcContext.SegCs;
|
|
pTFrame->wSS = (WORD)vcContext.SegSs;
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the high words
|
|
// of these registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to restore them.
|
|
//
|
|
setEDI( vcContext.Edi );
|
|
setESI( vcContext.Esi );
|
|
setEBX( vcContext.Ebx );
|
|
setEDX( vcContext.Edx );
|
|
setECX( vcContext.Ecx );
|
|
|
|
pTFrame->wAX = LOWORD(vcContext.Eax);
|
|
px86->Eax = MAKELONG(LOWORD(px86->Eax),HIWORD(vcContext.Eax));
|
|
|
|
setEBP( vcContext.Ebp );
|
|
|
|
pTFrame->wIP = LOWORD(vcContext.Eip);
|
|
px86->Eip = MAKELONG(LOWORD(px86->Eip),HIWORD(vcContext.Eip));
|
|
|
|
pTFrame->wFlags = LOWORD(vcContext.EFlags);
|
|
px86->EFlags = MAKELONG(LOWORD(px86->EFlags),HIWORD(vcContext.EFlags));
|
|
|
|
pTFrame->wSP = LOWORD(vcContext.Esp);
|
|
px86->Esp = MAKELONG(LOWORD(px86->Esp),HIWORD(vcContext.Esp));
|
|
#else
|
|
setDI( (WORD)vcContext.Edi );
|
|
setSI( (WORD)vcContext.Esi );
|
|
setBX( (WORD)vcContext.Ebx );
|
|
setDX( (WORD)vcContext.Edx );
|
|
setCX( (WORD)vcContext.Ecx );
|
|
pTFrame->wAX = (WORD)vcContext.Eax;
|
|
|
|
|
|
setBP( (WORD)vcContext.Ebp );
|
|
pTFrame->wIP = (WORD)vcContext.Eip;
|
|
pTFrame->wFlags = (WORD)vcContext.EFlags;
|
|
pTFrame->wSP = (WORD)vcContext.Esp;
|
|
#endif
|
|
|
|
}
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
BOOL GPFault(
|
|
PFFRAME16 pFFrame
|
|
) {
|
|
DWORD EventParams[4];
|
|
BOOL fResult;
|
|
VDMCONTEXT vcContext;
|
|
VDMINTERNALINFO viInfo;
|
|
#ifdef i386
|
|
PX86CONTEXT px86;
|
|
#endif
|
|
|
|
fResult = FALSE; // Default to Event not handled
|
|
|
|
#ifdef i386
|
|
|
|
// X86 Only, get pointer to Register Context Block
|
|
px86 = getIntelRegistersPointer();
|
|
#endif
|
|
|
|
GetNormalContext( &vcContext, &viInfo, EventParams, DBG_GPFAULT, PX86 );
|
|
|
|
vcContext.SegEs = (ULONG)pFFrame->wES;
|
|
vcContext.SegDs = (ULONG)pFFrame->wDS;
|
|
vcContext.SegCs = (ULONG)pFFrame->wCS;
|
|
vcContext.SegSs = (ULONG)pFFrame->wSS;
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the high words
|
|
// of these registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to recover them.
|
|
//
|
|
vcContext.Edi = MAKELONG(pFFrame->wDI, HIWORD(px86->Edi ));
|
|
vcContext.Esi = MAKELONG(pFFrame->wSI, HIWORD(px86->Esi ));
|
|
vcContext.Ebx = MAKELONG(pFFrame->wBX, HIWORD(px86->Ebx ));
|
|
vcContext.Edx = MAKELONG(pFFrame->wDX, HIWORD(px86->Edx ));
|
|
vcContext.Ecx = MAKELONG(pFFrame->wCX, HIWORD(px86->Ecx ));
|
|
vcContext.Eax = MAKELONG(pFFrame->wAX, HIWORD(px86->Eax ));
|
|
|
|
vcContext.Ebp = MAKELONG(pFFrame->wBP, HIWORD(px86->Ebp ));
|
|
vcContext.Eip = MAKELONG(pFFrame->wIP, HIWORD(px86->Eip ));
|
|
vcContext.Esp = MAKELONG(pFFrame->wSP, HIWORD(px86->Esp ));
|
|
vcContext.EFlags = MAKELONG(pFFrame->wFlags,HIWORD(px86->EFlags));
|
|
#else
|
|
vcContext.Edi = (ULONG)pFFrame->wDI;
|
|
vcContext.Esi = (ULONG)pFFrame->wSI;
|
|
vcContext.Ebx = (ULONG)pFFrame->wBX;
|
|
vcContext.Edx = (ULONG)pFFrame->wDX;
|
|
vcContext.Ecx = (ULONG)pFFrame->wCX;
|
|
vcContext.Eax = (ULONG)pFFrame->wAX;
|
|
|
|
vcContext.Ebp = (ULONG)pFFrame->wBP;
|
|
vcContext.Eip = (ULONG)pFFrame->wIP;
|
|
vcContext.Esp = (ULONG)pFFrame->wSP;
|
|
vcContext.EFlags = (ULONG)pFFrame->wFlags;
|
|
|
|
if ( (getMSW() & MSW_PE) == 0 ) {
|
|
vcContext.EFlags |= V86FLAGS_V86;
|
|
}
|
|
#endif
|
|
|
|
if ( fDebugged ) {
|
|
fResult = SendVDMEvent( EventParams );
|
|
|
|
if ( !fResult ) {
|
|
DWORD dw;
|
|
|
|
dw = SetErrorMode(0);
|
|
try {
|
|
RaiseException((DWORD)DBG_CONTROL_BREAK, 0, 0, (LPDWORD)0);
|
|
fResult = TRUE;
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
fResult = FALSE;
|
|
}
|
|
SetErrorMode(dw);
|
|
}
|
|
|
|
} else {
|
|
char text[100];
|
|
|
|
// Dump a simulated context
|
|
|
|
OutputDebugString("NTVDM:GP Fault detected, register dump follows:\n");
|
|
|
|
wsprintf(text,"eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n",
|
|
vcContext.Eax,
|
|
vcContext.Ebx,
|
|
vcContext.Ecx,
|
|
vcContext.Edx,
|
|
vcContext.Esi,
|
|
vcContext.Edi );
|
|
OutputDebugString(text);
|
|
|
|
wsprintf(text,"eip=%08lx esp=%08lx ebp=%08lx iopl=%d %s %s %s %s %s %s %s %s\n",
|
|
vcContext.Eip,
|
|
vcContext.Esp,
|
|
vcContext.Ebp,
|
|
(vcContext.EFlags & V86FLAGS_IOPL) >> V86FLAGS_IOPL_BITS,
|
|
(vcContext.EFlags & V86FLAGS_OVERFLOW ) ? "ov" : "nv",
|
|
(vcContext.EFlags & V86FLAGS_DIRECTION) ? "dn" : "up",
|
|
(vcContext.EFlags & V86FLAGS_INTERRUPT) ? "ei" : "di",
|
|
(vcContext.EFlags & V86FLAGS_SIGN ) ? "ng" : "pl",
|
|
(vcContext.EFlags & V86FLAGS_ZERO ) ? "zr" : "nz",
|
|
(vcContext.EFlags & V86FLAGS_AUXCARRY ) ? "ac" : "na",
|
|
(vcContext.EFlags & V86FLAGS_PARITY ) ? "po" : "pe",
|
|
(vcContext.EFlags & V86FLAGS_CARRY ) ? "cy" : "nc" );
|
|
OutputDebugString(text);
|
|
|
|
wsprintf(text,"cs=%04x ss=%04x ds=%04x es=%04x fs=%04x gs=%04x efl=%08lx\n",
|
|
(WORD)vcContext.SegCs,
|
|
(WORD)vcContext.SegSs,
|
|
(WORD)vcContext.SegDs,
|
|
(WORD)vcContext.SegEs,
|
|
(WORD)vcContext.SegFs,
|
|
(WORD)vcContext.SegGs,
|
|
vcContext.EFlags );
|
|
OutputDebugString(text);
|
|
}
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the FS and GS
|
|
// registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to restore them.
|
|
//
|
|
px86->SegGs = (WORD)vcContext.SegGs;
|
|
px86->SegFs = (WORD)vcContext.SegFs;
|
|
#else
|
|
// No need to set FS,GS, they don't exist
|
|
#endif
|
|
|
|
pFFrame->wES = (WORD)vcContext.SegEs;
|
|
pFFrame->wDS = (WORD)vcContext.SegDs;
|
|
pFFrame->wCS = (WORD)vcContext.SegCs;
|
|
pFFrame->wSS = (WORD)vcContext.SegSs;
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the high words
|
|
// of these registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to restore them.
|
|
//
|
|
pFFrame->wDI = LOWORD(vcContext.Edi);
|
|
px86->Edi = MAKELONG(LOWORD(px86->Edi),HIWORD(vcContext.Edi));
|
|
|
|
pFFrame->wSI = LOWORD(vcContext.Esi);
|
|
px86->Esi = MAKELONG(LOWORD(px86->Esi),HIWORD(vcContext.Esi));
|
|
|
|
pFFrame->wBX = LOWORD(vcContext.Ebx);
|
|
px86->Ebx = MAKELONG(LOWORD(px86->Ebx),HIWORD(vcContext.Ebx));
|
|
|
|
pFFrame->wDX = LOWORD(vcContext.Edx);
|
|
px86->Edx = MAKELONG(LOWORD(px86->Edx),HIWORD(vcContext.Edx));
|
|
|
|
pFFrame->wCX = LOWORD(vcContext.Ecx);
|
|
px86->Ecx = MAKELONG(LOWORD(px86->Ecx),HIWORD(vcContext.Ecx));
|
|
|
|
pFFrame->wAX = LOWORD(vcContext.Eax);
|
|
px86->Eax = MAKELONG(LOWORD(px86->Eax),HIWORD(vcContext.Eax));
|
|
|
|
pFFrame->wBP = LOWORD(vcContext.Ebp);
|
|
px86->Ebp = MAKELONG(LOWORD(px86->Ebp),HIWORD(vcContext.Ebp));
|
|
|
|
pFFrame->wIP = LOWORD(vcContext.Eip);
|
|
px86->Eip = MAKELONG(LOWORD(px86->Eip),HIWORD(vcContext.Eip));
|
|
|
|
pFFrame->wFlags = LOWORD(vcContext.EFlags);
|
|
px86->EFlags = MAKELONG(LOWORD(px86->EFlags),HIWORD(vcContext.EFlags));
|
|
|
|
pFFrame->wSP = LOWORD(vcContext.Esp);
|
|
px86->Esp = MAKELONG(LOWORD(px86->Esp),HIWORD(vcContext.Esp));
|
|
#else
|
|
pFFrame->wDI = (WORD)vcContext.Edi;
|
|
pFFrame->wSI = (WORD)vcContext.Esi;
|
|
pFFrame->wBX = (WORD)vcContext.Ebx;
|
|
pFFrame->wDX = (WORD)vcContext.Edx;
|
|
pFFrame->wCX = (WORD)vcContext.Ecx;
|
|
pFFrame->wAX = (WORD)vcContext.Eax;
|
|
|
|
|
|
pFFrame->wBP = (WORD)vcContext.Ebp;
|
|
pFFrame->wIP = (WORD)vcContext.Eip;
|
|
pFFrame->wFlags = (WORD)vcContext.EFlags;
|
|
pFFrame->wSP = (WORD)vcContext.Esp;
|
|
#endif
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
BOOL DivOverflow(
|
|
PTFRAME16 pTFrame
|
|
) {
|
|
BOOL fResult;
|
|
|
|
fResult = FALSE; // Default to Event not handled
|
|
|
|
if ( fDebugged ) {
|
|
DWORD EventParams[4];
|
|
VDMCONTEXT vcContext;
|
|
VDMINTERNALINFO viInfo;
|
|
#ifdef i386
|
|
PX86CONTEXT px86;
|
|
|
|
// X86 Only, get pointer to Register Context Block
|
|
px86 = getIntelRegistersPointer();
|
|
#endif
|
|
|
|
GetNormalContext( &vcContext, &viInfo, EventParams, DBG_DIVOVERFLOW, PX86 );
|
|
|
|
vcContext.SegDs = (ULONG)pTFrame->wDS;
|
|
vcContext.SegCs = (ULONG)pTFrame->wCS;
|
|
vcContext.SegSs = (ULONG)pTFrame->wSS;
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the high words
|
|
// of these registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to recover them.
|
|
//
|
|
vcContext.Eax = MAKELONG(pTFrame->wAX, HIWORD(px86->Eax ));
|
|
vcContext.Eip = MAKELONG(pTFrame->wIP, HIWORD(px86->Eip ));
|
|
vcContext.Esp = MAKELONG(pTFrame->wSP, HIWORD(px86->Esp ));
|
|
vcContext.EFlags = MAKELONG(pTFrame->wFlags,HIWORD(px86->EFlags));
|
|
#else
|
|
vcContext.Eax = (ULONG)pTFrame->wAX;
|
|
|
|
vcContext.Eip = (ULONG)pTFrame->wIP;
|
|
vcContext.Esp = (ULONG)pTFrame->wSP;
|
|
vcContext.EFlags = (ULONG)pTFrame->wFlags;
|
|
|
|
if ( (getMSW() & MSW_PE) == 0 ) {
|
|
vcContext.EFlags |= V86FLAGS_V86;
|
|
}
|
|
#endif
|
|
|
|
fResult = SendVDMEvent( EventParams );
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the FS and GS
|
|
// registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to restore them.
|
|
//
|
|
px86->SegGs = vcContext.SegGs;
|
|
px86->SegFs = vcContext.SegFs;
|
|
#else
|
|
// No need to set FS,GS, they don't exist
|
|
#endif
|
|
|
|
setES( (WORD)vcContext.SegEs );
|
|
pTFrame->wDS = (WORD)vcContext.SegDs;
|
|
pTFrame->wCS = (WORD)vcContext.SegCs;
|
|
pTFrame->wSS = (WORD)vcContext.SegSs;
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the high words
|
|
// of these registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to restore them.
|
|
//
|
|
setEDI( vcContext.Edi );
|
|
setESI( vcContext.Esi );
|
|
setEBX( vcContext.Ebx );
|
|
setEDX( vcContext.Edx );
|
|
setECX( vcContext.Ecx );
|
|
|
|
pTFrame->wAX = LOWORD(vcContext.Eax);
|
|
px86->Eax = MAKELONG(LOWORD(px86->Eax),HIWORD(vcContext.Eax));
|
|
|
|
setEBP( vcContext.Ebp );
|
|
|
|
pTFrame->wIP = LOWORD(vcContext.Eip);
|
|
px86->Eip = MAKELONG(LOWORD(px86->Eip),HIWORD(vcContext.Eip));
|
|
|
|
pTFrame->wFlags = LOWORD(vcContext.EFlags);
|
|
px86->EFlags = MAKELONG(LOWORD(px86->EFlags),HIWORD(vcContext.EFlags));
|
|
|
|
pTFrame->wSP = LOWORD(vcContext.Esp);
|
|
px86->Esp = MAKELONG(LOWORD(px86->Esp),HIWORD(vcContext.Esp));
|
|
#else
|
|
setDI( (WORD)vcContext.Edi );
|
|
setSI( (WORD)vcContext.Esi );
|
|
setBX( (WORD)vcContext.Ebx );
|
|
setDX( (WORD)vcContext.Edx );
|
|
setCX( (WORD)vcContext.Ecx );
|
|
pTFrame->wAX = (WORD)vcContext.Eax;
|
|
|
|
|
|
setBP( (WORD)vcContext.Ebp );
|
|
pTFrame->wIP = (WORD)vcContext.Eip;
|
|
pTFrame->wFlags = (WORD)vcContext.EFlags;
|
|
pTFrame->wSP = (WORD)vcContext.Esp;
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
|
|
BOOL DllStart(
|
|
PNDFRAME16 pNDFrame
|
|
) {
|
|
BOOL fResult;
|
|
|
|
fResult = FALSE; // Default to Event not handled
|
|
|
|
if ( fDebugged ) {
|
|
LPSTR lpModuleName;
|
|
LPSTR lpModulePath;
|
|
UINT length;
|
|
UCHAR fPE;
|
|
DWORD EventParams[4];
|
|
VDMCONTEXT vcContext;
|
|
VDMINTERNALINFO viInfo;
|
|
IMAGE_NOTE im;
|
|
#ifdef i386
|
|
PX86CONTEXT px86;
|
|
|
|
// X86 Only, get pointer to Register Context Block
|
|
px86 = getIntelRegistersPointer();
|
|
#endif
|
|
|
|
GetNormalContext( &vcContext, &viInfo, EventParams, DBG_DLLSTART, PX86 );
|
|
|
|
EventParams[2] = (DWORD)&im;
|
|
|
|
vcContext.SegDs = (ULONG)pNDFrame->wDS;
|
|
vcContext.SegCs = (ULONG)pNDFrame->wCS;
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the high words
|
|
// of these registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to recover them.
|
|
//
|
|
vcContext.Eax = MAKELONG(pNDFrame->wAX, HIWORD(px86->Eax ));
|
|
vcContext.Eip = MAKELONG(pNDFrame->wIP, HIWORD(px86->Eip ));
|
|
vcContext.EFlags = MAKELONG(pNDFrame->wFlags,HIWORD(px86->EFlags));
|
|
#else
|
|
vcContext.Eax = (ULONG)pNDFrame->wAX;
|
|
vcContext.Eip = (ULONG)pNDFrame->wIP;
|
|
vcContext.EFlags = (ULONG)pNDFrame->wFlags;
|
|
|
|
if ( (getMSW() & MSW_PE) == 0 ) {
|
|
vcContext.EFlags |= V86FLAGS_V86;
|
|
}
|
|
#endif
|
|
|
|
// The code in TASK.ASM pops the frame off the stack before it IRETs
|
|
vcContext.Esp += sizeof(NDFRAME16);
|
|
|
|
// Get the module's path and name
|
|
|
|
fPE = ISPESET;
|
|
|
|
lpModuleName = (LPSTR)Sim32GetVDMPointer(
|
|
(ULONG)pNDFrame->dwModuleName,
|
|
MAX_MODULE,
|
|
fPE );
|
|
|
|
lpModulePath = (LPSTR)Sim32GetVDMPointer(
|
|
(ULONG)pNDFrame->dwModulePath,
|
|
MAX_PATH,
|
|
fPE );
|
|
|
|
length = (UINT)((UCHAR)*lpModuleName++);
|
|
|
|
strncpy( im.Module, lpModuleName, length );
|
|
im.Module[length] = '\0';
|
|
|
|
length = (UINT)((UCHAR)*lpModulePath);
|
|
lpModulePath += 8;
|
|
length -= 8;
|
|
|
|
strncpy( im.FileName, lpModulePath, length );
|
|
im.FileName[length] = '\0';
|
|
|
|
im.hModule = pNDFrame->hModule;
|
|
im.hTask = pNDFrame->hTask;
|
|
|
|
fResult = SendVDMEvent( EventParams );
|
|
|
|
// See comment about what the code does above
|
|
vcContext.Esp -= sizeof(NDFRAME16);
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the FS and GS
|
|
// registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to restore them.
|
|
//
|
|
px86->SegGs = vcContext.SegGs;
|
|
px86->SegFs = vcContext.SegFs;
|
|
#else
|
|
// No need to set FS,GS, they don't exist
|
|
#endif
|
|
|
|
setES( (WORD)vcContext.SegEs );
|
|
pNDFrame->wDS = (WORD)vcContext.SegDs;
|
|
pNDFrame->wCS = (WORD)vcContext.SegCs;
|
|
setSS( (WORD)vcContext.SegSs );
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the high words
|
|
// of these registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to restore them.
|
|
//
|
|
setEDI( vcContext.Edi );
|
|
setESI( vcContext.Esi );
|
|
setEBX( vcContext.Ebx );
|
|
setEDX( vcContext.Edx );
|
|
setECX( vcContext.Ecx );
|
|
|
|
pNDFrame->wAX = LOWORD(vcContext.Eax);
|
|
px86->Eax = MAKELONG(LOWORD(px86->Eax),HIWORD(vcContext.Eax));
|
|
|
|
setEBP( vcContext.Ebp );
|
|
|
|
pNDFrame->wIP = LOWORD(vcContext.Eip);
|
|
px86->Eip = MAKELONG(LOWORD(px86->Eip),HIWORD(vcContext.Eip));
|
|
|
|
pNDFrame->wFlags = LOWORD(vcContext.EFlags);
|
|
px86->EFlags = MAKELONG(LOWORD(px86->EFlags),HIWORD(vcContext.EFlags));
|
|
|
|
setESP( vcContext.Esp );
|
|
#else
|
|
setDI( (WORD)vcContext.Edi );
|
|
setSI( (WORD)vcContext.Esi );
|
|
setBX( (WORD)vcContext.Ebx );
|
|
setDX( (WORD)vcContext.Edx );
|
|
setCX( (WORD)vcContext.Ecx );
|
|
pNDFrame->wAX = (WORD)vcContext.Eax;
|
|
|
|
|
|
setBP( (WORD)vcContext.Ebp );
|
|
pNDFrame->wIP = (WORD)vcContext.Eip;
|
|
pNDFrame->wFlags = (WORD)vcContext.EFlags;
|
|
|
|
setSP( (WORD)vcContext.Esp );
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
|
|
BOOL TaskStop(
|
|
PSTFRAME16 pSTFrame
|
|
) {
|
|
BOOL fResult;
|
|
|
|
fResult = FALSE; // Default to Event not handled
|
|
|
|
if ( fDebugged ) {
|
|
LPSTR lpModuleName;
|
|
LPSTR lpModulePath;
|
|
UINT length;
|
|
UCHAR fPE;
|
|
DWORD EventParams[4];
|
|
VDMCONTEXT vcContext;
|
|
VDMINTERNALINFO viInfo;
|
|
IMAGE_NOTE im;
|
|
#ifdef i386
|
|
PX86CONTEXT px86;
|
|
|
|
// X86 Only, get pointer to Register Context Block
|
|
px86 = getIntelRegistersPointer();
|
|
#endif
|
|
|
|
GetNormalContext( &vcContext, &viInfo, EventParams, DBG_TASKSTOP, PX86 );
|
|
|
|
EventParams[2] = (DWORD)&im;
|
|
|
|
// The code in TASK.ASM pops the frame off the stack before it IRETs
|
|
vcContext.Esp += sizeof(STFRAME16);
|
|
|
|
// Get the module's path and name
|
|
|
|
fPE = ISPESET;
|
|
|
|
lpModuleName = (LPSTR)Sim32GetVDMPointer(
|
|
(ULONG)pSTFrame->dwModuleName,
|
|
MAX_MODULE,
|
|
fPE );
|
|
|
|
lpModulePath = (LPSTR)Sim32GetVDMPointer(
|
|
(ULONG)pSTFrame->dwModulePath,
|
|
MAX_PATH,
|
|
fPE );
|
|
|
|
length = (UINT)((UCHAR)*lpModuleName++);
|
|
|
|
strncpy( im.Module, lpModuleName, length );
|
|
im.Module[length] = '\0';
|
|
|
|
length = (UINT)((UCHAR)*lpModulePath);
|
|
lpModulePath += 8;
|
|
length -= 8;
|
|
|
|
strncpy( im.FileName, lpModulePath, length );
|
|
im.FileName[length] = '\0';
|
|
|
|
im.hModule = pSTFrame->hModule;
|
|
im.hTask = pSTFrame->hTask;
|
|
|
|
fResult = SendVDMEvent( EventParams );
|
|
|
|
// See comment about what the code does above
|
|
vcContext.Esp -= sizeof(STFRAME16);
|
|
}
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// I looked through the Win 3.0/Win 3.1 sources, and all the SDM_... commands
|
|
// I could find were this: (The only ones we support for now will be
|
|
// SDM_LOADSEG,SDM_MOVESEG,SDM_FREESEG/RELEASESEG)
|
|
//
|
|
// ax = SDM_LOADSEG = 50h
|
|
// es:di = Module Name
|
|
// bx = segment number
|
|
// cx = loaded seg
|
|
// dx = instance number
|
|
// si = DataOrCodeSegment
|
|
// ax = SDM_MOVESEG = 51h
|
|
// push destseg
|
|
// push sourceseg
|
|
// push SDM_MOVESEG
|
|
// SDM_FREESEG = 52h
|
|
// bx = segment addr
|
|
// SDM_RELEASESEG = 5Ch
|
|
// bx = segment addr
|
|
// SDM_5A (DebugDebug)
|
|
// cx = dataoffset hGlobalHeap
|
|
// dx = ds (SetKernelDS)
|
|
// SDM_4F (DebugInit)
|
|
// push SDM_4F
|
|
// SDM_0 (Out Char)
|
|
// dl = character to output
|
|
// SDM_0F (Out Symbol)
|
|
// dx = offset
|
|
// cx = selector
|
|
// es = data segment of DOSX
|
|
// SDM_GLOBALHEAP = 3 (real mode only)
|
|
// push pGlobalHeap
|
|
// push ax
|
|
// SDM_CONWRITE = 12h
|
|
// ds:si = Pointer to string
|
|
// cx = length of string
|
|
// SDM_CONREAD = 1
|
|
// nothing, returns character read in al
|
|
// SDM_DGH = 56h
|
|
// cx = seg DumpGlobalHeap
|
|
// bx = codeoffset DumpGlobalHeap
|
|
// SDM_DFL = 57h
|
|
// cx = seg DumpFreeList
|
|
// bx = codeoffset DumpFreeList
|
|
// SDM_DLL = 58h
|
|
// cx = seg DumpLRUList
|
|
// bx = codeoffset DumpLRUList
|
|
// SDM_LOADTASK = 59h
|
|
// not used
|
|
// SDM_POSTLOAD = 60h
|
|
// push ax
|
|
// SDM_EXITCALL = 62h
|
|
// push ax
|
|
// SDM_INT2 = 63h (Ctrl-alt-sysreq)
|
|
// nothing.
|
|
// SDM_LOADDLL = 64h
|
|
// not used
|
|
// SDM_DELMODULE = 65h
|
|
// push module handle
|
|
// SDM_RIN = 9
|
|
// push seg ReplaceInst
|
|
// push codeoffset ReplaceInst
|
|
// push ax
|
|
// SDM_BANKLINE = 10
|
|
// push EMS_calc_swap_line
|
|
// push ax
|
|
// SDM_NEWTASK = 11
|
|
// push EMS PID
|
|
// push ax
|
|
// SDM_FLUSHTASK = 12
|
|
// push EMS PID
|
|
// push ax
|
|
// SDM_SWITCHOUT = 13
|
|
// ds = TDB
|
|
// SDM_SWITCHIN = 14
|
|
// ds = TDB
|
|
// SDM_KEYBOARD = 15
|
|
// not used (thankfully, it is the same number as SDM_0F)
|
|
// SDM_MAXFUNC = 15
|
|
// not used
|
|
|
|
void DBGDispatch()
|
|
{
|
|
UNALIGNED WORD *stack;
|
|
WORD mode;
|
|
WORD selector;
|
|
WORD segment;
|
|
WORD new_selector;
|
|
BOOL fBPRelease;
|
|
BOOL fData;
|
|
LPSTR lpModuleName;
|
|
LPSTR lpPathName;
|
|
UCHAR fPE;
|
|
PFFRAME16 pFFrame;
|
|
PTFRAME16 pTFrame;
|
|
PNDFRAME16 pNDFrame;
|
|
PSTFRAME16 pSTFrame;
|
|
WORD wFrame;
|
|
|
|
fPE = ISPESET;
|
|
|
|
stack = (UNALIGNED WORD *)Sim32GetVDMPointer(
|
|
((ULONG)getSS() << 16) + (ULONG)getSP(),
|
|
MAX_DBG_FRAME, fPE );
|
|
|
|
mode = *stack++;
|
|
switch( mode ) {
|
|
case DBG_SEGLOAD:
|
|
selector = *stack++;
|
|
segment = *stack++;
|
|
lpModuleName = (LPSTR)Sim32GetVDMPointer(
|
|
(ULONG)*stack + ((ULONG)(*(stack+1)) << 16),
|
|
0, fPE );
|
|
stack += 2;
|
|
lpPathName = (LPSTR)Sim32GetVDMPointer(
|
|
(ULONG)*stack + ((ULONG)(*(stack+1)) << 16),
|
|
0, fPE );
|
|
if ( lpPathName == NULL ) {
|
|
lpPathName = "";
|
|
}
|
|
|
|
stack += 2;
|
|
fData = (BOOL)(*stack++);
|
|
SegmentLoad( lpModuleName, lpPathName, selector, segment, fData );
|
|
break;
|
|
case DBG_SEGMOVE:
|
|
selector = *stack++;
|
|
new_selector = *stack++;
|
|
SegmentMove( selector, new_selector );
|
|
break;
|
|
case DBG_SEGFREE:
|
|
fBPRelease = (BOOL)*stack++;
|
|
selector = *stack++;
|
|
SegmentFree( selector, fBPRelease );
|
|
break;
|
|
case DBG_MODFREE:
|
|
lpModuleName = (LPSTR)Sim32GetVDMPointer(
|
|
(ULONG)*stack + ((ULONG)(*(stack+1)) << 16),
|
|
0, fPE );
|
|
stack += 2;
|
|
lpPathName = (LPSTR)Sim32GetVDMPointer(
|
|
(ULONG)*stack + ((ULONG)(*(stack+1)) << 16),
|
|
0, fPE );
|
|
if ( lpPathName == NULL ) {
|
|
lpPathName = "";
|
|
}
|
|
ModuleFree( lpModuleName, lpPathName );
|
|
break;
|
|
case DBG_MODLOAD:
|
|
|
|
// Why doesn't this do anything? - See JonLe
|
|
|
|
break;
|
|
|
|
case DBG_SINGLESTEP:
|
|
pTFrame = (PTFRAME16)Sim32GetVDMPointer(
|
|
(ULONG)((ULONG)getSS() << 16) + (ULONG)getSP(),
|
|
MAX_DBG_FRAME, fPE );
|
|
|
|
|
|
fData = SingleStep( pTFrame );
|
|
|
|
setAX((WORD)fData);
|
|
break;
|
|
|
|
case DBG_BREAK:
|
|
pTFrame = (PTFRAME16)Sim32GetVDMPointer(
|
|
(ULONG)((ULONG)getSS() << 16) + (ULONG)getSP(),
|
|
MAX_DBG_FRAME, fPE );
|
|
|
|
|
|
fData = Breakpoint( pTFrame );
|
|
|
|
setAX((WORD)fData);
|
|
break;
|
|
case DBG_GPFAULT:
|
|
wFrame = getBP() - (WORD)(FIELD_OFFSET(FFRAME16,wBP));
|
|
|
|
pFFrame = (PFFRAME16)Sim32GetVDMPointer(
|
|
((ULONG)getSS() << 16) + (ULONG)wFrame,
|
|
MAX_DBG_FRAME, fPE );
|
|
|
|
|
|
fData = GPFault( pFFrame );
|
|
|
|
setAX((WORD)fData);
|
|
break;
|
|
case DBG_DIVOVERFLOW:
|
|
pTFrame = (PTFRAME16)Sim32GetVDMPointer(
|
|
(ULONG)((ULONG)getSS() << 16) + (ULONG)getSP(),
|
|
MAX_DBG_FRAME, fPE );
|
|
|
|
|
|
fData = DivOverflow( pTFrame );
|
|
|
|
setAX((WORD)fData);
|
|
break;
|
|
case DBG_DLLSTART:
|
|
pNDFrame = (PNDFRAME16)Sim32GetVDMPointer(
|
|
(ULONG)((ULONG)getSS() << 16) + (ULONG)getSP(),
|
|
MAX_DBG_FRAME, fPE );
|
|
|
|
|
|
fData = DllStart( pNDFrame );
|
|
|
|
setAX((WORD)fData);
|
|
break;
|
|
case DBG_TASKSTOP:
|
|
pSTFrame = (PSTFRAME16)Sim32GetVDMPointer(
|
|
(ULONG)((ULONG)getSS() << 16) + (ULONG)getSP(),
|
|
MAX_DBG_FRAME, fPE );
|
|
|
|
fData = TaskStop( pSTFrame );
|
|
break;
|
|
case DBG_ATTACH:
|
|
break;
|
|
|
|
case DBG_TOOLHELP:
|
|
ulTHHOOK = (ULONG)*stack + ((ULONG)(*(stack+1)) << 16);
|
|
stack += 2;
|
|
f386 = (BOOL)*stack;
|
|
break;
|
|
|
|
default:
|
|
setAX(0); // Event not handled
|
|
break;
|
|
}
|
|
}
|
|
|
|
VOID DBGNotifyNewTask(
|
|
LPVOID lpvNTFrame,
|
|
UINT uFrameSize
|
|
) {
|
|
BOOL fResult;
|
|
PNTFRAME16 pNTFrame;
|
|
|
|
pNTFrame = (PNTFRAME16)lpvNTFrame;
|
|
|
|
if ( fDebugged ) {
|
|
LPSTR lpModuleName;
|
|
LPSTR lpModulePath;
|
|
UINT length;
|
|
UCHAR fPE;
|
|
DWORD EventParams[4];
|
|
VDMCONTEXT vcContext;
|
|
VDMINTERNALINFO viInfo;
|
|
IMAGE_NOTE im;
|
|
#ifdef i386
|
|
PX86CONTEXT px86;
|
|
|
|
// X86 Only, get pointer to Register Context Block
|
|
px86 = getIntelRegistersPointer();
|
|
#endif
|
|
|
|
GetNormalContext( &vcContext, &viInfo, EventParams, DBG_TASKSTART, PX86 );
|
|
|
|
EventParams[2] = (DWORD)&im;
|
|
|
|
vcContext.SegEs = (ULONG)pNTFrame->wES;
|
|
vcContext.SegDs = (ULONG)pNTFrame->wDS;
|
|
vcContext.SegCs = (ULONG)pNTFrame->wCS;
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the high words
|
|
// of these registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to recover them.
|
|
//
|
|
vcContext.Edi = MAKELONG(pNTFrame->wDI, HIWORD(px86->Edi ));
|
|
vcContext.Esi = MAKELONG(pNTFrame->wSI, HIWORD(px86->Esi ));
|
|
vcContext.Ebx = MAKELONG(pNTFrame->wBX, HIWORD(px86->Ebx ));
|
|
vcContext.Edx = MAKELONG(pNTFrame->wDX, HIWORD(px86->Edx ));
|
|
vcContext.Ecx = MAKELONG(pNTFrame->wCX, HIWORD(px86->Ecx ));
|
|
vcContext.Eax = MAKELONG(pNTFrame->wAX, HIWORD(px86->Eax ));
|
|
|
|
vcContext.Ebp = MAKELONG(pNTFrame->wBP, HIWORD(px86->Ebp ));
|
|
vcContext.Eip = MAKELONG(pNTFrame->wIP, HIWORD(px86->Eip ));
|
|
vcContext.EFlags = MAKELONG(pNTFrame->wFlags,HIWORD(px86->EFlags));
|
|
|
|
#else
|
|
vcContext.Edi = (ULONG)pNTFrame->wDI;
|
|
vcContext.Esi = (ULONG)pNTFrame->wSI;
|
|
vcContext.Ebx = (ULONG)pNTFrame->wBX;
|
|
vcContext.Edx = (ULONG)pNTFrame->wDX;
|
|
vcContext.Ecx = (ULONG)pNTFrame->wCX;
|
|
vcContext.Eax = (ULONG)pNTFrame->wAX;
|
|
|
|
vcContext.Ebp = (ULONG)pNTFrame->wBP;
|
|
vcContext.Eip = (ULONG)pNTFrame->wIP;
|
|
vcContext.EFlags = (ULONG)pNTFrame->wFlags;
|
|
|
|
if ( (getMSW() & MSW_PE) == 0 ) {
|
|
vcContext.EFlags |= V86FLAGS_V86;
|
|
}
|
|
#endif
|
|
// The code in TASKING.ASM does a dec bp before the IRET
|
|
vcContext.Ebp -= 1;
|
|
// The code copies frame off the stack then IRETs
|
|
vcContext.Esp += sizeof(NTFRAME16) + uFrameSize;
|
|
|
|
// Get the module's path and name
|
|
|
|
fPE = ISPESET;
|
|
|
|
lpModuleName = (LPSTR)Sim32GetVDMPointer(
|
|
(ULONG)pNTFrame->dwModuleName,
|
|
MAX_MODULE,
|
|
fPE );
|
|
|
|
lpModulePath = (LPSTR)Sim32GetVDMPointer(
|
|
(ULONG)pNTFrame->dwModulePath,
|
|
MAX_PATH,
|
|
fPE );
|
|
|
|
length = (UINT)((UCHAR)*lpModuleName++);
|
|
|
|
strncpy( im.Module, lpModuleName, length );
|
|
im.Module[length] = '\0';
|
|
|
|
length = (UINT)((UCHAR)*lpModulePath);
|
|
lpModulePath += 8;
|
|
length -= 8;
|
|
|
|
strncpy( im.FileName, lpModulePath, length );
|
|
im.FileName[length] = '\0';
|
|
|
|
im.hModule = pNTFrame->hModule;
|
|
im.hTask = pNTFrame->hTask;
|
|
|
|
fResult = SendVDMEvent( EventParams );
|
|
|
|
// See comments about what the code does above
|
|
vcContext.Ebp += 1;
|
|
vcContext.Esp -= sizeof(NTFRAME16) + uFrameSize;
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the FS and GS
|
|
// registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to restore them.
|
|
//
|
|
px86->SegGs = vcContext.SegGs;
|
|
px86->SegFs = vcContext.SegFs;
|
|
#else
|
|
// No need to set FS,GS, they don't exist
|
|
#endif
|
|
|
|
pNTFrame->wES = (WORD)vcContext.SegEs;
|
|
pNTFrame->wDS = (WORD)vcContext.SegDs;
|
|
pNTFrame->wCS = (WORD)vcContext.SegCs;
|
|
setSS( (WORD)vcContext.SegSs );
|
|
|
|
#ifdef i386
|
|
//
|
|
// On x86 systems, we really might have some data in the high words
|
|
// of these registers. Hopefully DOSX.EXE and KRNL286.EXE don't
|
|
// blow them away. Here is where we attempt to restore them.
|
|
//
|
|
pNTFrame->wDI = LOWORD(vcContext.Edi);
|
|
px86->Edi = MAKELONG(LOWORD(px86->Edi),HIWORD(vcContext.Edi));
|
|
|
|
pNTFrame->wSI = LOWORD(vcContext.Esi);
|
|
px86->Esi = MAKELONG(LOWORD(px86->Esi),HIWORD(vcContext.Esi));
|
|
|
|
pNTFrame->wBX = LOWORD(vcContext.Ebx);
|
|
px86->Ebx = MAKELONG(LOWORD(px86->Ebx),HIWORD(vcContext.Ebx));
|
|
|
|
pNTFrame->wDX = LOWORD(vcContext.Edx);
|
|
px86->Edx = MAKELONG(LOWORD(px86->Edx),HIWORD(vcContext.Edx));
|
|
|
|
pNTFrame->wCX = LOWORD(vcContext.Ecx);
|
|
px86->Ecx = MAKELONG(LOWORD(px86->Ecx),HIWORD(vcContext.Ecx));
|
|
|
|
pNTFrame->wAX = LOWORD(vcContext.Eax);
|
|
px86->Eax = MAKELONG(LOWORD(px86->Eax),HIWORD(vcContext.Eax));
|
|
|
|
pNTFrame->wBP = LOWORD(vcContext.Ebp);
|
|
px86->Ebp = MAKELONG(LOWORD(px86->Ebp),HIWORD(vcContext.Ebp));
|
|
|
|
pNTFrame->wIP = LOWORD(vcContext.Eip);
|
|
px86->Eip = MAKELONG(LOWORD(px86->Eip),HIWORD(vcContext.Eip));
|
|
|
|
pNTFrame->wFlags = LOWORD(vcContext.EFlags);
|
|
px86->EFlags = MAKELONG(LOWORD(px86->EFlags),HIWORD(vcContext.EFlags));
|
|
|
|
setESP( vcContext.Esp );
|
|
#else
|
|
pNTFrame->wDI = (WORD)vcContext.Edi;
|
|
pNTFrame->wSI = (WORD)vcContext.Esi;
|
|
pNTFrame->wBX = (WORD)vcContext.Ebx;
|
|
pNTFrame->wDX = (WORD)vcContext.Edx;
|
|
pNTFrame->wCX = (WORD)vcContext.Ecx;
|
|
pNTFrame->wAX = (WORD)vcContext.Eax;
|
|
|
|
pNTFrame->wBP = (WORD)vcContext.Ebp;
|
|
|
|
pNTFrame->wIP = (WORD)vcContext.Eip;
|
|
pNTFrame->wFlags = (WORD)vcContext.EFlags;
|
|
|
|
setSP( (WORD)vcContext.Esp );
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
VOID DBGNotifyRemoteThreadAddress(
|
|
LPVOID lpAddress,
|
|
DWORD lpBlock
|
|
) {
|
|
lpRemoteAddress = lpAddress;
|
|
lpRemoteBlock = lpBlock;
|
|
}
|
|
|
|
VOID DBGNotifyDebugged(
|
|
BOOL fNewDebugged
|
|
) {
|
|
fDebugged = fNewDebugged;
|
|
}
|