-
Notifications
You must be signed in to change notification settings - Fork 37
/
Copy pathCrashReporter.c
121 lines (107 loc) · 5.06 KB
/
CrashReporter.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
* MIT License
*
* Copyright (c) 2018 Wudi <[email protected]>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <Windows.h>
#include <DbgHelp.h>
#include "Common.h"
typedef BOOL(WINAPI *MiniDumpWriteDumpFunc)(
HANDLE hProcess,
DWORD ProcessId,
HANDLE hFile,
MINIDUMP_TYPE DumpType,
const MINIDUMP_EXCEPTION_INFORMATION *ExceptionInfo,
const MINIDUMP_USER_STREAM_INFORMATION *UserStreamInfo,
const MINIDUMP_CALLBACK_INFORMATION *Callback
);
static LPTOP_LEVEL_EXCEPTION_FILTER _lastExceptionFilter = NULL;
static LONG WINAPI _unhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtr) {
int rc = MessageBox(NULL, _T("An unexpected error occurred.\n\nDo you want to save the debug information?"),
_T("Application Crashed"), MB_YESNO);
if (rc != IDYES) {
return EXCEPTION_CONTINUE_SEARCH;
}
// We load DbgHelp.dll dynamically, to support Windows 2000
HMODULE hModule = LoadLibrary(_T("DbgHelp.dll"));
if (hModule) {
MiniDumpWriteDumpFunc miniDumpWriteDump = (MiniDumpWriteDumpFunc)GetProcAddress(hModule, "MiniDumpWriteDump");
if (miniDumpWriteDump) {
// fetch system time for dump-file name
SYSTEMTIME systemTime = { 0 };
GetLocalTime(&systemTime);
// choose proper path for dump-file
TCHAR dumpFilePath[MAX_PATH] = { 0 };
_sntprintf(dumpFilePath, MAX_PATH, _T("SpleeterMsvcExe_crash_%04d%02d%02d_%02d%02d%02d.dmp"),
systemTime.wYear, systemTime.wMonth, systemTime.wDay,
systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
_tprintf(_T("\ndumpFilePath = %s\n"), dumpFilePath);
fflush(stdout);
// create and open the dump-file
HANDLE hFile = CreateFile(dumpFilePath, GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_HIDDEN,
NULL
);
if (hFile != INVALID_HANDLE_VALUE) {
MINIDUMP_EXCEPTION_INFORMATION exceptionInfo = { 0 };
exceptionInfo.ThreadId = GetCurrentThreadId();
exceptionInfo.ExceptionPointers = exceptionPtr;
exceptionInfo.ClientPointers = FALSE;
// at last write crash-dump to file
bool succeeded = miniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile,
MiniDumpNormal, &exceptionInfo, NULL, NULL);
// dump-data is written, and we can close the file
CloseHandle(hFile);
if (succeeded) {
TCHAR buf[MAX_PATH + 100] = { 0 };
_sntprintf(buf, (MAX_PATH + 100), _T("The debug information has been successfully saved to file %s"), dumpFilePath);
MessageBox(NULL, buf, _T("Application Crashed"), MB_OK);
// Return from UnhandledExceptionFilter and execute the associated exception handler.
// This usually results in process termination.
return EXCEPTION_EXECUTE_HANDLER;
}
}
}
}
// Proceed with normal execution of UnhandledExceptionFilter.
// That means obeying the SetErrorMode flags,
// or invoking the Application Error pop-up message box.
return EXCEPTION_CONTINUE_SEARCH;
}
void CrashReporter_register(void) {
if (_lastExceptionFilter != NULL) {
MSG_DEBUG(_T("CrashReporter is already registered\n"));
}
SetErrorMode(SEM_FAILCRITICALERRORS);
_lastExceptionFilter = SetUnhandledExceptionFilter(_unhandledExceptionFilter);
}
void CrashReporter_unregister(void) {
SetUnhandledExceptionFilter(_lastExceptionFilter);
}