diff options
Diffstat (limited to 'private/mvdm/dbg/dbg.c')
-rw-r--r-- | private/mvdm/dbg/dbg.c | 1701 |
1 files changed, 1701 insertions, 0 deletions
diff --git a/private/mvdm/dbg/dbg.c b/private/mvdm/dbg/dbg.c new file mode 100644 index 000000000..a2ab1de92 --- /dev/null +++ b/private/mvdm/dbg/dbg.c @@ -0,0 +1,1701 @@ +/* + * 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; +} |