223 lines
No EOL
6.6 KiB
C++
223 lines
No EOL
6.6 KiB
C++
|
|
#include "stdafx.h"
|
|
#include "minidump.h"
|
|
|
|
LPTOP_LEVEL_EXCEPTION_FILTER pOldPointer = NULL;
|
|
|
|
LONG __stdcall Exception_Minidump(_EXCEPTION_POINTERS* pExceptionInfo)
|
|
{
|
|
TCHAR fileName[MAX_PATH];
|
|
GetModuleFileName(NULL, fileName, MAX_PATH);
|
|
TCHAR * ext = _tcsrchr(fileName, '.');
|
|
srand(timeGetTime());
|
|
_stprintf(ext ? ext : fileName+_tcslen(fileName), _T(".%d%d%d%d.dmp"), rand()%10, rand()%10, rand()%10, rand()%10);
|
|
|
|
HANDLE hProcess = GetCurrentProcess();
|
|
DWORD dwProcessID = GetCurrentProcessId();
|
|
HANDLE hFile = CreateFile(fileName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
MINIDUMP_EXCEPTION_INFORMATION eInfo;
|
|
eInfo.ThreadId = GetCurrentThreadId();
|
|
eInfo.ExceptionPointers = pExceptionInfo;
|
|
eInfo.ClientPointers = FALSE;
|
|
|
|
MiniDumpWriteDump(hProcess, dwProcessID, hFile, MiniDumpWithFullMemory, pExceptionInfo ? &eInfo : NULL, NULL, NULL);
|
|
|
|
return pOldPointer ? pOldPointer(pExceptionInfo) : EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
|
|
// STL À߸øµÈ Index ÂüÁ¶
|
|
static void myInvalidParameterHandler(const wchar_t* expression,
|
|
const wchar_t* function,
|
|
const wchar_t* file,
|
|
unsigned int line,
|
|
uintptr_t pReserved)
|
|
{
|
|
RaiseException( EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE , 0, 0);
|
|
}
|
|
|
|
// Pure virtual function call
|
|
static void myPurecallHandler()
|
|
{
|
|
RaiseException( EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE , 0, 0);
|
|
}
|
|
|
|
void SetMiniDump()
|
|
{
|
|
_set_invalid_parameter_handler( myInvalidParameterHandler );
|
|
_set_purecall_handler( myPurecallHandler );
|
|
SetUnhandledExceptionFilter(Exception_Minidump);
|
|
|
|
printf("DbgHelp API Version Num[%d]\n", API_VERSION_NUMBER);
|
|
}
|
|
|
|
void StoreMiniDump(const TCHAR * szFName, _MINIDUMP_TYPE dumptype)
|
|
{
|
|
HANDLE hProcess = GetCurrentProcess();
|
|
DWORD dwProcessID = GetCurrentProcessId();
|
|
HANDLE hFile = CreateFile(szFName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
MiniDumpWriteDump(hProcess, dwProcessID, hFile, dumptype, NULL, NULL, NULL);
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#if defined (API_VERSION_NUMBER) && (API_VERSION_NUMBER >= 11)
|
|
const MINIDUMP_TYPE MINIDUMP = (MINIDUMP_TYPE)(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory);
|
|
const MINIDUMP_TYPE MIDIDUMP = (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory | MiniDumpWithDataSegs | MiniDumpWithHandleData |
|
|
MiniDumpWithUnloadedModules);
|
|
const MINIDUMP_TYPE MAXIDUMP = (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithHandleData |
|
|
MiniDumpWithUnloadedModules);
|
|
#else
|
|
const MINIDUMP_TYPE MINIDUMP = (MINIDUMP_TYPE)(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory );
|
|
const MINIDUMP_TYPE MIDIDUMP = (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory | MiniDumpWithDataSegs | MiniDumpWithHandleData |
|
|
MiniDumpWithUnloadedModules);
|
|
const MINIDUMP_TYPE MAXIDUMP = (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithHandleData |
|
|
MiniDumpWithUnloadedModules );
|
|
#endif
|
|
//Handled Exception
|
|
LONG StoreMiniDump(_DUMPTYPE eType, EXCEPTION_POINTERS * pE)
|
|
{
|
|
//if you want use EXCEPTION_POINTERS case use __try __exception can using this func GetExceptionInformation()
|
|
// Open the file
|
|
TCHAR fileName[MAX_PATH];
|
|
GetModuleFileName(NULL, fileName, MAX_PATH);
|
|
TCHAR * ext = _tcsrchr(fileName, '.');
|
|
srand(timeGetTime());
|
|
_stprintf(ext ? ext : fileName+_tcslen(fileName), _T(".Exception.%d%d%d%d.dmp"), rand()%10, rand()%10, rand()%10, rand()%10);
|
|
|
|
HANDLE hProcess = GetCurrentProcess();
|
|
DWORD dwProcessID = GetCurrentProcessId();
|
|
HANDLE hFile = CreateFile(fileName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
|
|
{
|
|
// Create the minidump
|
|
MINIDUMP_EXCEPTION_INFORMATION mdei;
|
|
|
|
mdei.ThreadId = GetCurrentThreadId();
|
|
mdei.ExceptionPointers = pE;
|
|
mdei.ClientPointers = FALSE;
|
|
|
|
MINIDUMP_CALLBACK_INFORMATION mci;
|
|
|
|
mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MiniDumpCallBack;
|
|
mci.CallbackParam = 0;
|
|
|
|
MINIDUMP_TYPE mdt;
|
|
switch (eType)
|
|
{
|
|
case _DUMPTYPE_MINI: mdt = MINIDUMP; break;
|
|
case _DUMPTYPE_MIDI: mdt = MIDIDUMP; break;
|
|
case _DUMPTYPE_MAXI: mdt = MAXIDUMP; break;
|
|
default: mdt = MINIDUMP; break;
|
|
}
|
|
|
|
BOOL rv = MiniDumpWriteDump(hProcess, dwProcessID, hFile, mdt, (pE != NULL) ? &mdei : NULL, NULL, eType != _DUMPTYPE_MAXI ? &mci : NULL);
|
|
|
|
if(!rv) _tprintf(_T("MiniDumpWriteDump failed. Error: %d \n"), GetLastError());
|
|
else _tprintf(_T("Minidump created.\n") );
|
|
|
|
// Close the file
|
|
CloseHandle(hFile);
|
|
}
|
|
else
|
|
_tprintf(_T("CreateFile failed. Error: %u \n"), GetLastError());
|
|
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
|
|
BOOL CALLBACK MiniDumpCallBack(PVOID pParam, const PMINIDUMP_CALLBACK_INPUT pInput, PMINIDUMP_CALLBACK_OUTPUT pOutput)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
// Check parameters
|
|
if(pInput == 0) return FALSE;
|
|
if(pOutput == 0) return FALSE;
|
|
|
|
// Process the callbacks
|
|
switch(pInput->CallbackType)
|
|
{
|
|
case IncludeModuleCallback:
|
|
{
|
|
// Include the module into the dump
|
|
bRet = TRUE;
|
|
}
|
|
break;
|
|
|
|
case IncludeThreadCallback:
|
|
{
|
|
// Include the thread into the dump
|
|
bRet = TRUE;
|
|
}
|
|
break;
|
|
|
|
case ModuleCallback:
|
|
{
|
|
// Are data sections available for this module ?
|
|
if(pOutput->ModuleWriteFlags & ModuleWriteDataSeg)
|
|
{
|
|
// Yes, they are, but do we need them?
|
|
if(!IsDataSectionNeeded(pInput->Module.FullPath))
|
|
{
|
|
wprintf(L"Excluding module data sections: %s \n", pInput->Module.FullPath);
|
|
pOutput->ModuleWriteFlags &= (~ModuleWriteDataSeg);
|
|
}
|
|
}
|
|
|
|
bRet = TRUE;
|
|
}
|
|
break;
|
|
|
|
case ThreadCallback:
|
|
{
|
|
// Include all thread information into the minidump
|
|
bRet = TRUE;
|
|
}
|
|
break;
|
|
|
|
case ThreadExCallback:
|
|
{
|
|
// Include this information
|
|
bRet = TRUE;
|
|
}
|
|
break;
|
|
|
|
case MemoryCallback:
|
|
{
|
|
// We do not include any information here -> return FALSE
|
|
bRet = FALSE;
|
|
}
|
|
break;
|
|
#if defined (API_VERSION_NUMBER) && (API_VERSION_NUMBER >= 11)
|
|
case CancelCallback:
|
|
break;
|
|
#endif
|
|
}
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
bool IsDataSectionNeeded(const WCHAR* pModuleName)
|
|
{
|
|
// Check parameters
|
|
if(pModuleName == 0)
|
|
{
|
|
_ASSERT(_T("Parameter is null."));
|
|
return false;
|
|
}
|
|
|
|
// Extract the module name
|
|
WCHAR szFileName[_MAX_FNAME] = L"";
|
|
_wsplitpath(pModuleName, NULL, NULL, szFileName, NULL);
|
|
|
|
// Compare the name with the list of known names and decide
|
|
// Note: For this to work, the executable name must be "mididump.exe"
|
|
if(wcsicmp(szFileName, L"mididump") == 0)
|
|
return true;
|
|
else if(wcsicmp(szFileName, L"ntdll") == 0)
|
|
return true;
|
|
|
|
// Complete
|
|
return false;
|
|
} |