int CALLBACK WinMain( HINSTANCE /* hInstance */, HINSTANCE /* hPrevInstance */, LPSTR /* lpCmdLine */, int /* nCmdShow */ ) { int exitCode = 1; // start off assuming an error // trap and report all exceptions try { srand(static_cast<unsigned int>(time(0))); attach_console(); sweetie_rush::main(); exitCode = 0; // good, no errors :) } catch(std::exception const & e) { std::cerr << e.what() << std::endl; } catch(...) { std::cerr << "Unknown error" << std::endl; } return exitCode; }
static ssize_t do_read(void *handle, char *buffer, size_t size) { switch( use_console ) { case C_ATTACHED: return read_console(handle, buffer, size); case C_NONE: case C_READ: if ( ask_attach(TRUE) ) { if ( attach_console() ) return read_console(handle, buffer, size); } case C_NEVER: return -1; } return -1; }
static ssize_t do_write(void *handle, char *buffer, size_t size) { struct recall *rc = &recall_buffer; switch(use_console) { case C_ATTACHED: return write_console(handle, buffer, size); case C_NONE: if ( handle == Serror->handle ) { if ( ask_attach(FALSE) ) { if ( attach_console() ) return write_console(handle, buffer, size); } } break; case C_READ: break; case C_NEVER: return size; } if ( !rc->data ) { rc->allocated = 512; rc->data = PL_malloc(rc->allocated); rc->size = 0; } if ( size + rc->size <= rc->allocated ) { memcpy(&rc->data[rc->size], buffer, size); rc->size += size; } else if ( size >= rc->allocated ) { memcpy(rc->data, &buffer[size-rc->allocated], rc->allocated); rc->size = rc->allocated; } else { int leave = rc->allocated - size; memmove(rc->data, &rc->data[rc->size-leave], leave); memcpy(&rc->data+leave, buffer, size); rc->size = rc->allocated; } return size; }
void DoMain (HINSTANCE hInstance) { LONG WinWidth, WinHeight; int height, width, x, y; RECT cRect; TIMECAPS tc; DEVMODE displaysettings; try { #ifdef _MSC_VER _set_new_handler (NewFailure); #endif Args = new DArgs(__argc, __argv); // 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 = GetModuleHandle ("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) { // AttachConsole was introduced with Windows XP. (OTOH, since we // have to share the console with the shell, I'm not sure if it's // a good idea to actually attach to it.) typedef BOOL (WINAPI *ac)(DWORD); ac attach_console = kernel != NULL ? (ac)GetProcAddress(kernel, "AttachConsole") : NULL; if (attach_console != NULL && attach_console(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); } 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); /* killough 1/98: This fixes some problems with exit handling during abnormal situations. The old code called I_Quit() to end program, while now I_Quit() is installed as an exit handler and exit() is called to exit, either normally or abnormally. */ atexit (call_terms); atterm (I_Quit); // Figure out what directory the program resides in. char *program; #ifdef _MSC_VER if (_get_pgmptr(&program) != 0) { I_FatalError("Could not determine program location."); } #else char progbuff[1024]; GetModuleFileName(0, progbuff, sizeof(progbuff)); progbuff[1023] = '\0'; program = progbuff; #endif progdir = program; program = progdir.LockBuffer(); *(strrchr(program, '\\') + 1) = '\0'; FixPathSeperator(program); progdir.Truncate((long)strlen(program)); progdir.UnlockBuffer(); 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 = (LPCTSTR)WinClassName; /* register this new class with Windows */ if (!RegisterClass((LPWNDCLASS)&WndClass)) I_FatalError ("Could not register window class"); /* create window */ char caption[100]; mysnprintf(caption, countof(caption), "" GAMESIG " %s " X64 " (%s)", GetVersionString(), GetGitTime()); Window = CreateWindowEx( WS_EX_APPWINDOW, (LPCTSTR)WinClassName, (LPCTSTR)caption, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN, x, y, width, height, (HWND) NULL, (HMENU) NULL, hInstance, NULL); if (!Window) I_FatalError ("Could not open window"); 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 { atterm (UnWTS); } } } } GetClientRect (Window, &cRect); WinWidth = cRect.right; WinHeight = cRect.bottom; CoInitialize (NULL); atterm (UnCOM); C_InitConsole (((WinWidth / 8) + 2) * 8, (WinHeight / 12) * 8, false); I_DetectOS (); D_DoomMain (); } catch (class CNoRunExit &) { I_ShutdownGraphics(); if (!batchrun) { if (FancyStdOut && !AttachedStdOut) { // Outputting to a new console window: Wait for a keypress before quitting. DWORD bytes; HANDLE stdinput = GetStdHandle(STD_INPUT_HANDLE); ShowWindow(Window, SW_HIDE); WriteFile(StdOut, "Press any key to exit...", 24, &bytes, NULL); FlushConsoleInputBuffer(stdinput); SetConsoleMode(stdinput, 0); ReadConsole(stdinput, &bytes, 1, &bytes, NULL); } else if (StdOut == NULL) { ShowErrorPane(NULL); } } exit(0); } catch (class CDoomError &error) { I_ShutdownGraphics (); RestoreConView (); I_FlushBufferedConsoleStuff(); if (error.GetMessage ()) { if (!batchrun) { ShowErrorPane(error.GetMessage()); } else { Printf("%s\n", error.GetMessage()); } } exit (-1); } }