[Exception] Destroy windows and suspend threads

This commit is contained in:
momo5502 2017-02-10 09:50:08 +01:00
parent eefc16cbe0
commit ee06e79a28
10 changed files with 49 additions and 16 deletions

View File

@ -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

View File

@ -19,6 +19,8 @@ namespace Components
static void FreeNativeConsole();
static HWND GetWindow();
private:
// Text-based console stuff
static WINDOW* OutputWindow;

View File

@ -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);

View File

@ -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;
};
}

View File

@ -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, ...)

View File

@ -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>();

View File

@ -20,6 +20,8 @@ namespace Components
static bool IsCursorWithin(HWND window);
static HWND GetWindow();
private:
static BOOL CursorVisible;
static Dvar::Var NoBorder;

View File

@ -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);

View File

@ -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;

View File

@ -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()