mirror of
https://github.com/HolographicHat/Yae.git
synced 2025-12-15 02:48:12 +08:00
optimize code and update
This commit is contained in:
5
src/Events/IEventBase.cs
Normal file
5
src/Events/IEventBase.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
namespace YaeAchievement.Events;
|
||||
|
||||
public interface IEventBase {
|
||||
|
||||
}
|
||||
14
src/Events/PipeRecvEvent.cs
Normal file
14
src/Events/PipeRecvEvent.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace YaeAchievement.Events;
|
||||
|
||||
public class PipeRecvEvent : IEventBase {
|
||||
|
||||
private readonly byte[] _data;
|
||||
|
||||
public PipeRecvEvent(string content) {
|
||||
_data = Convert.FromBase64String(content);
|
||||
}
|
||||
|
||||
public byte[] GetData() {
|
||||
return _data;
|
||||
}
|
||||
}
|
||||
@@ -2,4 +2,7 @@
|
||||
|
||||
public static class GlobalVars {
|
||||
public static bool Verbose = false;
|
||||
}
|
||||
public const string LibName = "YaeAchievementLib.dll";
|
||||
public const string PipeName = "YaeAchievementPipe";
|
||||
public static bool UnexpectedExit = true;
|
||||
}
|
||||
|
||||
@@ -5,22 +5,17 @@ namespace YaeAchievement;
|
||||
|
||||
public static class Injector {
|
||||
|
||||
public static bool CreateProcess(string path, ref IntPtr phThread, ref IntPtr phProcess) {
|
||||
ProcessInformation pi;
|
||||
unsafe {
|
||||
var si = new StartupInfo();
|
||||
SecurityAttributes* attr = null;
|
||||
var result = Native.CreateProcess(
|
||||
path, null, ref *attr, ref *attr, false,
|
||||
CreationFlags.CreateSuspended, IntPtr.Zero, null, ref si, out pi
|
||||
);
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
phThread = pi.hThread;
|
||||
phProcess = pi.hProcess;
|
||||
return true;
|
||||
public static unsafe bool CreateProcess(string path, out IntPtr hProc, out IntPtr hThread, out uint pid) {
|
||||
var si = new StartupInfo();
|
||||
SecurityAttributes* attr = null;
|
||||
var result = Native.CreateProcess(
|
||||
path, null, ref *attr, ref *attr, false,
|
||||
CreationFlags.CreateSuspended, IntPtr.Zero, null, ref si, out var pi
|
||||
);
|
||||
pid = pi.dwProcessID;
|
||||
hProc = pi.hProcess;
|
||||
hThread = pi.hThread;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int LoadLibraryAndInject(IntPtr handle, string libPath) {
|
||||
|
||||
@@ -1,46 +1,66 @@
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Pipes;
|
||||
using YaeAchievement;
|
||||
using YaeAchievement.Events;
|
||||
using YaeAchievement.Win32;
|
||||
|
||||
var hThread = IntPtr.Zero;
|
||||
var hProcess = IntPtr.Zero;
|
||||
if (!Injector.CreateProcess("exePath", ref hThread, ref hProcess)) {
|
||||
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("ICreateProcess fail"));
|
||||
}
|
||||
if (Injector.LoadLibraryAndInject(hProcess, "YaeAchievementLib.dll") != 0) {
|
||||
if (!Native.TerminateProcess(hProcess, 0)) {
|
||||
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("TerminateProcess fail"));
|
||||
// ReSharper disable once UnusedLocalFunctionReturnValue
|
||||
Thread StartAndWaitResult(string exePath, Func<IEventBase, bool> onEvent) {
|
||||
if (!Injector.CreateProcess(exePath, out var hProcess, out var hThread, out var pid)) {
|
||||
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("ICreateProcess fail"));
|
||||
}
|
||||
}
|
||||
if (Native.ResumeThread(hThread) == 0xFFFFFFFF) {
|
||||
var e = new Win32Exception();
|
||||
if (!Native.TerminateProcess(hProcess, 0)) {
|
||||
new Win32Exception().PrintMsgAndReturnErrCode("TerminateProcess fail");
|
||||
}
|
||||
Environment.Exit(e.PrintMsgAndReturnErrCode("ResumeThread fail"));
|
||||
}
|
||||
if (!Native.CloseHandle(hProcess)) {
|
||||
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("CloseHandle fail"));
|
||||
}
|
||||
|
||||
bool OnXXXReceived(string something) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var ts = new ThreadStart(() => {
|
||||
var server = new NamedPipeServerStream("");
|
||||
server.WaitForConnection();
|
||||
var reader = new StreamReader(server);
|
||||
while (true) {
|
||||
var line = reader.ReadLine();
|
||||
if (line?.Length > 0) {
|
||||
if (OnXXXReceived(line)) {
|
||||
break;
|
||||
}
|
||||
server.Disconnect();
|
||||
server.WaitForConnection();
|
||||
if (Injector.LoadLibraryAndInject(hProcess, GlobalVars.LibName) != 0) {
|
||||
if (!Native.TerminateProcess(hProcess, 0)) {
|
||||
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("TerminateProcess fail"));
|
||||
}
|
||||
}
|
||||
if (Native.ResumeThread(hThread) == 0xFFFFFFFF) {
|
||||
var e = new Win32Exception();
|
||||
if (!Native.TerminateProcess(hProcess, 0)) {
|
||||
new Win32Exception().PrintMsgAndReturnErrCode("TerminateProcess fail");
|
||||
}
|
||||
Environment.Exit(e.PrintMsgAndReturnErrCode("ResumeThread fail"));
|
||||
}
|
||||
if (!Native.CloseHandle(hProcess)) {
|
||||
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("CloseHandle fail"));
|
||||
}
|
||||
var proc = Process.GetProcessById(Convert.ToInt32(pid));
|
||||
proc.EnableRaisingEvents = true;
|
||||
proc.Exited += (_, _) => {
|
||||
if (GlobalVars.UnexpectedExit) {
|
||||
Console.WriteLine($"Game process exit at {proc.ExitTime:HH:mm:ss}");
|
||||
Environment.Exit(114514);
|
||||
}
|
||||
};
|
||||
var ts = new ThreadStart(() => {
|
||||
var server = new NamedPipeServerStream(GlobalVars.PipeName);
|
||||
server.WaitForConnection();
|
||||
var reader = new StreamReader(server);
|
||||
while (true) {
|
||||
var line = reader.ReadLine();
|
||||
if (line?.Length > 0) {
|
||||
if (onEvent(new PipeRecvEvent(line))) {
|
||||
break;
|
||||
}
|
||||
server.Disconnect();
|
||||
server.WaitForConnection();
|
||||
}
|
||||
}
|
||||
});
|
||||
var th = new Thread(ts);
|
||||
th.Start();
|
||||
return th;
|
||||
}
|
||||
|
||||
StartAndWaitResult(@"D:\Genshin Impact Dev\2.8\YuanShen.exe", evt => {
|
||||
switch (evt) {
|
||||
case PipeRecvEvent @event: {
|
||||
var bytes = @event.GetData();
|
||||
GlobalVars.UnexpectedExit = false;
|
||||
return BitConverter.ToUInt32(bytes, 2) == 123456;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
});
|
||||
new Thread(ts).Start();
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
public static class AllocationType {
|
||||
public const int Commit = 0x1000;
|
||||
public const int Reserve = 0x2000;
|
||||
public const int Decommit = 0x4000;
|
||||
public const int Release = 0x8000;
|
||||
public const int Reset = 0x80000;
|
||||
public const int Physical = 0x400000;
|
||||
public const int TopDown = 0x100000;
|
||||
public const int WriteWatch = 0x200000;
|
||||
public const int LargePages = 0x20000000;
|
||||
[Flags]
|
||||
public enum AllocationType : uint {
|
||||
Commit = 0x1000,
|
||||
Reserve = 0x2000,
|
||||
Decommit = 0x4000,
|
||||
Release = 0x8000,
|
||||
Reset = 0x80000,
|
||||
Physical = 0x400000,
|
||||
TopDown = 0x100000,
|
||||
WriteWatch = 0x200000,
|
||||
LargePages = 0x20000000
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
public static class CreationFlags {
|
||||
public const int CreateSuspended = 0x00000004;
|
||||
public const int DetachedProcess = 0x00000008;
|
||||
public const int CreateNoWindow = 0x08000000;
|
||||
public const int ExtendedStartupInfoPresent = 0x00080000;
|
||||
[Flags]
|
||||
public enum CreationFlags : uint {
|
||||
CreateSuspended = 0x00000004,
|
||||
DetachedProcess = 0x00000008,
|
||||
CreateNoWindow = 0x08000000,
|
||||
ExtendedStartupInfoPresent = 0x00080000
|
||||
}
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
namespace YaeAchievement.Win32;
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
public static class MemoryProtection {
|
||||
public const int Execute = 0x10;
|
||||
public const int ExecuteRead = 0x20;
|
||||
public const int ExecuteReadWrite = 0x40;
|
||||
public const int ExecuteWriteCopy = 0x80;
|
||||
public const int NoAccess = 0x01;
|
||||
public const int ReadOnly = 0x02;
|
||||
public const int ReadWrite = 0x04;
|
||||
public const int WriteCopy = 0x08;
|
||||
public const int GuardModifierFlag = 0x100;
|
||||
public const int NoCacheModifierFlag = 0x200;
|
||||
public const int WriteCombineModifierFlag = 0x400;
|
||||
[Flags]
|
||||
public enum MemoryProtection : uint {
|
||||
Execute = 0x10,
|
||||
ExecuteRead = 0x20,
|
||||
ExecuteReadWrite = 0x40,
|
||||
ExecuteWriteCopy = 0x80,
|
||||
NoAccess = 0x01,
|
||||
ReadOnly = 0x02,
|
||||
ReadWrite = 0x04,
|
||||
WriteCopy = 0x08,
|
||||
GuardModifierFlag = 0x100,
|
||||
NoCacheModifierFlag = 0x200,
|
||||
WriteCombineModifierFlag = 0x400
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ public static class Native {
|
||||
ref SecurityAttributes lpProcessAttributes,
|
||||
ref SecurityAttributes lpThreadAttributes,
|
||||
bool bInheritHandles,
|
||||
int dwCreationFlags,
|
||||
CreationFlags dwCreationFlags,
|
||||
IntPtr lpEnvironment,
|
||||
string? lpCurrentDirectory,
|
||||
[In] ref StartupInfo lpStartupInfo,
|
||||
@@ -46,12 +46,12 @@ public static class Native {
|
||||
IntPtr hProcess,
|
||||
IntPtr lpAddress,
|
||||
int dwSize,
|
||||
int flAllocationType,
|
||||
int flProtect
|
||||
AllocationType flAllocationType,
|
||||
MemoryProtection flProtect
|
||||
);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)]
|
||||
public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, int dwFreeType);
|
||||
public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, AllocationType dwFreeType);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern uint ResumeThread(IntPtr hThread);
|
||||
|
||||
@@ -9,6 +9,6 @@ namespace YaeAchievement.Win32;
|
||||
public struct ProcessInformation {
|
||||
public IntPtr hProcess;
|
||||
public IntPtr hThread;
|
||||
public int dwProcessId;
|
||||
public int dwThreadId;
|
||||
public uint dwProcessID;
|
||||
public uint dwThreadID;
|
||||
}
|
||||
|
||||
@@ -7,20 +7,20 @@ namespace YaeAchievement.Win32;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct StartupInfo {
|
||||
public int cb;
|
||||
public uint cb;
|
||||
public string lpReserved;
|
||||
public string lpDesktop;
|
||||
public string lpTitle;
|
||||
public int dwX;
|
||||
public int dwY;
|
||||
public int dwXSize;
|
||||
public int dwYSize;
|
||||
public int dwXCountChars;
|
||||
public int dwYCountChars;
|
||||
public int dwFillAttribute;
|
||||
public int dwFlags;
|
||||
public short wShowWindow;
|
||||
public short cbReserved2;
|
||||
public uint dwX;
|
||||
public uint dwY;
|
||||
public uint dwXSize;
|
||||
public uint dwYSize;
|
||||
public uint dwXCountChars;
|
||||
public uint dwYCountChars;
|
||||
public uint dwFillAttribute;
|
||||
public uint dwFlags;
|
||||
public ushort wShowWindow;
|
||||
public ushort cbReserved2;
|
||||
public IntPtr lpReserved2;
|
||||
public IntPtr hStdInput;
|
||||
public IntPtr hStdOutput;
|
||||
|
||||
Reference in New Issue
Block a user