home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / image / drwatson / dump.c < prev    next >
C/C++ Source or Header  |  1996-12-13  |  10KB  |  324 lines

  1. /*++
  2.  
  3. Copyright (c) 1993  Microsoft Corporation
  4.  
  5. Module Name:
  6.  
  7.     dump.c
  8.  
  9. Abstract:
  10.  
  11.     This file implements the crash dump code.
  12.  
  13. Author:
  14.  
  15.     Wesley Witt (wesw) 27-Jan-1995
  16.  
  17. Environment:
  18.  
  19.     User Mode
  20.  
  21. --*/
  22.  
  23. #include <windows.h>
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <stddef.h>
  28. #include <crash.h>
  29.  
  30. #include "drwatson.h"
  31. #include "proto.h"
  32. #include "messages.h"
  33. #include "resource.h"
  34.  
  35.  
  36. #define MEM_SIZE (64*1024)
  37.  
  38.  
  39. //
  40. // these are here only so that we can link
  41. // with crashlib.  they are only referenced
  42. // when reading a kernel mode crash dump
  43. //
  44. DWORD KiProcessors;
  45. DWORD KiPcrBaseAddress;
  46.  
  47. //
  48. // private data structure use for communcating
  49. // crash dump data to the callback function
  50. //
  51. typedef struct _CRASH_DUMP_INFO {
  52.     PDEBUGPACKET                dp;
  53.     EXCEPTION_DEBUG_INFO        *ExceptionInfo;
  54.     DWORD                       MemoryCount;
  55.     DWORD                       Address;
  56.     PUCHAR                      MemoryData;
  57.     MEMORY_BASIC_INFORMATION    mbi;
  58.     BOOL                        MbiOffset;
  59.     ULONG                       MbiRemaining;
  60.     PTHREADCONTEXT              ptctx;
  61.     IMAGEHLP_MODULE             mi;
  62.     PCRASH_MODULE               CrashModule;
  63. } CRASH_DUMP_INFO, *PCRASH_DUMP_INFO;
  64.  
  65. LPSTR
  66. ExpandPath(
  67.     LPSTR lpPath
  68.     );
  69.  
  70. DWORD
  71. GetTeb(
  72.     HANDLE hTread
  73.     );
  74.  
  75. BOOL
  76. CrashDumpCallback(
  77.     DWORD               DataType,
  78.     PVOID               *DumpData,
  79.     LPDWORD             DumpDataLength,
  80.     PCRASH_DUMP_INFO    CrashdumpInfo
  81.     )
  82.  
  83. /*++
  84.  
  85. Routine Description:
  86.  
  87.     This function is the callback used by crashlib.
  88.     Its purpose is to provide data to DmpCreateUserDump()
  89.     for writting to the crashdump file.
  90.  
  91. Arguments:
  92.  
  93.     DataType        - requested data type
  94.     DumpData        - pointer to a pointer to the data
  95.     DumpDataLength  - pointer to the data length
  96.     CrashdumpInfo   - DrWatson private data
  97.  
  98. Return Value:
  99.  
  100.     TRUE    - continue calling back for the requested data type
  101.     FALSE   - stop calling back and go on to the next data type
  102.  
  103. --*/
  104.  
  105. {
  106.     DWORD   cb;
  107.  
  108.     switch( DataType ) {
  109.         case DMP_DEBUG_EVENT:
  110.             *DumpData = &CrashdumpInfo->dp->DebugEvent;
  111.             *DumpDataLength = sizeof(DEBUG_EVENT);
  112.             break;
  113.  
  114.         case DMP_THREAD_STATE:
  115.             {
  116.                 static CRASH_THREAD CrashThread;
  117.                 PTHREADCONTEXT  ptctx;
  118.                 PLIST_ENTRY     ListEntry;
  119.  
  120.                 *DumpData = &CrashThread;
  121.  
  122.                 if (CrashdumpInfo->ptctx == NULL) {
  123.                     ListEntry = CrashdumpInfo->dp->ThreadList.Flink;
  124.                 } else {
  125.                     ListEntry = CrashdumpInfo->ptctx->ThreadList.Flink;
  126.                 }
  127.  
  128.                 if (ListEntry == &CrashdumpInfo->dp->ThreadList) {
  129.                     CrashdumpInfo->ptctx = NULL;
  130.                     return FALSE;
  131.                 }
  132.  
  133.                 ptctx =
  134.                 CrashdumpInfo->ptctx = CONTAINING_RECORD(ListEntry, THREADCONTEXT, ThreadList);
  135.  
  136.                 ZeroMemory(&CrashThread, sizeof(CrashThread));
  137.  
  138.                 CrashThread.ThreadId = ptctx->dwThreadId;
  139.                 CrashThread.SuspendCount = SuspendThread(ptctx->hThread);
  140.                 if (CrashThread.SuspendCount != (DWORD)-1) {
  141.                     ResumeThread(ptctx->hThread);
  142.                 }
  143.                 CrashThread.PriorityClass = GetPriorityClass(CrashdumpInfo->dp->hProcess);
  144.                 CrashThread.Priority = GetThreadPriority(ptctx->hThread);
  145.                 CrashThread.Teb = GetTeb(ptctx->hThread);
  146.  
  147.                 *DumpDataLength = sizeof(CRASH_THREAD);
  148.             }
  149.             break;
  150.  
  151.         case DMP_MEMORY_BASIC_INFORMATION:
  152.             while( TRUE ) {
  153.                 CrashdumpInfo->Address += CrashdumpInfo->mbi.RegionSize;
  154.                 if (!VirtualQueryEx(
  155.                         CrashdumpInfo->dp->hProcess,
  156.                         (LPVOID)CrashdumpInfo->Address,
  157.                         &CrashdumpInfo->mbi,
  158.                         sizeof(MEMORY_BASIC_INFORMATION) )) {
  159.                     return FALSE;
  160.                 }
  161.                 if ((CrashdumpInfo->mbi.AllocationProtect & PAGE_GUARD) ||
  162.                     (CrashdumpInfo->mbi.AllocationProtect & PAGE_NOACCESS)) {
  163.                     continue;
  164.                 }
  165.                 if ((CrashdumpInfo->mbi.State & MEM_FREE) ||
  166.                     (CrashdumpInfo->mbi.State & MEM_RESERVE)) {
  167.                     continue;
  168.                 }
  169.                 break;
  170.             }
  171.             *DumpData = &CrashdumpInfo->mbi;
  172.             *DumpDataLength = sizeof(MEMORY_BASIC_INFORMATION);
  173.             break;
  174.  
  175.         case DMP_THREAD_CONTEXT:
  176.             {
  177.                 PLIST_ENTRY     ListEntry;
  178.  
  179.                 if (CrashdumpInfo->ptctx == NULL) {
  180.                     ListEntry = CrashdumpInfo->dp->ThreadList.Flink;
  181.                 } else {
  182.                     ListEntry = CrashdumpInfo->ptctx->ThreadList.Flink;
  183.                 }
  184.  
  185.                 if (ListEntry == &CrashdumpInfo->dp->ThreadList) {
  186.                     CrashdumpInfo->ptctx = NULL;
  187.                     return FALSE;
  188.                 }
  189.  
  190.                 CrashdumpInfo->ptctx = CONTAINING_RECORD(ListEntry, THREADCONTEXT, ThreadList);
  191.  
  192.                 *DumpData = &CrashdumpInfo->ptctx->context;
  193.                 *DumpDataLength = sizeof(CONTEXT);
  194.             }
  195.             break;
  196.  
  197.         case DMP_MODULE:
  198.             if (CrashdumpInfo->mi.BaseOfImage == 0) {
  199.                 return FALSE;
  200.             }
  201.             CrashdumpInfo->CrashModule->BaseOfImage = CrashdumpInfo->mi.BaseOfImage;
  202.             CrashdumpInfo->CrashModule->SizeOfImage = CrashdumpInfo->mi.ImageSize;
  203.             CrashdumpInfo->CrashModule->ImageNameLength = strlen(CrashdumpInfo->mi.ImageName) + 1;
  204.             strcpy( CrashdumpInfo->CrashModule->ImageName, CrashdumpInfo->mi.ImageName );
  205.             *DumpData = CrashdumpInfo->CrashModule;
  206.             *DumpDataLength = sizeof(CRASH_MODULE) + CrashdumpInfo->CrashModule->ImageNameLength;
  207.             if (!SymGetModuleInfo( CrashdumpInfo->dp->hProcess, (DWORD)-1, &CrashdumpInfo->mi )) {
  208.                 CrashdumpInfo->mi.BaseOfImage = 0;
  209.             }
  210.             break;
  211.  
  212.         case DMP_MEMORY_DATA:
  213.             if (!CrashdumpInfo->MemoryCount) {
  214.                 CrashdumpInfo->Address = 0;
  215.                 CrashdumpInfo->MbiOffset = 0;
  216.                 CrashdumpInfo->MbiRemaining = 0;
  217.                 ZeroMemory( &CrashdumpInfo->mbi, sizeof(MEMORY_BASIC_INFORMATION) );
  218.                 CrashdumpInfo->MemoryData = VirtualAlloc(
  219.                     NULL,
  220.                     MEM_SIZE,
  221.                     MEM_COMMIT,
  222.                     PAGE_READWRITE
  223.                     );
  224.             }
  225.             if (!CrashdumpInfo->MbiRemaining) {
  226.                 while( TRUE ) {
  227.                     CrashdumpInfo->Address += CrashdumpInfo->mbi.RegionSize;
  228.                     if (!VirtualQueryEx(
  229.                             CrashdumpInfo->dp->hProcess,
  230.                             (LPVOID)CrashdumpInfo->Address,
  231.                             &CrashdumpInfo->mbi,
  232.                             sizeof(MEMORY_BASIC_INFORMATION) )) {
  233.                         if (CrashdumpInfo->MemoryData) {
  234.                             VirtualFree( CrashdumpInfo->MemoryData, MEM_SIZE, MEM_RELEASE );
  235.                         }
  236.                         return FALSE;
  237.                     }
  238.                     if ((CrashdumpInfo->mbi.Protect & PAGE_GUARD) ||
  239.                         (CrashdumpInfo->mbi.Protect & PAGE_NOACCESS)) {
  240.                         continue;
  241.                     }
  242.                     if ((CrashdumpInfo->mbi.State & MEM_FREE) ||
  243.                         (CrashdumpInfo->mbi.State & MEM_RESERVE)) {
  244.                         continue;
  245.                     }
  246.                     CrashdumpInfo->MbiOffset = 0;
  247.                     CrashdumpInfo->MbiRemaining = CrashdumpInfo->mbi.RegionSize;
  248.                     CrashdumpInfo->MemoryCount += 1;
  249.                     break;
  250.                 }
  251.             }
  252.             *DumpDataLength = min( CrashdumpInfo->MbiRemaining, MEM_SIZE );
  253.             CrashdumpInfo->MbiRemaining -= *DumpDataLength;
  254.             ReadProcessMemory(
  255.                 CrashdumpInfo->dp->hProcess,
  256.                 (PUCHAR)((ULONG)CrashdumpInfo->mbi.BaseAddress + (ULONG)CrashdumpInfo->MbiOffset),
  257.                 CrashdumpInfo->MemoryData,
  258.                 *DumpDataLength,
  259.                 &cb
  260.                 );
  261.             *DumpData = CrashdumpInfo->MemoryData;
  262.             CrashdumpInfo->MbiOffset += *DumpDataLength;
  263.             break;
  264.     }
  265.  
  266.     return TRUE;
  267. }
  268.  
  269.  
  270. BOOL
  271. CreateDumpFile(
  272.     PDEBUGPACKET            dp,
  273.     LPEXCEPTION_DEBUG_INFO  ed
  274.     )
  275.  
  276. /*++
  277.  
  278. Routine Description:
  279.  
  280.     This function creates a crash dump file.
  281.  
  282. Arguments:
  283.  
  284.     dp              - debug packet for current process
  285.  
  286.     ed              - exception data
  287.  
  288. Return Value:
  289.  
  290.     TRUE    - Crash dump was created
  291.     FALSE   - Crash dump was NOT created
  292.  
  293. --*/
  294.  
  295. {
  296.     CRASH_DUMP_INFO     CrashdumpInfo;
  297.     LPSTR               p;
  298.  
  299.  
  300.     ZeroMemory( &CrashdumpInfo, sizeof(CRASH_DUMP_INFO) );
  301.  
  302.     CrashdumpInfo.dp = dp;
  303.     CrashdumpInfo.ExceptionInfo = ed;
  304.     CrashdumpInfo.ptctx = NULL;
  305.     //
  306.     // Get first entry in module list
  307.     //
  308.     SymGetModuleInfo( dp->hProcess, (DWORD)0, &CrashdumpInfo.mi );
  309.     CrashdumpInfo.CrashModule = LocalAlloc( LPTR, 4096 );
  310.  
  311.     p = ExpandPath( dp->options.szCrashDump );
  312.     if (!p) {
  313.         return FALSE;
  314.     }
  315.  
  316.     DmpCreateUserDump( p, CrashDumpCallback, &CrashdumpInfo );
  317.  
  318.     free( p );
  319.  
  320.     LocalFree( CrashdumpInfo.CrashModule );
  321.  
  322.     return TRUE;
  323. }
  324.