/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #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; }