From b9acc5a622613dbafb158d846bba34e16ac0a72c Mon Sep 17 00:00:00 2001 From: Dmytro Bogovych Date: Fri, 8 Jun 2018 11:43:03 +0300 Subject: [PATCH] - commit missed files - new crash reporter support + fixes for "press any key..." function --- src/engine/helper/HL_CrashRpt.cpp | 169 ++++++++++++++++++++++++++++++ src/engine/helper/HL_CrashRpt.h | 64 +++++++++++ src/engine/helper/HL_OsVersion.h | 3 + 3 files changed, 236 insertions(+) create mode 100644 src/engine/helper/HL_CrashRpt.cpp create mode 100644 src/engine/helper/HL_CrashRpt.h diff --git a/src/engine/helper/HL_CrashRpt.cpp b/src/engine/helper/HL_CrashRpt.cpp new file mode 100644 index 00000000..634101fe --- /dev/null +++ b/src/engine/helper/HL_CrashRpt.cpp @@ -0,0 +1,169 @@ +#include "HL_CrashRpt.h" +#include "HL_String.h" + +// Define this if CrashRpt has to be deployed as .dll +// #define CRASHRPT_DYNAMIC + +// --- CrashReporer --- +#if defined(TARGET_WIN) +#include "CrashRpt.h" + +BOOL WINAPI CrashReporter::Callback(LPVOID arg) +{ + return TRUE; +} + +typedef int(__stdcall *CrInstallProc)(__in PCR_INSTALL_INFOW pInfo); +static CrInstallProc CrInstall = nullptr; + +typedef int(__stdcall *CrUninstallProc)(); +static CrUninstallProc CrUninstall = nullptr; + +typedef int(__stdcall *CrInstallIntoCurrentThreadProc)(DWORD dwFlags); +static CrInstallIntoCurrentThreadProc CrInstallIntoCurrentThread = nullptr; + +typedef int(__stdcall *CrUninstallFromCurrentThreadProc)(); +static CrUninstallFromCurrentThreadProc CrUninstallFromCurrentThread = nullptr; + +typedef int(__stdcall *CrGetLastErrorMsgProc)(LPWSTR buffer, UINT size); +static CrGetLastErrorMsgProc CrGetLastErrorMsg = nullptr; + +static HMODULE CrLibraryHandle = NULL; +#endif + +void CrashReporter::init(const std::string& appname, const std::string& version, const std::string& url) +{ +#if defined(TARGET_WIN) +#if defined(CRASHRPT_DYNAMIC) + // Check if DLL functions are here + if (CrLibraryHandle) + return; // Library is loaded already - so initialized already + + CrLibraryHandle = ::LoadLibrary(TEXT("crashrpt.dll")); + if (!CrLibraryHandle) + return; // No logging here - initialization happens on very first stages, no chance to log anything + + CrInstall = (CrInstallProc)::GetProcAddress(CrLibraryHandle, "crInstallW"); + CrUninstall = (CrUninstallProc)::GetProcAddress(CrLibraryHandle, "crUninstall"); + CrInstallIntoCurrentThread = (CrInstallIntoCurrentThreadProc)::GetProcAddress(CrLibraryHandle, "crInstallToCurrentThread2"); + CrUninstallFromCurrentThread = (CrUninstallFromCurrentThreadProc)::GetProcAddress(CrLibraryHandle, "crUninstallFromCurrentThread"); + CrGetLastErrorMsg = (CrGetLastErrorMsgProc)::GetProcAddress(CrLibraryHandle, "crGetLastErrorMsgW"); +#else + CrInstall = &crInstallW; + CrUninstall = &crUninstall; + CrInstallIntoCurrentThread = &crInstallToCurrentThread2; + CrUninstallFromCurrentThread = &crUninstallFromCurrentThread; + CrGetLastErrorMsg = &crGetLastErrorMsgW; +#endif + + if (!isLoaded()) + return; + + CR_INSTALL_INFO info; + memset(&info, 0, sizeof(CR_INSTALL_INFO)); + info.cb = sizeof(CR_INSTALL_INFO); + struct + { + std::wstring appname, version, url; + } unicode; + unicode.appname = StringHelper::makeTstring(appname), + unicode.version = StringHelper::makeTstring(version), + unicode.url = StringHelper::makeTstring(url); + + if (unicode.appname.empty()) + unicode.appname = L"App"; + + if (unicode.url.empty()) + unicode.url = L"https://voipobjects.com/crashrpt/crashrpt.php"; + + if (unicode.version.empty()) + unicode.version = L"General version"; + + info.pszAppName = unicode.appname.c_str(); + info.pszAppVersion = unicode.version.c_str(); + info.pszEmailSubject = TEXT("Crash report"); + //info.pszEmailTo = L"amegyeri@minerva-soft.com"; + //info.pszUrl = L"http://ftp.minerva-soft.com/crashlog/crashrpt.php"; + //info.pszUrl = L"http://sip.crypttalk.com/crashlog/crashrpt.php"; + info.pszUrl = unicode.url.c_str(); + info.pfnCrashCallback = Callback; + info.uPriorities[CR_HTTP] = 1; + info.uPriorities[CR_SMTP] = CR_NEGATIVE_PRIORITY; + info.uPriorities[CR_SMAPI] = CR_NEGATIVE_PRIORITY; + info.dwFlags = 0; + info.pszCrashSenderPath = TEXT("."); + + int nResult = CrInstall(&info); + if (nResult) + { + wchar_t errorMsg[512] = L""; + CrGetLastErrorMsg(errorMsg, 512); + OutputDebugStringW(errorMsg); + //LogCritical("Core", << "Failed to install CrashReporter with code " << nResult << " and message " << errorMsg); + } +#endif +} + +void CrashReporter::free() +{ +#if defined(TARGET_WIN) + if (isLoaded()) + { + CrUninstall(); + CrInstall = nullptr; + CrUninstall = nullptr; + CrInstallIntoCurrentThread = nullptr; + CrUninstallFromCurrentThread = nullptr; + CrGetLastErrorMsg = nullptr; +#if defined(CRASHRPT_DYNAMIC) + ::FreeLibrary(CrLibraryHandle); CrLibraryHandle = NULL; +#endif + } +#endif +} + +bool CrashReporter::isLoaded() +{ +#if defined(TARGET_WIN) + return !(!CrInstall || !CrUninstall || !CrGetLastErrorMsg || + !CrInstallIntoCurrentThread || !CrUninstallFromCurrentThread); +#else + return false; +#endif +} + +void CrashReporter::initThread() +{ +#if defined(TARGET_WIN) + if (isLoaded()) + CrInstallIntoCurrentThread(0); +#endif +} + +void CrashReporter::freeThread() +{ +#if defined(TARGET_WIN) + if (isLoaded()) + CrUninstallFromCurrentThread(); +#endif +} + +CrashReporterThreadPoint::CrashReporterThreadPoint() +{ + CrashReporter::initThread(); +} + +CrashReporterThreadPoint::~CrashReporterThreadPoint() +{ + CrashReporter::freeThread(); +} + +CrashReporterGuard::CrashReporterGuard() +{ + CrashReporter::init("generic"); +} + +CrashReporterGuard::~CrashReporterGuard() +{ + CrashReporter::free(); +} diff --git a/src/engine/helper/HL_CrashRpt.h b/src/engine/helper/HL_CrashRpt.h new file mode 100644 index 00000000..13de47b8 --- /dev/null +++ b/src/engine/helper/HL_CrashRpt.h @@ -0,0 +1,64 @@ +#ifndef __CRASH_RPT_H +#define __CRASH_RPT_H + +#include + +#if defined(TARGET_WIN) +# include +# include +#endif + +// Helper class to translate SEH exceptions to C++ - sometimes it is needed +#if defined(TARGET_WIN) + +class SE_Exception +{ +private: + unsigned int nSE; +public: + SE_Exception() {} + SE_Exception(unsigned int n) : nSE(n) {} + ~SE_Exception() {} + unsigned int getSeNumber() { return nSE; } +}; + +extern void SEHToCpp(unsigned int, EXCEPTION_POINTERS*); + +// Although better way is to have _set_se_translator set - in our case we do not call it. +// The cause is usage of CrashRpt libraries - it gives better control on exception reporting. +# define SET_SEH_TO_CPP +//_set_se_translator(&SEHToCpp) +#else +# define SET_SEH_TO_CPP +#endif + +class CrashReporter +{ +public: + static void init(const std::string& appname, const std::string& version = "", const std::string& url = ""); + static void free(); + static void initThread(); + static void freeThread(); + static bool isLoaded(); + +#ifdef TARGET_WIN + static BOOL WINAPI Callback(LPVOID /*lpvState*/); +#endif +}; + +// RAII class to notify crash reporter about thread start/stop +class CrashReporterThreadPoint +{ +public: + CrashReporterThreadPoint(); + ~CrashReporterThreadPoint(); +}; + +class CrashReporterGuard +{ +public: + CrashReporterGuard(); + ~CrashReporterGuard(); +}; + +#endif diff --git a/src/engine/helper/HL_OsVersion.h b/src/engine/helper/HL_OsVersion.h index 952019c5..f6570647 100644 --- a/src/engine/helper/HL_OsVersion.h +++ b/src/engine/helper/HL_OsVersion.h @@ -48,4 +48,7 @@ extern int _kbhit(); #endif +#if defined(TARGET_WIN) +# include +#endif #endif