diff --git a/src/Export.cs b/src/Export.cs index 745545e..86e6240 100644 --- a/src/Export.cs +++ b/src/Export.cs @@ -16,6 +16,7 @@ public static class Export { [2] Paimon.moe [3] Seelie.me [4] 表格文件 + [5] 原魔工具箱 输入一个数字(0-4): ".Split("\n").Select(s => s.Trim()).JoinToString("\n") + " "); if (!int.TryParse(Console.ReadLine(), out var num)) num = 0; ((Action) (num switch { @@ -23,6 +24,7 @@ public static class Export { 2 => ToPaimon, 3 => ToSeelie, 4 => ToCSV, + 5 => ToWxApp1, 7 => ToRawJson, _ => ToCocogoat })).Invoke(data); @@ -46,6 +48,21 @@ public static class Export { : $"https://cocogoat.work/achievement?memo={memo.key}"); } + private static void ToWxApp1(AchievementAllDataNotify data) { + var id = Guid.NewGuid().ToString("N").Substring(20, 8); + var result = JsonConvert.SerializeObject(new Dictionary { + { "key", id }, + { "data", ExportToUIAFApp(data) } + }); + using var request = new HttpRequestMessage { + Method = HttpMethod.Post, + RequestUri = new Uri("https://api.qyinter.com/achievementRedis"), + Content = new StringContent(result, Encoding.UTF8, "application/json") + }; + using var response = Utils.CHttpClient.Value.Send(request); + Console.WriteLine($"在小程序导入页面输入以下代码: {id}"); + } + private static void ToSnapGenshin(AchievementAllDataNotify data) { if (CheckSnapScheme()) { Utils.CopyToClipboard(JsonConvert.SerializeObject(ExportToUIAFApp(data))); diff --git a/src/Injector.cs b/src/Injector.cs index 7a11d0f..7350275 100644 --- a/src/Injector.cs +++ b/src/Injector.cs @@ -1,5 +1,6 @@ using System.ComponentModel; using YaeAchievement.Win32; +using static YaeAchievement.Win32.Native; namespace YaeAchievement; @@ -19,31 +20,33 @@ public static class Injector { return result; } - public static int LoadLibraryAndInject(IntPtr handle, string libPath) { - var hKernel = Native.GetModuleHandle("kernel32.dll"); + // todo: refactor + public static int LoadLibraryAndInject(IntPtr hProc, string libPath) { + var hKernel = GetModuleHandle("kernel32.dll"); if (hKernel == IntPtr.Zero) { return new Win32Exception().PrintMsgAndReturnErrCode("GetModuleHandle fail"); } - var pLoadLibrary = Native.GetProcAddress(hKernel, "LoadLibraryA"); + var pLoadLibrary = GetProcAddress(hKernel, "LoadLibraryA"); if (pLoadLibrary == IntPtr.Zero) { return new Win32Exception().PrintMsgAndReturnErrCode("GetProcAddress fail"); } - var pBase = Native.VirtualAllocEx(handle, IntPtr.Zero, libPath.Length + 1, AllocationType.Reserve | AllocationType.Commit, MemoryProtection.ReadWrite); + var pBase = VirtualAllocEx(hProc, IntPtr.Zero, libPath.Length + 1, AllocationType.Reserve | AllocationType.Commit, MemoryProtection.ReadWrite); if (pBase == IntPtr.Zero) { return new Win32Exception().PrintMsgAndReturnErrCode("VirtualAllocEx fail"); } - if (!Native.WriteProcessMemory(handle, pBase, libPath.ToCharArray(), libPath.Length, out _)) { + if (!WriteProcessMemory(hProc, pBase, libPath.ToCharArray(), libPath.Length, out _)) { return new Win32Exception().PrintMsgAndReturnErrCode("WriteProcessMemory fail"); } - var hThread = Native.CreateRemoteThread(handle, IntPtr.Zero, 0, pLoadLibrary, pBase, 0, out _); + var hThread = CreateRemoteThread(hProc, IntPtr.Zero, 0, pLoadLibrary, pBase, 0, out _); if (hThread == IntPtr.Zero) { var e = new Win32Exception(); - if (!Native.VirtualFreeEx(handle, pBase, 0, AllocationType.Release)) { - new Win32Exception().PrintMsgAndReturnErrCode("VirtualFreeEx fail"); - } + VirtualFreeEx(hProc, pBase, 0, AllocationType.Release); return e.PrintMsgAndReturnErrCode("CreateRemoteThread fail"); } - return !Native.CloseHandle(hThread) ? new Win32Exception().PrintMsgAndReturnErrCode("CloseHandle fail") : 0; + if (WaitForSingleObject(hThread, 2000) == 0) { + VirtualFreeEx(hProc, pBase, 0, AllocationType.Release); + } + return !CloseHandle(hThread) ? new Win32Exception().PrintMsgAndReturnErrCode("CloseHandle fail") : 0; } } \ No newline at end of file diff --git a/src/Utils.cs b/src/Utils.cs index 9805466..7957fdb 100644 --- a/src/Utils.cs +++ b/src/Utils.cs @@ -168,7 +168,7 @@ public static class Utils { public static void CheckGenshinIsRunning() { Process.EnterDebugMode(); foreach (var process in Process.GetProcesses()) { - if (process.ProcessName is "GenshinImpact" or "YuanShen") { + if (process.ProcessName is "GenshinImpact" or "YuanShen" && !process.HasExited) { Console.WriteLine($"原神正在运行,请关闭后重试 ({process.Id})"); Environment.Exit(301); } diff --git a/src/Win32/AllocationType.cs b/src/Win32/AllocationType.cs index 254fc22..17c30d6 100644 --- a/src/Win32/AllocationType.cs +++ b/src/Win32/AllocationType.cs @@ -2,13 +2,15 @@ [Flags] public enum AllocationType : uint { - Commit = 0x1000, - Reserve = 0x2000, - Decommit = 0x4000, - Release = 0x8000, - Reset = 0x80000, - Physical = 0x400000, - TopDown = 0x100000, - WriteWatch = 0x200000, - LargePages = 0x20000000 + Commit = 0x00001000, + Reserve = 0x00002000, + Reset = 0x00080000, + TopDown = 0x00100000, + WriteWatch = 0x00200000, + Physical = 0x00400000, + Rotate = 0x00800000, + ResetUndo = 0x01000000, + LargePages = 0x20000000, + Decommit = 0x00004000, + Release = 0x00008000 } diff --git a/src/Win32/Native.cs b/src/Win32/Native.cs index dd31c55..e9bb060 100644 --- a/src/Win32/Native.cs +++ b/src/Win32/Native.cs @@ -146,4 +146,7 @@ public static class Native { [DllImport("user32.dll")] public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hdc); + [DllImport("kernel32.dll")] + public static extern uint WaitForSingleObject(IntPtr handle, ulong dwMilliseconds); + }