aboutsummaryrefslogtreecommitdiff
path: root/launcher/WindowsConsole.cpp
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 /launcher/WindowsConsole.cpp
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>
Diffstat (limited to 'launcher/WindowsConsole.cpp')
-rw-r--r--launcher/WindowsConsole.cpp134
1 files changed, 134 insertions, 0 deletions
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;
+}
+
+