BugSplat Native Windows DLL  3.6.0.0
BugSplat API reference for native Windows applications.
mdump - Copy.h
1 #include "dbghelp.h"
2 
3 #include "BugSplat.h"
4 #include "BugSplatImp.h"
5 
6 #include <vector>
7 #include <string>
8 
9 using namespace std;
10 
11 class SendReportProgressDlg;
12 
13 class MiniDumper;
14 
15 struct DumpData
16 {
17  LONG m_hRes;
18  MiniDumper* m_pMiniDumper;
19  CString m_strError;
20  struct _EXCEPTION_POINTERS * m_pExceptInfo;
21  DWORD m_dwThreadId;
22 };
23 
24 void getRegistryRoot(CString &str, const wchar_t * vendor, const wchar_t * app, const wchar_t * version);
25 
26 
27 //This class captures the total accumulated uptime of the application.
29 {
30 public:
31  TotalUptimeAndCrashCalculator(const wchar_t *szVendor, const wchar_t *szApp, const wchar_t *szVersion)
32  : m_strVendor((TCHAR *)szVendor)
33  , m_strApp((TCHAR *)szApp)
34  , m_strVersion((TCHAR *)szVersion)
35  {
36  GetSystemTime(&m_startTime);
37 
38  // Read the existing value from the registry and set the new value.
39  CString strRegRoot;
40  getRegistryRoot(strRegRoot, m_strVendor, m_strApp, m_strVersion);
41 
42  HKEY hKey;
43  LONG lErr = RegOpenKey(HKEY_CURRENT_USER, strRegRoot, &hKey);
44  if (ERROR_SUCCESS != lErr)
45  {
46  lErr = RegCreateKey(HKEY_CURRENT_USER, strRegRoot, &hKey);
47  }
48  if (ERROR_SUCCESS == lErr)
49  {
50  DWORD launchCount = 0L;
51  DWORD type;
52  DWORD size;
53  LONG ret = RegQueryValueEx(hKey, _T("LaunchCount"), 0, &type, reinterpret_cast<LPBYTE>(&launchCount), &size);
54  if (ret != ERROR_SUCCESS) {
55  launchCount = 0L;
56  }
57  launchCount++;
58 
59  ret = RegSetValueEx(hKey, _T("LaunchCount"), 0, REG_DWORD, reinterpret_cast<LPBYTE>(&launchCount), sizeof(launchCount));
60  ATLASSERT(ERROR_SUCCESS == ret);
61 
62  RegCloseKey(hKey);
63  return;
64  }
65  }
66 
68  {
69  }
70 
72  {
73  capture();
74  }
75 
76  _int64 Delta(const SYSTEMTIME st1, const SYSTEMTIME st2) {
77  union timeunion {
78  FILETIME fileTime;
79  ULARGE_INTEGER ul;
80  };
81 
82  timeunion ft1;
83  timeunion ft2;
84 
85  SystemTimeToFileTime(&st1, &ft1.fileTime);
86  SystemTimeToFileTime(&st2, &ft2.fileTime);
87 
88  return ft2.ul.QuadPart - ft1.ul.QuadPart;
89  }
90 
91  void capture(bool bIncrCrash=false)
92  {
93  // Get the uptime of the process
94  SYSTEMTIME endTime;
95  GetSystemTime(&endTime);
96 
97  // Find time until crash in seconds
98  _int64 toffset = Delta(m_startTime, endTime);
99  _int64 lgAdditionTimeInSecs = (toffset / 10000000);
100 
101  // Read the existing value from the registry and set the new value.
102  CString strRegRoot;
103  getRegistryRoot(strRegRoot, m_strVendor, m_strApp, m_strVersion);
104 
105  HKEY hKey;
106  LONG lErr = RegOpenKey(HKEY_CURRENT_USER, strRegRoot,&hKey);
107  if (ERROR_SUCCESS != lErr)
108  {
109  lErr = RegCreateKey(HKEY_CURRENT_USER, strRegRoot, &hKey);
110  }
111  if (ERROR_SUCCESS == lErr)
112  {
113  DWORD additionalTimeInSecs = (DWORD)(lgAdditionTimeInSecs);
114 
115  LONG ret = RegSetValueEx(hKey, _T("LaunchToLastCrashTime"), 0, REG_DWORD, reinterpret_cast<LPBYTE>(&additionalTimeInSecs), sizeof(additionalTimeInSecs));
116  ATLASSERT(ERROR_SUCCESS == ret);
117 
118  DWORD uptime = 0L;
119  DWORD type;
120  DWORD size = sizeof(uptime);
121  ret = RegQueryValueEx(hKey, _T("TotalUptime"), 0, &type, (LPBYTE)&uptime, &size);
122  ATLASSERT(ERROR_FILE_NOT_FOUND == ret || ERROR_SUCCESS == ret);
123  ATLASSERT(ERROR_SUCCESS == ret);
124 
125  // uptime+= additionalTimeInSecs;
126  // ret = RegSetValueEx(hKey, _T("TotalUptime"), 0, REG_DWORD, (LPBYTE)&uptime, sizeof(uptime));
127  //ATLASSERT(ERROR_SUCCESS == ret);
128 
129  ret = RegSetValueEx(hKey, _T("DJPVerifyUptime"), 0, REG_DWORD, (LPBYTE)&uptime, sizeof(uptime));
130  ATLASSERT(ERROR_SUCCESS == ret);
131 
132  ret = RegSetValueEx(hKey, _T("DJPVerifyAdditionalTIme"), 0, REG_DWORD, (LPBYTE)&additionalTimeInSecs, sizeof(additionalTimeInSecs));
133  ATLASSERT(ERROR_SUCCESS == ret);
134 
135  DWORD newUptime = additionalTimeInSecs + uptime;
136  ret = RegSetValueEx(hKey, _T("TotalUptime"), 0, REG_DWORD, (LPBYTE)&newUptime, sizeof(newUptime));
137  ATLASSERT(ERROR_SUCCESS == ret);
138 
139  if (bIncrCrash)
140  {
141  DWORD crashCount = 0L;
142  ret = RegQueryValueEx(hKey, _T("CrashCount"),0,&type,reinterpret_cast<LPBYTE>(&crashCount),&size);
143  if (ret != ERROR_SUCCESS) {
144  crashCount = 0L;
145  }
146  crashCount++;
147 
148  ret = RegSetValueEx(hKey, _T("CrashCount"),0,REG_DWORD,reinterpret_cast<LPBYTE>(&crashCount),sizeof(crashCount));
149  ATLASSERT(ERROR_SUCCESS == ret);
150  }
151 
152  //ret = RegSetValueEx(hKey, _T("TotalUptime"), 0, REG_DWORD, reinterpret_cast<LPBYTE>(&newUptime), sizeof(newUptime));
153 
154  RegCloseKey(hKey);
155  return;
156  }
157  //failure in RegOpenKey is ignorable, not all products enable CER
158  }
159 
160  DWORD getTotalTime()
161  {
162  //Get the existing value from the registry.
163  DWORD uptime = 0;
164  HKEY hKey;
165  CString strRegRoot;
166  getRegistryRoot(strRegRoot, m_strVendor, m_strApp, m_strVersion);
167  if (ERROR_SUCCESS == RegOpenKey(HKEY_CURRENT_USER, strRegRoot,&hKey))
168  {
169  DWORD type;
170  DWORD size;
171  LONG ret = RegQueryValueEx(hKey,_T("TotalUptime"),0,&type,reinterpret_cast<LPBYTE>(&uptime),&size);
172  ATLASSERT(ERROR_SUCCESS == ret);
173  RegCloseKey(hKey);
174  }
175  else
176  {
177  ATLASSERT(false);//shouldn't get here
178  }
179  return uptime;
180  }
181  DWORD getCrashCount()
182  {
183  //Get the existing value from the registry.
184  DWORD crashCount = 0;
185  HKEY hKey;
186  CString strRegRoot;
187  getRegistryRoot(strRegRoot, m_strVendor, m_strApp, m_strVersion);
188  if (ERROR_SUCCESS == RegOpenKey(HKEY_CURRENT_USER, strRegRoot,&hKey))
189  {
190  DWORD type;
191  DWORD size;
192  LONG ret = RegQueryValueEx(hKey,_T("CrashCount"),0,&type,reinterpret_cast<LPBYTE>(&crashCount),&size);
193  ATLASSERT(ERROR_SUCCESS == ret);
194  RegCloseKey(hKey);
195  }
196  else
197  {
198  ATLASSERT(false);//shouldn't get here
199  }
200  return crashCount;
201  }
202  DWORD captureAndGet(int &crashCount, bool bIncrCrash=false)
203  {
204  //if this method is called we are crashing. The destructor of this class will not be called (we call TerminateProcess)
205  capture(bIncrCrash);
206  crashCount = getCrashCount();
207  return getTotalTime();
208  }
209 private:
210  CString m_strVendor;
211  CString m_strApp;
212  CString m_strVersion;
213  SYSTEMTIME m_startTime;
214  CString m_strUserName;
215  CString m_strUserEmail;
216  CString m_strUserDescription;
217 }; //here's the one and only instance
218 
219 // Simple class to automate restoring original resource handle
221  HINSTANCE m_hClientResources;
222  HINSTANCE m_localRes;
223 public:
224  ResourceSwitch( const wchar_t * dllName ) {
225  // Store the current resource handle
226  m_hClientResources = _Module.GetResourceInstance();
227 
228  // Tell the client to use the .DLL's resources
229  m_localRes = (HINSTANCE)LoadLibrary(dllName);
230  if( m_localRes != NULL )
231  {
232  _Module.SetResourceInstance(m_localRes);
233  }
234  }
235 
236  ~ResourceSwitch()
237  {
238  // Restore the client application resource handle
239  _Module.SetResourceInstance(m_hClientResources);
240  FreeLibrary(m_localRes);
241  }
242 
243  void SetResourceDll(const wchar_t * dllName) {
244  // Tell the client to use the .DLL's resources
245  m_localRes = (HINSTANCE)LoadLibrary(dllName);
246  if( m_localRes != NULL )
247  {
248  _Module.SetResourceInstance(m_localRes);
249  }
250  }
251 
252  bool foundResources()
253  {
254  return (m_localRes != NULL);
255  }
256 };
257 
258 
259 
261 {
262 public:
263  MiniDumper();
264  virtual ~MiniDumper();
265 
266  void initExceptionHandler(const wchar_t *szVendor, const wchar_t *szAppName, const wchar_t *szVersion, const wchar_t *szDescription, DWORD dwFlags);
267 
268  bool enableExceptionFilter(bool enable = true);
269  bool isExceptionFilterEnabled() const;
270 
271  bool enableFullMemoryDumpAndExit(bool enable = true);
272  bool isFullMemoryDumpAndExitEnabled() const;
273 
274  // get/set the option flags
275  DWORD getFlags() const { return m_dwFlags; };
276  bool setFlags( DWORD dwFlags );
277 
278  // Get/set the minidump type.
279  MiniDmpSender::BS_MINIDUMP_TYPE getMiniDumpType() const;
280  void setMiniDumpType(MiniDmpSender::BS_MINIDUMP_TYPE m_eMiniDumpType);
281 
282  void resetVersionString(const wchar_t * szPath);
283  void resetDescriptionString(const wchar_t * szPath);
284  void sendAdditionalFile(const wchar_t * szPath);
285  bool removeAdditionalFile(const wchar_t * szPath);
286  void setUserZipPath(const wchar_t * szPath);
287  void setResourceDllPath(const wchar_t * szPath);
288 
289  void setDefaultUserName(const wchar_t * szPath);
290  void setDefaultUserEmail(const wchar_t * szPath);
291  void setDefaultUserDescription(const wchar_t * szPath);
292 
293  static LONG WINAPI TopLevelUnhandledExceptionFilter( PEXCEPTION_POINTERS pExceptionInfo );
294 
295  static LONG WINAPI ExceptionHandler( PEXCEPTION_POINTERS pExceptionInfo, DWORD dwThreadId=0L );
296 
297  static unsigned WINAPI CreateReportThreaded(PVOID);
298  static unsigned WINAPI SendReportThreaded(PVOID);
299 
300  // creates and sends a report
301  void createReport(DWORD dwThreadId = 0L);
302  void createReport(EXCEPTION_POINTERS * pExcepInfo);
303  void createReport(const wchar_t *szStackTracePath);
304  CString m_strStackTracePath;
305 
306  static UINT bugsplatMessage(const wchar_t * szMsg, UINT nCode= MB_ICONINFORMATION, UINT nDflt = MB_OK);
307 
308  static bool GetMFA(void * pAddress, LPTSTR pszMfa, int nSizeMFA);
309 
310  void setCallback(MiniDmpSenderCallback fnCallback);
311 
312  void LaunchHangDetection();
313  void TerminateHangDetection();
314 
315  LPVOID imp() { return &m_imp;}
316 
317  MiniDmpSenderCallback m_fnCallback;
318  CString m_strVendor;
319  CString m_strAppName;
320  CString m_strVersion;
321  CString m_strDescription;
322  CString m_strUserZipPath;
323  CString m_strResourceDllPath;
324  vector<CString> m_strAdditionalFiles;
325  CString m_strUserName; // Optional default value for user name
326  CString m_strUserEmail; // Optional default value for user email
327  CString m_strUserDescription; // Optional default value for user description
328  CString m_strDmpFile;
329  DWORD m_dwFlags;
330  MINIDUMP_TYPE m_eMiniDumpType;
331  DWORD m_hangProcess;
332 
333  TotalUptimeAndCrashCalculator * m_pUptimeAndCrashCalc;
334  char* m_pGuardBytes;
335 
336  static bool m_enableFilter;
337 
338  static bool m_doFullMemoryDumpThenExit;
339 
340  static MiniDumper * s_pThis;
341 
342  static LPTOP_LEVEL_EXCEPTION_FILTER m_previousExceptionFilter;
343 
344  static bool m_exceptionCaught;
345 
346  static int m_waitCreateReportThreaded;
347  static int m_waitSendReportThreaded;
348 
349 protected:
350  static BugSplatImp m_imp;
351 };
Definition: BugSplatImp.h:38
Definition: mdump - Copy.h:15
Definition: mdump - Copy.h:28
Definition: mdump - Copy.h:220
Definition: mdump - Copy.h:260