|
|
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.