Skip to content

Commit

Permalink
Fix console output on Windows
Browse files Browse the repository at this point in the history
Attempt to attach to the parent processes console, if that's successful then use it.

If '--console' is passed as an argument, then allocate a new console and use it.

GitHub fixes #10
  • Loading branch information
Karl Sabo committed Jun 3, 2020
1 parent e47f774 commit 0f35046
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 32 deletions.
1 change: 0 additions & 1 deletion PackrLauncher/src/main/cpp/packr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,6 @@ void launchJavaVM(const LaunchJavaVMCallback &callback) {
}

// read settings

sajson::document json = readConfigurationFile(configurationPath);

if (!json.is_valid()) {
Expand Down
112 changes: 81 additions & 31 deletions PackrLauncher/src/main/cpp/win32/packr_win32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <codecvt>

#include <packr.h>

Expand All @@ -46,40 +47,91 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
}

static void waitAtExit() {
cout << "Press ENTER key to exit." << endl;
cout << "Press ENTER key to exit." << endl << flush;
cin.get();
}

static bool attachToConsole(int argc, PTCHAR *argv) {
bool attach = false;
/**
* If the '--console' argument is passed, then a new console is allocated, otherwise attaching to the parent console is attempted.
*
* @param argc the number of elements in {@code argv}
* @param argv the list of arguments to parse for --console
* @return true if the parent console was successfully attached to or a new console was allocated. false if no console could be acquired
*/
static bool attachToOrAllocateConsole(int argc, PTCHAR *argv) {
bool allocConsole = false;

// pre-parse command line here to have a console in case of command line parse errors
for (int arg = 0; arg < argc && !attach; arg++) {
attach = (argv[arg] != nullptr && wcsicmp(argv[arg], TEXT("--console")) == 0);
for (int arg = 0; arg < argc && !allocConsole; arg++) {
allocConsole = (argv[arg] != nullptr && wcsicmp(argv[arg], TEXT("--console")) == 0);
}

if (attach) {
bool gotConsole = false;
if (allocConsole) {
FreeConsole();
AllocConsole();

freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
gotConsole = AllocConsole();
} else {
gotConsole = AttachConsole(ATTACH_PARENT_PROCESS);
}

atexit(waitAtExit);
if (gotConsole) {
// Open C standard streams
FILE *reusedThrowAwayHandle;
freopen_s(&reusedThrowAwayHandle, "CONOUT$", "w", stdout);
freopen_s(&reusedThrowAwayHandle, "CONOUT$", "w", stderr);
freopen_s(&reusedThrowAwayHandle, "CONIN$", "r", stdin);
cout.clear();
clog.clear();
cerr.clear();
cin.clear();

// Open the C++ wide streams
HANDLE hConOut = CreateFile(TEXT("CONOUT$"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
nullptr);
HANDLE hConIn = CreateFile(TEXT("CONIN$"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
nullptr);
SetStdHandle(STD_OUTPUT_HANDLE, hConOut);
SetStdHandle(STD_ERROR_HANDLE, hConOut);
SetStdHandle(STD_INPUT_HANDLE, hConIn);
wcout.clear();
wclog.clear();
wcerr.clear();
wcin.clear();

SetConsoleOutputCP(CP_UTF8);

if (allocConsole) {
atexit(waitAtExit);
}
}

return attach;
return gotConsole;
}

static void printLastError(const PTCHAR reason) {
LPTSTR buffer;
DWORD errorCode = GetLastError();

FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, errorCode, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), (LPTSTR) &buffer, 0, nullptr);
nullptr,
errorCode,
MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
(LPTSTR) &buffer,
0,
nullptr);

cerr << "Error code [" << errorCode << "] when trying to " << reason << ": " << buffer << endl;
wstring_convert<codecvt_utf8_utf16<wchar_t>> converter;
cerr << "Error code [" << errorCode << "] when trying to " << converter.to_bytes(reason) << ": " << converter.to_bytes(buffer) << endl;

LocalFree(buffer);
}
Expand All @@ -89,10 +141,6 @@ static void catchFunction(int signo) {
cerr << "Caught signal " << signo << endl;
}

static void atExitListener() {
cout << "Exiting" << endl;
}

bool g_showCrashDialog = false;

LONG WINAPI crashHandler(EXCEPTION_POINTERS * /*ExceptionInfo*/) {
Expand Down Expand Up @@ -143,8 +191,6 @@ static void registerSignalHandlers() {
cerr << "Failed to listen to SIGABRT_COMPAT" << endl;
}

atexit(atExitListener);

SetUnhandledExceptionFilter(crashHandler);
}

Expand All @@ -158,18 +204,17 @@ int CALLBACK WinMain(
try {
int argc = 0;
PTCHAR commandLine = GetCommandLine();
PTCHAR* argv = CommandLineToArgvW(commandLine, &argc);
attachToConsole(argc, argv);
PTCHAR *argv = CommandLineToArgvW(commandLine, &argc);
attachToOrAllocateConsole(argc, argv);
if (!setCmdLineArguments(argc, argv)) {
cerr << "Failed to set the command line arguments" << endl;
return EXIT_FAILURE;
}

cout << "launchJavaVM" << endl;
launchJavaVM(defaultLaunchVMDelegate);
} catch (std::exception &theException) {
} catch (exception &theException) {
cerr << "Caught exception:" << endl;
cerr << theException.what() << endl;
cerr << theException.what() << endl;
} catch (...) {
cerr << "Caught unknown exception:" << endl;
}
Expand All @@ -178,6 +223,7 @@ int CALLBACK WinMain(
}

int wmain(int argc, wchar_t **argv) {
SetConsoleOutputCP(CP_UTF8);
registerSignalHandlers();
clearEnvironment();
if (!setCmdLineArguments(argc, argv)) {
Expand Down Expand Up @@ -283,16 +329,20 @@ bool isZgcSupported() {
versionInformation.dwOSVersionInfoSize = sizeof(versionInformation);
if (RETURN_SUCCESS == rtlGetVersionFunction(&versionInformation)) {
if (verbose) {
std::cout << "versionInformation.dwMajorVersion=" << versionInformation.dwMajorVersion
<< ", versionInformation.dwMinorVersion=" << versionInformation.dwMinorVersion
<< ", versionInformation.dwBuildNumber=" << versionInformation.dwBuildNumber
<< std::endl;
cout
<< "versionInformation.dwMajorVersion="
<< versionInformation.dwMajorVersion
<< ", versionInformation.dwMinorVersion="
<< versionInformation.dwMinorVersion
<< ", versionInformation.dwBuildNumber="
<< versionInformation.dwBuildNumber
<< endl;
}
return (versionInformation.dwMajorVersion >= 10 && versionInformation.dwBuildNumber >= 17134)
|| (versionInformation.dwMajorVersion >= 10 && versionInformation.dwMinorVersion >= 1);
} else {
if (verbose) {
std::cout << "RtlGetVersion didn't work" << std::endl;
cout << "RtlGetVersion didn't work" << endl;
}
}
}
Expand Down

0 comments on commit 0f35046

Please sign in to comment.