mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-02-27 14:21:46 +00:00
- moved all exception handling out of the backends
The main catch is now in D_DoomMain, only calling platform specific functions to handle the output for the error. As a nice side effect, -norun can now be done without an exception, just by exiting D_DoomMain with a special exit code.
This commit is contained in:
parent
b5fa08bf15
commit
96006eb94f
11 changed files with 271 additions and 309 deletions
|
@ -917,7 +917,7 @@ int PrintString (int iprintlevel, const char *outline)
|
||||||
return 0; // Don't waste time on calculating this if nothing at all was printed...
|
return 0; // Don't waste time on calculating this if nothing at all was printed...
|
||||||
}
|
}
|
||||||
|
|
||||||
extern bool gameisdead;
|
bool gameisdead;
|
||||||
|
|
||||||
int VPrintf (int printlevel, const char *format, va_list parms)
|
int VPrintf (int printlevel, const char *format, va_list parms)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2326,6 +2326,11 @@ void I_FatalError(const char *error, ...)
|
||||||
std::terminate(); // recursive I_FatalErrors must immediately terminate.
|
std::terminate(); // recursive I_FatalErrors must immediately terminate.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void NewFailure ()
|
||||||
|
{
|
||||||
|
I_FatalError ("Failed to allocate memory from system heap");
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// I_Quit
|
// I_Quit
|
||||||
|
@ -2348,7 +2353,7 @@ void I_Quit()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void D_DoomMain (void)
|
static void D_DoomMain_Internal (void)
|
||||||
{
|
{
|
||||||
int p;
|
int p;
|
||||||
const char *v;
|
const char *v;
|
||||||
|
@ -2357,6 +2362,8 @@ void D_DoomMain (void)
|
||||||
FString *args;
|
FString *args;
|
||||||
int argcount;
|
int argcount;
|
||||||
FIWadManager *iwad_man;
|
FIWadManager *iwad_man;
|
||||||
|
|
||||||
|
std::set_new_handler(NewFailure);
|
||||||
const char *batchout = Args->CheckValue("-errorlog");
|
const char *batchout = Args->CheckValue("-errorlog");
|
||||||
|
|
||||||
C_InitConsole(80*8, 25*8, false);
|
C_InitConsole(80*8, 25*8, false);
|
||||||
|
@ -2739,7 +2746,7 @@ void D_DoomMain (void)
|
||||||
|
|
||||||
if (Args->CheckParm("-norun") || batchrun)
|
if (Args->CheckParm("-norun") || batchrun)
|
||||||
{
|
{
|
||||||
throw CNoRunExit();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
V_Init2();
|
V_Init2();
|
||||||
|
@ -2830,6 +2837,25 @@ void D_DoomMain (void)
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int D_DoomMain()
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
D_DoomMain_Internal();
|
||||||
|
ret = 1337;
|
||||||
|
}
|
||||||
|
catch (std::exception &error)
|
||||||
|
{
|
||||||
|
I_ShowFatalError(error.what());
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
// Unless something really bad happened, the game should only exit through this single point in the code.
|
||||||
|
// No more 'exit', please.
|
||||||
|
// Todo: Move all engine cleanup here instead of using exit handlers and replace the scattered 'exit' calls with a special exception.
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// clean up the resources
|
// clean up the resources
|
||||||
|
|
|
@ -45,7 +45,7 @@ struct CRestartException
|
||||||
char dummy;
|
char dummy;
|
||||||
};
|
};
|
||||||
|
|
||||||
void D_DoomMain (void);
|
int D_DoomMain (void);
|
||||||
|
|
||||||
|
|
||||||
void D_Display ();
|
void D_Display ();
|
||||||
|
|
|
@ -141,11 +141,7 @@ void I_DetectOS()
|
||||||
FArgs* Args; // command line arguments
|
FArgs* Args; // command line arguments
|
||||||
|
|
||||||
|
|
||||||
// Newer versions of GCC than 4.2 have a bug with C++ exceptions in Objective-C++ code.
|
int OriginalMainTry(int argc, char** argv)
|
||||||
// To work around we'll implement the try and catch in standard C++.
|
|
||||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61759
|
|
||||||
void OriginalMainExcept(int argc, char** argv);
|
|
||||||
void OriginalMainTry(int argc, char** argv)
|
|
||||||
{
|
{
|
||||||
Args = new FArgs(argc, argv);
|
Args = new FArgs(argc, argv);
|
||||||
|
|
||||||
|
@ -155,7 +151,7 @@ void OriginalMainTry(int argc, char** argv)
|
||||||
progdir = [[exePath stringByDeletingLastPathComponent] UTF8String];
|
progdir = [[exePath stringByDeletingLastPathComponent] UTF8String];
|
||||||
progdir += "/";
|
progdir += "/";
|
||||||
|
|
||||||
D_DoomMain();
|
return D_DoomMain();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
@ -163,19 +159,12 @@ namespace
|
||||||
|
|
||||||
TArray<FString> s_argv;
|
TArray<FString> s_argv;
|
||||||
|
|
||||||
|
|
||||||
void NewFailure()
|
|
||||||
{
|
|
||||||
I_FatalError("Failed to allocate memory from system heap");
|
|
||||||
}
|
|
||||||
|
|
||||||
int OriginalMain(int argc, char** argv)
|
int OriginalMain(int argc, char** argv)
|
||||||
{
|
{
|
||||||
printf(GAMENAME" %s - %s - Cocoa version\nCompiled on %s\n\n",
|
printf(GAMENAME" %s - %s - Cocoa version\nCompiled on %s\n\n",
|
||||||
GetVersionString(), GetGitTime(), __DATE__);
|
GetVersionString(), GetGitTime(), __DATE__);
|
||||||
|
|
||||||
seteuid(getuid());
|
seteuid(getuid());
|
||||||
std::set_new_handler(NewFailure);
|
|
||||||
|
|
||||||
// Set LC_NUMERIC environment variable in case some library decides to
|
// Set LC_NUMERIC environment variable in case some library decides to
|
||||||
// clear the setlocale call at least this will be correct.
|
// clear the setlocale call at least this will be correct.
|
||||||
|
@ -190,9 +179,7 @@ int OriginalMain(int argc, char** argv)
|
||||||
vid_defheight = static_cast<int>(screenSize.height);
|
vid_defheight = static_cast<int>(screenSize.height);
|
||||||
vid_vsync = true;
|
vid_vsync = true;
|
||||||
|
|
||||||
OriginalMainExcept(argc, argv);
|
return OriginalMainTry(argc, argv);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
|
|
|
@ -39,41 +39,10 @@
|
||||||
#include "atterm.h"
|
#include "atterm.h"
|
||||||
|
|
||||||
// Import some functions from i_main.mm
|
// Import some functions from i_main.mm
|
||||||
void Mac_I_FatalError(const char* const message);
|
|
||||||
void OriginalMainTry(int argc, char** argv);
|
void OriginalMainTry(int argc, char** argv);
|
||||||
|
|
||||||
void OriginalMainExcept(int argc, char** argv)
|
void OriginalMainExcept(int argc, char** argv)
|
||||||
{
|
{
|
||||||
try
|
OriginalMainTry(argc, argv);
|
||||||
{
|
|
||||||
OriginalMainTry(argc, argv);
|
|
||||||
}
|
|
||||||
catch(const std::exception& error)
|
|
||||||
{
|
|
||||||
const char* const message = error.what();
|
|
||||||
|
|
||||||
if (strcmp(message, "NoRunExit"))
|
|
||||||
{
|
|
||||||
if (CVMAbortException::stacktrace.IsNotEmpty())
|
|
||||||
{
|
|
||||||
Printf("%s", CVMAbortException::stacktrace.GetChars());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (batchrun)
|
|
||||||
{
|
|
||||||
Printf("%s\n", message);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Mac_I_FatalError(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
call_terms();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,6 +147,14 @@ void I_PrintStr(const char* const message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Mac_I_FatalError(const char* const message);
|
||||||
|
|
||||||
|
void I_ShowFatalError(const char *message)
|
||||||
|
{
|
||||||
|
Mac_I_FatalError(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int I_PickIWad(WadStuff* const wads, const int numwads, const bool showwin, const int defaultiwad)
|
int I_PickIWad(WadStuff* const wads, const int numwads, const bool showwin, const int defaultiwad)
|
||||||
{
|
{
|
||||||
if (!showwin)
|
if (!showwin)
|
||||||
|
|
|
@ -94,10 +94,6 @@ FArgs *Args;
|
||||||
// CODE --------------------------------------------------------------------
|
// CODE --------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
static void NewFailure ()
|
|
||||||
{
|
|
||||||
I_FatalError ("Failed to allocate memory from system heap");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int DoomSpecificInfo (char *buffer, char *end)
|
static int DoomSpecificInfo (char *buffer, char *end)
|
||||||
{
|
{
|
||||||
|
@ -170,8 +166,6 @@ int main (int argc, char **argv)
|
||||||
GetVersionString(), GetGitTime(), __DATE__);
|
GetVersionString(), GetGitTime(), __DATE__);
|
||||||
|
|
||||||
seteuid (getuid ());
|
seteuid (getuid ());
|
||||||
std::set_new_handler (NewFailure);
|
|
||||||
|
|
||||||
// Set LC_NUMERIC environment variable in case some library decides to
|
// Set LC_NUMERIC environment variable in case some library decides to
|
||||||
// clear the setlocale call at least this will be correct.
|
// clear the setlocale call at least this will be correct.
|
||||||
// Note that the LANG environment variable is overridden by LC_*
|
// Note that the LANG environment variable is overridden by LC_*
|
||||||
|
@ -205,6 +199,5 @@ int main (int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
I_StartupJoysticks();
|
I_StartupJoysticks();
|
||||||
D_DoomMain ();
|
return D_DoomMain ();
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,6 @@ void I_Init (void)
|
||||||
// I_Error
|
// I_Error
|
||||||
//
|
//
|
||||||
extern FILE *Logfile;
|
extern FILE *Logfile;
|
||||||
bool gameisdead;
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
void Mac_I_FatalError(const char* errortext);
|
void Mac_I_FatalError(const char* errortext);
|
||||||
|
|
|
@ -82,13 +82,6 @@ protected:
|
||||||
char m_Message[MAX_ERRORTEXT];
|
char m_Message[MAX_ERRORTEXT];
|
||||||
};
|
};
|
||||||
|
|
||||||
class CNoRunExit : public std::runtime_error
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CNoRunExit() : std::runtime_error("NoRunExit")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class CRecoverableError : public CDoomError
|
class CRecoverableError : public CDoomError
|
||||||
{
|
{
|
||||||
|
|
|
@ -145,15 +145,6 @@ static HMODULE hwtsapi32; // handle to wtsapi32.dll
|
||||||
|
|
||||||
// CODE --------------------------------------------------------------------
|
// CODE --------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
static int NewFailure (size_t size)
|
|
||||||
{
|
|
||||||
I_FatalError ("Failed to allocate %d bytes from process heap", size);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// UnCOM
|
// UnCOM
|
||||||
|
@ -765,214 +756,213 @@ void DoMain (HINSTANCE hInstance)
|
||||||
RECT cRect;
|
RECT cRect;
|
||||||
TIMECAPS tc;
|
TIMECAPS tc;
|
||||||
DEVMODE displaysettings;
|
DEVMODE displaysettings;
|
||||||
|
|
||||||
try
|
// Do not use the multibyte __argv here because we want UTF-8 arguments
|
||||||
|
// and those can only be done by converting the Unicode variants.
|
||||||
|
Args = new FArgs();
|
||||||
|
auto argc = __argc;
|
||||||
|
auto wargv = __wargv;
|
||||||
|
for (int i = 0; i < argc; i++)
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
Args->AppendArg(FString(wargv[i]));
|
||||||
_set_new_handler (NewFailure);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Do not use the multibyte __argv here because we want UTF-8 arguments
|
|
||||||
// and those can only be done by converting the Unicode variants.
|
|
||||||
Args = new FArgs();
|
|
||||||
auto argc = __argc;
|
|
||||||
auto wargv = __wargv;
|
|
||||||
for (int i = 0; i < argc; i++)
|
|
||||||
{
|
|
||||||
Args->AppendArg(FString(wargv[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load Win32 modules
|
|
||||||
Kernel32Module.Load({"kernel32.dll"});
|
|
||||||
Shell32Module.Load({"shell32.dll"});
|
|
||||||
User32Module.Load({"user32.dll"});
|
|
||||||
|
|
||||||
// Under XP, get our session ID so we can know when the user changes/locks sessions.
|
|
||||||
// Since we need to remain binary compatible with older versions of Windows, we
|
|
||||||
// need to extract the ProcessIdToSessionId function from kernel32.dll manually.
|
|
||||||
HMODULE kernel = GetModuleHandleA ("kernel32.dll");
|
|
||||||
|
|
||||||
if (Args->CheckParm("-stdout"))
|
|
||||||
{
|
|
||||||
// As a GUI application, we don't normally get a console when we start.
|
|
||||||
// If we were run from the shell and are on XP+, we can attach to its
|
|
||||||
// console. Otherwise, we can create a new one. If we already have a
|
|
||||||
// stdout handle, then we have been redirected and should just use that
|
|
||||||
// handle instead of creating a console window.
|
|
||||||
|
|
||||||
StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
if (StdOut != NULL)
|
|
||||||
{
|
|
||||||
// It seems that running from a shell always creates a std output
|
|
||||||
// for us, even if it doesn't go anywhere. (Running from Explorer
|
|
||||||
// does not.) If we can get file information for this handle, it's
|
|
||||||
// a file or pipe, so use it. Otherwise, pretend it wasn't there
|
|
||||||
// and find a console to use instead.
|
|
||||||
BY_HANDLE_FILE_INFORMATION info;
|
|
||||||
if (!GetFileInformationByHandle(StdOut, &info))
|
|
||||||
{
|
|
||||||
StdOut = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (StdOut == NULL)
|
|
||||||
{
|
|
||||||
if (AttachConsole(ATTACH_PARENT_PROCESS))
|
|
||||||
{
|
|
||||||
StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
DWORD foo; WriteFile(StdOut, "\n", 1, &foo, NULL);
|
|
||||||
AttachedStdOut = true;
|
|
||||||
}
|
|
||||||
if (StdOut == NULL && AllocConsole())
|
|
||||||
{
|
|
||||||
StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// These two functions do not exist in Windows XP.
|
|
||||||
BOOL (WINAPI* p_GetCurrentConsoleFontEx)(HANDLE hConsoleOutput, BOOL bMaximumWindow, PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx);
|
|
||||||
BOOL (WINAPI* p_SetCurrentConsoleFontEx)(HANDLE hConsoleOutput, BOOL bMaximumWindow, PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx);
|
|
||||||
|
|
||||||
p_SetCurrentConsoleFontEx = (decltype(p_SetCurrentConsoleFontEx))GetProcAddress(kernel, "SetCurrentConsoleFontEx");
|
|
||||||
p_GetCurrentConsoleFontEx = (decltype(p_GetCurrentConsoleFontEx))GetProcAddress(kernel, "GetCurrentConsoleFontEx");
|
|
||||||
if (p_SetCurrentConsoleFontEx && p_GetCurrentConsoleFontEx)
|
|
||||||
{
|
|
||||||
CONSOLE_FONT_INFOEX cfi;
|
|
||||||
cfi.cbSize = sizeof(cfi);
|
|
||||||
|
|
||||||
if (p_GetCurrentConsoleFontEx(StdOut, false, &cfi))
|
|
||||||
{
|
|
||||||
if (*cfi.FaceName == 0) // If the face name is empty, the default (useless) raster font is actoive.
|
|
||||||
{
|
|
||||||
//cfi.dwFontSize = { 8, 14 };
|
|
||||||
wcscpy(cfi.FaceName, L"Lucida Console");
|
|
||||||
cfi.FontFamily = FF_DONTCARE;
|
|
||||||
p_SetCurrentConsoleFontEx(StdOut, false, &cfi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FancyStdOut = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the timer to be as accurate as possible
|
|
||||||
if (timeGetDevCaps (&tc, sizeof(tc)) != TIMERR_NOERROR)
|
|
||||||
TimerPeriod = 1; // Assume minimum resolution of 1 ms
|
|
||||||
else
|
|
||||||
TimerPeriod = tc.wPeriodMin;
|
|
||||||
|
|
||||||
timeBeginPeriod (TimerPeriod);
|
|
||||||
atexit(UnTbp);
|
|
||||||
|
|
||||||
atexit (call_terms);
|
|
||||||
|
|
||||||
// Figure out what directory the program resides in.
|
|
||||||
WCHAR progbuff[1024];
|
|
||||||
if (GetModuleFileNameW(nullptr, progbuff, sizeof progbuff) == 0)
|
|
||||||
{
|
|
||||||
I_FatalError("Could not determine program location.");
|
|
||||||
}
|
|
||||||
progbuff[1023] = '\0';
|
|
||||||
if (auto lastsep = wcsrchr(progbuff, '\\'))
|
|
||||||
{
|
|
||||||
lastsep[1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
progdir = progbuff;
|
|
||||||
FixPathSeperator(progdir);
|
|
||||||
|
|
||||||
HDC screenDC = GetDC(0);
|
|
||||||
int dpi = GetDeviceCaps(screenDC, LOGPIXELSX);
|
|
||||||
ReleaseDC(0, screenDC);
|
|
||||||
width = (512 * dpi + 96 / 2) / 96;
|
|
||||||
height = (384 * dpi + 96 / 2) / 96;
|
|
||||||
|
|
||||||
// Many Windows structures that specify their size do so with the first
|
|
||||||
// element. DEVMODE is not one of those structures.
|
|
||||||
memset (&displaysettings, 0, sizeof(displaysettings));
|
|
||||||
displaysettings.dmSize = sizeof(displaysettings);
|
|
||||||
EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &displaysettings);
|
|
||||||
x = (displaysettings.dmPelsWidth - width) / 2;
|
|
||||||
y = (displaysettings.dmPelsHeight - height) / 2;
|
|
||||||
|
|
||||||
if (Args->CheckParm ("-0"))
|
|
||||||
{
|
|
||||||
x = y = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
WNDCLASS WndClass;
|
|
||||||
WndClass.style = 0;
|
|
||||||
WndClass.lpfnWndProc = LConProc;
|
|
||||||
WndClass.cbClsExtra = 0;
|
|
||||||
WndClass.cbWndExtra = 0;
|
|
||||||
WndClass.hInstance = hInstance;
|
|
||||||
WndClass.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_ICON1));
|
|
||||||
WndClass.hCursor = LoadCursor (NULL, IDC_ARROW);
|
|
||||||
WndClass.hbrBackground = NULL;
|
|
||||||
WndClass.lpszMenuName = NULL;
|
|
||||||
WndClass.lpszClassName = WinClassName;
|
|
||||||
|
|
||||||
/* register this new class with Windows */
|
|
||||||
if (!RegisterClass((LPWNDCLASS)&WndClass))
|
|
||||||
I_FatalError ("Could not register window class");
|
|
||||||
|
|
||||||
/* create window */
|
|
||||||
FStringf caption("" GAMESIG " %s " X64 " (%s)", GetVersionString(), GetGitTime());
|
|
||||||
std::wstring wcaption = caption.WideString();
|
|
||||||
Window = CreateWindowExW(
|
|
||||||
WS_EX_APPWINDOW,
|
|
||||||
WinClassName,
|
|
||||||
wcaption.c_str(),
|
|
||||||
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
|
|
||||||
x, y, width, height,
|
|
||||||
(HWND) NULL,
|
|
||||||
(HMENU) NULL,
|
|
||||||
hInstance,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (!Window)
|
|
||||||
{
|
|
||||||
MessageBoxA(nullptr, "Unable to create main window", "Fatal", MB_ICONEXCLAMATION|MB_OK);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kernel != NULL)
|
|
||||||
{
|
|
||||||
typedef BOOL (WINAPI *pts)(DWORD, DWORD *);
|
|
||||||
pts pidsid = (pts)GetProcAddress (kernel, "ProcessIdToSessionId");
|
|
||||||
if (pidsid != 0)
|
|
||||||
{
|
|
||||||
if (!pidsid (GetCurrentProcessId(), &SessionID))
|
|
||||||
{
|
|
||||||
SessionID = 0;
|
|
||||||
}
|
|
||||||
hwtsapi32 = LoadLibraryA ("wtsapi32.dll");
|
|
||||||
if (hwtsapi32 != 0)
|
|
||||||
{
|
|
||||||
FARPROC reg = GetProcAddress (hwtsapi32, "WTSRegisterSessionNotification");
|
|
||||||
if (reg == 0 || !((BOOL(WINAPI *)(HWND, DWORD))reg) (Window, NOTIFY_FOR_THIS_SESSION))
|
|
||||||
{
|
|
||||||
FreeLibrary (hwtsapi32);
|
|
||||||
hwtsapi32 = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
atexit (UnWTS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GetClientRect (Window, &cRect);
|
|
||||||
|
|
||||||
WinWidth = cRect.right;
|
|
||||||
WinHeight = cRect.bottom;
|
|
||||||
|
|
||||||
CoInitialize (NULL);
|
|
||||||
atexit (UnCOM);
|
|
||||||
|
|
||||||
D_DoomMain ();
|
|
||||||
}
|
}
|
||||||
catch (class CNoRunExit &)
|
|
||||||
|
// Load Win32 modules
|
||||||
|
Kernel32Module.Load({"kernel32.dll"});
|
||||||
|
Shell32Module.Load({"shell32.dll"});
|
||||||
|
User32Module.Load({"user32.dll"});
|
||||||
|
|
||||||
|
// Under XP, get our session ID so we can know when the user changes/locks sessions.
|
||||||
|
// Since we need to remain binary compatible with older versions of Windows, we
|
||||||
|
// need to extract the ProcessIdToSessionId function from kernel32.dll manually.
|
||||||
|
HMODULE kernel = GetModuleHandleA ("kernel32.dll");
|
||||||
|
|
||||||
|
if (Args->CheckParm("-stdout"))
|
||||||
{
|
{
|
||||||
|
// As a GUI application, we don't normally get a console when we start.
|
||||||
|
// If we were run from the shell and are on XP+, we can attach to its
|
||||||
|
// console. Otherwise, we can create a new one. If we already have a
|
||||||
|
// stdout handle, then we have been redirected and should just use that
|
||||||
|
// handle instead of creating a console window.
|
||||||
|
|
||||||
|
StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
if (StdOut != NULL)
|
||||||
|
{
|
||||||
|
// It seems that running from a shell always creates a std output
|
||||||
|
// for us, even if it doesn't go anywhere. (Running from Explorer
|
||||||
|
// does not.) If we can get file information for this handle, it's
|
||||||
|
// a file or pipe, so use it. Otherwise, pretend it wasn't there
|
||||||
|
// and find a console to use instead.
|
||||||
|
BY_HANDLE_FILE_INFORMATION info;
|
||||||
|
if (!GetFileInformationByHandle(StdOut, &info))
|
||||||
|
{
|
||||||
|
StdOut = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StdOut == NULL)
|
||||||
|
{
|
||||||
|
if (AttachConsole(ATTACH_PARENT_PROCESS))
|
||||||
|
{
|
||||||
|
StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
DWORD foo; WriteFile(StdOut, "\n", 1, &foo, NULL);
|
||||||
|
AttachedStdOut = true;
|
||||||
|
}
|
||||||
|
if (StdOut == NULL && AllocConsole())
|
||||||
|
{
|
||||||
|
StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// These two functions do not exist in Windows XP.
|
||||||
|
BOOL (WINAPI* p_GetCurrentConsoleFontEx)(HANDLE hConsoleOutput, BOOL bMaximumWindow, PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx);
|
||||||
|
BOOL (WINAPI* p_SetCurrentConsoleFontEx)(HANDLE hConsoleOutput, BOOL bMaximumWindow, PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx);
|
||||||
|
|
||||||
|
p_SetCurrentConsoleFontEx = (decltype(p_SetCurrentConsoleFontEx))GetProcAddress(kernel, "SetCurrentConsoleFontEx");
|
||||||
|
p_GetCurrentConsoleFontEx = (decltype(p_GetCurrentConsoleFontEx))GetProcAddress(kernel, "GetCurrentConsoleFontEx");
|
||||||
|
if (p_SetCurrentConsoleFontEx && p_GetCurrentConsoleFontEx)
|
||||||
|
{
|
||||||
|
CONSOLE_FONT_INFOEX cfi;
|
||||||
|
cfi.cbSize = sizeof(cfi);
|
||||||
|
|
||||||
|
if (p_GetCurrentConsoleFontEx(StdOut, false, &cfi))
|
||||||
|
{
|
||||||
|
if (*cfi.FaceName == 0) // If the face name is empty, the default (useless) raster font is actoive.
|
||||||
|
{
|
||||||
|
//cfi.dwFontSize = { 8, 14 };
|
||||||
|
wcscpy(cfi.FaceName, L"Lucida Console");
|
||||||
|
cfi.FontFamily = FF_DONTCARE;
|
||||||
|
p_SetCurrentConsoleFontEx(StdOut, false, &cfi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FancyStdOut = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the timer to be as accurate as possible
|
||||||
|
if (timeGetDevCaps (&tc, sizeof(tc)) != TIMERR_NOERROR)
|
||||||
|
TimerPeriod = 1; // Assume minimum resolution of 1 ms
|
||||||
|
else
|
||||||
|
TimerPeriod = tc.wPeriodMin;
|
||||||
|
|
||||||
|
timeBeginPeriod (TimerPeriod);
|
||||||
|
atexit(UnTbp);
|
||||||
|
|
||||||
|
atexit (call_terms);
|
||||||
|
|
||||||
|
// Figure out what directory the program resides in.
|
||||||
|
WCHAR progbuff[1024];
|
||||||
|
if (GetModuleFileNameW(nullptr, progbuff, sizeof progbuff) == 0)
|
||||||
|
{
|
||||||
|
MessageBoc(nullptr, "Fatal", "Could not determine program location.", MB_ICONEXCLAMATION|MB_OK);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
progbuff[1023] = '\0';
|
||||||
|
if (auto lastsep = wcsrchr(progbuff, '\\'))
|
||||||
|
{
|
||||||
|
lastsep[1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
progdir = progbuff;
|
||||||
|
FixPathSeperator(progdir);
|
||||||
|
|
||||||
|
HDC screenDC = GetDC(0);
|
||||||
|
int dpi = GetDeviceCaps(screenDC, LOGPIXELSX);
|
||||||
|
ReleaseDC(0, screenDC);
|
||||||
|
width = (512 * dpi + 96 / 2) / 96;
|
||||||
|
height = (384 * dpi + 96 / 2) / 96;
|
||||||
|
|
||||||
|
// Many Windows structures that specify their size do so with the first
|
||||||
|
// element. DEVMODE is not one of those structures.
|
||||||
|
memset (&displaysettings, 0, sizeof(displaysettings));
|
||||||
|
displaysettings.dmSize = sizeof(displaysettings);
|
||||||
|
EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &displaysettings);
|
||||||
|
x = (displaysettings.dmPelsWidth - width) / 2;
|
||||||
|
y = (displaysettings.dmPelsHeight - height) / 2;
|
||||||
|
|
||||||
|
if (Args->CheckParm ("-0"))
|
||||||
|
{
|
||||||
|
x = y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WNDCLASS WndClass;
|
||||||
|
WndClass.style = 0;
|
||||||
|
WndClass.lpfnWndProc = LConProc;
|
||||||
|
WndClass.cbClsExtra = 0;
|
||||||
|
WndClass.cbWndExtra = 0;
|
||||||
|
WndClass.hInstance = hInstance;
|
||||||
|
WndClass.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_ICON1));
|
||||||
|
WndClass.hCursor = LoadCursor (NULL, IDC_ARROW);
|
||||||
|
WndClass.hbrBackground = NULL;
|
||||||
|
WndClass.lpszMenuName = NULL;
|
||||||
|
WndClass.lpszClassName = WinClassName;
|
||||||
|
|
||||||
|
/* register this new class with Windows */
|
||||||
|
if (!RegisterClass((LPWNDCLASS)&WndClass))
|
||||||
|
{
|
||||||
|
MessageBoxA(nullptr, "Could not register window class", "Fatal", MB_ICONEXCLAMATION|MB_OK);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create window */
|
||||||
|
FStringf caption("" GAMESIG " %s " X64 " (%s)", GetVersionString(), GetGitTime());
|
||||||
|
std::wstring wcaption = caption.WideString();
|
||||||
|
Window = CreateWindowExW(
|
||||||
|
WS_EX_APPWINDOW,
|
||||||
|
WinClassName,
|
||||||
|
wcaption.c_str(),
|
||||||
|
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
|
||||||
|
x, y, width, height,
|
||||||
|
(HWND) NULL,
|
||||||
|
(HMENU) NULL,
|
||||||
|
hInstance,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (!Window)
|
||||||
|
{
|
||||||
|
MessageBoxA(nullptr, "Unable to create main window", "Fatal", MB_ICONEXCLAMATION|MB_OK);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kernel != NULL)
|
||||||
|
{
|
||||||
|
typedef BOOL (WINAPI *pts)(DWORD, DWORD *);
|
||||||
|
pts pidsid = (pts)GetProcAddress (kernel, "ProcessIdToSessionId");
|
||||||
|
if (pidsid != 0)
|
||||||
|
{
|
||||||
|
if (!pidsid (GetCurrentProcessId(), &SessionID))
|
||||||
|
{
|
||||||
|
SessionID = 0;
|
||||||
|
}
|
||||||
|
hwtsapi32 = LoadLibraryA ("wtsapi32.dll");
|
||||||
|
if (hwtsapi32 != 0)
|
||||||
|
{
|
||||||
|
FARPROC reg = GetProcAddress (hwtsapi32, "WTSRegisterSessionNotification");
|
||||||
|
if (reg == 0 || !((BOOL(WINAPI *)(HWND, DWORD))reg) (Window, NOTIFY_FOR_THIS_SESSION))
|
||||||
|
{
|
||||||
|
FreeLibrary (hwtsapi32);
|
||||||
|
hwtsapi32 = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
atexit (UnWTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GetClientRect (Window, &cRect);
|
||||||
|
|
||||||
|
WinWidth = cRect.right;
|
||||||
|
WinHeight = cRect.bottom;
|
||||||
|
|
||||||
|
CoInitialize (NULL);
|
||||||
|
atexit (UnCOM);
|
||||||
|
|
||||||
|
int ret = D_DoomMain ();
|
||||||
|
if (ret == 1337) // special exit code for 'norun'.
|
||||||
|
{
|
||||||
|
// The only way D_DoomMain can exit regularly is by executing a -norun startup, which was previously handled via exception.
|
||||||
I_ShutdownGraphics();
|
I_ShutdownGraphics();
|
||||||
if (!batchrun)
|
if (!batchrun)
|
||||||
{
|
{
|
||||||
|
@ -980,7 +970,7 @@ void DoMain (HINSTANCE hInstance)
|
||||||
{ // Outputting to a new console window: Wait for a keypress before quitting.
|
{ // Outputting to a new console window: Wait for a keypress before quitting.
|
||||||
DWORD bytes;
|
DWORD bytes;
|
||||||
HANDLE stdinput = GetStdHandle(STD_INPUT_HANDLE);
|
HANDLE stdinput = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
|
||||||
ShowWindow(Window, SW_HIDE);
|
ShowWindow(Window, SW_HIDE);
|
||||||
WriteFile(StdOut, "Press any key to exit...", 24, &bytes, NULL);
|
WriteFile(StdOut, "Press any key to exit...", 24, &bytes, NULL);
|
||||||
FlushConsoleInputBuffer(stdinput);
|
FlushConsoleInputBuffer(stdinput);
|
||||||
|
@ -992,32 +982,30 @@ void DoMain (HINSTANCE hInstance)
|
||||||
ShowErrorPane(NULL);
|
ShowErrorPane(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
catch (std::exception &error)
|
return ret;
|
||||||
{
|
}
|
||||||
I_ShutdownGraphics ();
|
|
||||||
RestoreConView ();
|
|
||||||
S_StopMusic(true);
|
|
||||||
I_FlushBufferedConsoleStuff();
|
|
||||||
auto msg = error.what();
|
|
||||||
if (strcmp(msg, "NoRunExit"))
|
|
||||||
{
|
|
||||||
if (CVMAbortException::stacktrace.IsNotEmpty())
|
|
||||||
{
|
|
||||||
Printf("%s", CVMAbortException::stacktrace.GetChars());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!batchrun)
|
void I_ShowFatalError(const char *msg)
|
||||||
{
|
{
|
||||||
ShowErrorPane(msg);
|
I_ShutdownGraphics ();
|
||||||
}
|
RestoreConView ();
|
||||||
else
|
S_StopMusic(true);
|
||||||
{
|
I_FlushBufferedConsoleStuff();
|
||||||
Printf("%s\n", msg);
|
auto msg = error.what();
|
||||||
}
|
|
||||||
}
|
if (CVMAbortException::stacktrace.IsNotEmpty())
|
||||||
exit(-1);
|
{
|
||||||
|
Printf("%s", CVMAbortException::stacktrace.GetChars());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!batchrun)
|
||||||
|
{
|
||||||
|
ShowErrorPane(msg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Printf("%s\n", msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,7 +137,6 @@ double PerfToSec, PerfToMillisec;
|
||||||
|
|
||||||
UINT TimerPeriod;
|
UINT TimerPeriod;
|
||||||
|
|
||||||
bool gameisdead;
|
|
||||||
int sys_ostype = 0;
|
int sys_ostype = 0;
|
||||||
|
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
Loading…
Reference in a new issue