[Exception] Destroy windows and suspend threads
This commit is contained in:
parent
eefc16cbe0
commit
ee06e79a28
@ -75,9 +75,9 @@ namespace Components
|
||||
wprintw(Console::InfoWindow, "%s : %d/%d players : map %s", hostname.data(), clientCount, maxclientCount, (mapname.size() ? mapname.data() : "none"));
|
||||
wnoutrefresh(Console::InfoWindow);
|
||||
}
|
||||
else if(IsWindow(*reinterpret_cast<HWND*>(0x64A3288)) != FALSE)
|
||||
else if(IsWindow(Console::GetWindow()) != FALSE)
|
||||
{
|
||||
SetWindowTextA(*reinterpret_cast<HWND*>(0x64A3288), Utils::String::VA("IW4x(" VERSION ") : %s", hostname.data()));
|
||||
SetWindowTextA(Console::GetWindow(), Utils::String::VA("IW4x(" VERSION ") : %s", hostname.data()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -389,7 +389,7 @@ namespace Components
|
||||
Game::Sys_ShowConsole();
|
||||
|
||||
MSG message;
|
||||
while (IsWindow(*reinterpret_cast<HWND*>(0x64A3288)) != FALSE && GetMessageA(&message, nullptr, 0, 0))
|
||||
while (IsWindow(Console::GetWindow()) != FALSE && GetMessageA(&message, nullptr, 0, 0))
|
||||
{
|
||||
TranslateMessage(&message);
|
||||
DispatchMessageA(&message);
|
||||
@ -494,6 +494,11 @@ namespace Components
|
||||
}
|
||||
}
|
||||
|
||||
HWND Console::GetWindow()
|
||||
{
|
||||
return *reinterpret_cast<HWND*>(0x64A3288);
|
||||
}
|
||||
|
||||
Game::dvar_t* Console::RegisterConColor(const char* name, float r, float g, float b, float a, float min, float max, int flags, const char* description)
|
||||
{
|
||||
static struct
|
||||
|
@ -19,6 +19,8 @@ namespace Components
|
||||
|
||||
static void FreeNativeConsole();
|
||||
|
||||
static HWND GetWindow();
|
||||
|
||||
private:
|
||||
// Text-based console stuff
|
||||
static WINDOW* OutputWindow;
|
||||
|
@ -15,6 +15,25 @@ namespace Components
|
||||
longjmp(_Buf, _Value);
|
||||
}
|
||||
|
||||
void Exception::SuspendProcess()
|
||||
{
|
||||
FreeConsole();
|
||||
|
||||
if (IsWindow(Console::GetWindow()) != FALSE) DestroyWindow(Console::GetWindow());
|
||||
if (IsWindow(Window::GetWindow()) != FALSE) DestroyWindow(Window::GetWindow());
|
||||
|
||||
// This makes sure we either destroy the windows or wait till they are destroyed
|
||||
MSG msg;
|
||||
while ((IsWindow(Window::GetWindow()) != FALSE || IsWindow(Console::GetWindow()) != FALSE) && GetMessage(&msg, nullptr, NULL, NULL))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
// This only suspends the main game threads, which is enough for us
|
||||
Game::Sys_SuspendOtherThreads();
|
||||
}
|
||||
|
||||
LONG WINAPI Exception::ExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo)
|
||||
{
|
||||
// Pass on harmless errors
|
||||
@ -34,10 +53,12 @@ namespace Components
|
||||
errorStr = Utils::String::VA("Fatal error (0x%08X) at 0x%08X.", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress);
|
||||
}
|
||||
|
||||
Exception::SuspendProcess();
|
||||
|
||||
bool doFullDump = Flags::HasFlag("bigdumps") || Flags::HasFlag("reallybigdumps");
|
||||
if (!doFullDump)
|
||||
{
|
||||
if (MessageBoxA(NULL,
|
||||
if (MessageBoxA(nullptr,
|
||||
Utils::String::VA("IW4x has encountered an exception and needs to close.\n"
|
||||
"%s\n" // errorStr
|
||||
"Would you like to create a full crash dump for the developers? (this can be almost 100mb)", errorStr),
|
||||
@ -55,8 +76,8 @@ namespace Components
|
||||
auto minidump = MinidumpUpload::CreateQueuedMinidump(ExceptionInfo, Exception::MiniDumpType);
|
||||
if (!minidump)
|
||||
{
|
||||
MessageBoxA(NULL, "Minidump Error",
|
||||
Utils::String::VA("There was an error creating the minidump (%s)! Hit OK to close the program.", Utils::GetLastWindowsError()), MB_OK | MB_ICONERROR);
|
||||
MessageBoxA(nullptr, "Minidump Error",
|
||||
Utils::String::VA("There was an error creating the minidump (%s)! Hit OK to close the program.", Utils::GetLastWindowsError().data()), MB_OK | MB_ICONERROR);
|
||||
OutputDebugStringA("Failed to create new minidump!");
|
||||
Utils::OutputDebugLastError();
|
||||
TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode);
|
||||
|
@ -13,14 +13,15 @@ namespace Components
|
||||
#endif
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER Hook();
|
||||
|
||||
static int MiniDumpType;
|
||||
static void SetMiniDumpType(bool codeseg, bool dataseg);
|
||||
|
||||
private:
|
||||
static void SuspendProcess();
|
||||
static LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo);
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilterStub(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
|
||||
static __declspec(noreturn) void ErrorLongJmp(jmp_buf _Buf, int _Value);
|
||||
|
||||
static int MiniDumpType;
|
||||
static Utils::Hook SetFilterHook;
|
||||
};
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ namespace Components
|
||||
|
||||
bool Logger::IsConsoleReady()
|
||||
{
|
||||
return (IsWindow(*reinterpret_cast<HWND*>(0x64A3288)) != FALSE || (Dedicated::IsEnabled() && !Flags::HasFlag("console")));
|
||||
return (IsWindow(Console::GetWindow()) != FALSE || (Dedicated::IsEnabled() && !Flags::HasFlag("console")));
|
||||
}
|
||||
|
||||
void Logger::PrintStub(int channel, const char* message, ...)
|
||||
|
@ -61,6 +61,11 @@ namespace Components
|
||||
return ((point.x - rect.left) > 0 && (point.y - rect.top) > 0 && (rect.right - point.x) > 0 && (rect.bottom - point.y) > 0);
|
||||
}
|
||||
|
||||
HWND Window::GetWindow()
|
||||
{
|
||||
return Window::MainWindow;
|
||||
}
|
||||
|
||||
int Window::IsNoBorder()
|
||||
{
|
||||
return Window::NoBorder.get<bool>();
|
||||
|
@ -20,6 +20,8 @@ namespace Components
|
||||
|
||||
static bool IsCursorWithin(HWND window);
|
||||
|
||||
static HWND GetWindow();
|
||||
|
||||
private:
|
||||
static BOOL CursorVisible;
|
||||
static Dvar::Var NoBorder;
|
||||
|
@ -244,6 +244,7 @@ namespace Game
|
||||
Sys_IsDatabaseThread_t Sys_IsDatabaseThread = Sys_IsDatabaseThread_t(0x4C6020);
|
||||
Sys_SendPacket_t Sys_SendPacket = Sys_SendPacket_t(0x60FDC0);
|
||||
Sys_ShowConsole_t Sys_ShowConsole = Sys_ShowConsole_t(0x4305E0);
|
||||
Sys_SuspendOtherThreads_t Sys_SuspendOtherThreads = Sys_SuspendOtherThreads_t(0x45A190);
|
||||
Sys_ListFiles_t Sys_ListFiles = Sys_ListFiles_t(0x45A660);
|
||||
Sys_Milliseconds_t Sys_Milliseconds = Sys_Milliseconds_t(0x42A660);
|
||||
|
||||
|
@ -598,6 +598,9 @@ namespace Game
|
||||
typedef void(__cdecl * Sys_ShowConsole_t)();
|
||||
extern Sys_ShowConsole_t Sys_ShowConsole;
|
||||
|
||||
typedef void(__cdecl * Sys_SuspendOtherThreads_t)();
|
||||
extern Sys_SuspendOtherThreads_t Sys_SuspendOtherThreads;
|
||||
|
||||
typedef void(__cdecl * UI_AddMenuList_t)(UiContext *dc, MenuList *menuList, int close);
|
||||
extern UI_AddMenuList_t UI_AddMenuList;
|
||||
|
||||
|
@ -26,14 +26,7 @@ namespace Utils
|
||||
void OutputDebugLastError()
|
||||
{
|
||||
DWORD errorMessageID = ::GetLastError();
|
||||
LPSTR messageBuffer = nullptr;
|
||||
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPSTR>(&messageBuffer), 0, nullptr);
|
||||
std::string message(messageBuffer, size);
|
||||
|
||||
OutputDebugStringA(Utils::String::VA("Last error code: 0x%08X (%s)\n", errorMessageID, message));
|
||||
|
||||
LocalFree(messageBuffer);
|
||||
OutputDebugStringA(Utils::String::VA("Last error code: 0x%08X (%s)\n", errorMessageID, GetLastWindowsError().data()));
|
||||
}
|
||||
|
||||
std::string GetLastWindowsError()
|
||||
|
Loading…
Reference in New Issue
Block a user