Sync DrDump crash handler with TortoiseSVN codebase
[TortoiseGit.git] / ext / CrashServer / CrashHandler / SendRpt / DumpWriter.cpp
blob851cb363d4fe7c6847aa03b49a7c1aeee4ef094a
1 // Copyright 2014 Idol Software, Inc.
2 //
3 // This file is part of Doctor Dump SDK.
4 //
5 // Doctor Dump SDK is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "stdafx.h"
19 #include "resource.h"
20 #include "DumpWriter.h"
21 #include <map>
22 #include "utils.h"
24 using namespace std;
26 DumpWriter::DumpWriter(Log& log)
27 : m_log(log)
28 , m_hDbgHelp(NULL)
29 , m_pfnMiniDumpWriteDump(NULL)
33 DumpWriter::~DumpWriter()
35 m_pfnMiniDumpWriteDump = NULL;
36 if (m_hDbgHelp)
38 FreeLibrary(m_hDbgHelp);
39 m_hDbgHelp = NULL;
43 void DumpWriter::Init(LPCWSTR dbgHelpPath)
45 if (dbgHelpPath)
46 m_dbgHelpPath = dbgHelpPath;
47 m_hDbgHelp = LoadLibraryW(m_dbgHelpPath);
48 if (!m_hDbgHelp)
50 m_hDbgHelp = LoadLibrary(_T("dbghelp.dll"));
51 if (!m_hDbgHelp)
52 throw runtime_error("failed to load dbghelp.dll");
55 #define GetProc(func)\
56 m_pfn##func = (fn##func) GetProcAddress(m_hDbgHelp, #func);\
57 if (!m_pfn##func)\
58 throw runtime_error("failed to get " #func);
60 GetProc(MiniDumpWriteDump);
61 #undef GetProc
64 bool DumpWriter::WriteMiniDump(
65 HANDLE hProcess,
66 DWORD dwProcessId,
67 MINIDUMP_EXCEPTION_INFORMATION* pExceptInfo,
68 LPCTSTR pszFileName,
69 MINIDUMP_TYPE DumpType,
70 MINIDUMP_CALLBACK_INFORMATION* pCallback)
72 if (!m_pfnMiniDumpWriteDump)
73 return false;
75 HANDLE hFile = CreateFile(pszFileName,
76 GENERIC_WRITE,
78 NULL,
79 CREATE_ALWAYS,
80 FILE_ATTRIBUTE_NORMAL,
81 NULL);
83 if (hFile == INVALID_HANDLE_VALUE)
84 return false;
86 bool result = m_pfnMiniDumpWriteDump(hProcess, dwProcessId,
87 hFile, DumpType, pExceptInfo, NULL, pCallback) != FALSE;
89 DWORD err = GetLastError();
91 if (result)
93 DWORD dwFileSize = GetFileSize(hFile, NULL);
94 result = dwFileSize != INVALID_FILE_SIZE && dwFileSize > 1024;
95 if (!result)
96 err = ERROR_INVALID_DATA;
98 else
100 m_log.Error(_T("MiniDumpWriteDump failed, 0x%08x"), err);
103 CloseHandle(hFile);
105 SetLastError(err);
107 return result;
110 DumpFilter::DumpFilter(bool& cancel, DWORD saveOnlyThisThreadID)
111 : m_saveOnlyThisThreadID(saveOnlyThisThreadID), m_cancel(cancel)
113 m_callback.CallbackRoutine = _MinidumpCallback;
114 m_callback.CallbackParam = this;
117 BOOL DumpFilter::MinidumpCallback(const PMINIDUMP_CALLBACK_INPUT CallbackInput, PMINIDUMP_CALLBACK_OUTPUT CallbackOutput)
119 if (!CallbackInput)
120 return TRUE;
122 switch (CallbackInput->CallbackType)
124 case CancelCallback:
125 CallbackOutput->CheckCancel = TRUE;
126 if (m_cancel)
127 CallbackOutput->Cancel = TRUE;
128 break;
129 case IncludeThreadCallback:
130 if (m_saveOnlyThisThreadID != 0 && CallbackInput->IncludeThread.ThreadId != m_saveOnlyThisThreadID)
132 CallbackOutput->ThreadWriteFlags = 0;
133 return FALSE;
135 break;
136 case ThreadCallback:
137 if (m_saveOnlyThisThreadID != 0 && CallbackInput->Thread.ThreadId != m_saveOnlyThisThreadID)
138 CallbackOutput->ThreadWriteFlags = 0;
139 break;
142 return TRUE;
145 BOOL CALLBACK DumpFilter::_MinidumpCallback(PVOID CallbackParam, const PMINIDUMP_CALLBACK_INPUT CallbackInput, PMINIDUMP_CALLBACK_OUTPUT CallbackOutput)
147 return static_cast<DumpFilter*>(CallbackParam)->MinidumpCallback(CallbackInput, CallbackOutput);