diff --git a/components/crashcatcher/windows_crashcatcher.cpp b/components/crashcatcher/windows_crashcatcher.cpp index af5125928a..d51db945cf 100644 --- a/components/crashcatcher/windows_crashcatcher.cpp +++ b/components/crashcatcher/windows_crashcatcher.cpp @@ -27,7 +27,8 @@ namespace Crash CrashCatcher* CrashCatcher::sInstance = nullptr; - CrashCatcher::CrashCatcher(int argc, char** argv, const std::filesystem::path& crashLogPath) + CrashCatcher::CrashCatcher( + int argc, char** argv, const std::filesystem::path& crashDumpPath, const std::filesystem::path& freezeDumpPath) { assert(sInstance == nullptr); // don't allow two instances @@ -49,7 +50,7 @@ namespace Crash if (!shmHandle) { setupIpc(); - startMonitorProcess(crashLogPath); + startMonitorProcess(crashDumpPath, freezeDumpPath); installHandler(); } else @@ -126,7 +127,8 @@ namespace Crash SetUnhandledExceptionFilter(vectoredExceptionHandler); } - void CrashCatcher::startMonitorProcess(const std::filesystem::path& crashLogPath) + void CrashCatcher::startMonitorProcess( + const std::filesystem::path& crashDumpPath, const std::filesystem::path& freezeDumpPath) { std::wstring executablePath; DWORD copied = 0; @@ -137,14 +139,23 @@ namespace Crash } while (copied >= executablePath.size()); executablePath.resize(copied); - memset(mShm->mStartup.mLogFilePath, 0, sizeof(mShm->mStartup.mLogFilePath)); - const auto str = crashLogPath.u8string(); + memset(mShm->mStartup.mCrashDumpFilePath, 0, sizeof(mShm->mStartup.mCrashDumpFilePath)); + const auto str = crashDumpPath.u8string(); size_t length = str.length(); if (length >= MAX_LONG_PATH) length = MAX_LONG_PATH - 1; - strncpy_s(mShm->mStartup.mLogFilePath, sizeof mShm->mStartup.mLogFilePath, + strncpy_s(mShm->mStartup.mCrashDumpFilePath, sizeof mShm->mStartup.mCrashDumpFilePath, Misc::StringUtils::u8StringToString(str).c_str(), length); - mShm->mStartup.mLogFilePath[length] = '\0'; + mShm->mStartup.mCrashDumpFilePath[length] = '\0'; + + memset(mShm->mStartup.mFreezeDumpFilePath, 0, sizeof(mShm->mStartup.mFreezeDumpFilePath)); + const auto strFreeze = freezeDumpPath.u8string(); + length = strFreeze.length(); + if (length >= MAX_LONG_PATH) + length = MAX_LONG_PATH - 1; + strncpy_s(mShm->mStartup.mFreezeDumpFilePath, sizeof mShm->mStartup.mFreezeDumpFilePath, + Misc::StringUtils::u8StringToString(strFreeze).c_str(), length); + mShm->mStartup.mFreezeDumpFilePath[length] = '\0'; // note that we don't need to lock the SHM here, the other process has not started yet mShm->mEvent = CrashSHM::Event::Startup; @@ -204,7 +215,7 @@ namespace Crash waitMonitor(); std::string message = "OpenMW has encountered a fatal error.\nCrash log saved to '" - + std::string(mShm->mStartup.mLogFilePath) + + std::string(mShm->mStartup.mCrashDumpFilePath) + "'.\nPlease report this to https://gitlab.com/OpenMW/openmw/issues !"; SDL_ShowSimpleMessageBox(0, "Fatal Error", message.c_str(), nullptr); } diff --git a/components/crashcatcher/windows_crashcatcher.hpp b/components/crashcatcher/windows_crashcatcher.hpp index 2b0fc31e34..206cc2a2bb 100644 --- a/components/crashcatcher/windows_crashcatcher.hpp +++ b/components/crashcatcher/windows_crashcatcher.hpp @@ -27,7 +27,8 @@ namespace Crash class CrashCatcher final { public: - CrashCatcher(int argc, char** argv, const std::filesystem::path& crashLogPath); + CrashCatcher(int argc, char** argv, const std::filesystem::path& crashDumpPath, + const std::filesystem::path& freezeDumpPath); ~CrashCatcher(); private: @@ -54,7 +55,8 @@ namespace Crash void shmUnlock(); - void startMonitorProcess(const std::filesystem::path& crashLogPath); + void startMonitorProcess( + const std::filesystem::path& crashDumpPath, const std::filesystem::path& freezeDumpPath); void waitMonitor(); diff --git a/components/crashcatcher/windows_crashmonitor.cpp b/components/crashcatcher/windows_crashmonitor.cpp index d2d3177489..ea316c8a5c 100644 --- a/components/crashcatcher/windows_crashmonitor.cpp +++ b/components/crashcatcher/windows_crashmonitor.cpp @@ -192,7 +192,7 @@ namespace Crash case CrashSHM::Event::None: break; case CrashSHM::Event::Crashed: - handleCrash(); + handleCrash(false); running = false; break; case CrashSHM::Event::Shutdown: @@ -211,10 +211,10 @@ namespace Crash if (mFreezeAbort) { - handleCrash(); + handleCrash(true); TerminateProcess(mAppProcessHandle, 0xDEAD); std::string message = "OpenMW appears to have frozen.\nCrash log saved to '" - + std::string(mShm->mStartup.mLogFilePath) + + std::string(mShm->mStartup.mFreezeDumpFilePath) + "'.\nPlease report this to https://gitlab.com/OpenMW/openmw/issues !"; SDL_ShowSimpleMessageBox(0, "Fatal Error", message.c_str(), nullptr); } @@ -238,7 +238,7 @@ namespace Crash return utf16; } - void CrashMonitor::handleCrash() + void CrashMonitor::handleCrash(bool isFreeze) { DWORD processId = GetProcessId(mAppProcessHandle); @@ -256,7 +256,8 @@ namespace Crash if (miniDumpWriteDump == NULL) return; - std::wstring utf16Path = utf8ToUtf16(mShm->mStartup.mLogFilePath); + std::wstring utf16Path + = utf8ToUtf16(isFreeze ? mShm->mStartup.mFreezeDumpFilePath : mShm->mStartup.mCrashDumpFilePath); if (utf16Path.empty()) return; diff --git a/components/crashcatcher/windows_crashmonitor.hpp b/components/crashcatcher/windows_crashmonitor.hpp index 35ff91495d..3e6d3adb98 100644 --- a/components/crashcatcher/windows_crashmonitor.hpp +++ b/components/crashcatcher/windows_crashmonitor.hpp @@ -51,7 +51,7 @@ namespace Crash void shmUnlock(); - void handleCrash(); + void handleCrash(bool isFreeze); void showFreezeMessageBox(); diff --git a/components/crashcatcher/windows_crashshm.hpp b/components/crashcatcher/windows_crashshm.hpp index eba478e744..1b3150fe84 100644 --- a/components/crashcatcher/windows_crashshm.hpp +++ b/components/crashcatcher/windows_crashshm.hpp @@ -28,7 +28,8 @@ namespace Crash HANDLE mSignalApp; HANDLE mSignalMonitor; HANDLE mShmMutex; - char mLogFilePath[MAX_LONG_PATH]; + char mCrashDumpFilePath[MAX_LONG_PATH]; + char mFreezeDumpFilePath[MAX_LONG_PATH]; } mStartup; struct Crashed diff --git a/components/debug/debugging.cpp b/components/debug/debugging.cpp index 4364ec1af5..ff1046f5e6 100644 --- a/components/debug/debugging.cpp +++ b/components/debug/debugging.cpp @@ -17,6 +17,19 @@ #include #include #include + +#include + +#pragma push_macro("FAR") +#pragma push_macro("NEAR") +#undef FAR +#define FAR +#undef NEAR +#define NEAR +#include +#pragma pop_macro("NEAR") +#pragma pop_macro("FAR") + #endif #include @@ -169,10 +182,7 @@ namespace Debug CurrentDebugLevel = Verbose; } - virtual std::streamsize writeImpl(const char* str, std::streamsize size, Level debugLevel) - { - return size; - } + virtual std::streamsize writeImpl(const char* str, std::streamsize size, Level debugLevel) { return size; } }; #if defined _WIN32 && defined _DEBUG @@ -319,9 +329,16 @@ int wrapApplication(int (*innerApplication)(int argc, char* argv[]), int argc, c env == nullptr || Misc::StringUtils::toNumeric(env, 0) == 0) { #if defined(_WIN32) - const std::string crashLogName = Misc::StringUtils::lowerCase(appName) + "-crash.dmp"; - Crash::CrashCatcher crashy( - argc, argv, Files::pathToUnicodeString(std::filesystem::temp_directory_path() / crashLogName)); + const std::string crashDumpName = Misc::StringUtils::lowerCase(appName) + "-crash.dmp"; + const std::string freezeDumpName = Misc::StringUtils::lowerCase(appName) + "-freeze.dmp"; + std::filesystem::path dumpDirectory = std::filesystem::temp_directory_path(); + PWSTR userProfile = nullptr; + if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Profile, 0, nullptr, &userProfile))) + { + dumpDirectory = userProfile; + } + CoTaskMemFree(userProfile); + Crash::CrashCatcher crashy(argc, argv, dumpDirectory / crashDumpName, dumpDirectory / freezeDumpName); #else const std::string crashLogName = Misc::StringUtils::lowerCase(appName) + "-crash.log"; // install the crash handler as soon as possible.