csharp/Aekras1a/KoiVM-modded/KoiVM.Confuser/KoiInfo.cs

KoiInfo.cs
#region

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Windows.Forms;
using Confuser.Core;

#endregion

namespace KoiVM.Confuser
{
    internal static clast KoiInfo
    {
        internal static KoiSettings settings;
        private static bool inited;
        private static readonly List astemblies = new List();

        public static string KoiDirectory
        {
            get;
            private set;
        }

        private static astembly OnastemblyResolve(object sender, ResolveEventArgs args)
        {
            var name = new astemblyName(args.Name).Name;
            foreach(var asm in astemblies)
                if(asm.GetName().Name == name)
                    return asm;

            var folderPath = Path.GetDirectoryName(astembly.GetExecutingastembly().Location);
            var astemblyPath = Path.Combine(folderPath, name + ".dll");
            if(File.Exists(astemblyPath) == false)
                return null;

            var astembly = astembly.LoadFrom(astemblyPath);
            return astembly;
        }

        internal static void Init()
        {
            lock(typeof(KoiInfo))
            {
                if(inited)
                    return;

                AppDomain.CurrentDomain.astemblyResolve += OnastemblyResolve;
                KoiDirectory = Path.GetDirectoryName(astembly.GetExecutingastembly().Location);
                settings = new KoiSettings();

                inited = true;
            }
        }

        internal static void Init(ConfuserContext ctx)
        {
            lock(typeof(KoiInfo))
            {
                if(inited)
                    return;

                AppDomain.CurrentDomain.astemblyResolve += OnastemblyResolve;
                KoiDirectory = Path.GetDirectoryName(astembly.GetExecutingastembly().Location);
                settings = new KoiSettings();

                // Check if not yet processed.
                if(astembly.GetExecutingastembly().ManifestModule.GetType("KoiVM.Confuser.Internal.Fish") != null)
                    return;

                if(ctx != null)
                {
                    var packPath = Path.Combine(KoiDirectory, "koi.pack");

                    if(!File.Exists(packPath))
                        RetrieveKoi(ctx);

                    else if(!settings.NoCheck)
                        CheckUpdate(ctx);

                    InitKoi();
                }
                inited = true;
            }
        }

        private static void CheckUpdate(ConfuserContext ctx)
        {
            var ver = new KoiSystem().GetVersion(settings.KoiID);
            if(ver == settings.Version)
                return;

            ctx.Logger.LogFormat("New version of KoiVM: {0}", ver);
            ctx.Logger.LogFormat("Current version of KoiVM: {0}", settings.Version);

            if(settings.NoUI)
            {
                ctx.Logger.LogFormat("Updating...");
                var sys = new KoiSystem();
                var hnd = new ManualResetEvent(false);
                var okay = false;
                sys.Progress += _ => { };
                sys.Finish += f =>
                {
                    okay = f;
                    hnd.Set();
                };
                sys.Login(settings.KoiID);
                hnd.WaitOne();
                if(!okay)
                    throw new InvalidOperationException("Authentication failed.");
                settings.Version = ver;
                settings.Save();
            }
            else
            {
                Application.EnableVisualStyles();
                if(new UpdatePrompt(ver) {TopLevel = true}.ShowDialog() != DialogResult.OK)
                    throw new InvalidOperationException("Authentication failed.");
            }
        }

        private static void RetrieveKoi(ConfuserContext ctx)
        {
            if(settings.NoUI)
            {
                ctx.Logger.Log("Retrieving Koi...");

                var sys = new KoiSystem();
                var hnd = new ManualResetEvent(false);
                var okay = false;
                sys.Progress += _ => { };
                sys.Finish += f =>
                {
                    okay = f;
                    hnd.Set();
                };
                sys.Login(settings.KoiID);
                hnd.WaitOne();
                if(!okay)
                    throw new InvalidOperationException("Authentication failed.");
            }
            else
            {
                Application.EnableVisualStyles();
                if(new LoginPrompt {TopLevel = true}.ShowDialog() != DialogResult.OK)
                    throw new InvalidOperationException("Authentication failed.");
            }
        }

        internal static void InitKoi(bool runCctor = true)
        {
            var rc4 = new RC4(Convert.FromBase64String("S29pVk0gaXMgY3V0ZSEhIQ=="));
            var buf = File.ReadAllBytes(Path.Combine(KoiDirectory, "koi.pack"));
            rc4.Crypt(buf, 0, buf.Length);
            using(var deflate = new DeflateStream(new MemoryStream(buf), CompressionMode.Decompress))
            using(var reader = new BinaryReader(deflate))
            {
                var count = reader.ReadInt32();
                astemblies.Clear();
                for(var i = 0; i < count; i++)
                {
                    var asm = astembly.Load(reader.ReadBytes(reader.ReadInt32()));
                    astemblies.Add(asm);
                }
            }

            if(!runCctor)
                return;
            foreach(var asm in astemblies) // Initialize the modules, since internal calls might not trigger module cctor
                RuntimeHelpers.RunModuleConstructor(asm.ManifestModule.ModuleHandle);
        }
    }
}