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

源代码地址

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

.h

 1 // FileZilla - a Windows ftp client

 2 

 3 // Copyright (C) 2004 - Tim Kosse <[email protected]>

 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 <[email protected]>

  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: [email protected]\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 [email protected] 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("[email protected]"), _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 }

你可能感兴趣的:(开源项目)