Created
June 8, 2012 02:27
-
-
Save rhoot/2893136 to your computer and use it in GitHub Desktop.
Win32 application entry point redirection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** \file WinMain.cpp | |
* \author rhoot <https://github.com/rhoot> | |
* | |
* \brief Redirects calls from the windows specific WinMain() entry point to a more | |
* standard main() entry point defined someplace else. In debug builds, also | |
* allocates a console and redirects stdin, stderr, stdout to that console. | |
* | |
* \remark The std* stream redirection is based on RedirectIOToConsole(), as can be found | |
* at http://dslweb.nwnexus.com/~ast/dload/guicon.htm. | |
*/ | |
/* This only has to be compiled for WIN32 builds, others always use main() as entry point. */ | |
#ifdef _WIN32 | |
/* Update this bit as you see fit. */ | |
#ifdef _DEBUG | |
# define ALLOC_CONSOLE | |
# define CONSOLE_LINES 0x200 | |
#endif | |
#define WIN32_LEAN_AND_MEAN | |
#include <windows.h> | |
/* Only allocates console and redirects streams if this is defined. See above. */ | |
#ifdef ALLOC_CONSOLE | |
#include <iostream> | |
#include <io.h> | |
#include <fcntl.h> | |
namespace | |
{ | |
/* Stash away the old std* streams, so we can restore them later. */ | |
FILE oldStdout = *stdout; | |
FILE oldStdin = *stdin; | |
FILE oldStderr = *stderr; | |
/** Redirects a std stream from its default output/input, to the console. | |
* \param[in] stdHandleId One of STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE. | |
* \param[in] stream Stream to redirect. | |
* \param[in] direction "r" for input streams, "w" for output streams. */ | |
void redirectStream(DWORD stdHandleId, FILE* stream, const char* direction) | |
{ | |
intptr_t stdHandle = reinterpret_cast<intptr_t>(::GetStdHandle(stdHandleId)); | |
int fileHandle = _open_osfhandle(stdHandle, _O_TEXT); | |
FILE* fp = _fdopen(fileHandle, direction); | |
*stream = *fp; | |
setvbuf(stream, NULL, _IONBF, 0); | |
} | |
/** Allocates a console for this application, increases the buffer size, and redirects std* streams | |
* to this console. */ | |
void prepareConsole() | |
{ | |
::AllocConsole(); | |
// increase the size of the screen buffer, so we can scroll text rather than have it dissappear on us | |
CONSOLE_SCREEN_BUFFER_INFO consoleInfo; | |
HANDLE stdOutHandle = ::GetStdHandle(STD_OUTPUT_HANDLE); | |
::GetConsoleScreenBufferInfo(stdOutHandle, &consoleInfo); | |
consoleInfo.dwSize.Y = 500; | |
::SetConsoleScreenBufferSize(stdOutHandle, consoleInfo.dwSize); | |
// Redirect all the standard streams to the newly allocated console, and finally make sure the | |
// std::stream classes do as well | |
redirectStream(STD_OUTPUT_HANDLE, stdout, "w"); | |
redirectStream(STD_ERROR_HANDLE, stderr, "w"); | |
redirectStream(STD_INPUT_HANDLE, stdin, "r"); | |
std::ios::sync_with_stdio(); | |
} | |
/** Frees the allocated console and restores the std* streams to their default. */ | |
void cleanupConsole() | |
{ | |
::FreeConsole(); | |
*stdout = oldStdout; | |
*stdin = oldStdin; | |
*stderr = oldStderr; | |
std::ios::sync_with_stdio(); | |
} | |
}; // anon namespace | |
#endif // ALLOC_CONSOLE | |
/* External reference to the main() method to use as entry point. */ | |
extern int main(int argc, char** argv); | |
/** Application entry point. Redirects the call from this function to the main() function defined | |
* elsewhere. If ALLOC_CONSOLE is defined, it will allocate a console before the call to main() | |
* and free it after the call has finished. */ | |
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) | |
{ | |
#ifdef ALLOC_CONSOLE | |
prepareConsole(); | |
#endif | |
int ret = main(__argc, __argv); | |
#ifdef ALLOC_CONSOLE | |
cleanupConsole(); | |
#endif | |
return ret; | |
} | |
#endif // _WIN32 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment