diff --git a/IPA.Injector/Bootstrapper.cs b/IPA.Injector/Bootstrapper.cs index a673a294..1d0f2261 100644 --- a/IPA.Injector/Bootstrapper.cs +++ b/IPA.Injector/Bootstrapper.cs @@ -14,7 +14,7 @@ namespace IPA.Injector { //if (Environment.CommandLine.Contains("--verbose")) //{ - Ipa.Injector.Windows.GuiConsole.CreateConsole(); + Ipa.Injector.Windows.WinConsole.Initialize(); //} } diff --git a/IPA.Injector/ConsoleWindow.cs b/IPA.Injector/ConsoleWindow.cs index d95329ab..1121d765 100644 --- a/IPA.Injector/ConsoleWindow.cs +++ b/IPA.Injector/ConsoleWindow.cs @@ -7,66 +7,98 @@ using Microsoft.Win32.SafeHandles; namespace Ipa.Injector.Windows { + // https://stackoverflow.com/a/48864902/3117125 + static class WinConsole + { + static public void Initialize(bool alwaysCreateNewConsole = true) + { + bool consoleAttached = true; + if (alwaysCreateNewConsole + || (AttachConsole(ATTACH_PARRENT) == 0 + && Marshal.GetLastWin32Error() != ERROR_ACCESS_DENIED)) + { + consoleAttached = AllocConsole() != 0; + } - class GuiConsole - { - public static void CreateConsole() - { - if (hasConsole) - return; - if (oldOut == IntPtr.Zero) - oldOut = GetStdHandle( -11 ); - if (! AllocConsole()) - throw new Exception("AllocConsole() failed"); - conOut = CreateFile( "CONOUT$", 0x40000000, 2, IntPtr.Zero, 3, 0, IntPtr.Zero ); - if (! SetStdHandle(-11, conOut)) - throw new Exception("SetStdHandle() failed"); - StreamToConsole(); - hasConsole = true; - } - public static void ReleaseConsole() - { - if (! hasConsole) - return; - if (! CloseHandle(conOut)) - throw new Exception("CloseHandle() failed"); - conOut = IntPtr.Zero; - if (! FreeConsole()) - throw new Exception("FreeConsole() failed"); - if (! SetStdHandle(-11, oldOut)) - throw new Exception("SetStdHandle() failed"); - StreamToConsole(); - hasConsole = false; - } - private static void StreamToConsole() - { - Stream cstm = Console.OpenStandardOutput(); - StreamWriter cstw = new StreamWriter( cstm, Encoding.Default ); - cstw.AutoFlush = true; - Console.SetOut( cstw ); - Console.SetError( cstw ); - } - private static bool hasConsole = false; - private static IntPtr conOut; - private static IntPtr oldOut; - [DllImport("kernel32.dll", SetLastError=true)] - private static extern bool AllocConsole(); - [DllImport("kernel32.dll", SetLastError=false)] - private static extern bool FreeConsole(); - [DllImport("kernel32.dll", SetLastError=true)] - private static extern IntPtr GetStdHandle( int nStdHandle ); - [DllImport("kernel32.dll", SetLastError=true)] - private static extern bool SetStdHandle(int nStdHandle, IntPtr hConsoleOutput); - [DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)] - private static extern IntPtr CreateFile( - string fileName, - int desiredAccess, - int shareMode, - IntPtr securityAttributes, - int creationDisposition, - int flagsAndAttributes, - IntPtr templateFile ); - [DllImport("kernel32.dll", ExactSpelling=true, SetLastError=true)] - private static extern bool CloseHandle(IntPtr handle); - } + if (consoleAttached) + { + InitializeOutStream(); + InitializeInStream(); + } + } + + private static void InitializeOutStream() + { + var fs = CreateFileStream("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE, FileAccess.Write); + if (fs != null) + { + var writer = new StreamWriter(fs) { AutoFlush = true }; + Console.SetOut(writer); + Console.SetError(writer); + } + } + + private static void InitializeInStream() + { + var fs = CreateFileStream("CONIN$", GENERIC_READ, FILE_SHARE_READ, FileAccess.Read); + if (fs != null) + { + Console.SetIn(new StreamReader(fs)); + } + } + + private static FileStream CreateFileStream(string name, uint win32DesiredAccess, uint win32ShareMode, + FileAccess dotNetFileAccess) + { + var file = new SafeFileHandle(CreateFileW(name, win32DesiredAccess, win32ShareMode, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero), true); + if (!file.IsInvalid) + { + var fs = new FileStream(file, dotNetFileAccess); + return fs; + } + return null; + } + + #region Win API Functions and Constants + [DllImport("kernel32.dll", + EntryPoint = "AllocConsole", + SetLastError = true, + CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + private static extern int AllocConsole(); + + [DllImport("kernel32.dll", + EntryPoint = "AttachConsole", + SetLastError = true, + CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + private static extern UInt32 AttachConsole(UInt32 dwProcessId); + + [DllImport("kernel32.dll", + EntryPoint = "CreateFileW", + SetLastError = true, + CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr CreateFileW( + string lpFileName, + UInt32 dwDesiredAccess, + UInt32 dwShareMode, + IntPtr lpSecurityAttributes, + UInt32 dwCreationDisposition, + UInt32 dwFlagsAndAttributes, + IntPtr hTemplateFile + ); + + private const UInt32 GENERIC_WRITE = 0x40000000; + private const UInt32 GENERIC_READ = 0x80000000; + private const UInt32 FILE_SHARE_READ = 0x00000001; + private const UInt32 FILE_SHARE_WRITE = 0x00000002; + private const UInt32 OPEN_EXISTING = 0x00000003; + private const UInt32 FILE_ATTRIBUTE_NORMAL = 0x80; + private const UInt32 ERROR_ACCESS_DENIED = 5; + + private const UInt32 ATTACH_PARRENT = 0xFFFFFFFF; + + #endregion + } } \ No newline at end of file diff --git a/IPA.Injector/Injector.cs b/IPA.Injector/Injector.cs index 6947a3f4..a36e2cb0 100644 --- a/IPA.Injector/Injector.cs +++ b/IPA.Injector/Injector.cs @@ -1,5 +1,4 @@ -using IllusionInjector; -using IPA.Loader; +using IPA.Loader; using IPA.Logging; using System; using System.IO; diff --git a/IPA.Loader/Loader/PluginComponent.cs b/IPA.Loader/Loader/PluginComponent.cs index f38cd221..07e1e054 100644 --- a/IPA.Loader/Loader/PluginComponent.cs +++ b/IPA.Loader/Loader/PluginComponent.cs @@ -34,7 +34,7 @@ namespace IPA.Loader bsPlugins = new CompositeBSPlugin(PluginManager.BSPlugins); ipaPlugins = new CompositeIPAPlugin(PluginManager.Plugins); - gameObject.AddComponent(); + gameObject.AddComponent(); bsPlugins.OnApplicationStart(); ipaPlugins.OnApplicationStart(); diff --git a/IPA.Loader/Updating/ModsaberML/Updater.cs b/IPA.Loader/Updating/ModsaberML/Updater.cs index 823a7ab8..6ce5daab 100644 --- a/IPA.Loader/Updating/ModsaberML/Updater.cs +++ b/IPA.Loader/Updating/ModsaberML/Updater.cs @@ -1,5 +1,4 @@ -using IllusionInjector.Updating.Backup; -using IPA.Utilities; +using IPA.Utilities; using IPA.Loader; using Ionic.Zip; using Newtonsoft.Json; @@ -17,6 +16,7 @@ using System.Threading.Tasks; using UnityEngine; using UnityEngine.Networking; using Logger = IPA.Logging.Logger; +using IPA.Updating.Backup; namespace IPA.Updating.ModsaberML {