WindowsErrorReporting.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. // Description : Support for Windows Error Reporting (WER)
  9. #include "CrySystem_precompiled.h"
  10. #ifdef WIN32
  11. #include "System.h"
  12. #include <AzCore/PlatformIncl.h>
  13. #include <tchar.h>
  14. #include "errorrep.h"
  15. #include "ISystem.h"
  16. #include <DbgHelp.h>
  17. static WCHAR szPath[MAX_PATH + 1];
  18. static WCHAR szFR[] = L"\\System32\\FaultRep.dll";
  19. WCHAR* GetFullPathToFaultrepDll(void)
  20. {
  21. UINT rc = GetSystemWindowsDirectoryW(szPath, ARRAYSIZE(szPath));
  22. if (rc == 0 || rc > ARRAYSIZE(szPath) - ARRAYSIZE(szFR) - 1)
  23. {
  24. return NULL;
  25. }
  26. wcscat_s(szPath, szFR);
  27. return szPath;
  28. }
  29. typedef BOOL (WINAPI * MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
  30. CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
  31. CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
  32. CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam
  33. );
  34. //////////////////////////////////////////////////////////////////////////
  35. LONG WINAPI CryEngineExceptionFilterMiniDump(struct _EXCEPTION_POINTERS* pExceptionPointers, const char* szDumpPath, MINIDUMP_TYPE DumpType)
  36. {
  37. // note: In debug mode, this dll is loaded on startup anyway, so this should not incur an additional load unless it crashes
  38. // very early during startup.
  39. fflush(nullptr); // according to MSDN on fflush, calling fflush on null flushes all buffers.
  40. HMODULE hndDBGHelpDLL = LoadLibraryA("DBGHELP.DLL");
  41. if (!hndDBGHelpDLL)
  42. {
  43. CryLogAlways("Failed to record DMP file: Could not open DBGHELP.DLL");
  44. return EXCEPTION_CONTINUE_SEARCH;
  45. }
  46. MINIDUMPWRITEDUMP dumpFnPtr = (MINIDUMPWRITEDUMP)::GetProcAddress(hndDBGHelpDLL, "MiniDumpWriteDump");
  47. if (!dumpFnPtr)
  48. {
  49. CryLogAlways("Failed to record DMP file: Unable to find MiniDumpWriteDump in DBGHELP.DLL");
  50. return EXCEPTION_CONTINUE_SEARCH;
  51. }
  52. AZStd::wstring szDumpPathW;
  53. AZStd::to_wstring(szDumpPathW, szDumpPath);
  54. HANDLE hFile = ::CreateFileW(szDumpPathW.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  55. if (hFile == INVALID_HANDLE_VALUE)
  56. {
  57. CryLogAlways("Failed to record DMP file: could not open file '%s' for writing - error code: %d", szDumpPath, GetLastError());
  58. return EXCEPTION_CONTINUE_SEARCH;
  59. }
  60. _MINIDUMP_EXCEPTION_INFORMATION ExInfo;
  61. ExInfo.ThreadId = ::GetCurrentThreadId();
  62. ExInfo.ExceptionPointers = pExceptionPointers;
  63. ExInfo.ClientPointers = NULL;
  64. BOOL bOK = dumpFnPtr(GetCurrentProcess(), GetCurrentProcessId(), hFile, DumpType, &ExInfo, NULL, NULL);
  65. ::CloseHandle(hFile);
  66. if (bOK)
  67. {
  68. CryLogAlways("Successfully recorded DMP file: '%s'", szDumpPath);
  69. return EXCEPTION_EXECUTE_HANDLER; // SUCCESS! you can execute your handlers now
  70. }
  71. else
  72. {
  73. CryLogAlways("Failed to record DMP file: '%s' - error code: %d", szDumpPath, GetLastError());
  74. }
  75. return EXCEPTION_CONTINUE_SEARCH;
  76. }
  77. //////////////////////////////////////////////////////////////////////////
  78. LONG WINAPI CryEngineExceptionFilterWER(struct _EXCEPTION_POINTERS* pExceptionPointers)
  79. {
  80. if (g_cvars.sys_WER > 1)
  81. {
  82. AZ::IO::FixedMaxPath dumpPath{ "@log@/CE2Dump.dmp" };
  83. if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr)
  84. {
  85. dumpPath = fileIoBase->ResolvePath(dumpPath, "@log@/CE2Dump.dmp");
  86. }
  87. MINIDUMP_TYPE mdumpValue = (MINIDUMP_TYPE)(MiniDumpNormal);
  88. if (g_cvars.sys_WER > 1)
  89. {
  90. mdumpValue = (MINIDUMP_TYPE)(g_cvars.sys_WER - 2);
  91. }
  92. return CryEngineExceptionFilterMiniDump(pExceptionPointers, dumpPath.c_str(), mdumpValue);
  93. }
  94. LONG lRet = EXCEPTION_CONTINUE_SEARCH;
  95. WCHAR* psz = GetFullPathToFaultrepDll();
  96. if (psz)
  97. {
  98. HMODULE hFaultRepDll = LoadLibraryW(psz);
  99. if (hFaultRepDll)
  100. {
  101. pfn_REPORTFAULT pfn = (pfn_REPORTFAULT)GetProcAddress(hFaultRepDll, "ReportFault");
  102. if (pfn)
  103. {
  104. pfn(pExceptionPointers, 0);
  105. lRet = EXCEPTION_EXECUTE_HANDLER;
  106. }
  107. FreeLibrary(hFaultRepDll);
  108. }
  109. }
  110. return lRet;
  111. }
  112. #endif // WIN32