|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: debug.c ! 8: ! 9: Abstract: ! 10: ! 11: This file implements the debug module for drwatson. This module ! 12: processes all debug events and generates the postmortem dump. ! 13: ! 14: Author: ! 15: ! 16: Wesley Witt (wesw) 1-May-1993 ! 17: ! 18: Environment: ! 19: ! 20: User Mode ! 21: ! 22: --*/ ! 23: ! 24: #include <windows.h> ! 25: #include <stdlib.h> ! 26: #include <stdio.h> ! 27: #include <string.h> ! 28: ! 29: #include "drwatson.h" ! 30: #include "proto.h" ! 31: #include "messages.h" ! 32: #include "resource.h" ! 33: ! 34: typedef struct _tagSYSINFO { ! 35: char szUserName[MAX_PATH]; ! 36: char szMachineName[MAX_PATH]; ! 37: } SYSINFO, *PSYSINFO; ! 38: ! 39: ! 40: #define DBG_EXCEPTION_HANDLED ((DWORD)0x00010001L) ! 41: #define STATUS_POSSIBLE_DEADLOCK ((DWORD)0xC0000194L) ! 42: #define STATUS_SEGMENT_NOTIFICATION ((DWORD)0x40000005L) ! 43: #define STATUS_VDM_EVENT STATUS_SEGMENT_NOTIFICATION ! 44: ! 45: PMODULEINFO AllocMi( PDEBUGPACKET dp ); ! 46: PTHREADCONTEXT AllocTctx( PDEBUGPACKET dp ); ! 47: void PostMortemDump( PDEBUGPACKET dp, LPEXCEPTION_DEBUG_INFO ed ); ! 48: void AttachToActiveProcess ( PDEBUGPACKET dp ); ! 49: void ProcessCreateProcess( PDEBUGPACKET dp, LPDEBUG_EVENT de ); ! 50: void ProcessCreateThread( PDEBUGPACKET dp, LPDEBUG_EVENT de ); ! 51: void ProcessLoadDll( PDEBUGPACKET dp, LPDEBUG_EVENT de ); ! 52: void LogSystemInformation( PDEBUGPACKET dp ); ! 53: DWORD SysInfoThread( PSYSINFO si ); ! 54: void LogDisassembly( PDEBUGPACKET dp, PCRASHES pCrash ); ! 55: void LogStackWalk( PDEBUGPACKET dp ); ! 56: void LogStackDump( PDEBUGPACKET dp ); ! 57: char * GetExceptionText( DWORD dwExceptionCode ); ! 58: ! 59: ! 60: DWORD ! 61: DispatchDebugEventThread( PDEBUGPACKET dp ) ! 62: ! 63: /*++ ! 64: ! 65: Routine Description: ! 66: ! 67: This is the entry point for DRWTSN32 ! 68: ! 69: Arguments: ! 70: ! 71: None. ! 72: ! 73: Return Value: ! 74: ! 75: None. ! 76: ! 77: --*/ ! 78: ! 79: { ! 80: DEBUG_EVENT de; ! 81: DWORD rc = 0; ! 82: char szLogFileName[1024]; ! 83: char buf[1024]; ! 84: ! 85: ! 86: if (dp->dwPidToDebug == 0) { ! 87: rc = 1; ! 88: goto exit; ! 89: } ! 90: ! 91: SetErrorMode( SEM_FAILCRITICALERRORS | ! 92: SEM_NOGPFAULTERRORBOX | ! 93: SEM_NOOPENFILEERRORBOX ); ! 94: ! 95: AttachToActiveProcess( dp ); ! 96: ! 97: strcpy( szLogFileName, dp->options.szLogPath ); ! 98: MakeLogFileName( szLogFileName ); ! 99: OpenLogFile( szLogFileName, ! 100: dp->options.fAppendToLogFile, ! 101: dp->options.fVisual ! 102: ); ! 103: ! 104: while (TRUE) { ! 105: if (!WaitForDebugEvent( &de, 10000 )) { ! 106: rc = GetLastError(); ! 107: goto exit; ! 108: } ! 109: switch (de.dwDebugEventCode) { ! 110: case EXCEPTION_DEBUG_EVENT: ! 111: if (de.u.Exception.ExceptionRecord.ExceptionCode == STATUS_BREAKPOINT) { ! 112: if (de.u.Exception.dwFirstChance) { ! 113: if ( dp->hEventToSignal ) { ! 114: SetEvent(dp->hEventToSignal); ! 115: dp->hEventToSignal = 0L; ! 116: } ! 117: ContinueDebugEvent( de.dwProcessId, de.dwThreadId, DBG_EXCEPTION_HANDLED ); ! 118: continue; ! 119: } ! 120: } ! 121: if (dp->options.fVisual) { ! 122: // ! 123: // this notification is necessary because the shell must know when ! 124: // the debugee has been attached. if it doesn't know and the user is ! 125: // allowed to terminate drwatson then the system may intervene with ! 126: // a popup. ! 127: // ! 128: SendMessage( dp->hwnd, WM_ATTACHCOMPLETE, 0, 0 ); ! 129: wsprintf( buf, ! 130: LoadRcString( IDS_AE_TEXT ), ! 131: GetExceptionText(de.u.Exception.ExceptionRecord.ExceptionCode), ! 132: de.u.Exception.ExceptionRecord.ExceptionCode, ! 133: de.u.Exception.ExceptionRecord.ExceptionAddress ); ! 134: SendMessage( dp->hwnd, WM_EXCEPTIONINFO, 0, (LPARAM) buf ); ! 135: } ! 136: PostMortemDump( dp, &de.u.Exception ); ! 137: ContinueDebugEvent( de.dwProcessId, de.dwThreadId, DBG_EXCEPTION_NOT_HANDLED ); ! 138: continue; ! 139: ! 140: case CREATE_THREAD_DEBUG_EVENT: ! 141: ProcessCreateThread( dp, &de ); ! 142: break; ! 143: ! 144: case CREATE_PROCESS_DEBUG_EVENT: ! 145: ProcessModuleLoad( dp, &de ); ! 146: de.u.CreateThread.hThread = de.u.CreateProcessInfo.hThread; ! 147: ProcessCreateThread( dp, &de ); ! 148: break; ! 149: ! 150: case EXIT_THREAD_DEBUG_EVENT: ! 151: break; ! 152: ! 153: case EXIT_PROCESS_DEBUG_EVENT: ! 154: goto exit; ! 155: break; ! 156: ! 157: case LOAD_DLL_DEBUG_EVENT: ! 158: ProcessModuleLoad( dp, &de ); ! 159: break; ! 160: ! 161: case UNLOAD_DLL_DEBUG_EVENT: ! 162: break; ! 163: ! 164: case OUTPUT_DEBUG_STRING_EVENT: ! 165: break; ! 166: ! 167: case RIP_EVENT: ! 168: break; ! 169: ! 170: default: ! 171: lprintf( MSG_INVALID_DEBUG_EVENT, de.dwDebugEventCode ); ! 172: break; ! 173: } ! 174: ContinueDebugEvent( de.dwProcessId, de.dwThreadId, DBG_CONTINUE ); ! 175: } ! 176: ! 177: exit: ! 178: CloseLogFile(); ! 179: ! 180: if (dp->options.fVisual) { ! 181: SendMessage( dp->hwnd, WM_DUMPCOMPLETE, 0, 0 ); ! 182: } ! 183: ! 184: return 0; ! 185: } ! 186: ! 187: PTHREADCONTEXT ! 188: AllocTctx( PDEBUGPACKET dp ) ! 189: { ! 190: PTHREADCONTEXT ptctx; ! 191: ! 192: ptctx = (PTHREADCONTEXT) malloc( sizeof(THREADCONTEXT) ); ! 193: if (ptctx == NULL) { ! 194: if (dp->options.fVisual) { ! 195: FatalError( LoadRcString(IDS_MEMORY) ); ! 196: } ! 197: else { ! 198: ExitProcess( 1 ); ! 199: } ! 200: } ! 201: memset( ptctx, 0, sizeof(THREADCONTEXT) ); ! 202: ! 203: if (dp->tctxHead == NULL) { ! 204: dp->tctxHead = dp->tctxTail = ptctx; ! 205: } ! 206: else { ! 207: dp->tctxTail->next = ptctx; ! 208: dp->tctxTail = ptctx; ! 209: } ! 210: ! 211: return ptctx; ! 212: } ! 213: ! 214: void ! 215: ProcessCreateThread( PDEBUGPACKET dp, LPDEBUG_EVENT de ) ! 216: { ! 217: dp->tctx = AllocTctx( dp ); ! 218: dp->tctx->hThread = de->u.CreateThread.hThread; ! 219: dp->tctx->dwThreadId = de->dwThreadId; ! 220: ! 221: return; ! 222: } ! 223: ! 224: void ! 225: PostMortemDump( PDEBUGPACKET dp, LPEXCEPTION_DEBUG_INFO ed ) ! 226: { ! 227: PMODULEINFO mi = dp->miHead; ! 228: PTHREADCONTEXT ptctx; ! 229: char dbuf[1024]; ! 230: char szDate[20]; ! 231: char szTime[20]; ! 232: CRASHES crash; ! 233: DWORD dwThreadId; ! 234: HANDLE hThread; ! 235: ! 236: ! 237: GetLocalTime( &crash.time ); ! 238: crash.dwExceptionCode = ed->ExceptionRecord.ExceptionCode; ! 239: crash.dwAddress = (DWORD)ed->ExceptionRecord.ExceptionAddress; ! 240: strcpy( crash.szAppName, dp->miHead->szName ); ! 241: ! 242: lprintf( MSG_APP_EXCEPTION ); ! 243: wsprintf( dbuf, "%d", dp->dwPidToDebug ); ! 244: lprintf( MSG_APP_EXEP_NAME, crash.szAppName, dbuf ); ! 245: wsprintf( szDate, "%d/%d/%d", crash.time.wMonth, ! 246: crash.time.wDay, ! 247: crash.time.wYear ); ! 248: wsprintf( szTime, "%d:%d:%d.%d", crash.time.wHour, ! 249: crash.time.wMinute, ! 250: crash.time.wSecond, ! 251: crash.time.wMilliseconds ); ! 252: lprintf( MSG_APP_EXEP_WHEN, szDate, szTime ); ! 253: wsprintf( dbuf, "%08lx", ed->ExceptionRecord.ExceptionCode ); ! 254: lprintf( MSG_EXCEPTION_NUMBER, dbuf ); ! 255: ! 256: ! 257: lprintfs( "(%s)\r\n\r\n", ! 258: GetExceptionText(ed->ExceptionRecord.ExceptionCode) ); ! 259: ! 260: LogSystemInformation( dp ); ! 261: ! 262: LogTaskList(); ! 263: ! 264: mi = dp->miHead; ! 265: lprintf( MSG_MODULE_LIST ); ! 266: while (mi) { ! 267: lprintfs( "(%08x - %08x) %s\r\n", ! 268: (DWORD)mi->dwLoadAddress, ! 269: (DWORD)mi->dwLoadAddress + mi->dwImageSize, ! 270: mi->szName ! 271: ); ! 272: mi = mi->next; ! 273: } ! 274: lprintfs( "\r\n" ); ! 275: ! 276: ptctx = dp->tctxHead; ! 277: while (ptctx) { ! 278: dp->tctx = ptctx; ! 279: ! 280: GetContextForThread( dp ); ! 281: ! 282: if (ptctx->pc == (DWORD)ed->ExceptionRecord.ExceptionAddress) { ! 283: ptctx->fFaultingContext = TRUE; ! 284: } ! 285: ! 286: if ((!ptctx->fFaultingContext && dp->options.fDumpAllThreads) || ptctx->fFaultingContext) { ! 287: wsprintf( dbuf, "%x", dp->tctx->dwThreadId ); ! 288: lprintf( MSG_STATE_DUMP, dbuf ); ! 289: OutputAllRegs( dp ); ! 290: LogDisassembly( dp, &crash ); ! 291: LogStackWalk( dp ); ! 292: LogStackDump( dp ); ! 293: } ! 294: ! 295: ptctx = ptctx->next; ! 296: if (ptctx->next == NULL) { ! 297: // this forces the loop to ignore the last thread ! 298: // we want to do this because the last thread is a ! 299: // remote thread created by kernel32.dll for the purpose ! 300: // of attaching the debugger to the faulting process ! 301: break; ! 302: } ! 303: } ! 304: ! 305: if (dp->options.fDumpSymbols) { ! 306: DumpSymbols( dp ); ! 307: } ! 308: ! 309: ElSaveCrash( &crash, dp->options.dwMaxCrashes ); ! 310: ! 311: hThread = CreateThread( NULL, ! 312: 16000, ! 313: (LPTHREAD_START_ROUTINE)TerminationThread, ! 314: dp, ! 315: THREAD_SET_INFORMATION, ! 316: (LPDWORD)&dwThreadId ! 317: ); ! 318: ! 319: WaitForSingleObject( hThread, 30000 ); ! 320: ! 321: return; ! 322: } ! 323: ! 324: void ! 325: LogStackDump( PDEBUGPACKET dp ) ! 326: { ! 327: DWORD i; ! 328: DWORD j; ! 329: BYTE stack[1024]; ! 330: ! 331: ! 332: ! 333: memset( stack, 0, sizeof(stack) ); ! 334: if (!ReadProcessMemory( dp->hProcess, ! 335: (LPVOID)dp->tctx->stack, ! 336: (LPVOID)stack, ! 337: sizeof(stack), ! 338: (LPDWORD)&i )) { ! 339: return; ! 340: } ! 341: ! 342: lprintf( MSG_STACK_DUMP_HEADER ); ! 343: ! 344: for( i = 0; i < 20; i++ ) { ! 345: j = i * 16; ! 346: lprintfs( "%08x %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x %02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\r\n", ! 347: j + dp->tctx->stack, ! 348: stack[ j + 0 ], ! 349: stack[ j + 1 ], ! 350: stack[ j + 2 ], ! 351: stack[ j + 3 ], ! 352: stack[ j + 4 ], ! 353: stack[ j + 5 ], ! 354: stack[ j + 6 ], ! 355: stack[ j + 7 ], ! 356: stack[ j + 8 ], ! 357: stack[ j + 9 ], ! 358: stack[ j + 10 ], ! 359: stack[ j + 11 ], ! 360: stack[ j + 12 ], ! 361: stack[ j + 13 ], ! 362: stack[ j + 14 ], ! 363: stack[ j + 15 ], ! 364: isprint( stack[ j + 0 ]) ? stack[ j + 0 ] : '.', ! 365: isprint( stack[ j + 1 ]) ? stack[ j + 1 ] : '.', ! 366: isprint( stack[ j + 2 ]) ? stack[ j + 2 ] : '.', ! 367: isprint( stack[ j + 3 ]) ? stack[ j + 3 ] : '.', ! 368: isprint( stack[ j + 4 ]) ? stack[ j + 4 ] : '.', ! 369: isprint( stack[ j + 5 ]) ? stack[ j + 5 ] : '.', ! 370: isprint( stack[ j + 6 ]) ? stack[ j + 6 ] : '.', ! 371: isprint( stack[ j + 7 ]) ? stack[ j + 7 ] : '.', ! 372: isprint( stack[ j + 8 ]) ? stack[ j + 8 ] : '.', ! 373: isprint( stack[ j + 9 ]) ? stack[ j + 9 ] : '.', ! 374: isprint( stack[ j + 10 ]) ? stack[ j + 10 ] : '.', ! 375: isprint( stack[ j + 11 ]) ? stack[ j + 11 ] : '.', ! 376: isprint( stack[ j + 12 ]) ? stack[ j + 12 ] : '.', ! 377: isprint( stack[ j + 13 ]) ? stack[ j + 13 ] : '.', ! 378: isprint( stack[ j + 14 ]) ? stack[ j + 14 ] : '.', ! 379: isprint( stack[ j + 15 ]) ? stack[ j + 15 ] : '.' ! 380: ); ! 381: } ! 382: ! 383: lprintfs( "\r\n" ); ! 384: return; ! 385: } ! 386: ! 387: void ! 388: LogStackWalk( PDEBUGPACKET dp ) ! 389: { ! 390: STACKWALK stk; ! 391: PSYMBOL psym; ! 392: DWORD dwDisplacement = 0; ! 393: DWORD frames = 0; ! 394: char *szSymName; ! 395: ! 396: ! 397: lprintf( MSG_STACKTRACE ); ! 398: ! 399: stk.frame = dp->tctx->frame; ! 400: stk.pc = dp->tctx->pc; ! 401: stk.ul = 0; ! 402: ! 403: if (!StackWalkInit(&stk, dp)) { ! 404: lprintf( MSG_STACKTRACE_FAIL ); ! 405: return; ! 406: } ! 407: ! 408: lprintf( MSG_STACKTRACE_HEADER ); ! 409: ! 410: do { ! 411: psym = GetSymFromAddrAllContexts( stk.pc, &dwDisplacement, dp ); ! 412: if (psym) { ! 413: szSymName = UnDName( &psym->szName[1] ); ! 414: } ! 415: else { ! 416: szSymName = "<nosymbols>"; ! 417: } ! 418: lprintfs( "%08x %08x %08x %08x %08x %08x ", ! 419: stk.pc, ! 420: stk.frame, ! 421: stk.params[0], ! 422: stk.params[1], ! 423: stk.params[2], ! 424: stk.params[3] ! 425: ); ! 426: ! 427: lprintfs( "%s\r\n", szSymName ); ! 428: } while (StackWalkNext(&stk, dp) && frames++ < 100); ! 429: ! 430: lprintfs( "\r\n" ); ! 431: ! 432: return; ! 433: } ! 434: ! 435: void ! 436: LogDisassembly( PDEBUGPACKET dp, PCRASHES pCrash ) ! 437: { ! 438: PSYMBOL psym; ! 439: DWORD dwFuncAddr; ! 440: DWORD dwFuncSize; ! 441: DWORD dwDisplacement = 0; ! 442: char *szSymName; ! 443: DWORD offset; ! 444: int i; ! 445: int j; ! 446: char dbuf[1024]; ! 447: BOOL fFaultingInst; ! 448: int dwStartDis; ! 449: int dwEndDis; ! 450: ! 451: ! 452: psym = GetSymFromAddr( dp->tctx->pc, &dwDisplacement, dp->tctx->mi ); ! 453: ! 454: if (psym) { ! 455: dwFuncAddr = psym->addr; ! 456: dwFuncSize = psym->size; ! 457: szSymName = UnDName( &psym->szName[1] ); ! 458: } ! 459: else { ! 460: dwFuncAddr = dp->tctx->pc - 50; ! 461: dwFuncSize = 100; ! 462: szSymName = "<nosymbols>"; ! 463: } ! 464: ! 465: if (dp->tctx->fFaultingContext) { ! 466: strcpy( pCrash->szFunction, szSymName ); ! 467: } ! 468: ! 469: lprintf( MSG_FUNCTION, szSymName ); ! 470: ! 471: tryagain: ! 472: // ! 473: // count the number of instructions in the function ! 474: // also, save the instruction number of context's pc ! 475: // ! 476: for (i=0,offset=dwFuncAddr,j=-1; offset<dwFuncAddr+dwFuncSize; i++) { ! 477: if (offset == dp->tctx->pc) { ! 478: j = i; ! 479: } ! 480: if (!disasm( dp, &offset, dbuf, TRUE )) { ! 481: break; ! 482: } ! 483: } ! 484: ! 485: if (j == -1) { ! 486: // ! 487: // we didn't find a match for the current pc ! 488: // this because we don't have symbols for the current pc and ! 489: // therefore had to just backup and start disassembling. we try ! 490: // to recover by adding 1 to the func addr and do it again. ! 491: // eventually we will hit the pc and we will be a-ok. ! 492: // ! 493: dwFuncAddr++; ! 494: goto tryagain; ! 495: } ! 496: ! 497: // ! 498: // print the disassemled instructions. only print the number ! 499: // of instructions before and after the current pc that the ! 500: // user specified in the registry options. ! 501: // ! 502: dwStartDis = max(0,j - (int)dp->options.dwInstructions); ! 503: dwEndDis = j+(int)dp->options.dwInstructions; ! 504: fFaultingInst = FALSE; ! 505: for (i=0,offset=dwFuncAddr; offset<dwFuncAddr+dwFuncSize; i++) { ! 506: if (offset == dp->tctx->pc) { ! 507: fFaultingInst = TRUE; ! 508: } ! 509: if (!disasm( dp, &offset, dbuf, TRUE )) { ! 510: break; ! 511: } ! 512: if (i >= dwStartDis) { ! 513: if (fFaultingInst && dp->tctx->fFaultingContext) { ! 514: fFaultingInst = FALSE; ! 515: lprintf( MSG_FAULT ); ! 516: } ! 517: else { ! 518: lprintfs( " " ); ! 519: } ! 520: lprintfs( "%s\r\n", dbuf ); ! 521: } ! 522: if (i > dwEndDis) { ! 523: break; ! 524: } ! 525: } ! 526: ! 527: lprintfs( "\r\n" ); ! 528: return; ! 529: } ! 530: ! 531: void ! 532: AttachToActiveProcess ( PDEBUGPACKET dp ) ! 533: { ! 534: HANDLE Token; ! 535: PTOKEN_PRIVILEGES NewPrivileges; ! 536: BYTE OldPriv[1024]; ! 537: PBYTE pbOldPriv; ! 538: ULONG cbNeeded; ! 539: BOOLEAN fRc; ! 540: LUID LuidPrivilege; ! 541: ! 542: // ! 543: // Make sure we have access to adjust and to get the old token privileges ! 544: // ! 545: if (!OpenProcessToken( GetCurrentProcess(), ! 546: TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ! 547: &Token)) { ! 548: if (dp->options.fVisual) { ! 549: FatalError( LoadRcString(IDS_DEBUGPRIV) ); ! 550: } ! 551: else { ! 552: ExitProcess( 1 ); ! 553: } ! 554: } ! 555: ! 556: cbNeeded = 0; ! 557: ! 558: // ! 559: // Initialize the privilege adjustment structure ! 560: // ! 561: ! 562: LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &LuidPrivilege ); ! 563: ! 564: NewPrivileges = ! 565: (PTOKEN_PRIVILEGES)LocalAlloc(LMEM_ZEROINIT, ! 566: sizeof(TOKEN_PRIVILEGES) + ! 567: (1 - ANYSIZE_ARRAY) * ! 568: sizeof(LUID_AND_ATTRIBUTES)); ! 569: if (NewPrivileges == NULL) { ! 570: if (dp->options.fVisual) { ! 571: FatalError( LoadRcString(IDS_DEBUGPRIV) ); ! 572: } ! 573: else { ! 574: ExitProcess( 1 ); ! 575: } ! 576: } ! 577: ! 578: NewPrivileges->PrivilegeCount = 1; ! 579: NewPrivileges->Privileges[0].Luid = LuidPrivilege; ! 580: NewPrivileges->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; ! 581: ! 582: // ! 583: // Enable the privilege ! 584: // ! 585: ! 586: pbOldPriv = OldPriv; ! 587: fRc = AdjustTokenPrivileges( Token, ! 588: FALSE, ! 589: NewPrivileges, ! 590: 1024, ! 591: (PTOKEN_PRIVILEGES)pbOldPriv, ! 592: &cbNeeded ); ! 593: ! 594: if (!fRc) { ! 595: ! 596: // ! 597: // If the stack was too small to hold the privileges ! 598: // then allocate off the heap ! 599: // ! 600: if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { ! 601: ! 602: pbOldPriv = LocalAlloc(LMEM_FIXED, cbNeeded); ! 603: if (pbOldPriv == NULL) { ! 604: if (dp->options.fVisual) { ! 605: FatalError( LoadRcString(IDS_DEBUGPRIV) ); ! 606: } ! 607: else { ! 608: ExitProcess( 1 ); ! 609: } ! 610: } ! 611: ! 612: fRc = AdjustTokenPrivileges( Token, ! 613: FALSE, ! 614: NewPrivileges, ! 615: cbNeeded, ! 616: (PTOKEN_PRIVILEGES)pbOldPriv, ! 617: &cbNeeded ); ! 618: } ! 619: } ! 620: ! 621: ! 622: if (!DebugActiveProcess( dp->dwPidToDebug )) { ! 623: FatalError( LoadRcString(IDS_ATTACHFAIL) ); ! 624: if (dp->options.fVisual) { ! 625: FatalError( LoadRcString(IDS_ATTACHFAIL) ); ! 626: } ! 627: else { ! 628: ExitProcess( 1 ); ! 629: } ! 630: } ! 631: ! 632: return; ! 633: } ! 634: ! 635: void ! 636: LogSystemInformation( PDEBUGPACKET dp ) ! 637: { ! 638: char buf[1024]; ! 639: SYSTEM_INFO si; ! 640: DWORD ver; ! 641: SYSINFO mySi; ! 642: DWORD dwThreadId; ! 643: HANDLE hThread; ! 644: ! 645: lprintf( MSG_SYSINFO_HEADER ); ! 646: hThread = CreateThread( NULL, ! 647: 16000, ! 648: (LPTHREAD_START_ROUTINE)SysInfoThread, ! 649: &mySi, ! 650: THREAD_SET_INFORMATION, ! 651: (LPDWORD)&dwThreadId ! 652: ); ! 653: Sleep( 0 ); ! 654: if (WaitForSingleObject( hThread, 30000 ) == WAIT_TIMEOUT) { ! 655: Assert(TerminateThread( hThread, 0 ) == TRUE); ! 656: } ! 657: lprintf( MSG_SYSINFO_COMPUTER, mySi.szMachineName ); ! 658: lprintf( MSG_SYSINFO_USER, mySi.szUserName ); ! 659: GetSystemInfo( &si ); ! 660: wsprintf( buf, "%d", si.dwNumberOfProcessors ); ! 661: lprintf( MSG_SYSINFO_NUM_PROC, buf ); ! 662: lprintf( MSG_SYSINFO_PROC_TYPE ); ! 663: switch(si.dwProcessorType) { ! 664: case PROCESSOR_INTEL_386: ! 665: lprintf( MSG_SYSINFO_I386 ); ! 666: break; ! 667: ! 668: case PROCESSOR_INTEL_486: ! 669: lprintf( MSG_SYSINFO_I486 ); ! 670: break; ! 671: ! 672: case PROCESSOR_INTEL_860: ! 673: lprintf( MSG_SYSINFO_I860 ); ! 674: break; ! 675: ! 676: case PROCESSOR_MIPS_R2000: ! 677: lprintf( MSG_SYSINFO_R2000 ); ! 678: break; ! 679: ! 680: case PROCESSOR_MIPS_R3000: ! 681: lprintf( MSG_SYSINFO_R3000 ); ! 682: break; ! 683: ! 684: case PROCESSOR_MIPS_R4000: ! 685: lprintf( MSG_SYSINFO_R4000 ); ! 686: break; ! 687: ! 688: case PROCESSOR_ALPHA_21064: ! 689: lprintf( MSG_SYSINFO_A21064 ); ! 690: break; ! 691: ! 692: default: ! 693: lprintf( MSG_SYSINFO_UNKNOWN ); ! 694: break; ! 695: } ! 696: ver = GetVersion(); ! 697: wsprintf( buf, "%d.%d", LOBYTE(LOWORD(ver)), HIBYTE(LOWORD(ver)) ); ! 698: lprintf( MSG_SYSINFO_WINVER, buf ); ! 699: RegLogCurrentVersion(); ! 700: lprintfs( "\r\n" ); ! 701: } ! 702: ! 703: DWORD ! 704: SysInfoThread( PSYSINFO si ) ! 705: { ! 706: DWORD len; ! 707: ! 708: strcpy( si->szMachineName, "<unknown machine name>" ); ! 709: strcpy( si->szUserName, "<unknown user name>" ); ! 710: len = sizeof(si->szMachineName); ! 711: GetComputerName( si->szMachineName, &len ); ! 712: len = sizeof(si->szUserName); ! 713: GetUserName( si->szUserName, &len ); ! 714: ! 715: return 0; ! 716: } ! 717: ! 718: DWORD ! 719: TerminationThread( PDEBUGPACKET dp ) ! 720: { ! 721: HANDLE hProcess; ! 722: ! 723: hProcess = OpenProcess( PROCESS_TERMINATE, FALSE, dp->dwPidToDebug ); ! 724: if (hProcess != NULL) { ! 725: TerminateProcess( hProcess, 0 ); ! 726: CloseHandle( hProcess ); ! 727: } ! 728: ! 729: return 0; ! 730: } ! 731: ! 732: char * ! 733: GetExceptionText( DWORD dwExceptionCode ) ! 734: { ! 735: static char buf[80]; ! 736: DWORD dwFormatId = 0; ! 737: ! 738: memset( buf, 0, sizeof(buf) ); ! 739: ! 740: switch (dwExceptionCode) { ! 741: case STATUS_SINGLE_STEP: ! 742: dwFormatId = MSG_SINGLE_STEP_EXCEPTION; ! 743: break; ! 744: ! 745: case DBG_CONTROL_C: ! 746: dwFormatId = MSG_CONTROLC_EXCEPTION; ! 747: break; ! 748: ! 749: case DBG_CONTROL_BREAK: ! 750: dwFormatId = MSG_CONTROL_BRK_EXCEPTION; ! 751: break; ! 752: ! 753: case STATUS_ACCESS_VIOLATION: ! 754: dwFormatId = MSG_ACCESS_VIOLATION_EXCEPTION; ! 755: break; ! 756: ! 757: case STATUS_STACK_OVERFLOW: ! 758: dwFormatId = MSG_STACK_OVERFLOW_EXCEPTION; ! 759: break; ! 760: ! 761: case STATUS_INTEGER_DIVIDE_BY_ZERO: ! 762: dwFormatId = MSG_INTEGER_DIVIDE_BY_ZERO_EXCEPTION; ! 763: break; ! 764: ! 765: case STATUS_PRIVILEGED_INSTRUCTION: ! 766: dwFormatId = MSG_PRIVILEGED_INSTRUCTION_EXCEPTION; ! 767: break; ! 768: ! 769: case STATUS_ILLEGAL_INSTRUCTION: ! 770: dwFormatId = MSG_ILLEGAL_INSTRUCTION_EXCEPTION; ! 771: break; ! 772: ! 773: case STATUS_IN_PAGE_ERROR: ! 774: dwFormatId = MSG_IN_PAGE_IO_EXCEPTION; ! 775: break; ! 776: ! 777: case STATUS_DATATYPE_MISALIGNMENT: ! 778: dwFormatId = MSG_DATATYPE_EXCEPTION; ! 779: break; ! 780: ! 781: case STATUS_POSSIBLE_DEADLOCK: ! 782: dwFormatId = MSG_DEADLOCK_EXCEPTION; ! 783: break; ! 784: ! 785: case STATUS_VDM_EVENT: ! 786: dwFormatId = MSG_VDM_EXCEPTION; ! 787: break; ! 788: ! 789: case STATUS_BREAKPOINT: ! 790: dwFormatId = MSG_BREAKPOINT_EXCEPTION; ! 791: break; ! 792: ! 793: default: ! 794: lprintfs( "\r\n" ); ! 795: break; ! 796: } ! 797: ! 798: FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY, ! 799: NULL, ! 800: dwFormatId, ! 801: 0, // GetUserDefaultLangID(), ! 802: buf, ! 803: sizeof(buf), ! 804: NULL ! 805: ); ! 806: ! 807: return buf; ! 808: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.