aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRachel Powers <508861+Ryex@users.noreply.github.com>2023-07-30 13:32:31 -0700
committerRachel Powers <508861+Ryex@users.noreply.github.com>2023-07-30 13:38:47 -0700
commit186211244de92b432713759c14629234cf3e8c1a (patch)
tree684b3eee5c343e70dee5e1d2943e207add7465ad
parent5740ee04449865158c752e1806e0c329dbe74117 (diff)
downloadPrismLauncher-186211244de92b432713759c14629234cf3e8c1a.tar.gz
PrismLauncher-186211244de92b432713759c14629234cf3e8c1a.tar.bz2
PrismLauncher-186211244de92b432713759c14629234cf3e8c1a.zip
refactor(windows console): move to external file
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
-rw-r--r--launcher/Application.cpp113
-rw-r--r--launcher/CMakeLists.txt8
-rw-r--r--launcher/WindowsConsole.cpp134
-rw-r--r--launcher/WindowsConsole.h25
4 files changed, 170 insertions, 110 deletions
diff --git a/launcher/Application.cpp b/launcher/Application.cpp
index ff6864f5..745aa31c 100644
--- a/launcher/Application.cpp
+++ b/launcher/Application.cpp
@@ -136,15 +136,7 @@
#endif
#if defined Q_OS_WIN32
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <fcntl.h>
-#include <io.h>
-#include <stdio.h>
-#include <windows.h>
-#include <iostream>
-
+#include "WindowsConsole.h"
#endif
#define STRINGIFY(x) #x
@@ -174,112 +166,13 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QSt
} // namespace
-#if defined Q_OS_WIN32
-
-// taken from https://stackoverflow.com/a/25927081
-// getting a proper output to console with redirection support on windows is apearently hell
-void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr)
-{
- // Re-initialize the C runtime "FILE" handles with clean handles bound to "nul". We do this because it has been
- // observed that the file number of our standard handle file objects can be assigned internally to a value of -2
- // when not bound to a valid target, which represents some kind of unknown internal invalid state. In this state our
- // call to "_dup2" fails, as it specifically tests to ensure that the target file number isn't equal to this value
- // before allowing the operation to continue. We can resolve this issue by first "re-opening" the target files to
- // use the "nul" device, which will place them into a valid state, after which we can redirect them to our target
- // using the "_dup2" function.
- if (bindStdIn) {
- FILE* dummyFile;
- freopen_s(&dummyFile, "nul", "r", stdin);
- }
- if (bindStdOut) {
- FILE* dummyFile;
- freopen_s(&dummyFile, "nul", "w", stdout);
- }
- if (bindStdErr) {
- FILE* dummyFile;
- freopen_s(&dummyFile, "nul", "w", stderr);
- }
-
- // Redirect unbuffered stdin from the current standard input handle
- if (bindStdIn) {
- HANDLE stdHandle = GetStdHandle(STD_INPUT_HANDLE);
- if (stdHandle != INVALID_HANDLE_VALUE) {
- int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
- if (fileDescriptor != -1) {
- FILE* file = _fdopen(fileDescriptor, "r");
- if (file != NULL) {
- int dup2Result = _dup2(_fileno(file), _fileno(stdin));
- if (dup2Result == 0) {
- setvbuf(stdin, NULL, _IONBF, 0);
- }
- }
- }
- }
- }
-
- // Redirect unbuffered stdout to the current standard output handle
- if (bindStdOut) {
- HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
- if (stdHandle != INVALID_HANDLE_VALUE) {
- int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
- if (fileDescriptor != -1) {
- FILE* file = _fdopen(fileDescriptor, "w");
- if (file != NULL) {
- int dup2Result = _dup2(_fileno(file), _fileno(stdout));
- if (dup2Result == 0) {
- setvbuf(stdout, NULL, _IONBF, 0);
- }
- }
- }
- }
- }
-
- // Redirect unbuffered stderr to the current standard error handle
- if (bindStdErr) {
- HANDLE stdHandle = GetStdHandle(STD_ERROR_HANDLE);
- if (stdHandle != INVALID_HANDLE_VALUE) {
- int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
- if (fileDescriptor != -1) {
- FILE* file = _fdopen(fileDescriptor, "w");
- if (file != NULL) {
- int dup2Result = _dup2(_fileno(file), _fileno(stderr));
- if (dup2Result == 0) {
- setvbuf(stderr, NULL, _IONBF, 0);
- }
- }
- }
- }
- }
-
- // Clear the error state for each of the C++ standard stream objects. We need to do this, as attempts to access the
- // standard streams before they refer to a valid target will cause the iostream objects to enter an error state. In
- // versions of Visual Studio after 2005, this seems to always occur during startup regardless of whether anything
- // has been read from or written to the targets or not.
- if (bindStdIn) {
- std::wcin.clear();
- std::cin.clear();
- }
- if (bindStdOut) {
- std::wcout.clear();
- std::cout.clear();
- }
- if (bindStdErr) {
- std::wcerr.clear();
- std::cerr.clear();
- }
-}
-#endif
Application::Application(int& argc, char** argv) : QApplication(argc, argv)
{
#if defined Q_OS_WIN32
// attach the parent console if stdout not already captured
- auto stdout_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
- if (stdout_type == FILE_TYPE_CHAR || stdout_type == FILE_TYPE_UNKNOWN) {
- if (AttachConsole(ATTACH_PARENT_PROCESS)) {
- BindCrtHandlesToStdHandles(true, true, true);
- consoleAttached = true;
- }
+ if (AttachWindowsConsole()) {
+ consoleAttached = true;
}
#endif
setOrganizationName(BuildConfig.LAUNCHER_NAME);
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index 2d06dbf4..276f1d05 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -1018,6 +1018,14 @@ SET(LAUNCHER_SOURCES
ui/instanceview/VisualGroup.h
)
+if(WIN32)
+ set(LAUNCHER_SOURCES
+ WindowsConsole.cpp
+ WindowsConsole.h
+ ${LAUNCHER_SOURCES}
+ )
+endif()
+
qt_wrap_ui(LAUNCHER_UI
ui/MainWindow.ui
ui/setupwizard/PasteWizardPage.ui
diff --git a/launcher/WindowsConsole.cpp b/launcher/WindowsConsole.cpp
new file mode 100644
index 00000000..fa9920ef
--- /dev/null
+++ b/launcher/WindowsConsole.cpp
@@ -0,0 +1,134 @@
+/*
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <fcntl.h>
+#include <io.h>
+#include <stdio.h>
+#include <windows.h>
+#include <iostream>
+
+// taken from https://stackoverflow.com/a/25927081
+// getting a proper output to console with redirection support on windows is apparently hell
+void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr)
+{
+ // Re-initialize the C runtime "FILE" handles with clean handles bound to "nul". We do this because it has been
+ // observed that the file number of our standard handle file objects can be assigned internally to a value of -2
+ // when not bound to a valid target, which represents some kind of unknown internal invalid state. In this state our
+ // call to "_dup2" fails, as it specifically tests to ensure that the target file number isn't equal to this value
+ // before allowing the operation to continue. We can resolve this issue by first "re-opening" the target files to
+ // use the "nul" device, which will place them into a valid state, after which we can redirect them to our target
+ // using the "_dup2" function.
+ if (bindStdIn) {
+ FILE* dummyFile;
+ freopen_s(&dummyFile, "nul", "r", stdin);
+ }
+ if (bindStdOut) {
+ FILE* dummyFile;
+ freopen_s(&dummyFile, "nul", "w", stdout);
+ }
+ if (bindStdErr) {
+ FILE* dummyFile;
+ freopen_s(&dummyFile, "nul", "w", stderr);
+ }
+
+ // Redirect unbuffered stdin from the current standard input handle
+ if (bindStdIn) {
+ HANDLE stdHandle = GetStdHandle(STD_INPUT_HANDLE);
+ if (stdHandle != INVALID_HANDLE_VALUE) {
+ int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
+ if (fileDescriptor != -1) {
+ FILE* file = _fdopen(fileDescriptor, "r");
+ if (file != NULL) {
+ int dup2Result = _dup2(_fileno(file), _fileno(stdin));
+ if (dup2Result == 0) {
+ setvbuf(stdin, NULL, _IONBF, 0);
+ }
+ }
+ }
+ }
+ }
+
+ // Redirect unbuffered stdout to the current standard output handle
+ if (bindStdOut) {
+ HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (stdHandle != INVALID_HANDLE_VALUE) {
+ int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
+ if (fileDescriptor != -1) {
+ FILE* file = _fdopen(fileDescriptor, "w");
+ if (file != NULL) {
+ int dup2Result = _dup2(_fileno(file), _fileno(stdout));
+ if (dup2Result == 0) {
+ setvbuf(stdout, NULL, _IONBF, 0);
+ }
+ }
+ }
+ }
+ }
+
+ // Redirect unbuffered stderr to the current standard error handle
+ if (bindStdErr) {
+ HANDLE stdHandle = GetStdHandle(STD_ERROR_HANDLE);
+ if (stdHandle != INVALID_HANDLE_VALUE) {
+ int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
+ if (fileDescriptor != -1) {
+ FILE* file = _fdopen(fileDescriptor, "w");
+ if (file != NULL) {
+ int dup2Result = _dup2(_fileno(file), _fileno(stderr));
+ if (dup2Result == 0) {
+ setvbuf(stderr, NULL, _IONBF, 0);
+ }
+ }
+ }
+ }
+ }
+
+ // Clear the error state for each of the C++ standard stream objects. We need to do this, as attempts to access the
+ // standard streams before they refer to a valid target will cause the iostream objects to enter an error state. In
+ // versions of Visual Studio after 2005, this seems to always occur during startup regardless of whether anything
+ // has been read from or written to the targets or not.
+ if (bindStdIn) {
+ std::wcin.clear();
+ std::cin.clear();
+ }
+ if (bindStdOut) {
+ std::wcout.clear();
+ std::cout.clear();
+ }
+ if (bindStdErr) {
+ std::wcerr.clear();
+ std::cerr.clear();
+ }
+}
+
+
+bool AttachWindowsConsole() {
+ auto stdout_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
+ if (stdout_type == FILE_TYPE_CHAR || stdout_type == FILE_TYPE_UNKNOWN) {
+ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
+ BindCrtHandlesToStdHandles(true, true, true);
+ return true;
+ }
+ }
+ return false;
+}
+
+
diff --git a/launcher/WindowsConsole.h b/launcher/WindowsConsole.h
new file mode 100644
index 00000000..ab53864b
--- /dev/null
+++ b/launcher/WindowsConsole.h
@@ -0,0 +1,25 @@
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+/*
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr);
+bool AttachWindowsConsole();