|
|
1.1 ! root 1: // ************************************************************************ ! 2: // MODULE : DEBDebug.c ! 3: // PURPOSE : Debug support functions for the Debug Event Browser ! 4: // FUNCTIONS : ! 5: // DbgEventThread() - debug event processing thread ! 6: // GetModuleFileNameFromHeader() - get the module name ! 7: // SkipBreakPoint() - skips over the break point in the debugee ! 8: // COMMENTS : ! 9: // ************************************************************************ ! 10: #include <Windows.H> ! 11: #include <String.H> // strcpy(), strcat() ! 12: #include <StdIO.H> // sprintf() ! 13: ! 14: #include "LinkList.H" ! 15: #include "DEBMain.H" ! 16: #include "DEBMisc.H" ! 17: #include "DEBDebug.H" ! 18: ! 19: ! 20: // ************************************************************************ ! 21: // FUNCTION : DebugEventThread( LPCTSTR ) ! 22: // PURPOSE : Main debug event processing loop ! 23: // COMMENTS : A new debug event thread is created for each debugee process. ! 24: // DebugeeFileName may be the process ID of and active process ! 25: // or the name of a process to create. ! 26: // Note: this build only supports browsing one process at a time. ! 27: // ************************************************************************ ! 28: DWORD ! 29: DebugEventThread( LPCTSTR DebugeeFileName ) ! 30: { ! 31: static BOOL fFirstTime = TRUE; ! 32: static PNODE ThreadNode; // used for inserting new thread nodes ! 33: ! 34: PNODE TempNode; // used for queries on thread linked list ! 35: DEBUG_EVENT DebugEvent; ! 36: TCHAR szDebugEventBuffer[256]; ! 37: TCHAR szTempBuf[256]; ! 38: DWORD NumberOfBytesRead; ! 39: ! 40: //-- temporary thread info node used for queries ! 41: CreateNode( &ProcessList, &TempNode ); ! 42: ! 43: //-- determine if 'attach to' or 'open' debugee ! 44: // DebugeeFileName may be dwProcessId and an actual filename ! 45: if( !DebugActiveProcess( (DWORD) DebugeeFileName ) ) { ! 46: ! 47: //-- create the debugee process instead ! 48: if( !CreateProcess( ! 49: NULL, ! 50: DebugeeFileName, ! 51: (LPSECURITY_ATTRIBUTES) NULL, ! 52: (LPSECURITY_ATTRIBUTES) NULL, ! 53: TRUE, ! 54: DebugMode | DebugeePriority | CREATE_NEW_CONSOLE, ! 55: (LPVOID) NULL, ! 56: (LPTSTR) NULL, ! 57: &si, &pi ) ) { ! 58: ! 59: return( FALSE ); ! 60: ! 61: } ! 62: else { ! 63: ! 64: hProcess = pi.hProcess; ! 65: CloseHandle( pi.hProcess ); ! 66: CloseHandle( pi.hThread ); ! 67: ! 68: } ! 69: } ! 70: ! 71: for(;;) { ! 72: if( !WaitForDebugEvent( &DebugEvent, (DWORD) -1L ) ) { ! 73: ListBoxPrintF( "%s", "Waiting..." ); ! 74: continue; ! 75: } ! 76: ! 77: switch( DebugEvent.dwDebugEventCode ) { ! 78: ! 79: case EXCEPTION_DEBUG_EVENT: ! 80: MakeDebugEventString( szDebugEventBuffer, "Exception:", ! 81: &DebugEvent); ! 82: ! 83: switch( DebugEvent.u.Exception.ExceptionRecord.ExceptionCode ) { ! 84: ! 85: case EXCEPTION_ACCESS_VIOLATION: ! 86: strcat(szDebugEventBuffer, "ACCESS_VIOLATION"); ! 87: break; ! 88: ! 89: case EXCEPTION_BREAKPOINT: ! 90: strcat(szDebugEventBuffer, "BREAKPOINT"); ! 91: break; ! 92: ! 93: case EXCEPTION_DATATYPE_MISALIGNMENT: ! 94: strcat(szDebugEventBuffer, "DATATYPE_MISALIGNMENT"); ! 95: break; ! 96: ! 97: case EXCEPTION_SINGLE_STEP: ! 98: strcat(szDebugEventBuffer, "SINGLE_STEP"); ! 99: break; ! 100: ! 101: case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: ! 102: strcat(szDebugEventBuffer, "ARRAY_BOUNDS_EXCEEDED"); ! 103: break; ! 104: ! 105: case EXCEPTION_FLT_DIVIDE_BY_ZERO: ! 106: strcat(szDebugEventBuffer, "FLT_DIVIDE_BY_ZERO"); ! 107: break; ! 108: ! 109: case EXCEPTION_FLT_INVALID_OPERATION: ! 110: strcat(szDebugEventBuffer, "FLT_INVALID_OPERATION"); ! 111: break; ! 112: ! 113: case EXCEPTION_FLT_OVERFLOW: ! 114: strcat(szDebugEventBuffer, "FLT_OVERFLOW"); ! 115: break; ! 116: ! 117: case EXCEPTION_FLT_STACK_CHECK: ! 118: strcat(szDebugEventBuffer, "FLT_STACK_CHECK"); ! 119: break; ! 120: ! 121: case EXCEPTION_FLT_UNDERFLOW: ! 122: strcat(szDebugEventBuffer, "FLT_UNDERFLOW"); ! 123: break; ! 124: ! 125: case EXCEPTION_INT_DIVIDE_BY_ZERO: ! 126: strcat(szDebugEventBuffer, "INT_DIVIDE_BY_ZERO"); ! 127: break; ! 128: ! 129: case EXCEPTION_INT_OVERFLOW: ! 130: strcat(szDebugEventBuffer, "INT_OVERFLOW"); ! 131: break; ! 132: ! 133: case EXCEPTION_PRIV_INSTRUCTION: ! 134: strcat(szDebugEventBuffer, "PRIV_INSTRUCTION"); ! 135: break; ! 136: ! 137: default: ! 138: strcat(szDebugEventBuffer, "Unknown [0x"); ! 139: strcat(szDebugEventBuffer, ! 140: LongToCharUpper( (LONG) DebugEvent.u.Exception.ExceptionRecord.ExceptionCode, szTempBuf, 16) ); ! 141: strcat(szDebugEventBuffer, "]"); ! 142: break; ! 143: } ! 144: if( fVerbose ) { ! 145: strcat(szDebugEventBuffer, " - dwFirstChance:"); ! 146: strcat(szDebugEventBuffer, ! 147: LongToCharUpper( (LONG) DebugEvent.u.Exception.dwFirstChance, szTempBuf, 10) ); ! 148: } ! 149: else { ! 150: if(DebugEvent.u.Exception.dwFirstChance != 0) ! 151: strcat(szDebugEventBuffer, " - First Chance"); ! 152: else ! 153: strcat(szDebugEventBuffer, " - Second Chance"); ! 154: } ! 155: break; ! 156: ! 157: case CREATE_THREAD_DEBUG_EVENT: ! 158: MakeDebugEventString(szDebugEventBuffer, "Create Thread", ! 159: &DebugEvent); ! 160: if( fVerbose ) { ! 161: strcat(szDebugEventBuffer, " - hThread:0x"); ! 162: strcat(szDebugEventBuffer, ! 163: LongToCharUpper( (LONG) DebugEvent.u.CreateThread.hThread, szTempBuf, 16) ); ! 164: strcat(szDebugEventBuffer, " - lpStartAddress:0x"); ! 165: strcat(szDebugEventBuffer, ! 166: LongToCharUpper( (LONG) DebugEvent.u.CreateThread.lpStartAddress, szTempBuf, 16) ); ! 167: } ! 168: break; ! 169: ! 170: case CREATE_PROCESS_DEBUG_EVENT: ! 171: MakeDebugEventString(szDebugEventBuffer, "Create Process", ! 172: &DebugEvent); ! 173: if( fVerbose ) { ! 174: strcat(szDebugEventBuffer, " - hFile:0x"); ! 175: strcat(szDebugEventBuffer, ! 176: LongToCharUpper( (LONG) DebugEvent.u.CreateProcessInfo.hFile, szTempBuf, 16) ); ! 177: strcat(szDebugEventBuffer, " - hProcess:0x"); ! 178: strcat(szDebugEventBuffer, ! 179: LongToCharUpper( (LONG) DebugEvent.u.CreateProcessInfo.hProcess, szTempBuf, 16) ); ! 180: strcat(szDebugEventBuffer, " - hThread:0x"); ! 181: strcat(szDebugEventBuffer, ! 182: LongToCharUpper( (LONG) DebugEvent.u.CreateProcessInfo.hThread, szTempBuf, 16) ); ! 183: strcat(szDebugEventBuffer, " - lpBaseOfImage:0x"); ! 184: strcat(szDebugEventBuffer, ! 185: LongToCharUpper( (LONG) DebugEvent.u.CreateProcessInfo.lpBaseOfImage, szTempBuf, 16) ); ! 186: strcat(szDebugEventBuffer, " - dwDebugInfoFileOffset:"); ! 187: strcat(szDebugEventBuffer, ! 188: LongToCharUpper( (LONG) DebugEvent.u.CreateProcessInfo.dwDebugInfoFileOffset, szTempBuf, 10) ); ! 189: strcat(szDebugEventBuffer, " - nDebugInfoSize:"); ! 190: strcat(szDebugEventBuffer, ! 191: LongToCharUpper( (LONG) DebugEvent.u.CreateProcessInfo.nDebugInfoSize, szTempBuf, 10) ); ! 192: strcat(szDebugEventBuffer, " - lpStartAddress:0x"); ! 193: strcat(szDebugEventBuffer, ! 194: LongToCharUpper( (LONG) DebugEvent.u.CreateProcessInfo.lpStartAddress, szTempBuf, 16) ); ! 195: } ! 196: break; ! 197: ! 198: case EXIT_THREAD_DEBUG_EVENT: ! 199: MakeDebugEventString(szDebugEventBuffer, "Exit Thread", ! 200: &DebugEvent); ! 201: ! 202: if( fVerbose ) { ! 203: strcat(szDebugEventBuffer, " - dwExitCode:"); ! 204: } ! 205: else { ! 206: strcat(szDebugEventBuffer, " - Returned:"); ! 207: } ! 208: strcat(szDebugEventBuffer, ! 209: LongToCharUpper( (LONG) DebugEvent.u.ExitThread.dwExitCode, szTempBuf, 10) ); ! 210: break; ! 211: ! 212: case EXIT_PROCESS_DEBUG_EVENT: ! 213: MakeDebugEventString(szDebugEventBuffer, "Exit Process", ! 214: &DebugEvent); ! 215: if( fVerbose ) { ! 216: strcat(szDebugEventBuffer, " - dwExitCode:"); ! 217: } ! 218: else { ! 219: strcat(szDebugEventBuffer, " - Returned:"); ! 220: } ! 221: strcat(szDebugEventBuffer, ! 222: LongToCharUpper( (LONG) DebugEvent.u.ExitProcess.dwExitCode, szTempBuf, 10) ); ! 223: break; ! 224: ! 225: case LOAD_DLL_DEBUG_EVENT: ! 226: MakeDebugEventString(szDebugEventBuffer, "Load DLL:", ! 227: &DebugEvent); ! 228: ! 229: GetModuleFileNameFromHeader( ! 230: hProcess, DebugEvent.u.LoadDll.hFile, ! 231: szTempBuf, 256 ); ! 232: strcat( szDebugEventBuffer, szTempBuf ); ! 233: if( fVerbose ) { ! 234: strcat(szDebugEventBuffer, " - hFile:0x"); ! 235: strcat(szDebugEventBuffer, ! 236: LongToCharUpper( (LONG) DebugEvent.u.LoadDll.hFile, szTempBuf, 16) ); ! 237: strcat(szDebugEventBuffer, " - lpBaseOfDll:0x"); ! 238: strcat(szDebugEventBuffer, ! 239: LongToCharUpper( (LONG) DebugEvent.u.LoadDll.lpBaseOfDll, szTempBuf, 16) ); ! 240: strcat(szDebugEventBuffer, " - dwDebugInfoFileOffset:"); ! 241: strcat(szDebugEventBuffer, ! 242: LongToCharUpper( (LONG) DebugEvent.u.LoadDll.dwDebugInfoFileOffset, szTempBuf, 10) ); ! 243: strcat(szDebugEventBuffer, " - nDebugInfoSize:"); ! 244: strcat(szDebugEventBuffer, ! 245: LongToCharUpper( (LONG) DebugEvent.u.LoadDll.nDebugInfoSize, szTempBuf, 10) ); ! 246: } ! 247: break; ! 248: ! 249: case UNLOAD_DLL_DEBUG_EVENT: ! 250: MakeDebugEventString(szDebugEventBuffer, "Unload DLL", ! 251: &DebugEvent); ! 252: if( fVerbose ) { ! 253: strcat(szDebugEventBuffer, " - lpBaseOfDLL:0x"); ! 254: strcat(szDebugEventBuffer, ! 255: LongToCharUpper( (LONG) DebugEvent.u.UnloadDll.lpBaseOfDll, szTempBuf, 16) ); ! 256: } ! 257: break; ! 258: ! 259: case OUTPUT_DEBUG_STRING_EVENT: ! 260: MakeDebugEventString(szDebugEventBuffer, "Output Debug String", ! 261: &DebugEvent); ! 262: strcat(szDebugEventBuffer, ":\""); ! 263: ! 264: //-- According to Win32 Specs Rev3, I need to use ReadVirtualMemory ! 265: // however this incorrect. ReadProcessMemory is the correct API ! 266: ReadProcessMemory( hProcess, ! 267: DebugEvent.u.DebugString.lpDebugStringData, ! 268: szTempBuf, DebugEvent.u.DebugString.nDebugStringLength, ! 269: &NumberOfBytesRead ); ! 270: strcat(szDebugEventBuffer, szTempBuf ); ! 271: strcat(szDebugEventBuffer, "\"" ); ! 272: if( fVerbose ) { ! 273: strcat(szDebugEventBuffer, " - fUnicode:"); ! 274: strcat(szDebugEventBuffer, ! 275: LongToCharUpper( (LONG) DebugEvent.u.DebugString.fUnicode, szTempBuf, 10) ); ! 276: strcat(szDebugEventBuffer, " - nDebugStringLength:"); ! 277: strcat(szDebugEventBuffer, ! 278: LongToCharUpper( (LONG) DebugEvent.u.DebugString.nDebugStringLength, szTempBuf, 10) ); ! 279: } ! 280: break; ! 281: ! 282: default: ! 283: MakeDebugEventString(szDebugEventBuffer, "Debug Event:", ! 284: &DebugEvent); ! 285: strcat(szDebugEventBuffer, "Unknown [0x"); ! 286: strcat(szDebugEventBuffer, ! 287: LongToCharUpper( (LONG) DebugEvent.dwDebugEventCode, szTempBuf, 16) ); ! 288: strcat(szDebugEventBuffer, "]"); ! 289: break; ! 290: } ! 291: ! 292: //-- insert the debug event string into the listbox ! 293: ListBoxPrintF( "%s", szDebugEventBuffer ); ! 294: ! 295: //-- handle minimal exception handling needs for particular events ! 296: switch( DebugEvent.dwDebugEventCode ) { ! 297: ! 298: case EXCEPTION_DEBUG_EVENT: ! 299: switch( DebugEvent.u.Exception.ExceptionRecord.ExceptionCode ) { ! 300: ! 301: #if( MIPS == 1 ) ! 302: case STATUS_BREAKPOINT: ! 303: //-- increment instruction pointer past the break point ! 304: // only needed for the MIPS R4000 ! 305: if( !SkipBreakPoint( DebugEvent.dwThreadId ) ) ! 306: ListBoxInsert( hWndDebugList, &MaxStrLen, ! 307: "--> Failed To skip over the Break Point" ); ! 308: break; ! 309: #endif ! 310: ! 311: case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: ! 312: case EXCEPTION_FLT_DIVIDE_BY_ZERO: ! 313: case EXCEPTION_FLT_INVALID_OPERATION: ! 314: case EXCEPTION_FLT_OVERFLOW: ! 315: case EXCEPTION_FLT_STACK_CHECK: ! 316: case EXCEPTION_FLT_UNDERFLOW: ! 317: case EXCEPTION_INT_DIVIDE_BY_ZERO: ! 318: case EXCEPTION_INT_OVERFLOW: ! 319: case EXCEPTION_PRIV_INSTRUCTION: ! 320: case STATUS_ACCESS_VIOLATION: ! 321: ContinueDebugEvent( DebugEvent.dwProcessId, DebugEvent.dwThreadId, ! 322: DBG_EXCEPTION_NOT_HANDLED ); ! 323: } ! 324: break; ! 325: ! 326: case CREATE_PROCESS_DEBUG_EVENT: ! 327: CreateNode( &ProcessList, &ThreadNode ); ! 328: (ThreadNode->NodeData).dwThreadId = DebugEvent.dwThreadId; ! 329: (ThreadNode->NodeData).hThread = DebugEvent.u.CreateProcessInfo.hThread; ! 330: InsertNode( &ProcessList, ThreadNode ); ! 331: if( ++ActiveProcesses == 1 ) { ! 332: //-- store the current process handle in the temp global handle ! 333: hProcess = DebugEvent.u.CreateProcessInfo.hProcess; ! 334: } ! 335: break; ! 336: ! 337: case CREATE_THREAD_DEBUG_EVENT: ! 338: CreateNode( &ProcessList, &ThreadNode ); ! 339: (ThreadNode->NodeData).dwThreadId = DebugEvent.dwThreadId; ! 340: (ThreadNode->NodeData).hThread = DebugEvent.u.CreateThread.hThread; ! 341: InsertNode( &ProcessList, ThreadNode ); ! 342: break; ! 343: ! 344: case EXIT_THREAD_DEBUG_EVENT: ! 345: (ThreadNode->NodeData).dwThreadId = DebugEvent.dwThreadId; ! 346: GetNode( &ProcessList, &ThreadNode, OrderFunc, 1 ); ! 347: DeleteCurrentNode( &ProcessList ); ! 348: break; ! 349: ! 350: case EXIT_PROCESS_DEBUG_EVENT: ! 351: //-- if the event was EXIT_PROCESS_DEBUG_EVENT and it was the ! 352: // original process opened/attached to then exit the ! 353: // debug event processing thread. Also do some cleanup first. ! 354: (ThreadNode->NodeData).dwThreadId = DebugEvent.dwThreadId; ! 355: GetNode( &ProcessList, &ThreadNode, OrderFunc, 1 ); ! 356: DeleteCurrentNode( &ProcessList ); ! 357: DestroyNode( TempNode ); ! 358: if( --ActiveProcesses == 0 ) { ! 359: ExitThread( TRUE ); ! 360: } ! 361: break; ! 362: } ! 363: ! 364: //-- default action - just continue ! 365: ContinueDebugEvent( DebugEvent.dwProcessId, DebugEvent.dwThreadId, ! 366: DBG_CONTINUE ); ! 367: } ! 368: ! 369: return( FALSE ); ! 370: } ! 371: ! 372: ! 373: // ************************************************************************ ! 374: // FUNCTION : GetModuleFileNameFromHeader( HANDLE, HANDLE, LPTSTR, DWORD ) ! 375: // PURPOSE : Retrieves the DLL module name for a given file handle of a ! 376: // the module. Reads the module name from the EXE header. ! 377: // COMMENTS : Retrieves only the module name and not the pathname ! 378: // ************************************************************************ ! 379: DWORD APIENTRY ! 380: GetModuleFileNameFromHeader( HANDLE hProcess, HANDLE hFile, LPTSTR lpszPath, ! 381: DWORD cbPath ) ! 382: { ! 383: #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ ! 384: #define IMAGE_OS2_SIGNATURE 0x454E // NE ! 385: #define IMAGE_NT_SIGNATURE 0x00004550 // PE00 ! 386: ! 387: #define IMAGE_SECOND_HEADER_OFFSET (15 * sizeof(ULONG)) // relative to file beginning ! 388: #define IMAGE_BASE_OFFSET (13 * sizeof(DWORD)) // relative to PE header base ! 389: #define IMAGE_EXPORT_TABLE_RVA_OFFSET (30 * sizeof(DWORD)) // relative to PE header base ! 390: #define IMAGE_NAME_RVA_OFFSET (3 * sizeof(DWORD)) // relative to Exports/Imports table base ! 391: ! 392: WORD DosSignature; ! 393: DWORD NtSignature; ! 394: DWORD NumberOfBytesRead; ! 395: ! 396: DWORD PeHeader, ImageBase, ExportTableRVA, NameRVA; ! 397: ! 398: //-- verify that the handle is not NULL ! 399: if( !hFile ) { ! 400: strcpy( lpszPath, "hFile is NULL!" ); ! 401: return( 0 ); ! 402: } ! 403: ! 404: //-- verify that the handle is for a disk file ! 405: if( GetFileType(hFile) != FILE_TYPE_DISK ) { ! 406: strcpy( lpszPath, "Incorrect hFile Type!" ); ! 407: return( 0 ); ! 408: } ! 409: ! 410: //-- Extract the filename from the EXE header ! 411: ReadFile( hFile, &DosSignature, sizeof(DosSignature), &NumberOfBytesRead, ! 412: (LPOVERLAPPED) NULL); ! 413: ! 414: if( DosSignature == IMAGE_DOS_SIGNATURE ) { ! 415: ! 416: SetFilePointer( hFile, IMAGE_SECOND_HEADER_OFFSET, (LPLONG) NULL, ! 417: FILE_BEGIN ); ! 418: ReadFile( hFile, &PeHeader, sizeof(PeHeader), ! 419: &NumberOfBytesRead, (LPOVERLAPPED) NULL ); ! 420: ! 421: SetFilePointer( hFile, PeHeader, (LPLONG) NULL, ! 422: FILE_BEGIN ); ! 423: ReadFile( hFile, &NtSignature, sizeof(NtSignature), ! 424: &NumberOfBytesRead, (LPOVERLAPPED) NULL); ! 425: ! 426: if( NtSignature == IMAGE_NT_SIGNATURE ) { ! 427: ! 428: SetFilePointer( hFile, PeHeader+IMAGE_BASE_OFFSET, ! 429: (LPLONG) NULL, FILE_BEGIN ); ! 430: ReadFile( hFile, &ImageBase, sizeof(ImageBase), ! 431: &NumberOfBytesRead, (LPOVERLAPPED) NULL); ! 432: ! 433: SetFilePointer( hFile, PeHeader + IMAGE_EXPORT_TABLE_RVA_OFFSET, ! 434: (LPLONG) NULL, FILE_BEGIN ); ! 435: ReadFile( hFile, &ExportTableRVA, sizeof(ExportTableRVA), ! 436: &NumberOfBytesRead, (LPOVERLAPPED) NULL); ! 437: ! 438: //-- now read from the virtual address space in the process ! 439: ReadProcessMemory( hProcess, ! 440: (LPVOID) (ImageBase + ExportTableRVA + IMAGE_NAME_RVA_OFFSET), ! 441: &NameRVA, sizeof(NameRVA), &NumberOfBytesRead ); ! 442: ! 443: ReadProcessMemory( hProcess, ! 444: (LPVOID) (ImageBase+NameRVA), ! 445: lpszPath, cbPath, &NumberOfBytesRead ); ! 446: ! 447: return( NumberOfBytesRead ); ! 448: } ! 449: else ! 450: sprintf( lpszPath, "NtSignature is 0x%x!", NtSignature ); ! 451: ! 452: } ! 453: else ! 454: sprintf( lpszPath, "DosSignature is 0x%x!", DosSignature ); ! 455: ! 456: return( 0 ); ! 457: } ! 458: ! 459: ! 460: #if( MIPS == 1 ) ! 461: // ************************************************************************ ! 462: // FUNCTION : SkipThreadBreakPoint( DWORD ); ! 463: // PURPOSE : Skip over the break point instruction belonging to ! 464: // dwThreadId ! 465: // COMMENTS : Only the MIPS R4000 requires this ! 466: // ************************************************************************ ! 467: BOOL ! 468: SkipBreakPoint( DWORD dwThreadId ) ! 469: { ! 470: CONTEXT Context; ! 471: PNODE ThreadNode; ! 472: PNODE InputNode; ! 473: ! 474: CreateNode( &ProcessList, &InputNode ); ! 475: ThreadNode = InputNode; ! 476: (InputNode->NodeData).dwThreadId = dwThreadId; ! 477: ! 478: if( GetNode( &ProcessList, &ThreadNode, OrderFunc, 1 ) == NO_MATCH_ERROR ) { ! 479: ListBoxInsert( hWndDebugList, &MaxStrLen, "--> Error: Node not found" ); ! 480: return( FALSE ); ! 481: } ! 482: ! 483: Context.ContextFlags = CONTEXT_CONTROL; ! 484: ! 485: if( !GetThreadContext( (ThreadNode->NodeData).hThread, &Context ) ) { ! 486: char szTempBuf[64]; ! 487: ! 488: sprintf(szTempBuf, "--> Error: dwThreadId = 0x%8.8lx", dwThreadId ); ! 489: ListBoxInsert( hWndDebugList, &MaxStrLen, szTempBuf ); ! 490: sprintf(szTempBuf, "--> Error: GetThreadContext( %lx ) failed, error 0x%8.8lx", ! 491: (DWORD) (ThreadNode->NodeData).hThread, ! 492: (DWORD) GetLastError() ); ! 493: ListBoxInsert( hWndDebugList, &MaxStrLen, szTempBuf); ! 494: ! 495: return( FALSE ); ! 496: } ! 497: ! 498: Context.Fir += 4L; // Fir is the PC (program counter) ! 499: // BREAK (breakpoint instruction) occupies 4 bytes ! 500: ! 501: // ----------------------------------------------------------------------- ! 502: // Below would be equvalent for the Intel 80x86 if it were necessary ! 503: // Context.Eip += 2L; // Eip is the PC (program counter) ! 504: // // int 3 (breakpoint instruction) occupies 2 bytes ! 505: // ----------------------------------------------------------------------- ! 506: ! 507: SetThreadContext( (ThreadNode->NodeData).hThread, &Context ); ! 508: DestroyNode( InputNode ); ! 509: ! 510: return( TRUE ); ! 511: } ! 512: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.