在国外一个开源项目摘出来的一个异常抛出DMP 类

源代码地址

http://www.koders.com/cpp/fid0D70CAB44456E71247468C98A1D01A2F758153FE.aspx?s=md5

.h

 1 // FileZilla - a Windows ftp client
 2 
 3 // Copyright (C) 2004 - Tim Kosse <tim.kosse@gmx.de>
 4 
 5 // This program is free software; you can redistribute it and/or
 6 // modify it under the terms of the GNU General Public License
 7 // as published by the Free Software Foundation; either version 2
 8 // of the License, or (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 General Public License for more details.
14 
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 // OptionsTypePage.cpp: Implementierungsdatei
20 //
21 
22 #pragma once
23 
24 class CExceptionReport
25 {
26 public:
27     CExceptionReport();
28     ~CExceptionReport();
29 
30     static LONG WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo);
31 
32 private:
33     static void CreateReport(PEXCEPTION_POINTERS pExceptionInfo);
34 
35     static void StackWalk(CONTEXT Context);
36     static BOOL GetAddrDetails(PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD& offset);
37     static bool writeMiniDump(PEXCEPTION_POINTERS pExceptionInfo);
38     static LPTSTR GetExceptionString(DWORD dwCode);
39 
40     static int sendMail();
41     static void SuspendThreads();
42 
43     static void AddToReport(const WCHAR * pText);
44     static void AddToReport(const char * pText);
45     static void AddToReport(int number);
46     static void AddToReportHex(_int64 number, int minDigits = 0);
47 
48     static LPTOP_LEVEL_EXCEPTION_FILTER m_previousExceptionFilter;
49     static TCHAR m_pLogFileName[MAX_PATH];
50     static HANDLE m_hReportFile;
51     static TCHAR m_pDmpFileName[MAX_PATH];
52     static HANDLE m_hDumpFile;
53     
54     static BOOL m_bFirstRun;
55 };
56 
57 
58 extern CExceptionReport ExceptionReport; //global instance of class

http://www.koders.com/cpp/fidFDBB1BB2C131F08BC93D5A3E6C9F8C772340A919.aspx?s=md5

CPP

View Code
  1 // FileZilla - a Windows ftp client
  2 
  3 // Copyright (C) 2004 - Tim Kosse <tim.kosse@gmx.de>
  4 
  5 // This program is free software; you can redistribute it and/or
  6 // modify it under the terms of the GNU General Public License
  7 // as published by the Free Software Foundation; either version 2
  8 // of the License, or (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 General Public License for more details.
 14 
 15 // You should have received a copy of the GNU General Public License
 16 // along with this program; if not, write to the Free Software
 17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 18 
 19 // OptionsTypePage.cpp: Implementierungsdatei
 20 //
 21 
 22 #include "stdafx.h"
 23 #include <dbghelp.h>
 24 #include "ExceptionReport.h"
 25 #include "..\version.h"
 26 #include "ProcessorInfo.h"
 27 #include "WindowsVersion.h"
 28 #include "mailmsg.h"
 29 #include "Tlhelp32.h"
 30 
 31 typedef BOOL
 32 (_stdcall *tSymFromAddr)(
 33     IN  HANDLE            hProcess,
 34     IN  DWORD64            Address,
 35     OUT PDWORD64        Displacement,
 36     IN OUT PSYMBOL_INFO    Symbol
 37     );
 38 
 39 typedef DWORD
 40 (_stdcall *tSymGetOptions)(
 41     );
 42 
 43 typedef DWORD
 44 (_stdcall *tSymSetOptions)(
 45     IN DWORD   SymOptions
 46     );
 47 
 48 typedef BOOL
 49 (_stdcall *tSymCleanup)(
 50     IN HANDLE hProcess
 51     );
 52 
 53 typedef BOOL
 54 (_stdcall *tSymInitialize)(
 55     IN HANDLE    hProcess,
 56     IN PSTR        UserSearchPath,
 57     IN BOOL        fInvadeProcess
 58     );
 59 
 60 typedef BOOL
 61 (_stdcall *tSymGetLineFromAddr)(
 62     IN  HANDLE                hProcess,
 63     IN  DWORD                dwAddr,
 64     OUT PDWORD                pdwDisplacement,
 65     OUT PIMAGEHLP_LINE        Line
 66     );
 67 
 68 typedef BOOL
 69 (_stdcall *tStackWalk)(
 70     DWORD                            MachineType,
 71     HANDLE                            hProcess,
 72     HANDLE                            hThread,
 73     LPSTACKFRAME                    StackFrame,
 74     PVOID                            ContextRecord,
 75     PREAD_PROCESS_MEMORY_ROUTINE    ReadMemoryRoutine,
 76     PFUNCTION_TABLE_ACCESS_ROUTINE    FunctionTableAccessRoutine,
 77     PGET_MODULE_BASE_ROUTINE        GetModuleBaseRoutine,
 78     PTRANSLATE_ADDRESS_ROUTINE        TranslateAddress
 79     );
 80 
 81 typedef PVOID
 82 (_stdcall *tSymFunctionTableAccess)(
 83     HANDLE  hProcess,
 84     DWORD   AddrBase
 85     );
 86 
 87 typedef DWORD
 88 (_stdcall *tSymGetModuleBase)(
 89     IN  HANDLE              hProcess,
 90     IN  DWORD               dwAddr
 91     );
 92 
 93 typedef BOOL
 94 (_stdcall *tMiniDumpWriteDump)(
 95     HANDLE hProcess,
 96     DWORD ProcessId,
 97     HANDLE hFile,
 98     MINIDUMP_TYPE DumpType,
 99     PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
100     PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
101     PMINIDUMP_CALLBACK_INFORMATION CallbackParam
102     );
103 
104 static tSymCleanup                pSymCleanup;
105 static tSymInitialize            pSymInitialize;
106 static tSymGetOptions            pSymGetOptions;
107 static tSymSetOptions            pSymSetOptions;
108 static tSymGetLineFromAddr        pSymGetLineFromAddr;
109 static tSymFromAddr                pSymFromAddr;
110 static tStackWalk                pStackWalk;
111 static tSymFunctionTableAccess    pSymFunctionTableAccess;
112 static tSymGetModuleBase        pSymGetModuleBase;
113 static tMiniDumpWriteDump        pMiniDumpWriteDump;
114 
115 // Global class instance
116 // static CExceptionReport ExceptionReport;
117 
118 LPTOP_LEVEL_EXCEPTION_FILTER CExceptionReport::m_previousExceptionFilter;
119 TCHAR CExceptionReport::m_pLogFileName[MAX_PATH];
120 HANDLE CExceptionReport::m_hReportFile;
121 TCHAR CExceptionReport::m_pDmpFileName[MAX_PATH];
122 HANDLE CExceptionReport::m_hDumpFile;
123 BOOL CExceptionReport::m_bFirstRun;
124 
125 CExceptionReport::CExceptionReport()
126 {
127     m_bFirstRun = TRUE;
128 
129     m_previousExceptionFilter = SetUnhandledExceptionFilter(UnhandledExceptionFilter);
130 
131     // Retrieve report/dump filenames
132     GetModuleFileName(0, m_pLogFileName, MAX_PATH);
133 
134     // Look for the '.' before the "EXE" extension.  Replace the extension
135     // with "RPT"
136     LPTSTR p = _tcsrchr(m_pLogFileName, _T('.'));
137     if (p)
138     {
139         p++;
140         *p = 0;
141         _tcscpy(m_pDmpFileName, m_pLogFileName);
142         _tcscpy(p, _T("rpt"));
143         _tcscat(m_pDmpFileName, _T("dmp"));
144     }
145 }
146 
147 CExceptionReport::~CExceptionReport()
148 {
149     SetUnhandledExceptionFilter(m_previousExceptionFilter);
150 }
151 
152 LONG WINAPI CExceptionReport::UnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
153 {
154     if (!m_bFirstRun)
155     {
156         // Don't generate exception report twice
157         if (m_previousExceptionFilter)
158             return m_previousExceptionFilter(pExceptionInfo);
159         else
160             return EXCEPTION_CONTINUE_SEARCH;
161     }
162     else
163         m_bFirstRun = FALSE;
164 
165     // Suspend all threads to freeze the current state
166     SuspendThreads();
167     
168     HMODULE hDll = LoadLibrary(_T("dbghelp.dll"));
169     if (!hDll)
170     {
171         if (m_previousExceptionFilter)
172             return m_previousExceptionFilter(pExceptionInfo);
173         else
174             return EXCEPTION_CONTINUE_SEARCH;
175     }
176 
177     pSymCleanup                = (tSymCleanup)GetProcAddress(hDll, "SymCleanup");
178     pSymInitialize            = (tSymInitialize)GetProcAddress(hDll, "SymInitialize");
179     pSymGetOptions            = (tSymGetOptions)GetProcAddress(hDll, "SymGetOptions");
180     pSymSetOptions            = (tSymSetOptions)GetProcAddress(hDll, "SymSetOptions");
181     pSymGetLineFromAddr        = (tSymGetLineFromAddr)GetProcAddress(hDll, "SymGetLineFromAddr");
182     pSymFromAddr            = (tSymFromAddr)GetProcAddress(hDll, "SymFromAddr");
183     pStackWalk                = (tStackWalk)GetProcAddress(hDll, "StackWalk");
184     pSymFunctionTableAccess    = (tSymFunctionTableAccess)GetProcAddress(hDll, "SymFunctionTableAccess");
185     pSymGetModuleBase        = (tSymGetModuleBase)GetProcAddress(hDll, "SymGetModuleBase");
186     pMiniDumpWriteDump        = (tMiniDumpWriteDump)GetProcAddress(hDll, "MiniDumpWriteDump");
187 
188     if (!pSymCleanup            ||
189         !pSymInitialize            ||
190         !pSymGetOptions            ||
191         !pSymSetOptions            ||
192         !pSymGetLineFromAddr    ||
193         !pSymFromAddr            ||
194         !pStackWalk                ||
195         !pSymFunctionTableAccess||
196         !pSymGetModuleBase        ||
197         !pMiniDumpWriteDump)
198     {
199         FreeLibrary(hDll);
200         if (m_previousExceptionFilter)
201             return m_previousExceptionFilter(pExceptionInfo);
202         else
203             return EXCEPTION_CONTINUE_SEARCH;
204     }
205 
206     if (::MessageBox(NULL,
207 _T("An unhandled exception has occurred in FileZilla Server\r\n\
208 FileZilla Server has to be closed.\r\n\r\n\
209 Would you like to generate an exception report?\r\n\
210 The report contains all neccessary information about the exception,\r\n\
211 including a call stack with function parameters and local variables.\r\n\r\n\
212 If you're using the latest version of FileZilla Server, please send the generated exception record to the following mail address: Tim.Kosse@gmx.de\r\n\
213 The report will be analyzed and the reason for this exception will be fixed in the next version of FileZilla Server.\r\n\r\n\
214 Please note: It may be possible - though unlikely - that the exception report may contain personal and or confidential information. All exception reports will be processed higly confidential and solely to analyze the crash. The reports will be deleted immediately after processing.\r\n"),
215         _T("FileZilla Server - Unhandled exception"), MB_APPLMODAL | MB_YESNO | MB_ICONSTOP)==IDYES)
216     {
217         m_hReportFile = CreateFile(m_pLogFileName, GENERIC_WRITE,FILE_SHARE_READ,
218                                    0, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
219     
220         m_hDumpFile = CreateFile(m_pDmpFileName, GENERIC_WRITE, FILE_SHARE_READ,
221                                  0, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,    0);
222     
223         if (m_hReportFile == INVALID_HANDLE_VALUE)
224         {
225             TCHAR tmp[MAX_PATH];
226             _tcscpy(tmp, m_pLogFileName);
227             TCHAR *pos=_tcsrchr(tmp, '\\');
228             if (pos)
229             {
230                 pos++;
231                 _stprintf(m_pLogFileName, _T("c:\\%s"), pos);
232             }
233             else
234                 _stprintf(m_pLogFileName, _T("c:\\%s"), tmp);
235         
236             m_hReportFile = CreateFile(m_pLogFileName, GENERIC_WRITE,FILE_SHARE_READ,
237                                        0, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
238         }
239         if (m_hDumpFile == INVALID_HANDLE_VALUE)
240         {
241             TCHAR tmp[MAX_PATH];
242             _tcscpy(tmp, m_pDmpFileName);
243             TCHAR *pos=_tcsrchr(tmp, '\\');
244             if (pos)
245             {
246                 pos++;
247                 _stprintf(m_pDmpFileName, _T("c:\\%s"), pos);
248             }
249             else
250                 _stprintf(m_pDmpFileName, _T("c:\\%s"), tmp);
251         
252             m_hDumpFile = CreateFile(m_pDmpFileName, GENERIC_WRITE, FILE_SHARE_READ,
253                                      0, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,    0);
254         }
255 
256         int nError=0;
257         if (m_hReportFile == INVALID_HANDLE_VALUE && INVALID_HANDLE_VALUE)
258             nError = GetLastError();
259         else
260         {
261 #ifdef TRY
262             TRY
263 #endif
264             {
265                 if (m_hReportFile != INVALID_HANDLE_VALUE)
266                     CreateReport(pExceptionInfo);
267     
268                 CloseHandle(m_hReportFile);
269             }
270 #ifdef TRY
271             CATCH_ALL(e);
272             {
273                 nError = GetLastError();
274                 CloseHandle(m_hReportFile);
275             }
276             END_CATCH_ALL
277 
278             TRY
279 #endif
280             {
281                 if (m_hDumpFile != INVALID_HANDLE_VALUE)
282                     writeMiniDump(pExceptionInfo);
283 
284                 CloseHandle(m_hDumpFile);
285                 nError = 0;
286             }
287 #ifdef TRY
288             CATCH_ALL(e);
289             {
290                 CloseHandle(m_hDumpFile);
291             }
292             END_CATCH_ALL
293 #endif
294         }
295 
296         if (nError)
297         {
298         
299             TCHAR tmp[1000];
300             _stprintf(tmp, _T("Unable to create exception report, error code %d."), nError);
301             MessageBox(0, tmp, _T("FileZilla Server - Unhandled eception"), MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION);
302         }
303         else
304         {
305             sendMail();
306 
307             TCHAR tmp[1000];
308             _stprintf(tmp, _T("The exception report has been saved to \"%s\" and \"%s\".\n\
309 Please make sure that you are using the latest version of FileZilla Server.\n\
310 You can download the latest version from http://sourceforge.net/projects/filezilla/.\n\
311 If you do use the latest version, please send the exception report to Tim.Kosse@gmx.de along with a brief explanation what you did before FileZilla Server crashed."), m_pLogFileName, m_pDmpFileName);
312             MessageBox(0, tmp, _T("FileZilla Server - Unhandled eception"), MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION);
313 
314             FreeLibrary(hDll);
315             return EXCEPTION_CONTINUE_SEARCH;
316         }
317     }
318     FreeLibrary(hDll);
319     if (m_previousExceptionFilter)
320         return m_previousExceptionFilter(pExceptionInfo);
321     else
322         return EXCEPTION_CONTINUE_SEARCH;
323 
324 }
325 
326 void CExceptionReport::CreateReport(PEXCEPTION_POINTERS pExceptionInfo)
327 {
328     // Start out with a banner
329     AddToReport("Exception report created by ");
330     AddToReport(GetVersionString());
331     AddToReport("\r\n===================================================\r\n\r\n");
332     AddToReport("System details:\r\n");
333     AddToReport("---------------\r\n\r\nOperating System:      ");
334     
335     TCHAR buffer[200];
336     if (DisplaySystemVersion(buffer))
337     {
338         AddToReport(buffer);
339         AddToReport("\r\n");
340     }
341     else
342         AddToReport("Could not get OS version\r\n");
343     
344     CProcessorInfo pi;
345     CMemoryInfo mi;
346     AddToReport("Processor Information: ");
347     AddToReport(pi.GetProcessorName());
348     AddToReport("\r\nMemory Information:    ");
349     AddToReport(mi.GetMemoryInfo());
350     
351     PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
352 
353     // Print fault type
354     AddToReport("\r\nException Details:\r\n------------------\r\n\r\nException code: ");
355     AddToReportHex(pExceptionRecord->ExceptionCode, 8);
356     AddToReport(" ");
357     AddToReport(GetExceptionString(pExceptionRecord->ExceptionCode));
358     
359     // Add fault address and module
360     TCHAR szModule[MAX_PATH];
361     memset(szModule, 0, MAX_PATH);
362     DWORD dwSection, dwOffset;
363     GetAddrDetails(pExceptionRecord->ExceptionAddress,
364                       szModule,
365                       sizeof(szModule),
366                       dwSection, dwOffset);
367 
368     AddToReport("\r\nFault address:  ");
369     AddToReportHex((int)pExceptionRecord->ExceptionAddress, 8);
370     AddToReport(" ");
371     AddToReportHex(dwSection, 2);
372     AddToReport(":");
373     AddToReportHex(dwOffset, 8);
374     AddToReport(" ");
375     AddToReport(szModule);
376     AddToReport("\r\n");
377 
378     // Set up the symbol engine.
379     DWORD dwOptions = pSymGetOptions() ;
380 
381     // Turn on line loading and deferred loading.
382     pSymSetOptions(dwOptions | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);
383 
384     PCONTEXT pContext = pExceptionInfo->ContextRecord;
385 
386     // Initialize DbgHelp
387     if (!pSymInitialize(GetCurrentProcess(), 0, TRUE))
388         return;
389 
390     StackWalk(*pContext);
391 
392     pSymCleanup(GetCurrentProcess());
393 }
394 
395 LPTSTR CExceptionReport::GetExceptionString(DWORD dwCode)
396 {
397     #define EXCEPTION(x) case EXCEPTION_##x: return _T(#x);
398 
399     switch (dwCode)
400     {
401         EXCEPTION(ACCESS_VIOLATION)
402         EXCEPTION(DATATYPE_MISALIGNMENT)
403         EXCEPTION(BREAKPOINT)
404         EXCEPTION(SINGLE_STEP)
405         EXCEPTION(ARRAY_BOUNDS_EXCEEDED)
406         EXCEPTION(FLT_DENORMAL_OPERAND)
407         EXCEPTION(FLT_DIVIDE_BY_ZERO)
408         EXCEPTION(FLT_INEXACT_RESULT)
409         EXCEPTION(FLT_INVALID_OPERATION)
410         EXCEPTION(FLT_OVERFLOW)
411         EXCEPTION(FLT_STACK_CHECK)
412         EXCEPTION(FLT_UNDERFLOW)
413         EXCEPTION(INT_DIVIDE_BY_ZERO)
414         EXCEPTION(INT_OVERFLOW)
415         EXCEPTION(PRIV_INSTRUCTION)
416         EXCEPTION(IN_PAGE_ERROR)
417         EXCEPTION(ILLEGAL_INSTRUCTION)
418         EXCEPTION(NONCONTINUABLE_EXCEPTION)
419         EXCEPTION(STACK_OVERFLOW)
420         EXCEPTION(INVALID_DISPOSITION)
421         EXCEPTION(GUARD_PAGE)
422         EXCEPTION(INVALID_HANDLE)
423     }
424 
425     // Try to get descripbion of unknown exceptions
426     static TCHAR buffer[512] = {0};
427 
428     FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
429                   GetModuleHandle(_T("NTDLL.DLL")),
430                   dwCode, 0, buffer, sizeof(buffer), 0);
431 
432     return buffer;
433 }
434 
435 void CExceptionReport::StackWalk(CONTEXT Context)
436 {
437     USES_CONVERSION;
438     AddToReport("\r\nCall stack:\r\n-----------\r\n\r\n");
439     AddToReport("Address   Frame     Function            SourceFile\r\n");
440     
441     DWORD dwMachineType = 0;
442 
443     STACKFRAME sf;
444     memset(&sf, 0, sizeof(sf));
445 
446 #ifdef _M_IX86
447     // Initialize the STACKFRAME structure for the first call.  This is only
448     // necessary for Intel CPUs, and isn't mentioned in the documentation.
449     sf.AddrPC.Offset    = Context.Eip;
450     sf.AddrPC.Mode        = AddrModeFlat;
451     sf.AddrStack.Offset    = Context.Esp;
452     sf.AddrStack.Mode    = AddrModeFlat;
453     sf.AddrFrame.Offset    = Context.Ebp;
454     sf.AddrFrame.Mode    = AddrModeFlat;
455 
456     dwMachineType = IMAGE_FILE_MACHINE_I386;
457 #endif
458 
459     while (TRUE)
460     {
461         // Get next stack frame
462         if (!pStackWalk(dwMachineType, GetCurrentProcess(), GetCurrentThread(),
463                         &sf, &Context, 0, 
464                         pSymFunctionTableAccess, pSymGetModuleBase,    0))
465             break;
466 
467         if (!sf.AddrFrame.Offset)
468             break; //Invalid frame
469 
470         AddToReportHex(sf.AddrPC.Offset, 8);
471         AddToReport("  ");
472         AddToReportHex(sf.AddrFrame.Offset, 8);
473         AddToReport("  ");
474         
475         // Get function name for stack frame entry
476         BYTE symbolBuffer[ sizeof(SYMBOL_INFO) + 1024 ];
477         PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;
478         pSymbol->SizeOfStruct = sizeof(symbolBuffer);
479         pSymbol->MaxNameLen = 1024;
480                     
481         DWORD64 symDisplacement = 0;    // Displacement of the input address,
482                                         // relative to the start of the symbol
483 
484         if (pSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset, &symDisplacement, pSymbol))
485         {
486             AddToReport(pSymbol->Name);
487             AddToReport("+");
488             AddToReportHex(symDisplacement);
489         }
490         else    // No symbol found.  Print out the logical address instead.
491         {
492             TCHAR szModule[MAX_PATH] = _T("");
493             DWORD section = 0, offset = 0;
494 
495             GetAddrDetails((PVOID)sf.AddrPC.Offset,
496                                 szModule, sizeof(szModule), section, offset);
497 
498             AddToReportHex(section, 4);
499             AddToReport(":");
500             AddToReportHex(offset, 8);
501             AddToReport(" ");
502             AddToReport(szModule);
503         }
504 
505         // Get the source line for this stack frame entry
506         IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) };
507         DWORD dwLineDisplacement;
508         if (pSymGetLineFromAddr(GetCurrentProcess(), sf.AddrPC.Offset,
509                                 &dwLineDisplacement, &lineInfo))
510         {
511             AddToReport("  ");
512             AddToReport(lineInfo.FileName);
513             AddToReport(" line ");
514             AddToReport(lineInfo.LineNumber);
515         }
516 
517         AddToReport("\r\n");
518     }
519 
520 }
521 
522 bool CExceptionReport::writeMiniDump(PEXCEPTION_POINTERS pExceptionInfo)
523 {
524     // Write the minidump to the file
525     MINIDUMP_EXCEPTION_INFORMATION eInfo;
526     eInfo.ThreadId = GetCurrentThreadId();
527     eInfo.ExceptionPointers = pExceptionInfo;
528     eInfo.ClientPointers = FALSE;
529 
530     MINIDUMP_CALLBACK_INFORMATION cbMiniDump;
531     cbMiniDump.CallbackRoutine = 0;
532     cbMiniDump.CallbackParam = 0;
533 
534 
535     pMiniDumpWriteDump(
536         GetCurrentProcess(),
537         GetCurrentProcessId(),
538         m_hDumpFile,
539         MiniDumpNormal,
540         pExceptionInfo ? &eInfo : NULL,
541         NULL,
542         &cbMiniDump);
543 
544     // Close file
545     CloseHandle(m_hDumpFile);
546 
547     return true;
548 }
549 
550 int CExceptionReport::sendMail()
551 {
552     CMailMsg mail;
553 
554     mail.SetTo(_T("tim.kosse@gmx.de"), _T("Tim Kosse"));
555 
556     TCHAR str[4096];
557     _stprintf(str, _T("Exception report created by %s\r\n\r\n"), (LPCTSTR)GetVersionString());
558     mail.SetSubject(str);
559 
560     mail.SetMessage(_T("Enter your comments here, what did you do with FileZilla Server before it crashed?"));
561 
562     mail.AddAttachment(m_pLogFileName, _T("FileZillaServer.rpt"));
563     mail.AddAttachment(m_pDmpFileName, _T("FileZillaServer.dmp"));
564 
565     return mail.Send();
566 }
567 
568 void CExceptionReport::SuspendThreads()
569 {
570     // Try to get OpenThread and Thread32* function from kernel32.dll, since it's not available on Win95/98
571     typedef HANDLE (WINAPI *tOpenThread)    (DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId);
572     typedef BOOL (WINAPI *tThread32First)    (HANDLE hSnapshot, LPTHREADENTRY32 lpte);
573     typedef BOOL (WINAPI *tThread32Next)    (HANDLE hSnapshot, LPTHREADENTRY32 lpte);
574     typedef HANDLE (WINAPI *tCreateToolhelp32Snapshot)    (DWORD dwFlags, DWORD th32ProcessID);
575 
576     HMODULE hKernel32Dll = LoadLibrary(_T("kernel32.dll"));
577     if (!hKernel32Dll)
578         return;
579     tOpenThread        pOpenThread        = (tOpenThread)        GetProcAddress(hKernel32Dll, "OpenThread");
580     tThread32First    pThread32First    = (tThread32First)    GetProcAddress(hKernel32Dll, "Thread32First");
581     tThread32Next    pThread32Next    = (tThread32Next)    GetProcAddress(hKernel32Dll, "Thread32Next");
582     tCreateToolhelp32Snapshot pCreateToolhelp32Snapshot    = (tCreateToolhelp32Snapshot)    GetProcAddress(hKernel32Dll, "CreateToolhelp32Snapshot");
583     if (!pOpenThread    ||
584         !pThread32First    ||
585         !pThread32Next    ||
586         !pCreateToolhelp32Snapshot)
587     {
588         CloseHandle(hKernel32Dll);
589         return;
590     }
591 
592     HANDLE hSnapshot = pCreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
593 
594     // Get information about own process/thread
595     DWORD ownProcessId = GetCurrentProcessId();
596     DWORD ownThreadId = GetCurrentThreadId();
597 
598     // Enumerate threads
599     THREADENTRY32 entry;
600     entry.dwSize = sizeof(THREADENTRY32);
601     BOOL bNext = pThread32First(hSnapshot, &entry);
602     while (bNext)
603     {
604         if (entry.th32OwnerProcessID == ownProcessId &&
605             entry.th32ThreadID != ownThreadId)
606         {
607             // Suspen threads of own process
608             HANDLE hThread = pOpenThread(THREAD_SUSPEND_RESUME, FALSE, entry.th32ThreadID);
609             if (hThread)
610                 SuspendThread(hThread);
611         }
612         bNext = pThread32Next(hSnapshot, &entry);
613     }
614     CloseHandle(hKernel32Dll);
615 }
616 
617 void CExceptionReport::AddToReport(const char * pText)
618 {
619     DWORD bytesWritten = 0;
620     WriteFile(m_hReportFile, pText, strlen(pText), &bytesWritten, 0);
621 }
622 
623 void CExceptionReport::AddToReport(const WCHAR * pText)
624 {
625     USES_CONVERSION;
626     AddToReport(W2A(pText));
627 }
628 
629 void CExceptionReport::AddToReport(int number)
630 {
631     char buffer[sizeof(int) * 4];
632     sprintf(buffer, "%d", number);
633     AddToReport(buffer);
634 }
635 
636 void CExceptionReport::AddToReportHex(_int64 number, int minDigits /*=0*/)
637 {
638     char buffer[sizeof(_int64) * 2 + 1];
639     if (!minDigits)
640         sprintf(buffer, "%I64X", number);
641     else
642     {
643         char fmt[10];
644         sprintf(fmt, "%%0%dI64X", minDigits);
645         sprintf(buffer, fmt, number);
646     }
647     AddToReport(buffer);
648 }
649 
650 BOOL CExceptionReport::GetAddrDetails(PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD& offset)
651 {
652     // Get details about an address: Module name, section and offet
653     
654     // Get information about the provided address
655     MEMORY_BASIC_INFORMATION mbi;
656     if (!VirtualQuery(addr, &mbi, sizeof(mbi)))
657         return FALSE;
658 
659     // Get module
660     DWORD hMod = (DWORD)mbi.AllocationBase;
661     if (!GetModuleFileName((HMODULE)hMod, szModule, len))
662         return FALSE;
663 
664     
665     // Get DOS header of module
666     PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hMod;
667 
668     // Advance to PE header and get the section information
669     PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(hMod + pDosHeader->e_lfanew);
670     PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHeader);
671 
672     // Get module load address
673     DWORD lAddr = (DWORD)addr - hMod; 
674 
675     // Search for a section which contains the address
676     for (unsigned int i = 0; i < pNtHeader->FileHeader.NumberOfSections; i++)
677     {
678         // Calculate section start and end addresses
679         DWORD startAddr = pSection->VirtualAddress;
680         DWORD endAddr = startAddr;
681         if (pSection->SizeOfRawData > pSection->Misc.VirtualSize)
682             endAddr += pSection->SizeOfRawData;
683         else
684             pSection->Misc.VirtualSize;
685 
686         // Look if provided address is between startAddr and endAddr
687         if (lAddr >= startAddr && lAddr <= endAddr)
688         {
689             // We've found the section, set section index and offset
690             section = i+1;
691             offset = lAddr - startAddr;
692             return TRUE;
693         }
694         pSection++;
695     }
696 
697     // Section not found, very strange
698     return FALSE;
699 }
原文地址:https://www.cnblogs.com/FCoding/p/2579683.html