[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"));
|
wprintw(Console::InfoWindow, "%s : %d/%d players : map %s", hostname.data(), clientCount, maxclientCount, (mapname.size() ? mapname.data() : "none"));
|
||||||
wnoutrefresh(Console::InfoWindow);
|
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();
|
Game::Sys_ShowConsole();
|
||||||
|
|
||||||
MSG message;
|
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);
|
TranslateMessage(&message);
|
||||||
DispatchMessageA(&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)
|
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
|
static struct
|
||||||
|
@ -19,6 +19,8 @@ namespace Components
|
|||||||
|
|
||||||
static void FreeNativeConsole();
|
static void FreeNativeConsole();
|
||||||
|
|
||||||
|
static HWND GetWindow();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Text-based console stuff
|
// Text-based console stuff
|
||||||
static WINDOW* OutputWindow;
|
static WINDOW* OutputWindow;
|
||||||
|
@ -15,6 +15,25 @@ namespace Components
|
|||||||
longjmp(_Buf, _Value);
|
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)
|
LONG WINAPI Exception::ExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo)
|
||||||
{
|
{
|
||||||
// Pass on harmless errors
|
// 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);
|
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");
|
bool doFullDump = Flags::HasFlag("bigdumps") || Flags::HasFlag("reallybigdumps");
|
||||||
if (!doFullDump)
|
if (!doFullDump)
|
||||||
{
|
{
|
||||||
if (MessageBoxA(NULL,
|
if (MessageBoxA(nullptr,
|
||||||
Utils::String::VA("IW4x has encountered an exception and needs to close.\n"
|
Utils::String::VA("IW4x has encountered an exception and needs to close.\n"
|
||||||
"%s\n" // errorStr
|
"%s\n" // errorStr
|
||||||
"Would you like to create a full crash dump for the developers? (this can be almost 100mb)", 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);
|
auto minidump = MinidumpUpload::CreateQueuedMinidump(ExceptionInfo, Exception::MiniDumpType);
|
||||||
if (!minidump)
|
if (!minidump)
|
||||||
{
|
{
|
||||||
MessageBoxA(NULL, "Minidump Error",
|
MessageBoxA(nullptr, "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);
|
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!");
|
OutputDebugStringA("Failed to create new minidump!");
|
||||||
Utils::OutputDebugLastError();
|
Utils::OutputDebugLastError();
|
||||||
TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode);
|
TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode);
|
||||||
|
@ -13,14 +13,15 @@ namespace Components
|
|||||||
#endif
|
#endif
|
||||||
static LPTOP_LEVEL_EXCEPTION_FILTER Hook();
|
static LPTOP_LEVEL_EXCEPTION_FILTER Hook();
|
||||||
|
|
||||||
static int MiniDumpType;
|
|
||||||
static void SetMiniDumpType(bool codeseg, bool dataseg);
|
static void SetMiniDumpType(bool codeseg, bool dataseg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static void SuspendProcess();
|
||||||
static LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo);
|
static LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo);
|
||||||
static LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilterStub(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
|
static LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilterStub(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
|
||||||
static __declspec(noreturn) void ErrorLongJmp(jmp_buf _Buf, int _Value);
|
static __declspec(noreturn) void ErrorLongJmp(jmp_buf _Buf, int _Value);
|
||||||
|
|
||||||
|
static int MiniDumpType;
|
||||||
static Utils::Hook SetFilterHook;
|
static Utils::Hook SetFilterHook;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ namespace Components
|
|||||||
|
|
||||||
bool Logger::IsConsoleReady()
|
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, ...)
|
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);
|
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()
|
int Window::IsNoBorder()
|
||||||
{
|
{
|
||||||
return Window::NoBorder.get<bool>();
|
return Window::NoBorder.get<bool>();
|
||||||
|
@ -20,6 +20,8 @@ namespace Components
|
|||||||
|
|
||||||
static bool IsCursorWithin(HWND window);
|
static bool IsCursorWithin(HWND window);
|
||||||
|
|
||||||
|
static HWND GetWindow();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static BOOL CursorVisible;
|
static BOOL CursorVisible;
|
||||||
static Dvar::Var NoBorder;
|
static Dvar::Var NoBorder;
|
||||||
|
@ -244,6 +244,7 @@ namespace Game
|
|||||||
Sys_IsDatabaseThread_t Sys_IsDatabaseThread = Sys_IsDatabaseThread_t(0x4C6020);
|
Sys_IsDatabaseThread_t Sys_IsDatabaseThread = Sys_IsDatabaseThread_t(0x4C6020);
|
||||||
Sys_SendPacket_t Sys_SendPacket = Sys_SendPacket_t(0x60FDC0);
|
Sys_SendPacket_t Sys_SendPacket = Sys_SendPacket_t(0x60FDC0);
|
||||||
Sys_ShowConsole_t Sys_ShowConsole = Sys_ShowConsole_t(0x4305E0);
|
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_ListFiles_t Sys_ListFiles = Sys_ListFiles_t(0x45A660);
|
||||||
Sys_Milliseconds_t Sys_Milliseconds = Sys_Milliseconds_t(0x42A660);
|
Sys_Milliseconds_t Sys_Milliseconds = Sys_Milliseconds_t(0x42A660);
|
||||||
|
|
||||||
|
@ -598,6 +598,9 @@ namespace Game
|
|||||||
typedef void(__cdecl * Sys_ShowConsole_t)();
|
typedef void(__cdecl * Sys_ShowConsole_t)();
|
||||||
extern Sys_ShowConsole_t Sys_ShowConsole;
|
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);
|
typedef void(__cdecl * UI_AddMenuList_t)(UiContext *dc, MenuList *menuList, int close);
|
||||||
extern UI_AddMenuList_t UI_AddMenuList;
|
extern UI_AddMenuList_t UI_AddMenuList;
|
||||||
|
|
||||||
|
@ -26,14 +26,7 @@ namespace Utils
|
|||||||
void OutputDebugLastError()
|
void OutputDebugLastError()
|
||||||
{
|
{
|
||||||
DWORD errorMessageID = ::GetLastError();
|
DWORD errorMessageID = ::GetLastError();
|
||||||
LPSTR messageBuffer = nullptr;
|
OutputDebugStringA(Utils::String::VA("Last error code: 0x%08X (%s)\n", errorMessageID, GetLastWindowsError().data()));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetLastWindowsError()
|
std::string GetLastWindowsError()
|
||||||
|
Loading…
Reference in New Issue
Block a user