From 7b48707ba339c60604064e2e3f909503486fa4d9 Mon Sep 17 00:00:00 2001 From: exdownloader Date: Wed, 18 Apr 2018 16:33:43 +0100 Subject: [PATCH] ConsoleColor support --- BepInEx/BepInEx.csproj | 1 + BepInEx/ConsoleUtil/ConsoleWindow.cs | 15 ++- BepInEx/ConsoleUtil/Kon.cs | 152 +++++++++++++++++++++++++++ 3 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 BepInEx/ConsoleUtil/Kon.cs diff --git a/BepInEx/BepInEx.csproj b/BepInEx/BepInEx.csproj index 99d3d82..ada2bfb 100644 --- a/BepInEx/BepInEx.csproj +++ b/BepInEx/BepInEx.csproj @@ -58,6 +58,7 @@ + diff --git a/BepInEx/ConsoleUtil/ConsoleWindow.cs b/BepInEx/ConsoleUtil/ConsoleWindow.cs index aeb26b0..c3dd349 100644 --- a/BepInEx/ConsoleUtil/ConsoleWindow.cs +++ b/BepInEx/ConsoleUtil/ConsoleWindow.cs @@ -26,13 +26,17 @@ namespace UnityInjector.ConsoleUtil // Store Current Window IntPtr currWnd = GetForegroundWindow(); - if (!AllocConsole()) - throw new Exception("AllocConsole() failed"); + //Check for existing console before allocating + if (GetConsoleWindow() == IntPtr.Zero) + if (!AllocConsole()) + throw new Exception("AllocConsole() failed"); // Restore Foreground SetForegroundWindow(currWnd); - _cOut = CreateFile("CONOUT$", 0x40000000, 2, IntPtr.Zero, 3, 0, IntPtr.Zero); + _cOut = CreateFile("CONOUT$", 0x80000000 | 0x40000000, 2, IntPtr.Zero, 3, 0, IntPtr.Zero); + BepInEx.ConsoleUtil.Kon.conOut = _cOut; + if (!SetStdHandle(-11, _cOut)) throw new Exception("SetStdHandle() failed"); Init(); @@ -65,13 +69,16 @@ namespace UnityInjector.ConsoleUtil [DllImport("kernel32.dll", SetLastError = true)] private static extern bool AllocConsole(); + [DllImport("kernel32.dll")] + private static extern IntPtr GetConsoleWindow(); + [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)] private static extern bool CloseHandle(IntPtr handle); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CreateFile( string fileName, - int desiredAccess, + uint desiredAccess, int shareMode, IntPtr securityAttributes, int creationDisposition, diff --git a/BepInEx/ConsoleUtil/Kon.cs b/BepInEx/ConsoleUtil/Kon.cs new file mode 100644 index 0000000..96b5d99 --- /dev/null +++ b/BepInEx/ConsoleUtil/Kon.cs @@ -0,0 +1,152 @@ +using System; +using System.Runtime.InteropServices; +using System.Security.Permissions; + +namespace BepInEx.ConsoleUtil +{ + internal class Kon + { + #region pinvoke + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern bool SetConsoleTextAttribute(IntPtr hConsoleOutput, short attributes); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern IntPtr GetStdHandle(int nStdHandle); + + #endregion + + #region Types + + private struct CONSOLE_SCREEN_BUFFER_INFO + { + internal COORD dwSize; + internal COORD dwCursorPosition; + internal short wAttributes; + internal SMALL_RECT srWindow; + internal COORD dwMaximumWindowSize; + } + + private struct COORD + { + internal short X; + internal short Y; + } + + private struct SMALL_RECT + { + internal short Left; + internal short Top; + internal short Right; + internal short Bottom; + } + + private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); + + #endregion + + #region Private + + private static short ConsoleColorToColorAttribute(short color, bool isBackground) + { + if ((color & -16) != 0) + throw new ArgumentException("Arg_InvalidConsoleColor"); + if (isBackground) + color <<= 4; + return color; + } + + private static CONSOLE_SCREEN_BUFFER_INFO GetBufferInfo(bool throwOnNoConsole, out bool succeeded) + { + succeeded = false; + if (!(conOut == INVALID_HANDLE_VALUE)) + { + CONSOLE_SCREEN_BUFFER_INFO console_SCREEN_BUFFER_INFO; + if (!GetConsoleScreenBufferInfo(conOut, out console_SCREEN_BUFFER_INFO)) + { + bool consoleScreenBufferInfo = GetConsoleScreenBufferInfo(GetStdHandle(-12), out console_SCREEN_BUFFER_INFO); + if (!consoleScreenBufferInfo) + consoleScreenBufferInfo = GetConsoleScreenBufferInfo(GetStdHandle(-10), out console_SCREEN_BUFFER_INFO); + + if (!consoleScreenBufferInfo) + if (Marshal.GetLastWin32Error() == 6 && !throwOnNoConsole) + return default(CONSOLE_SCREEN_BUFFER_INFO); + } + succeeded = true; + return console_SCREEN_BUFFER_INFO; + } + if (!throwOnNoConsole) + return default(CONSOLE_SCREEN_BUFFER_INFO); + throw new Exception("IO.IO_NoConsole"); + } + + private static void SetConsoleColor(bool isBackground, ConsoleColor c) + { + new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); + var color = ConsoleColorToColorAttribute((short)c, isBackground); + bool flag; + var bufferInfo = GetBufferInfo(false, out flag); + if (!flag) return; + var num = bufferInfo.wAttributes; + num &= (short)(isBackground ? -241 : -16); + num = (short)((ushort)num | (ushort)color); + SetConsoleTextAttribute(conOut, num); + } + + private static ConsoleColor GetConsoleColor(bool isBackground) + { + bool flag; + var bufferInfo = GetBufferInfo(false, out flag); + if (!flag) return isBackground ? ConsoleColor.Black : ConsoleColor.Gray; + return ColorAttributeToConsoleColor((short)(bufferInfo.wAttributes & 240)); + } + + private static ConsoleColor ColorAttributeToConsoleColor(short c) + { + if ((short)(c & 255) != 0) + c >>= 4; + return (ConsoleColor)c; + } + + internal static IntPtr conOut = IntPtr.Zero; + + #endregion + + #region Public + + public static void ResetConsoleColor() + { + SetConsoleColor(true, ConsoleColor.Black); + SetConsoleColor(false, ConsoleColor.Gray); + } + + public static ConsoleColor ForegroundColor + { + get + { + return GetConsoleColor(false); + } + set + { + SetConsoleColor(false, value); + } + } + + public static ConsoleColor BackgroundColor + { + get + { + return GetConsoleColor(true); + } + set + { + SetConsoleColor(true, value); + } + } + + #endregion + } +}