DoctorDumpSDK
CrashRpt.h
Go to the documentation of this file.
1 // Copyright (c) 2014, Idol Software, Inc.
2 // All rights reserved.
3 //
4 // This file is part of Doctor Dump SDK.
5 //
6 // Redistribution and use in source and binary forms without modification, are permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9 //
10 // 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the distribution.
12 //
13 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
14 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
15 // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
16 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
17 // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
18 // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19 //
20 // Project web site http://drdump.com
21 
22 #ifndef __CRASH_RPT_H__
23 #define __CRASH_RPT_H__
24 
25 #include <windows.h>
26 
29 #if !(defined CRASHRPT_ENABLE_RELEASE_ASSERTS)
30 # define CRASHRPT_ENABLE_RELEASE_ASSERTS 1
42 # undef CRASHRPT_ENABLE_RELEASE_ASSERTS // this is to make doxygen document CRASHRPT_ENABLE_RELEASE_ASSERTS macro
43 #elif CRASHRPT_ENABLE_RELEASE_ASSERTS == 1
44 # include <assert.h>
45 # ifndef _DEBUG
46 # undef assert
47 # define assert(expr) ((void) (!(expr) && (crash_rpt::SkipDoctorDump_ReportAssertionViolation<__COUNTER__>(__FUNCTION__ ": "#expr " is false" ), true)))
48 # endif // !_DEBUG
49 #endif // CRASHRPT_ENABLE_RELEASE_ASSERTS
50 
51 namespace crash_rpt {
52 
53 namespace {
54 
55  // This template should be in anonymous namespace since __COUNTER__ is unique only for a single translation unit (as anonymous namespace items)
56  template<unsigned uniqueAssertId>
57  __forceinline static void SkipDoctorDump_ReportAssertionViolation(LPCSTR dumpGroup)
58  {
59  static LONG volatile isAlreadyReported = FALSE;
60  if (TRUE == InterlockedCompareExchange(&isAlreadyReported, TRUE, FALSE))
61  return;
62  ::RaiseException(CrashRpt::ExceptionAssertionViolated, 0, 1, reinterpret_cast<ULONG_PTR*>(&dumpGroup));
63  }
64 
65 } // namespace {
66 
69 {
71  LPCSTR ApplicationGUID;
72  LPCSTR Prefix;
73  LPCWSTR AppName;
74  LPCWSTR Company;
75  USHORT V[4];
76  USHORT Hotfix;
77  LPCWSTR PrivacyPolicyUrl;
78 };
79 
84 {
88  BOOL UseWER;
89  DWORD SubmitterID;
92  DWORD FullDumpType;
93  LPCWSTR LangFilePath;
94  LPCWSTR SendRptPath;
95  LPCWSTR DbgHelpPath;
96 };
98 
103 class CrashRpt
104 {
105 public:
108 
112  LPCSTR applicationGUID,
113  LPCWSTR appName,
114  LPCWSTR company
115  ) throw()
116  {
117  if (!LoadDll())
118  return;
119 
120  InitCrashRpt(applicationGUID, NULL, appName, company, TRUE);
121  }
122 
126  LPCSTR applicationGUID,
127  LPCSTR prefix,
128  LPCWSTR appName,
129  LPCWSTR company,
130  BOOL ownProcess = TRUE
131  ) throw()
134  {
135  if (!LoadDll())
136  return;
137 
138  InitCrashRpt(applicationGUID, prefix, appName, company, ownProcess);
139  }
140 
144  LPCWSTR crashrptPath,
145  LPCSTR applicationGUID,
146  LPCSTR prefix,
147  LPCWSTR appName,
148  LPCWSTR company,
149  BOOL ownProcess = TRUE
150  ) throw()
153  {
154  if (!LoadDll(crashrptPath))
155  return;
156 
157  InitCrashRpt(applicationGUID, prefix, appName, company, ownProcess);
158  }
159 
163  ApplicationInfo* applicationInfo,
164  HandlerSettings* handlerSettings,
165  BOOL ownProcess = TRUE
166  ) throw()
169  {
170  if (!LoadDll())
171  return;
172 
173  InitCrashRpt(applicationInfo, handlerSettings, ownProcess);
174  }
175 
179  LPCWSTR crashrptPath,
180  ApplicationInfo* applicationInfo,
181  HandlerSettings* handlerSettings,
182  BOOL ownProcess = TRUE
183  ) throw()
186  {
187  if (!LoadDll(crashrptPath))
188  return;
189 
190  InitCrashRpt(applicationInfo, handlerSettings, ownProcess);
191  }
192 
193 
197  LPCWSTR crashrptPath = NULL
198  ) throw()
199  {
200  LoadDll(crashrptPath);
201  }
202 
207  {
208  if (!m_IsReadyToExit)
209  return;
210 
211  // If crash has happen not in main thread we should wait here until report will be sent
212  // or else program will be terminated after return from main() and report sending will be halted.
213  while (!m_IsReadyToExit())
214  ::Sleep(100);
215 
216 #if _WIN32_WINNT >= 0x0501 /*_WIN32_WINNT_WINXP*/
217  if (m_bSkipAssertsAdded)
218  RemoveVectoredExceptionHandler(SkipAsserts);
219 #endif
220  }
221 
225  {
226  return m_bWorking;
227  }
228 
233  ApplicationInfo* applicationInfo,
234  HandlerSettings* handlerSettings,
235  BOOL ownProcess = TRUE
236  ) throw()
239  {
240  if (!m_InitCrashRpt)
241  return false;
242 
243  m_bWorking = m_InitCrashRpt(applicationInfo, handlerSettings, ownProcess) != FALSE;
244 
245  return m_bWorking;
246  }
247 
251  __declspec(deprecated)
253  ApplicationInfo* applicationInfo,
254  HandlerSettings* handlerSettings,
255  BOOL ownProcess = TRUE
256  ) throw()
259  {
260  return InitCrashRpt(applicationInfo, handlerSettings, ownProcess);
261  }
262 
263 
268  LPCSTR applicationGUID,
269  LPCSTR prefix,
270  LPCWSTR appName,
271  LPCWSTR company,
272  BOOL ownProcess = TRUE
273  ) throw()
276  {
277  if (!m_GetVersionFromApp)
278  return false;
279 
280  ApplicationInfo appInfo;
281  memset(&appInfo, 0, sizeof(appInfo));
282  appInfo.ApplicationInfoSize = sizeof(appInfo);
283  appInfo.ApplicationGUID = applicationGUID;
284  appInfo.Prefix = prefix;
285  appInfo.AppName = appName;
286  appInfo.Company = company;
287  if (!m_GetVersionFromApp(&appInfo))
288  appInfo.V[0] = 1;
289 
290  HandlerSettings handlerSettings;
291  memset(&handlerSettings, 0, sizeof(handlerSettings));
292  handlerSettings.HandlerSettingsSize = sizeof(handlerSettings);
293  handlerSettings.OpenProblemInBrowser = TRUE;
294 
295  return InitCrashRpt(&appInfo, &handlerSettings, ownProcess);
296  }
297 
304  LPCWSTR text
305  )
306  {
307  if (!m_SetCustomInfo)
308  return false;
309  m_SetCustomInfo(text);
310  return true;
311  }
312 
317  LPCWSTR key,
318  LPCWSTR value
319  ) throw()
320  {
321  if (!m_AddUserInfoToReport)
322  return false;
323  m_AddUserInfoToReport(key, value);
324  return true;
325  }
326 
331  LPCWSTR key
332  )
333  {
334  if (!m_RemoveUserInfoFromReport)
335  return false;
336  m_RemoveUserInfoFromReport(key);
337  return true;
338  }
339 
345  LPCWSTR path,
346  LPCWSTR reportFileName /* = NULL */
347  ) throw()
348  {
349  if (!m_AddFileToReport)
350  return false;
351  m_AddFileToReport(path, reportFileName);
352  return true;
353  }
354 
359  LPCWSTR path
360  ) throw()
361  {
362  if (!m_RemoveFileFromReport)
363  return false;
364  m_RemoveFileFromReport(path);
365  return true;
366  }
367 
372  ApplicationInfo* appInfo
373  ) throw()
374  {
375  if (!m_GetVersionFromApp)
376  return false;
377  return m_GetVersionFromApp(appInfo) != FALSE;
378  }
379 
383  LPCWSTR path,
384  ApplicationInfo* appInfo
385  ) throw()
386  {
387  if (!m_GetVersionFromFile)
388  return false;
389  return m_GetVersionFromFile(path, appInfo) != FALSE;
390  }
391 
411  EXCEPTION_POINTERS* exceptionPointers
412  )
414  {
415  if (!m_SendReport)
416  return EXCEPTION_CONTINUE_SEARCH;
417  // There is no crash handler but asserts should continue anyway
418  if (exceptionPointers->ExceptionRecord->ExceptionCode == ExceptionAssertionViolated)
419  return EXCEPTION_CONTINUE_EXECUTION;
420  return m_SendReport(exceptionPointers);
421  }
422 
431  static const DWORD ExceptionAssertionViolated = ((DWORD)0xCCE17000);
432 
438  LPCSTR dumpGroup = NULL
439  ) const
440  {
441  if (!m_bWorking)
442  return;
443  if (dumpGroup)
444  ::RaiseException(CrashRpt::ExceptionAssertionViolated, 0, 1, reinterpret_cast<ULONG_PTR*>(&dumpGroup));
445  else
446  ::RaiseException(CrashRpt::ExceptionAssertionViolated, 0, 0, NULL);
447  }
448 
449 private:
450  bool LoadDll(LPCWSTR crashrptPath = NULL) throw()
451  {
452  m_bLoaded = false;
453  m_bWorking = false;
454  m_bSkipAssertsAdded = false;
455  m_InitCrashRpt = NULL;
456  m_SendReport = NULL;
457  m_IsReadyToExit = NULL;
458  m_SetCustomInfo = NULL;
459  m_AddUserInfoToReport = NULL;
460  m_RemoveUserInfoFromReport = NULL;
461  m_AddFileToReport = NULL;
462  m_RemoveFileFromReport = NULL;
463  m_GetVersionFromApp = NULL;
464  m_GetVersionFromFile = NULL;
465 
466  // hCrashrptDll should not be unloaded, crash may appear even after return from main().
467  // So hCrashrptDll is not saved after construction.
468  HMODULE hCrashrptDll = ::LoadLibraryW(crashrptPath ? crashrptPath : L"crashrpt.dll");
469  if (hCrashrptDll != NULL)
470  {
471  m_InitCrashRpt = (pfnInitCrashRpt) GetProcAddress(hCrashrptDll, "InitCrashRpt");
472  m_SendReport = (pfnSendReport) GetProcAddress(hCrashrptDll, "SendReport");
473  m_IsReadyToExit = (pfnIsReadyToExit) GetProcAddress(hCrashrptDll, "IsReadyToExit");
474  m_SetCustomInfo = (pfnSetCustomInfo) GetProcAddress(hCrashrptDll, "SetCustomInfo");
475  m_AddUserInfoToReport = (pfnAddUserInfoToReport) GetProcAddress(hCrashrptDll, "AddUserInfoToReport");
476  m_RemoveUserInfoFromReport = (pfnRemoveUserInfoFromReport) GetProcAddress(hCrashrptDll, "RemoveUserInfoFromReport");
477  m_AddFileToReport = (pfnAddFileToReport) GetProcAddress(hCrashrptDll, "AddFileToReport");
478  m_RemoveFileFromReport = (pfnRemoveFileFromReport) GetProcAddress(hCrashrptDll, "RemoveFileFromReport");
479  m_GetVersionFromApp = (pfnGetVersionFromApp) GetProcAddress(hCrashrptDll, "GetVersionFromApp");
480  m_GetVersionFromFile = (pfnGetVersionFromFile) GetProcAddress(hCrashrptDll, "GetVersionFromFile");
481 
482  m_bLoaded = m_InitCrashRpt
483  && m_SendReport
484  && m_IsReadyToExit
485  && m_SetCustomInfo
486  && m_AddUserInfoToReport
487  && m_RemoveUserInfoFromReport
488  && m_AddFileToReport
489  && m_RemoveFileFromReport
490  && m_GetVersionFromApp
491  && m_GetVersionFromFile;
492  }
493 
494 #if _WIN32_WINNT >= 0x0501 /*_WIN32_WINNT_WINXP*/
495  // if no crash processing was started, we need to ignore ExceptionAssertionViolated exceptions.
496  if (!m_bLoaded)
497  {
498  ::AddVectoredExceptionHandler(TRUE, SkipAsserts);
499  m_bSkipAssertsAdded = true;
500  }
501 #endif
502 
503  return m_bLoaded;
504  }
505 
506  static LONG CALLBACK SkipAsserts(EXCEPTION_POINTERS* pExceptionInfo)
507  {
508  if (pExceptionInfo->ExceptionRecord->ExceptionCode == ExceptionAssertionViolated)
509  return EXCEPTION_CONTINUE_EXECUTION;
510  return EXCEPTION_CONTINUE_SEARCH;
511  }
512 
513  bool m_bLoaded;
514  bool m_bWorking;
515  bool m_bSkipAssertsAdded;
516 
517  typedef BOOL (*pfnInitCrashRpt)(ApplicationInfo* applicationInfo, HandlerSettings* handlerSettings, BOOL ownProcess);
518  typedef LONG (*pfnSendReport)(EXCEPTION_POINTERS* exceptionPointers);
519  typedef BOOL (*pfnIsReadyToExit)();
520  typedef void (*pfnSetCustomInfo)(LPCWSTR text);
521  typedef void (*pfnAddUserInfoToReport)(LPCWSTR key, LPCWSTR value);
522  typedef void (*pfnRemoveUserInfoFromReport)(LPCWSTR key);
523  typedef void (*pfnAddFileToReport)(LPCWSTR path, LPCWSTR reportFileName /* = NULL */);
524  typedef void (*pfnRemoveFileFromReport)(LPCWSTR path);
525  typedef BOOL (*pfnGetVersionFromApp)(ApplicationInfo* appInfo);
526  typedef BOOL (*pfnGetVersionFromFile)(LPCWSTR path, ApplicationInfo* appInfo);
527 
528  pfnInitCrashRpt m_InitCrashRpt;
529  pfnSendReport m_SendReport;
530  pfnIsReadyToExit m_IsReadyToExit;
531  pfnSetCustomInfo m_SetCustomInfo;
532  pfnAddUserInfoToReport m_AddUserInfoToReport;
533  pfnRemoveUserInfoFromReport m_RemoveUserInfoFromReport;
534  pfnAddFileToReport m_AddFileToReport;
535  pfnRemoveFileFromReport m_RemoveFileFromReport;
536  pfnGetVersionFromApp m_GetVersionFromApp;
537  pfnGetVersionFromFile m_GetVersionFromFile;
538 };
539 
540 } // namespace crash_rpt
541 
542 __declspec(deprecated) typedef crash_rpt::CrashRpt CrashHandler;
543 __declspec(deprecated) typedef crash_rpt::ApplicationInfo ApplicationInfo;
544 __declspec(deprecated) typedef crash_rpt::HandlerSettings HandlerSettings;
545 
546 #endif // __CRASH_RPT_H__
static const DWORD ExceptionAssertionViolated
Definition: CrashRpt.h:431
BOOL OpenProblemInBrowser
To open Web-page belonging to the uploaded report after it was uploaded set this member to TRUE...
Definition: CrashRpt.h:87
bool AddFileToReport(LPCWSTR path, LPCWSTR reportFileName)
Definition: CrashRpt.h:344
void SkipDoctorDump_SendAssertionViolated(LPCSTR dumpGroup=NULL) const
Definition: CrashRpt.h:437
bool SetCustomInfo(LPCWSTR text)
Definition: CrashRpt.h:303
bool AddUserInfoToReport(LPCWSTR key, LPCWSTR value)
Definition: CrashRpt.h:316
LPCSTR ApplicationGUID
GUID assigned to this application in form 00000000-0000-0000-0000-000000000000.
Definition: CrashRpt.h:71
LPCWSTR PrivacyPolicyUrl
URL to privacy policy. If NULL default privacy policy is used.
Definition: CrashRpt.h:77
BOOL OverrideDefaultFullDumpType
To override default type of data gathered by the library set this member to TRUE and set required typ...
Definition: CrashRpt.h:91
CrashRpt(LPCWSTR crashrptPath, LPCSTR applicationGUID, LPCSTR prefix, LPCWSTR appName, LPCWSTR company, BOOL ownProcess=TRUE)
Definition: CrashRpt.h:143
bool GetVersionFromApp(ApplicationInfo *appInfo)
Definition: CrashRpt.h:371
CrashRpt(LPCSTR applicationGUID, LPCSTR prefix, LPCWSTR appName, LPCWSTR company, BOOL ownProcess=TRUE)
Definition: CrashRpt.h:125
bool RemoveUserInfoFromReport(LPCWSTR key)
Definition: CrashRpt.h:330
LPCWSTR Company
Company name that will be shown in message box.
Definition: CrashRpt.h:74
CrashRpt(LPCWSTR crashrptPath, ApplicationInfo *applicationInfo, HandlerSettings *handlerSettings, BOOL ownProcess=TRUE)
Definition: CrashRpt.h:178
~CrashRpt()
Definition: CrashRpt.h:206
LPCWSTR SendRptPath
Set this member to NULL to use default behavior when SendRpt is named sendrpt.exe and exist in same f...
Definition: CrashRpt.h:94
CrashRpt(LPCSTR applicationGUID, LPCWSTR appName, LPCWSTR company)
Definition: CrashRpt.h:111
bool InitCrashRpt(ApplicationInfo *applicationInfo, HandlerSettings *handlerSettings, BOOL ownProcess=TRUE)
Definition: CrashRpt.h:232
DWORD FullDumpType
The type of information to be generated when full dump is requested by Doctor Dump. This parameter can be one or more of the values from the MINIDUMP_TYPE enumeration.
Definition: CrashRpt.h:92
To enable crash processing you should create an instance of this class.
Definition: CrashRpt.h:103
bool InitCrashHandler(ApplicationInfo *applicationInfo, HandlerSettings *handlerSettings, BOOL ownProcess=TRUE)
Definition: CrashRpt.h:252
bool IsCrashHandlingEnabled() const
Definition: CrashRpt.h:224
CrashRpt(ApplicationInfo *applicationInfo, HandlerSettings *handlerSettings, BOOL ownProcess=TRUE)
Definition: CrashRpt.h:162
LPCSTR Prefix
Prefix that will be used with the dump name: YourPrefix_v1.v2.v3.v4_YYYYMMDD_HHMMSS.mini.dmp.
Definition: CrashRpt.h:72
DWORD SubmitterID
Doctor Dump user ID. Uploaded report will be marked as uploaded by this user. This is useful for Doct...
Definition: CrashRpt.h:89
bool RemoveFileFromReport(LPCWSTR path)
Definition: CrashRpt.h:358
bool GetVersionFromFile(LPCWSTR path, ApplicationInfo *appInfo)
Definition: CrashRpt.h:382
USHORT V[4]
Version of this application.
Definition: CrashRpt.h:75
CrashRpt(LPCWSTR crashrptPath=NULL)
Definition: CrashRpt.h:196
bool InitCrashRpt(LPCSTR applicationGUID, LPCSTR prefix, LPCWSTR appName, LPCWSTR company, BOOL ownProcess=TRUE)
Definition: CrashRpt.h:267
Contains crash handling behavior customization parameters.
Definition: CrashRpt.h:83
BOOL UseWER
To continue use Microsoft Windows Error Reporting (WER) set this member to TRUE. In that case after D...
Definition: CrashRpt.h:88
USHORT Hotfix
Version of hotfix for this application (reserved for future use, should be 0).
Definition: CrashRpt.h:76
LONG SendReport(EXCEPTION_POINTERS *exceptionPointers)
Definition: CrashRpt.h:410
BOOL SendAdditionalDataWithoutApproval
To automatically accepted the question "Do you want to send more information about the problem...
Definition: CrashRpt.h:90
BOOL LeaveDumpFilesInTempFolder
To leave error reports in temp folder you should set this member to TRUE. Your support or test lab te...
Definition: CrashRpt.h:86
DWORD ApplicationInfoSize
Size of this structure. Should be set to sizeof(ApplicationInfo).
Definition: CrashRpt.h:70
LPCWSTR LangFilePath
To customize localization set this member to the path to the language file (including file name)...
Definition: CrashRpt.h:93
Contains data that identifies your application.
Definition: CrashRpt.h:68
LPCWSTR DbgHelpPath
Definition: CrashRpt.h:95
DWORD HandlerSettingsSize
Size of this structure. Should be set to sizeof(HandlerSettings).
Definition: CrashRpt.h:85
LPCWSTR AppName
Application name that will be shown in message box.
Definition: CrashRpt.h:73