#include "stdafx.h"
#include < WINDOWS.H >
#include < PSAPI.H >
#include < DBGHELP.H >
#include < STRING >
#pragma comment(lib, "psapi.lib")
#pragma comment(lib, "dbghelp.lib")
static bool CreateMinidump(const char outputFileName[], _EXCEPTION_POINTERS* ExceptionInfo);
static LPTOP_LEVEL_EXCEPTION_FILTER prevFilter = NULL;
static _invalid_parameter_handler prevInvParamHandler = NULL;
static _purecall_handler prevPureCallHandler = NULL;
static bool s_enableSorryDialogBoxAtCrash = true;
static MINIDUMP_TYPE s_miniDumpType = MiniDumpWithFullMemory;
wchar_t s_AdditionalInformation[256];
wchar_t s_GraphicInformation[256];
wchar_t s_SystemInformation[4096];
void WriteSystemInformation(const wchar_t* graphicInfo, const wchar_t* additionalInfo, wchar_t* destBuf, size_t destBufSize)
{
std::string result;
wchar_t* bufEnd = destBuf + destBufSize;
wchar_t* pBuf = destBuf;
// remained buffer size
#define rbs (bufEnd - pBuf)
SYSTEM_INFO si;
GetSystemInfo(&si);
{
pBuf += swprintf_s(pBuf, rbs, L"OEM ID: %d, Number of processors: %d\n", si.dwOemId, si.dwNumberOfProcessors);
pBuf += swprintf_s(pBuf, rbs, L"Processor type: %d, Processor level: %d, Processor revision: %d\n", si.dwProcessorType, si.wProcessorLevel, si.wProcessorRevision);
}
{
HKEY hKey;
LONG lResult = ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Hardware/Description/System/CentralProcessor/0", 0, KEY_QUERY_VALUE, &hKey);
if (lResult == ERROR_SUCCESS)
{
DWORD dwVal;
DWORD dwSize;
wchar_t buf[256];
DWORD typeDword = REG_DWORD;
DWORD typeSz = REG_SZ;
dwSize = sizeof(dwVal);
if (lResult = RegQueryValueExW(hKey, L"~MHz", NULL, &typeDword, (LPBYTE)&dwVal, &dwSize), lResult == ERROR_SUCCESS)
{
pBuf += swprintf_s(pBuf, rbs, L"CPU speed: %d MHz\n", dwVal);
}
dwSize = sizeof(buf) - 2;
if (lResult = RegQueryValueExW(hKey, L"ProcessorNameString", NULL, &typeSz, (LPBYTE)buf, &dwSize), lResult == ERROR_SUCCESS)
{
pBuf += swprintf_s(pBuf, rbs, L"Processor name: %s\n", buf);
}
dwSize = sizeof(buf) - 2;
if (lResult = RegQueryValueExW(hKey, L"Identifier", NULL, &typeSz, (LPBYTE)buf, &dwSize), lResult == ERROR_SUCCESS)
{
pBuf += swprintf_s(pBuf, rbs, L"Processor identifier: %s\n", buf);
}
RegCloseKey(hKey);
}
}
_OSVERSIONINFOEXW osVersionInfoEx;
ZeroMemory(&osVersionInfoEx, sizeof(_OSVERSIONINFOEXW));
osVersionInfoEx.dwOSVersionInfoSize = sizeof(_OSVERSIONINFOEXW);
if (GetVersionExW((_OSVERSIONINFOW*)&osVersionInfoEx))
{
pBuf += swprintf_s(pBuf, rbs,
L"dwMajorVersion: %ld; dwMinorVersion: %ld; dwBuildNumber: %ld; wServicePackMajor: %d; wServicePackMinor: %d\n",
osVersionInfoEx.dwMajorVersion, osVersionInfoEx.dwMinorVersion, osVersionInfoEx.dwBuildNumber, osVersionInfoEx.wServicePackMajor, osVersionInfoEx.wServicePackMinor);
}
MEMORYSTATUS ms;
GlobalMemoryStatus(&ms);
{
pBuf += swprintf_s(pBuf, rbs,
L"TotalPhys : %8luk, AvailPhys : %8luk, "
L"TotalPagefile : %8luk, AvailPageFile : %8luk, "
L"TotalVirtual : %8luk, AvailVirtual : %8luk\n",
ms.dwTotalPhys / 1024, ms.dwAvailPhys/ 1024,
ms.dwTotalPageFile/ 1024, ms.dwAvailPageFile/ 1024,
ms.dwTotalVirtual/ 1024, ms.dwAvailVirtual/ 1024);
}
PROCESS_MEMORY_COUNTERS_EX pmcex;
pmcex.cb = sizeof(pmcex);
if(GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmcex, sizeof(pmcex)))
{
pBuf += swprintf_s(pBuf, rbs, L" Process memory information ===\n");
pBuf += swprintf_s(pBuf, rbs, L"Page fault count : %12ld, \n", pmcex.PageFaultCount);
pBuf += swprintf_s(pBuf, rbs, L"PeakWorkingSetSize : %12ldk, WorkingSetSize : %12ldk\n", pmcex.PeakWorkingSetSize/1024, pmcex.WorkingSetSize/1024);
pBuf += swprintf_s(pBuf, rbs, L"QuotaPeakPagedPoolUsage : %12ldk, QuotaPagedPoolUsage : %12ldk\n", pmcex.QuotaPeakPagedPoolUsage/1024, pmcex.QuotaPagedPoolUsage/1024);
pBuf += swprintf_s(pBuf, rbs, L"QuotaPeakNonPagedPoolUsage : %12ldk, QuotaNonPagedPoolUsage : %12ldk\n", pmcex.QuotaPeakNonPagedPoolUsage/1024, pmcex.QuotaNonPagedPoolUsage/1024);
pBuf += swprintf_s(pBuf, rbs, L"PeakPagefileUsage : %12ldk, PagefileUsage : %12ldk\n", pmcex.PeakPagefileUsage/1024, pmcex.PagefileUsage/1024);
pBuf += swprintf_s(pBuf, rbs, L"PrivateUsage : %12ldk\n", pmcex.PrivateUsage/1024);
}
else
{
pBuf += swprintf_s(pBuf, rbs, L"Process memory information unavailable.\n");
}
pBuf += swprintf_s(pBuf, rbs, L"\n Graphic Information ===\n%s\n", graphicInfo);
pBuf += swprintf_s(pBuf, rbs, L"\n Additional Information ===\n%s\n", additionalInfo);
#undef rbs
}
static bool CreateMinidump(const char outputFileName[], _EXCEPTION_POINTERS* ExceptionInfo)
{
WriteSystemInformation(s_GraphicInformation, s_AdditionalInformation, s_SystemInformation, 4096);
MINIDUMP_EXCEPTION_INFORMATION* pExcInfo = NULL;
MINIDUMP_EXCEPTION_INFORMATION excInfo;
if(ExceptionInfo)
{
excInfo.ClientPointers = FALSE;
excInfo.ExceptionPointers = ExceptionInfo;
excInfo.ThreadId = GetCurrentThreadId();
pExcInfo = &excInfo;
}
MINIDUMP_USER_STREAM userStreams[2];
userStreams[0].Type = SystemInfoStream;
userStreams[0].BufferSize = sizeof(SYSTEM_INFO);
SYSTEM_INFO si;
GetSystemInfo(&si);
userStreams[0].Buffer = &si;
userStreams[1].Type = CommentStreamW;
userStreams[1].BufferSize = 4096;
userStreams[1].Buffer = s_SystemInformation;
MINIDUMP_USER_STREAM_INFORMATION userInfo;
userInfo.UserStreamCount = 2;
userInfo.UserStreamArray = userStreams;
HANDLE fileHandle = CreateFileA(outputFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(fileHandle == INVALID_HANDLE_VALUE)
return false;
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
fileHandle, s_miniDumpType, pExcInfo, &userInfo, NULL);
CloseHandle(fileHandle);
return true;
}
static void MakeDumpFileName(char dumpFileName[], void* address)
{
//실행 파일
char execPath[MAX_PATH];
GetModuleFileName(NULL, execPath, MAX_PATH);
char* p = strrchr(execPath, '\\');
// 컴퓨터 이름
char computerName[MAX_PATH];
DWORD len = MAX_PATH;
GetComputerName(computerName, &len);
//현재 시간
SYSTEMTIME lt;
GetLocalTime(<);
sprintf_s(dumpFileName, MAX_PATH, "%s %p @ %s (%d-%02d-%02d %02d;%02d;%02d).dmp",
p + 1, address,
computerName, lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute, lt.wSecond);
}
void CreateMiniDumpNow()
{
char outputFileName[MAX_PATH] = "minidump.dmp";
MakeDumpFileName(outputFileName, (void*)0x7FFFFFFF);
CreateMinidump(outputFileName, NULL);
}
static LONG WINAPI CrashHandlerExceptionFilter(_EXCEPTION_POINTERS* exceptionInfo)
{
char outputFileName[MAX_PATH];
strcpy(outputFileName, "minidump.dmp");
MakeDumpFileName(outputFileName, exceptionInfo->ExceptionRecord->ExceptionAddress);
CreateMinidump(outputFileName, exceptionInfo);
// 에러메시지창을 띄우고
MessageBox(NULL, "프로그램이 죽었습니다.\n\n개발팀에 문의해주세요.", "MapleStory2", MB_OK);
// 프로세스 종료
TerminateProcess(GetCurrentProcess(), 2);
return EXCEPTION_EXECUTE_HANDLER;
}
static void InvParamHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved)
{
_asm int 3;
}
static void PureVirtualFunctionCallHandler()
{
_asm int 3;
}
int _tmain(int argc, _TCHAR* argv[])
{
prevFilter = SetUnhandledExceptionFilter(CrashHandlerExceptionFilter);
prevInvParamHandler = _set_invalid_parameter_handler(&InvParamHandler);
prevPureCallHandler = _set_purecall_handler(&PureVirtualFunctionCallHandler);
int* x = 0;
*x = 100;
return 0;
}