DumpCollect.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #include "StdAfx.h"
  2. #include "DumpCollect.h"
  3. namespace DumpCollect
  4. {
  5. TCHAR _szDrive[_MAX_DRIVE] = { 0 };
  6. TCHAR _szDir[_MAX_DIR] = { 0 };
  7. TCHAR _szFna[_MAX_DIR] = { 0 };
  8. TCHAR _szExt[_MAX_DIR] = { 0 };
  9. TCHAR _szModulePath[MAX_PATH] = {0};
  10. TCHAR _szModuleFileName[MAX_PATH] = {0};
  11. void GetName()
  12. {
  13. static BOOL bGetName = FALSE;
  14. if ( bGetName )
  15. return;
  16. ::GetModuleFileName(NULL, _szModulePath, sizeof(_szModulePath) / sizeof(TCHAR));
  17. _stprintf_s(_szModuleFileName, _T("%s"), _szModulePath);
  18. _tsplitpath_s(_szModulePath, _szDrive, _szDir, _szFna, _szExt);
  19. _tcscpy_s(_szModulePath, _szDrive);
  20. _tcscat_s(_szModulePath, _szDir);
  21. }
  22. void CreateDumpFile( IN LPCTSTR lpstrDumpFilePath, IN EXCEPTION_POINTERS *pException )
  23. {
  24. // 创建Dump文件;
  25. HANDLE hDumpFile = CreateFile( lpstrDumpFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
  26. if ( (hDumpFile != NULL) && (hDumpFile != INVALID_HANDLE_VALUE) )
  27. {
  28. // Dump信息;
  29. MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
  30. ZeroMemory(&dumpInfo, sizeof(MINIDUMP_EXCEPTION_INFORMATION));
  31. dumpInfo.ThreadId = GetCurrentThreadId();
  32. dumpInfo.ExceptionPointers = pException;
  33. dumpInfo.ClientPointers = TRUE;
  34. // 写入Dump文件内容;
  35. MINIDUMP_CALLBACK_INFORMATION mci;
  36. ZeroMemory(&mci, sizeof(MINIDUMP_CALLBACK_INFORMATION));
  37. mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MiniDumpCallback;
  38. mci.CallbackParam = 0;
  39. ::MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, (pException != NULL) ? &dumpInfo : NULL, NULL, &mci );
  40. CloseHandle(hDumpFile);
  41. }
  42. }
  43. BOOL CALLBACK MiniDumpCallback( IN PVOID pParam, IN const PMINIDUMP_CALLBACK_INPUT pInput, IN PMINIDUMP_CALLBACK_OUTPUT pOutput )
  44. {
  45. if ( pInput == NULL || pOutput == NULL )
  46. {
  47. return FALSE;
  48. }
  49. switch(pInput->CallbackType)
  50. {
  51. case ModuleCallback:
  52. if ( pOutput->ModuleWriteFlags & ModuleWriteDataSeg )
  53. {
  54. if ( !IsDataSectionNeeded(pInput->Module.FullPath) )
  55. {
  56. pOutput->ModuleWriteFlags &= (~ModuleWriteDataSeg);
  57. }
  58. }
  59. case IncludeModuleCallback:
  60. case IncludeThreadCallback:
  61. case ThreadCallback:
  62. case ThreadExCallback:
  63. return TRUE;
  64. default:
  65. break;
  66. }
  67. return FALSE;
  68. }
  69. BOOL IsDataSectionNeeded( IN const WCHAR* pModuleName )
  70. {
  71. if ( pModuleName == NULL || pModuleName[0] == '\0' )
  72. {
  73. return FALSE;
  74. }
  75. WCHAR szFileName[_MAX_FNAME] = L"";
  76. _wsplitpath(pModuleName, NULL, NULL, szFileName, NULL);
  77. if ( _wcsicmp( szFileName, L"ntdll" ) == 0 )
  78. {
  79. return TRUE;
  80. }
  81. return FALSE;
  82. }
  83. LONG CALLBACK MyUnhandledExceptionFilter( IN PEXCEPTION_POINTERS pExceptionInfo )
  84. {
  85. TCHAR szDumpFile[MAX_PATH] = {0};
  86. _stprintf_s(szDumpFile, MAX_PATH, _T("%s%s[%s].dmp"), _szModulePath, _szFna, CTime::GetCurrentTime().Format(_T("%Y%m%d%H%M%S")));
  87. CreateDumpFile(szDumpFile, pExceptionInfo);
  88. return EXCEPTION_EXECUTE_HANDLER;
  89. }
  90. // 此函数一旦成功调用,之后对SetUnhandledExceptionFilter的调用将无效;
  91. void DisableSetUnhandledExceptionFilter()
  92. {
  93. #if 1
  94. void *addr = (void*)GetProcAddress(LoadLibrary(_T("kernel32.dll")), "SetUnhandledExceptionFilter");
  95. if ( addr )
  96. {
  97. BYTE byCode[16] = {0};
  98. INT nSize = 0;
  99. byCode[nSize++] = 0x33;
  100. byCode[nSize++] = 0xC0;
  101. byCode[nSize++] = 0xC2;
  102. byCode[nSize++] = 0x04;
  103. byCode[nSize++] = 0x00;
  104. DWORD dwOldFlag, dwTempFlag;
  105. VirtualProtect(addr, nSize, PAGE_READWRITE, &dwOldFlag);
  106. WriteProcessMemory(GetCurrentProcess(), addr, byCode, nSize, NULL);
  107. VirtualProtect(addr, nSize, dwOldFlag, &dwTempFlag);
  108. }
  109. #else
  110. HMODULE hkernel32 = LoadLibrary(_T("kernel32.dll"));
  111. if ( hkernel32 == NULL)
  112. {
  113. return ;
  114. }
  115. void *pOrgEntry = GetProcAddress(hkernel32, "SetUnhandledExceptionFilter");
  116. if ( pOrgEntry == NULL )
  117. return;
  118. BYTE newJump[100];
  119. DWORD dwOrgEntryAddr = (DWORD)pOrgEntry;
  120. dwOrgEntryAddr += 5;
  121. void *pNewFunc = &MyUnhandledExceptionFilter;
  122. DWORD dwNewEntryAddr = (DWORD)pNewFunc;
  123. DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr;
  124. newJump[0] = 0xE9; // Jmp absolute
  125. memcpy(&newJump[1], &dwRelativeAddr, sizeof(pNewFunc));
  126. SIZE_T bytesWritten;
  127. BOOL bRet = WriteProcessMemory(GetCurrentProcess(), pOrgEntry, newJump, sizeof(pNewFunc) + 1, &bytesWritten);
  128. #endif
  129. }
  130. void InitMinDump()
  131. {
  132. GetName();
  133. // 注册异常处理函数;
  134. SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)MyUnhandledExceptionFilter);
  135. // 使VS2005 自动设置SetUnhandledExceptionFilter无效;
  136. DisableSetUnhandledExceptionFilter();
  137. }
  138. }