// Launches CrashSender.exe process int CCrashHandler::LaunchCrashSender(CString sCmdLineParams, BOOL bWait) { crSetErrorMsg(_T("Success.")); /* Create CrashSender process */ STARTUPINFO si; memset(&si, 0, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); PROCESS_INFORMATION pi; memset(&pi, 0, sizeof(PROCESS_INFORMATION)); CString sCmdLine; sCmdLine.Format(_T("\"%s\" \"%s\""), sCmdLineParams, sCmdLineParams.GetBuffer(0)); BOOL bCreateProcess = CreateProcess( m_sPathToCrashSender, sCmdLine.GetBuffer(0), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); if(!bCreateProcess) { ATLASSERT(bCreateProcess); crSetErrorMsg(_T("Error creating CrashSender process.")); return 1; } if(bWait) { /* Wait until CrashSender finishes with making screenshot, copying files, creating minidump. */ WaitForSingleObject(m_hEvent, INFINITE); } return 0; }
crExceptionFilter(unsigned int code, struct _EXCEPTION_POINTERS* ep) { crSetErrorMsg(_T("Unspecified error.")); CCrashHandler *pCrashHandler = CCrashHandler::GetCurrentProcessCrashHandler(); if(pCrashHandler==NULL) { crSetErrorMsg(_T("Crash handler wasn't previously installed for current process.")); return EXCEPTION_CONTINUE_SEARCH; } CR_EXCEPTION_INFO ei; memset(&ei, 0, sizeof(CR_EXCEPTION_INFO)); ei.cb = sizeof(CR_EXCEPTION_INFO); ei.exctype = CR_SEH_EXCEPTION; ei.pexcptrs = ep; ei.code = code; int res = pCrashHandler->GenerateErrorReport(&ei); if(res!=0) { // If goes here than GenerateErrorReport() failed return EXCEPTION_CONTINUE_SEARCH; } crSetErrorMsg(_T("Success.")); return EXCEPTION_EXECUTE_HANDLER; }
crGenerateErrorReport( CR_EXCEPTION_INFO* pExceptionInfo) { crSetErrorMsg(_T("Unspecified error.")); if(pExceptionInfo==NULL || pExceptionInfo->cb!=sizeof(CR_EXCEPTION_INFO)) { crSetErrorMsg(_T("Exception info is NULL or invalid.")); return 1; } CCrashHandler *pCrashHandler = CCrashHandler::GetCurrentProcessCrashHandler(); if(pCrashHandler==NULL) { // Handler is not installed for current process crSetErrorMsg(_T("Crash handler wasn't previously installed for current process.")); ATLASSERT(pCrashHandler!=NULL); return 2; } return pCrashHandler->GenerateErrorReport(pExceptionInfo); }
crAddRegKeyW( LPCWSTR pszRegKey, LPCWSTR pszDstFileName, DWORD dwFlags ) { crSetErrorMsg(_T("Unspecified error.")); strconv_t strconv; LPCTSTR pszRegKeyT = strconv.w2t(pszRegKey); LPCTSTR pszDstFileNameT = strconv.w2t(pszDstFileName); CCrashHandler *pCrashHandler = CCrashHandler::GetCurrentProcessCrashHandler(); if(pCrashHandler==NULL) { crSetErrorMsg(_T("Crash handler wasn't previously installed for current process.")); return 1; // No handler installed for current process? } int nResult = pCrashHandler->AddRegKey(pszRegKeyT, pszDstFileNameT, dwFlags); if(nResult!=0) { crSetErrorMsg(_T("Invalid parameter or key doesn't exist.")); return 2; // Failed to add the property } crSetErrorMsg(_T("Success.")); return 0; }
crAddPropertyW( LPCWSTR pszPropName, LPCWSTR pszPropValue ) { crSetErrorMsg(_T("Unspecified error.")); strconv_t strconv; LPCTSTR pszPropNameT = strconv.w2t(pszPropName); LPCTSTR pszPropValueT = strconv.w2t(pszPropValue); CCrashHandler *pCrashHandler = CCrashHandler::GetCurrentProcessCrashHandler(); if(pCrashHandler==NULL) { crSetErrorMsg(_T("Crash handler wasn't previously installed for current process.")); return 1; // No handler installed for current process? } int nResult = pCrashHandler->AddProperty(CString(pszPropNameT), CString(pszPropValueT)); if(nResult!=0) { crSetErrorMsg(_T("Invalid property name specified.")); return 2; // Failed to add the property } crSetErrorMsg(_T("Success.")); return 0; }
crAddFile2W(PCWSTR pszFile, PCWSTR pszDestFile, PCWSTR pszDesc, DWORD dwFlags) { crSetErrorMsg(_T("Success.")); strconv_t strconv; CCrashHandler *pCrashHandler = CCrashHandler::GetCurrentProcessCrashHandler(); if(pCrashHandler==NULL) { crSetErrorMsg(_T("Crash handler wasn't previously installed for current process.")); return 1; // No handler installed for current process? } LPCTSTR lptszFile = strconv.w2t((LPWSTR)pszFile); LPCTSTR lptszDestFile = strconv.w2t((LPWSTR)pszDestFile); LPCTSTR lptszDesc = strconv.w2t((LPWSTR)pszDesc); int nAddResult = pCrashHandler->AddFile(lptszFile, lptszDestFile, lptszDesc, dwFlags); if(nAddResult!=0) { // Couldn't add file return 2; } // OK. return 0; }
int CCrashHandler::Destroy() { crSetErrorMsg(_T("Unspecified error.")); if(!m_bInitialized) { crSetErrorMsg(_T("Can't destroy not initialized handler.")); return 1; } // Reset exception callback if (m_oldSehHandler) SetUnhandledExceptionFilter(m_oldSehHandler); m_oldSehHandler = NULL; // All installed per-thread C++ exception handlers should be uninstalled // using crUninstallFromCurrentThread() before calling Destroy() { CAutoLock lock(&m_csThreadExceptionHandlers); ATLASSERT(m_ThreadExceptionHandlers.size()==0); } m_pProcessCrashHandler = NULL; // OK. m_bInitialized = FALSE; crSetErrorMsg(_T("Success.")); return 0; }
CRASHRPTAPI(int) crUninstall() { crSetErrorMsg(_T("Success.")); CCrashHandler *pCrashHandler = CCrashHandler::GetCurrentProcessCrashHandler(); if(pCrashHandler==NULL || !pCrashHandler->IsInitialized()) { crSetErrorMsg(_T("Crash handler wasn't preiviously installed for this process.")); return 1; } // Uninstall main thread's C++ exception handlers int nUnset = pCrashHandler->UnSetThreadExceptionHandlers(); if(nUnset!=0) return 2; int nDestroy = pCrashHandler->Destroy(); if(nDestroy!=0) return 3; delete pCrashHandler; return 0; }
int CCrashHandler::AddProperty(CString sPropName, CString sPropValue) { crSetErrorMsg(_T("Unspecified error.")); if(sPropName.IsEmpty()) { crSetErrorMsg(_T("Invalid property name specified.")); return 1; } m_props[sPropName] = sPropValue; // OK. crSetErrorMsg(_T("Success.")); return 0; }
int CCrashHandler::AddScreenshot(DWORD dwFlags) { m_bAddScreenshot = TRUE; m_dwScreenshotFlags = dwFlags; crSetErrorMsg(_T("Success.")); return 0; }
crAddScreenshot( DWORD dwFlags ) { crSetErrorMsg(_T("Unspecified error.")); CCrashHandler *pCrashHandler = CCrashHandler::GetCurrentProcessCrashHandler(); if(pCrashHandler==NULL) { crSetErrorMsg(_T("Crash handler wasn't previously installed for current thread.")); return 1; // Invalid parameter? } return pCrashHandler->AddScreenshot(dwFlags); }
int CCrashHandler::UnSetThreadExceptionHandlers() { crSetErrorMsg(_T("Unspecified error.")); DWORD dwThreadId = GetCurrentThreadId(); CAutoLock lock(&m_csThreadExceptionHandlers); std::map<DWORD, ThreadExceptionHandlers>::iterator it = m_ThreadExceptionHandlers.find(dwThreadId); if(it==m_ThreadExceptionHandlers.end()) { // No exception handlers were installed for the caller thread? ATLASSERT(0); crSetErrorMsg(_T("Crash handler wasn't previously installed for current thread.")); return 1; } ThreadExceptionHandlers* handlers = &(it->second); if(handlers->m_prevTerm!=NULL) set_terminate(handlers->m_prevTerm); if(handlers->m_prevUnexp!=NULL) set_unexpected(handlers->m_prevUnexp); if(handlers->m_prevSigFPE!=NULL) signal(SIGFPE, handlers->m_prevSigFPE); if(handlers->m_prevSigILL!=NULL) signal(SIGINT, handlers->m_prevSigILL); if(handlers->m_prevSigSEGV!=NULL) signal(SIGSEGV, handlers->m_prevSigSEGV); // Remove from the list m_ThreadExceptionHandlers.erase(it); // OK. crSetErrorMsg(_T("Success.")); return 0; }
crInstallToCurrentThread2(DWORD dwFlags) { crSetErrorMsg(_T("Success.")); CCrashHandler *pCrashHandler = CCrashHandler::GetCurrentProcessCrashHandler(); if(pCrashHandler==NULL) { crSetErrorMsg(_T("Crash handler was already installed for current thread.")); return 1; } int nResult = pCrashHandler->SetThreadExceptionHandlers(dwFlags); if(nResult!=0) return 2; // Error? // Ok. return 0; }
crUninstallFromCurrentThread() { crSetErrorMsg(_T("Success.")); CCrashHandler *pCrashHandler = CCrashHandler::GetCurrentProcessCrashHandler(); if(pCrashHandler==NULL) { ATLASSERT(pCrashHandler!=NULL); crSetErrorMsg(_T("Crash handler wasn't previously installed for current thread.")); return 1; // Invalid parameter? } int nResult = pCrashHandler->UnSetThreadExceptionHandlers(); if(nResult!=0) return 2; // Error? // OK. return 0; }
crAddVideo( DWORD dwFlags, int nDuration, int nFrameInterval, SIZE* pDesiredFrameSize, HWND hWndParent ) { crSetErrorMsg(_T("Unspecified error.")); CCrashHandler *pCrashHandler = CCrashHandler::GetCurrentProcessCrashHandler(); if(pCrashHandler==NULL) { crSetErrorMsg(_T("Crash handler wasn't previously installed for current process.")); return 1; // Invalid parameter? } return pCrashHandler->AddVideo(dwFlags, nDuration, nFrameInterval, pDesiredFrameSize, hWndParent); }
crInstallToCurrentThread2(DWORD dwFlags) { crSetErrorMsg(_T("Success.")); CCrashHandler *pCrashHandler = CCrashHandler::GetCurrentProcessCrashHandler(); if(pCrashHandler==NULL) { // AS: Correction of error message crSetErrorMsg(_T("Crash handler not installed for this process.")); return 1; } int nResult = pCrashHandler->SetThreadExceptionHandlers(dwFlags); if(nResult!=0) return 2; // Error? // Ok. return 0; }
crSetCrashCallbackA( PFNCRASHCALLBACKA pfnCallbackFunc, LPVOID lpParam ) { crSetErrorMsg(_T("Unspecified error.")); CCrashHandler *pCrashHandler = CCrashHandler::GetCurrentProcessCrashHandler(); if(pCrashHandler==NULL) { crSetErrorMsg(_T("Crash handler wasn't previously installed for current process.")); return 1; // No handler installed for current process? } pCrashHandler->SetCrashCallbackA(pfnCallbackFunc, lpParam); // OK crSetErrorMsg(_T("Success.")); return 0; }
int CCrashHandler::AddFile(LPCTSTR pszFile, LPCTSTR pszDestFile, LPCTSTR pszDesc, DWORD dwFlags) { crSetErrorMsg(_T("Unspecified error.")); // make sure the file exist struct _stat st; int result = _tstat(pszFile, &st); if (result!=0 && (dwFlags&CR_AF_MISSING_FILE_OK)==0) { ATLASSERT(0); crSetErrorMsg(_T("Couldn't stat file. File may not exist.")); return 1; } // Add file to file list. FileItem fi; fi.m_sDescription = pszDesc; fi.m_sFileName = pszFile; fi.m_bMakeCopy = (dwFlags&CR_AF_MAKE_FILE_COPY)!=0; if(pszDestFile!=NULL) m_files[pszDestFile] = fi; else { CString sDestFile = pszFile; int pos = -1; sDestFile.Replace('/', '\\'); pos = sDestFile.ReverseFind('\\'); if(pos!=-1) sDestFile = sDestFile.Mid(pos+1); m_files[sDestFile] = fi; } // OK. crSetErrorMsg(_T("Success.")); return 0; }
int CCrashHandler::UnSetProcessExceptionHandlers() { crSetErrorMsg(_T("Unspecified error.")); // Unset all previously set handlers #if _MSC_VER>=1300 if(m_prevPurec!=NULL) _set_purecall_handler(m_prevPurec); if(m_prevNewHandler!=NULL) _set_new_handler(m_prevNewHandler); #endif #if _MSC_VER>=1400 if(m_prevInvpar!=NULL) _set_invalid_parameter_handler(m_prevInvpar); #endif //_MSC_VER>=1400 #if _MSC_VER>=1300 && _MSC_VER<1400 if(m_prevSec!=NULL) _set_security_error_handler(m_prevSec); #endif //_MSC_VER<1400 if(m_prevSigABRT!=NULL) signal(SIGABRT, m_prevSigABRT); if(m_prevSigINT!=NULL) signal(SIGINT, m_prevSigINT); if(m_prevSigTERM!=NULL) signal(SIGTERM, m_prevSigTERM); crSetErrorMsg(_T("Success.")); return 0; }
crExceptionFilter(unsigned int code, struct _EXCEPTION_POINTERS* ep) { crSetErrorMsg(_T("Unspecified error.")); CCrashHandler *pCrashHandler = CCrashHandler::GetCurrentProcessCrashHandler(); if(pCrashHandler==NULL) { crSetErrorMsg(_T("Crash handler wasn't previously installed for current process.")); return EXCEPTION_CONTINUE_SEARCH; } #ifdef CRASHRPT_EX // AS: Unless the user will indeed check for the user choice this makes no real // sense here. // We assume that the execute_handler does what it should -> close the app. pCrashHandler ->AllowContinue(0); #endif CR_EXCEPTION_INFO ei; memset(&ei, 0, sizeof(CR_EXCEPTION_INFO)); ei.cb = sizeof(CR_EXCEPTION_INFO); ei.exctype = CR_SEH_EXCEPTION; ei.pexcptrs = ep; ei.code = code; int res = pCrashHandler->GenerateErrorReport(&ei); if(res!=0) { // If goes here than GenerateErrorReport() failed return EXCEPTION_CONTINUE_SEARCH; } crSetErrorMsg(_T("Success.")); return EXCEPTION_EXECUTE_HANDLER; }
CRASHRPTAPI(int) crUninstall() { crSetErrorMsg(_T("Success.")); // Get crash handler singleton CCrashHandler *pCrashHandler = CCrashHandler::GetCurrentProcessCrashHandler(); // Check if found if(pCrashHandler==NULL || !pCrashHandler->IsInitialized()) { crSetErrorMsg(_T("Crash handler wasn't preiviously installed for this process.")); return 1; } // Uninstall main thread's C++ exception handlers int nUnset = pCrashHandler->UnSetThreadExceptionHandlers(); if(nUnset!=0) return 2; // Destroy the crash handler. int nDestroy = pCrashHandler->Destroy(); if(nDestroy!=0) return 3; // Free the crash handler object. delete pCrashHandler; // Clear last error message list. g_cs.Lock(); g_sErrorMsg.clear(); g_cs.Unlock(); return 0; }
int CCrashHandler::Init( LPCTSTR lpcszAppName, LPCTSTR lpcszAppVersion, LPCTSTR lpcszCrashSenderPath, LPGETLOGFILE lpfnCallback, LPCTSTR lpcszTo, LPCTSTR lpcszSubject, LPCTSTR lpcszUrl, UINT (*puPriorities)[5], DWORD dwFlags, LPCTSTR lpcszPrivacyPolicyURL) { crSetErrorMsg(_T("Unspecified error.")); // save user supplied callback if (lpfnCallback) m_lpfnCallback = lpfnCallback; // Get handle to the EXE module used to create this process HMODULE hExeModule = GetModuleHandle(NULL); if(hExeModule==NULL) { ATLASSERT(hExeModule!=NULL); crSetErrorMsg(_T("Couldn't get module handle for the executable.")); return 1; } TCHAR szExeName[_MAX_PATH]; DWORD dwLength = GetModuleFileName(hExeModule, szExeName, _MAX_PATH); if(dwLength==0) { // Couldn't get the name of EXE that was used to create current process ATLASSERT(0); crSetErrorMsg(_T("Couldn't get the name of EXE that was used to create current process.")); return 1; } // Save EXE image name m_sImageName = CString(szExeName, dwLength); // Save application name m_sAppName = lpcszAppName; // If no app name provided, use the default (EXE name) if(m_sAppName.IsEmpty()) m_sAppName = CUtility::getAppName(); // Save app version m_sAppVersion = lpcszAppVersion; // If no app version provided, use the default (EXE product version) if(m_sAppVersion.IsEmpty()) { DWORD dwBuffSize = GetFileVersionInfoSize(szExeName, 0); LPBYTE pBuff = new BYTE[dwBuffSize]; if(0!=GetFileVersionInfo(szExeName, 0, dwBuffSize, pBuff)) { VS_FIXEDFILEINFO* fi = NULL; UINT uLen = 0; VerQueryValue(pBuff, _T("\\"), (LPVOID*)&fi, &uLen); WORD dwVerMajor = (WORD)(fi->dwProductVersionMS>>16); WORD dwVerMinor = (WORD)(fi->dwProductVersionMS&0xFF); WORD dwPatchLevel = (WORD)(fi->dwProductVersionLS>>16); WORD dwVerBuild = (WORD)(fi->dwProductVersionLS&0xFF); m_sAppVersion.Format(_T("%u.%u.%u.%u"), dwVerMajor, dwVerMinor, dwPatchLevel, dwVerBuild); }
int CCrashHandler::CreateInternalCrashInfoFile(CString sFileName, EXCEPTION_POINTERS* pExInfo) { crSetErrorMsg(_T("Unspecified error.")); strconv_t strconv; DWORD dwProcessId = GetCurrentProcessId(); DWORD dwThreadId = GetCurrentThreadId(); FILE* f = NULL; #if _MSC_VER>=1400 _tfopen_s(&f, sFileName, _T("wt")); #else f = _tfopen(sFileName, _T("wt")); #endif if(f==NULL) { crSetErrorMsg(_T("Couldn't create internal crash info file.")); return 1; // Couldn't create file } // Add <?xml version="1.0" encoding="utf-8" ?> element fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); // Add root element fprintf(f, "<CrashRptInternal version=\"%d\">\n", CRASHRPT_VER); // Add CrashGUID tag fprintf(f, " <CrashGUID>%s</CrashGUID>\n", XmlEncodeStr(m_sCrashGUID).c_str()); // Add ReportFolder tag fprintf(f, " <ReportFolder>%s</ReportFolder>\n", XmlEncodeStr(m_sReportFolderName).c_str()); // Add DbgHelpPath tag fprintf(f, " <DbgHelpPath>%s</DbgHelpPath>\n", XmlEncodeStr(m_sPathToDebugHelpDll).c_str()); // Add MinidumpType tag fprintf(f, " <MinidumpType>%lu</MinidumpType>\n", m_MiniDumpType); // Add ProcessId tag fprintf(f, " <ProcessId>%lu</ProcessId>\n", dwProcessId); // Add ThreadId tag fprintf(f, " <ThreadId>%lu</ThreadId>\n", dwThreadId); // Add ExceptionPointersAddress tag fprintf(f, " <ExceptionPointersAddress>%p</ExceptionPointersAddress>\n", pExInfo); // Add EmailSubject tag fprintf(f, " <EmailSubject>%s</EmailSubject>\n", XmlEncodeStr(m_sEmailSubject).c_str()); // Add EmailTo tag fprintf(f, " <EmailTo>%s</EmailTo>\n", XmlEncodeStr(m_sEmailTo).c_str()); // Add EmailText tag fprintf(f, " <EmailText>%s</EmailText>\n", XmlEncodeStr(m_sEmailText).c_str()); // Add SmtpPort tag fprintf(f, " <SmtpPort>%d</SmtpPort>\n", m_nSmtpPort); // Add SmtpProxyServer tag fprintf(f, " <SmtpProxyServer>%s</SmtpProxyServer>\n", XmlEncodeStr(m_sSmtpProxyServer).c_str()); // Add SmtpProxyPort tag fprintf(f, " <SmtpProxyPort>%d</SmtpProxyPort>\n", m_nSmtpProxyPort); // Add Url tag fprintf(f, " <Url>%s</Url>\n", XmlEncodeStr(m_sUrl).c_str()); // Add PrivacyPolicyUrl tag fprintf(f, " <PrivacyPolicyUrl>%s</PrivacyPolicyUrl>\n", XmlEncodeStr(m_sPrivacyPolicyURL).c_str()); // Add HttpPriority tag fprintf(f, " <HttpPriority>%d</HttpPriority>\n", m_uPriorities[CR_HTTP]); // Add SmtpPriority tag fprintf(f, " <SmtpPriority>%d</SmtpPriority>\n", m_uPriorities[CR_SMTP]); // Add MapiPriority tag fprintf(f, " <MapiPriority>%d</MapiPriority>\n", m_uPriorities[CR_SMAPI]); // Add AddScreenshot tag fprintf(f, " <AddScreenshot>%d</AddScreenshot>\n", m_bAddScreenshot); // Add ScreenshotFlags tag fprintf(f, " <ScreenshotFlags>%lu</ScreenshotFlags>\n", m_dwScreenshotFlags); // Add AppWindowRect tag fprintf(f, " <AppWindowRect left=\"%d\" top=\"%d\" right=\"%d\" bottom=\"%d\" />\n", m_rcAppWnd.left, m_rcAppWnd.top, m_rcAppWnd.right, m_rcAppWnd.bottom); // Add CursorPos tag fprintf(f, " <CursorPos x=\"%d\" y=\"%d\" />\n", m_ptCursorPos.x, m_ptCursorPos.y); // Add MultiPartHttpUploads tag fprintf(f, " <HttpBinaryEncoding>%d</HttpBinaryEncoding>\n", m_bHttpBinaryEncoding); // Add SilentMode tag fprintf(f, " <SilentMode>%d</SilentMode>\n", m_bSilentMode); // Add SendErrorReport tag fprintf(f, " <SendErrorReport>%d</SendErrorReport>\n", m_bSendErrorReport); // Add AppRestart tag fprintf(f, " <AppRestart>%d</AppRestart>\n", m_bAppRestart); // Add RestartCmdLine tag fprintf(f, " <RestartCmdLine>%s</RestartCmdLine>\n", XmlEncodeStr(m_sRestartCmdLine).c_str()); // Add GenerateMinidump tag fprintf(f, " <GenerateMinidump>%d</GenerateMinidump>\n", m_bGenerateMinidump); // Add LangFileName tag fprintf(f, " <LangFileName>%s</LangFileName>\n", XmlEncodeStr(m_sLangFileName).c_str()); // Write file list fprintf(f, " <FileList>\n"); std::map<CString, FileItem>::iterator it; for(it=m_files.begin(); it!=m_files.end(); it++) { fprintf(f, " <FileItem destfile=\"%s\" srcfile=\"%s\" description=\"%s\" makecopy=\"%d\" />\n", XmlEncodeStr(it->first).c_str(), XmlEncodeStr(it->second.m_sFileName).c_str(), XmlEncodeStr(it->second.m_sDescription).c_str(), it->second.m_bMakeCopy?1:0 ); } fprintf(f, " </FileList>\n"); fprintf(f, "</CrashRptInternal>\n"); fclose(f); crSetErrorMsg(_T("Success.")); return 0; }
int CCrashHandler::CreateCrashDescriptionXML( LPTSTR pszFileName, PCR_EXCEPTION_INFO pExceptionInfo) { crSetErrorMsg(_T("Unspecified error.")); strconv_t strconv; FILE* f = NULL; #if _MSC_VER>=1400 _tfopen_s(&f, pszFileName, _T("wt")); #else f = _tfopen(pszFileName, _T("wt")); #endif if(f==NULL) return 1; // Couldn't create file // Add <?xml version="1.0" encoding="utf-8" ?> element fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); // Add root element fprintf(f, "<CrashRpt version=\"%d\">\n", CRASHRPT_VER); // Write crash GUID fprintf(f, " <CrashGUID>%s</CrashGUID>\n", XmlEncodeStr(m_sCrashGUID.GetBuffer(0)).c_str()); // Write application name fprintf(f, " <AppName>%s</AppName>\n", XmlEncodeStr(m_sAppName.GetBuffer(0)).c_str()); // Write application version fprintf(f, " <AppVersion>%s</AppVersion>\n", XmlEncodeStr(m_sAppVersion.GetBuffer(0)).c_str()); // Write EXE image name fprintf(f, " <ImageName>%s</ImageName>\n", XmlEncodeStr(m_sImageName.GetBuffer(0)).c_str()); // Write operating system friendly name fprintf(f, " <OperatingSystem>%s</OperatingSystem>\n", XmlEncodeStr(m_sOSName.GetBuffer(0)).c_str()); // Write system time in UTC format fprintf(f, " <SystemTimeUTC>%s</SystemTimeUTC>\n", XmlEncodeStr(m_sCrashTime.GetBuffer(0)).c_str()); // Write exception type fprintf(f, " <ExceptionType>%d</ExceptionType>\n", pExceptionInfo->exctype); if(pExceptionInfo->exctype==CR_SEH_EXCEPTION) { // Write exception code fprintf(f, " <ExceptionCode>0x%X</ExceptionCode>\n", pExceptionInfo->pexcptrs->ExceptionRecord->ExceptionCode); } if(pExceptionInfo->exctype==CR_CPP_SIGFPE) { // Write FPE exception subcode fprintf(f, " <FPESubcode>%d</FPESubcode>\n", pExceptionInfo->fpe_subcode); } #if _MSC_VER>=1400 if(pExceptionInfo->exctype==CR_CPP_INVALID_PARAMETER) { if(pExceptionInfo->expression!=NULL) { // Write expression fprintf(f, " <InvParamExpression>%s</InvParamExpression>\n", XmlEncodeStr(pExceptionInfo->expression).c_str()); } if(pExceptionInfo->function!=NULL) { // Write function fprintf(f, " <InvParamFunction>%s</InvParamFunction>\n", XmlEncodeStr(pExceptionInfo->function).c_str()); } if(pExceptionInfo->file!=NULL) { // Write file fprintf(f, " <InvParamFile>%s</InvParamFile>\n", XmlEncodeStr(pExceptionInfo->file).c_str()); // Write line number fprintf(f, " <InvParamLine>%d</InvParamLine>\n", pExceptionInfo->line); } } #endif // Write the number of GUI resources in use fprintf(f, " <GUIResourceCount>%lu</GUIResourceCount>\n", m_dwGuiResources); // Write count of open handles that belong to current process fprintf(f, " <OpenHandleCount>%lu</OpenHandleCount>\n", m_dwProcessHandleCount); // Write memory usage info fprintf(f, " <MemoryUsageKbytes>%s</MemoryUsageKbytes>\n", XmlEncodeStr(m_sMemUsage.GetBuffer(0)).c_str()); // Write list of custom user-added properties fprintf(f, " <CustomProps>\n"); std::map<CString, CString>::iterator pit = m_props.begin(); unsigned i; for (i = 0; i < m_props.size(); i++, pit++) { CString sPropName = pit->first; CString sPropValue = pit->second; fprintf(f, " <Prop name=\"%s\" value=\"%s\" />\n", XmlEncodeStr(sPropName).c_str(), XmlEncodeStr(sPropValue).c_str()); } fprintf(f, " </CustomProps>\n"); // Write list of files that present in this crash report fprintf(f, " <FileList>\n"); std::map<CString, FileItem>::iterator cur = m_files.begin(); for (i = 0; i < m_files.size(); i++, cur++) { CString sDestFile = (*cur).first; int pos = -1; sDestFile.Replace('/', '\\'); pos = sDestFile.ReverseFind('\\'); if(pos!=-1) sDestFile = sDestFile.Mid(pos+1); FileItem& fi = cur->second; fprintf(f, " <FileItem name=\"%s\" description=\"%s\" />\n", XmlEncodeStr(sDestFile).c_str(), XmlEncodeStr(fi.m_sDescription).c_str()); } fprintf(f, " </FileList>\n"); fprintf(f, "</CrashRpt>\n"); fclose(f); crSetErrorMsg(_T("Success.")); return 0; }
int CCrashHandler::SetProcessExceptionHandlers(DWORD dwFlags) { crSetErrorMsg(_T("Unspecified error.")); // If 0 is specified as dwFlags, assume all handlers should be // installed if((dwFlags&0x1FF)==0) dwFlags |= 0x1FFF; if(dwFlags&CR_INST_STRUCTURED_EXCEPTION_HANDLER) { // Install top-level SEH handler m_oldSehHandler = SetUnhandledExceptionFilter(SehHandler); } _set_error_mode(_OUT_TO_STDERR); #if _MSC_VER>=1300 if(dwFlags&CR_INST_PURE_CALL_HANDLER) { // Catch pure virtual function calls. // Because there is one _purecall_handler for the whole process, // calling this function immediately impacts all threads. The last // caller on any thread sets the handler. // http://msdn.microsoft.com/en-us/library/t296ys27.aspx m_prevPurec = _set_purecall_handler(PureCallHandler); } if(dwFlags&CR_INST_NEW_OPERATOR_ERROR_HANDLER) { // Catch new operator memory allocation exceptions _set_new_mode(1); // Force malloc() to call new handler too m_prevNewHandler = _set_new_handler(NewHandler); } #endif #if _MSC_VER>=1400 if(dwFlags&CR_INST_INVALID_PARAMETER_HANDLER) { // Catch invalid parameter exceptions. m_prevInvpar = _set_invalid_parameter_handler(InvalidParameterHandler); } #endif #if _MSC_VER>=1300 && _MSC_VER<1400 if(dwFlags&CR_INST_SECURITY_ERROR_HANDLER) { // Catch buffer overrun exceptions // The _set_security_error_handler is deprecated in VC8 C++ run time library m_prevSec = _set_security_error_handler(SecurityHandler); } #endif // Set up C++ signal handlers if(dwFlags&CR_INST_SIGABRT_HANDLER) { #if _MSC_VER>=1400 _set_abort_behavior(_CALL_REPORTFAULT, _CALL_REPORTFAULT); #endif // Catch an abnormal program termination m_prevSigABRT = signal(SIGABRT, SigabrtHandler); } if(dwFlags&CR_INST_SIGILL_HANDLER) { // Catch illegal instruction handler m_prevSigINT = signal(SIGINT, SigintHandler); } if(dwFlags&CR_INST_TERMINATE_HANDLER) { // Catch a termination request m_prevSigTERM = signal(SIGTERM, SigtermHandler); } crSetErrorMsg(_T("Success.")); return 0; }
// Installs C++ exception handlers that function on per-thread basis int CCrashHandler::SetThreadExceptionHandlers(DWORD dwFlags) { crSetErrorMsg(_T("Unspecified error.")); // If 0 is specified as dwFlags, assume all available exception handlers should be // installed if((dwFlags&0x1FFF)==0) dwFlags |= 0x1FFF; DWORD dwThreadId = GetCurrentThreadId(); CAutoLock lock(&m_csThreadExceptionHandlers); std::map<DWORD, ThreadExceptionHandlers>::iterator it = m_ThreadExceptionHandlers.find(dwThreadId); if(it!=m_ThreadExceptionHandlers.end()) { // handlers are already set for the thread ATLASSERT(0); crSetErrorMsg(_T("Can't install handlers for current thread twice.")); return 1; // failed } ThreadExceptionHandlers handlers; if(dwFlags&CR_INST_TERMINATE_HANDLER) { // Catch terminate() calls. // In a multithreaded environment, terminate functions are maintained // separately for each thread. Each new thread needs to install its own // terminate function. Thus, each thread is in charge of its own termination handling. // http://msdn.microsoft.com/en-us/library/t6fk7h29.aspx handlers.m_prevTerm = set_terminate(TerminateHandler); } if(dwFlags&CR_INST_UNEXPECTED_HANDLER) { // Catch unexpected() calls. // In a multithreaded environment, unexpected functions are maintained // separately for each thread. Each new thread needs to install its own // unexpected function. Thus, each thread is in charge of its own unexpected handling. // http://msdn.microsoft.com/en-us/library/h46t5b69.aspx handlers.m_prevUnexp = set_unexpected(UnexpectedHandler); } if(dwFlags&CR_INST_SIGFPE_HANDLER) { // Catch a floating point error typedef void (*sigh)(int); handlers.m_prevSigFPE = signal(SIGFPE, (sigh)SigfpeHandler); } if(dwFlags&CR_INST_SIGILL_HANDLER) { // Catch an illegal instruction handlers.m_prevSigILL = signal(SIGILL, SigillHandler); } if(dwFlags&CR_INST_SIGSEGV_HANDLER) { // Catch illegal storage access errors handlers.m_prevSigSEGV = signal(SIGSEGV, SigsegvHandler); } // Insert the structure to the list of handlers m_ThreadExceptionHandlers[dwThreadId] = handlers; // OK. crSetErrorMsg(_T("Success.")); return 0; }
int CCrashHandler::GenerateErrorReport( PCR_EXCEPTION_INFO pExceptionInfo) { crSetErrorMsg(_T("Unspecified error.")); // Validate input parameters if(pExceptionInfo==NULL) { crSetErrorMsg(_T("Exception info is NULL.")); return 1; } // Get exception pointers if not provided. if(pExceptionInfo->pexcptrs==NULL) { GetExceptionPointers(pExceptionInfo->code, &pExceptionInfo->pexcptrs); } // Collect miscellaneous crash info (current time etc.) CollectMiscCrashInfo(); // If error report is being generated manually, disable app restart. if(pExceptionInfo->bManual) m_bAppRestart = FALSE; // Let client add application-specific files / desktop screenshot // to the report via the crash callback function. if (m_lpfnCallback!=NULL && m_lpfnCallback(NULL)==FALSE) { crSetErrorMsg(_T("The operation was cancelled by client application.")); return 2; } if(m_bAddScreenshot) { m_rcAppWnd.SetRectEmpty(); // Find main app window HWND hWndMain = Utility::FindAppWindow(); if(hWndMain) { GetWindowRect(hWndMain, &m_rcAppWnd); } } // Create directory for the error report. BOOL bCreateDir = Utility::CreateFolder(m_sReportFolderName); if(!bCreateDir) { ATLASSERT(bCreateDir); CString szCaption; szCaption.Format(_T("%s has stopped working"), Utility::getAppName()); CString szMessage; // Try notify user about crash using message box. szMessage.Format(_T("Couldn't save error report.")); MessageBox(NULL, szMessage, szCaption, MB_OK|MB_ICONERROR); return 1; // Failed to create directory } // Create crash description file in XML format. CString sFileName; sFileName.Format(_T("%s\\crashrpt.xml"), m_sReportFolderName); AddFile(sFileName, NULL, _T("Crash Log"), CR_AF_MISSING_FILE_OK); int result = CreateCrashDescriptionXML(sFileName.GetBuffer(0), pExceptionInfo); ATLASSERT(result==0); // Write internal crash info to file. This info is required by // CrashSender.exe only and will not be sent anywhere. sFileName = m_sReportFolderName + _T("\\~CrashRptInternal.xml"); result = CreateInternalCrashInfoFile(sFileName, pExceptionInfo->pexcptrs); ATLASSERT(result==0); SetFileAttributes(sFileName, FILE_ATTRIBUTE_HIDDEN); // Start the CrashSender process which will take the dekstop screenshot, // copy user-specified files to the error report folder, create minidump, // notify user about crash, compress the report into ZIP archive and send // the error report. result = LaunchCrashSender(sFileName, TRUE); if(result!=0) { ATLASSERT(result==0); crSetErrorMsg(_T("Error launching CrashSender.exe")); // Failed to launch crash sender process. // Try notify user about crash using message box. CString szCaption; szCaption.Format(_T("%s has stopped working"), Utility::getAppName()); CString szMessage; szMessage.Format(_T("Error launching CrashSender.exe")); MessageBox(NULL, szMessage, szCaption, MB_OK|MB_ICONERROR); return 3; } // OK crSetErrorMsg(_T("Success.")); return 0; }
int CCrashHandler::Init( LPCTSTR lpcszAppName, LPCTSTR lpcszAppVersion, LPCTSTR lpcszCrashSenderPath, LPGETLOGFILE lpfnCallback, LPCTSTR lpcszTo, LPCTSTR lpcszSubject, LPCTSTR lpcszUrl, UINT (*puPriorities)[5], DWORD dwFlags, LPCTSTR lpcszPrivacyPolicyURL, LPCTSTR lpcszDebugHelpDLLPath, MINIDUMP_TYPE MiniDumpType, LPCTSTR lpcszErrorReportSaveDir, LPCTSTR lpcszRestartCmdLine, LPCTSTR lpcszLangFilePath, LPCTSTR lpcszEmailText, LPCTSTR lpcszSmtpProxy) { crSetErrorMsg(_T("Unspecified error.")); // Save application start time GetSystemTime(&m_AppStartTime); // Save minidump type m_bGenerateMinidump = (dwFlags&CR_INST_NO_MINIDUMP)?FALSE:TRUE; m_MiniDumpType = MiniDumpType; // Determine if should work in silent mode. FALSE is the default. m_bSilentMode = (dwFlags&CR_INST_NO_GUI)?TRUE:FALSE; // Save user supplied callback m_lpfnCallback = lpfnCallback; // Get handle to the EXE module used to create this process HMODULE hExeModule = GetModuleHandle(NULL); if(hExeModule==NULL) { ATLASSERT(hExeModule!=NULL); crSetErrorMsg(_T("Couldn't get module handle for the executable.")); return 1; } // Save EXE image name m_sImageName = Utility::GetModuleName(hExeModule); // Save application name m_sAppName = lpcszAppName; // If no app name provided, use the default (EXE name) if(m_sAppName.IsEmpty()) { m_sAppName = Utility::getAppName(); } // Save app version m_sAppVersion = lpcszAppVersion; // If no app version provided, use the default (EXE product version) if(m_sAppVersion.IsEmpty()) { m_sAppVersion = Utility::GetProductVersion(m_sImageName); } // Save URL to send reports via HTTP if(lpcszUrl!=NULL) { m_sUrl = CString(lpcszUrl); } // Determine what encoding to use when sending reports over HTTP. // FALSE is the default (use Base64 encoding for attachment). m_bHttpBinaryEncoding = (dwFlags&CR_INST_HTTP_BINARY_ENCODING)?TRUE:FALSE; m_bSendErrorReport = (dwFlags&CR_INST_DONT_SEND_REPORT)?FALSE:TRUE; if(!m_bSilentMode && !m_bSendErrorReport) { crSetErrorMsg(_T("Can't disable error sending when in GUI mode (incompatible flags specified).")); return 1; } m_bAppRestart = (dwFlags&CR_INST_APP_RESTART)?TRUE:FALSE; m_sRestartCmdLine = lpcszRestartCmdLine; // Save Email recipient address m_sEmailTo = lpcszTo; m_nSmtpPort = 25; // Check for custom SMTP port int pos = m_sEmailTo.ReverseFind(':'); if(pos>=0) { CString sServer = m_sEmailTo.Mid(0, pos); CString sPort = m_sEmailTo.Mid(pos+1); m_sEmailTo = sServer; m_nSmtpPort = _ttoi(sPort); } if(lpcszSmtpProxy!=NULL) { m_sSmtpProxyServer = lpcszSmtpProxy; m_nSmtpProxyPort = 25; int pos = m_sSmtpProxyServer.ReverseFind(':'); if(pos>=0) { CString sServer = m_sSmtpProxyServer.Mid(0, pos); CString sPort = m_sSmtpProxyServer.Mid(pos+1); m_sSmtpProxyServer = sServer; m_nSmtpProxyPort = _ttoi(sPort); } } // Save E-mail subject m_sEmailSubject = lpcszSubject; // If the subject is empty... if(m_sEmailSubject.IsEmpty()) { // Generate the default subject m_sEmailSubject.Format(_T("%s %s Error Report"), m_sAppName, m_sAppVersion.IsEmpty()?_T("[unknown_ver]"):m_sAppVersion); } // Save Email text. m_sEmailText = lpcszEmailText; // Save report sending priorities if(puPriorities!=NULL) memcpy(&m_uPriorities, puPriorities, 3*sizeof(UINT)); else memset(&m_uPriorities, 0, 3*sizeof(UINT)); // Save privacy policy URL (if exists) if(lpcszPrivacyPolicyURL!=NULL) m_sPrivacyPolicyURL = lpcszPrivacyPolicyURL; // Get the name of CrashRpt DLL LPTSTR pszCrashRptModule = NULL; #ifndef CRASHRPT_LIB #ifdef _DEBUG pszCrashRptModule = _T("CrashRptd.dll"); #else pszCrashRptModule = _T("CrashRpt.dll"); #endif //_DEBUG #else //!CRASHRPT_LIB pszCrashRptModule = NULL; #endif // Get handle to the CrashRpt module that is loaded by the current process HMODULE hCrashRptModule = GetModuleHandle(pszCrashRptModule); if(hCrashRptModule==NULL) { ATLASSERT(hCrashRptModule!=NULL); crSetErrorMsg(_T("Couldn't get handle to CrashRpt.dll.")); return 1; } // Save path to CrashSender.exe if(lpcszCrashSenderPath==NULL) { // By default assume that CrashSender.exe is located in the same dir as CrashRpt.dll m_sPathToCrashSender = Utility::GetModulePath(hCrashRptModule); } else { // Save user-specified path m_sPathToCrashSender = CString(lpcszCrashSenderPath); } // Remove ending backslash if any if(m_sPathToCrashSender.Right(1)!='\\') m_sPathToCrashSender+="\\"; // Determine where to look for language file. if(lpcszLangFilePath!=NULL) { // User has provided the custom lang file path. m_sLangFileName = lpcszLangFilePath; } else { // Look for crashrpt_lang.ini in the same folder as CrashSender.exe. m_sLangFileName = m_sPathToCrashSender + _T("crashrpt_lang.ini"); } CString sLangFileVer = Utility::GetINIString(m_sLangFileName, _T("Settings"), _T("CrashRptVersion")); int lang_file_ver = _ttoi(sLangFileVer); if(lang_file_ver!=CRASHRPT_VER) { ATLASSERT(lang_file_ver==CRASHRPT_VER); crSetErrorMsg(_T("Missing language file or wrong language file version.")); return 1; // Language INI file has wrong version! } // Get CrashSender EXE name CString sCrashSenderName; #ifdef _DEBUG sCrashSenderName = _T("CrashSenderd.exe"); #else sCrashSenderName = _T("CrashSender.exe"); #endif //_DEBUG m_sPathToCrashSender+=sCrashSenderName; // Check that CrashSender.exe file exists HANDLE hFile = CreateFile(m_sPathToCrashSender, FILE_GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if(hFile==INVALID_HANDLE_VALUE) { ATLASSERT(hFile!=INVALID_HANDLE_VALUE); crSetErrorMsg(_T("Couldn't locate CrashSender.exe in specified directory.")); return 1; // CrashSender not found! } CloseHandle(hFile); if(lpcszDebugHelpDLLPath==NULL) { // By default assume that debughlp.dll is located in the same dir as CrashRpt.dll m_sPathToDebugHelpDll = Utility::GetModulePath(hCrashRptModule); } else m_sPathToDebugHelpDll = CString(lpcszDebugHelpDLLPath); if(m_sPathToDebugHelpDll.Right(1)!='\\') m_sPathToDebugHelpDll+="\\"; const CString sDebugHelpDLL_name = "dbghelp.dll"; m_sPathToDebugHelpDll+=sDebugHelpDLL_name; m_hDbgHelpDll = LoadLibrary(m_sPathToDebugHelpDll); if(!m_hDbgHelpDll) { //try again ... fallback to dbghelp.dll in path m_hDbgHelpDll = LoadLibrary(sDebugHelpDLL_name); if(!m_hDbgHelpDll) { ATLASSERT(m_hDbgHelpDll); crSetErrorMsg(_T("Couldn't load dbghelp.dll.")); return 1; } } FreeLibrary(m_hDbgHelpDll); // Generate unique GUID for this crash report. if(0!=Utility::GenerateGUID(m_sCrashGUID)) { ATLASSERT(0); crSetErrorMsg(_T("Couldn't generate crash GUID.")); return 1; } // Create event that will be used to synchronize with CrashSender.exe process CString sEventName; sEventName.Format(_T("Local\\CrashRptEvent_%s"), m_sCrashGUID); m_hEvent = CreateEvent(NULL, FALSE, FALSE, sEventName); if(m_hEvent==NULL) { ATLASSERT(0); crSetErrorMsg(_T("Couldn't create synchronization event.")); return 1; } // Get operating system friendly name. if(0!=Utility::GetOSFriendlyName(m_sOSName)) { ATLASSERT(0); crSetErrorMsg(_T("Couldn't get operating system's friendly name.")); return 1; } if(lpcszErrorReportSaveDir==NULL) { // Create %LOCAL_APPDATA%\CrashRpt\UnsavedCrashReports\AppName_AppVer folder. CString sLocalAppDataFolder; DWORD dwCSIDL = CSIDL_LOCAL_APPDATA; Utility::GetSpecialFolder(dwCSIDL, sLocalAppDataFolder); m_sUnsentCrashReportsFolder.Format(_T("%s\\CrashRpt\\UnsentCrashReports\\%s_%s"), sLocalAppDataFolder, m_sAppName, m_sAppVersion); } else { m_sUnsentCrashReportsFolder = lpcszErrorReportSaveDir; } BOOL bCreateDir = Utility::CreateFolder(m_sUnsentCrashReportsFolder); if(!bCreateDir) { ATLASSERT(0); crSetErrorMsg(_T("Couldn't create crash report directory.")); return 1; } // Save the name of the folder we will save this crash report (if occur) m_sReportFolderName = m_sUnsentCrashReportsFolder + _T("\\") + m_sCrashGUID; // Set exception handlers with initial values (NULLs) InitPrevExceptionHandlerPointers(); // Set exception handlers that work on per-process basis int nSetProcessHandlers = SetProcessExceptionHandlers(dwFlags); if(nSetProcessHandlers!=0) { ATLASSERT(nSetProcessHandlers==0); crSetErrorMsg(_T("Couldn't set C++ exception handlers for current process.")); return 1; } // Set exception handlers that work on per-thread basis int nSetThreadHandlers = SetThreadExceptionHandlers(dwFlags); if(nSetThreadHandlers!=0) { ATLASSERT(nSetThreadHandlers==0); crSetErrorMsg(_T("Couldn't set C++ exception handlers for main execution thread.")); return 1; } // Associate this handler with the caller process m_pProcessCrashHandler = this; //LaunchCrashSender(_T("/resend"), FALSE); // OK. m_bInitialized = TRUE; crSetErrorMsg(_T("Success.")); return 0; }
CRASHRPTAPI(int) crInstallW(CR_INSTALL_INFOW* pInfo) { int nStatus = -1; crSetErrorMsg(_T("Success.")); strconv_t strconv; CCrashHandler *pCrashHandler = NULL; // Validate input parameters. if(pInfo==NULL || pInfo->cb!=sizeof(CR_INSTALL_INFOW)) { crSetErrorMsg(_T("pInfo is NULL or pInfo->cb member is not valid.")); nStatus = 1; goto cleanup; } // Check if crInstall() already was called for current process. pCrashHandler = CCrashHandler::GetCurrentProcessCrashHandler(); if(pCrashHandler!=NULL && pCrashHandler->IsInitialized()) { crSetErrorMsg(_T("Can't install crash handler to the same process twice.")); nStatus = 2; goto cleanup; } if(pCrashHandler==NULL) { pCrashHandler = new CCrashHandler(); if(pCrashHandler==NULL) { crSetErrorMsg(_T("Error allocating memory for crash handler.")); nStatus = 3; goto cleanup; } } LPCTSTR ptszAppName = strconv.w2t((LPWSTR)pInfo->pszAppName); LPCTSTR ptszAppVersion = strconv.w2t((LPWSTR)pInfo->pszAppVersion); LPCTSTR ptszCrashSenderPath = strconv.w2t((LPWSTR)pInfo->pszCrashSenderPath); LPCTSTR ptszEmailTo = strconv.w2t((LPWSTR)pInfo->pszEmailTo); LPCTSTR ptszEmailSubject = strconv.w2t((LPWSTR)pInfo->pszEmailSubject); LPCTSTR ptszUrl = strconv.w2t((LPWSTR)pInfo->pszUrl); LPCTSTR ptszPrivacyPolicyURL = strconv.w2t((LPWSTR)pInfo->pszPrivacyPolicyURL); LPCTSTR ptszDebugHelpDLL_file = strconv.w2t((LPWSTR)pInfo->pszDebugHelpDLL); MINIDUMP_TYPE miniDumpType = pInfo->uMiniDumpType; LPCTSTR ptszErrorReportSaveDir = strconv.w2t((LPWSTR)pInfo->pszErrorReportSaveDir); LPCTSTR ptszRestartCmdLine = strconv.w2t((LPWSTR)pInfo->pszRestartCmdLine); LPCTSTR ptszLangFilePath = strconv.w2t((LPWSTR)pInfo->pszLangFilePath); LPCTSTR ptszEmailText = strconv.w2t((LPWSTR)pInfo->pszEmailText); LPCTSTR ptszSmtpProxy = strconv.w2t((LPWSTR)pInfo->pszSmtpProxy); int nInitResult = pCrashHandler->Init( ptszAppName, ptszAppVersion, ptszCrashSenderPath, pInfo->pfnCrashCallback, ptszEmailTo, ptszEmailSubject, ptszUrl, &pInfo->uPriorities, pInfo->dwFlags, ptszPrivacyPolicyURL, ptszDebugHelpDLL_file, miniDumpType, ptszErrorReportSaveDir, ptszRestartCmdLine, ptszLangFilePath, ptszEmailText, ptszSmtpProxy ); if(nInitResult!=0) { nStatus = 4; goto cleanup; } // OK. nStatus = 0; cleanup: if(nStatus!=0) // If failed { if(pCrashHandler!=NULL && !pCrashHandler->IsInitialized()) { // Release crash handler object CCrashHandler::ReleaseCurrentProcessCrashHandler(); } } return nStatus; }