optimize code and update

This commit is contained in:
HolographicHat
2022-06-11 00:36:54 +08:00
parent 3917f3e6c7
commit ef6a72312c
11 changed files with 139 additions and 99 deletions

5
src/Events/IEventBase.cs Normal file
View File

@@ -0,0 +1,5 @@
namespace YaeAchievement.Events;
public interface IEventBase {
}

View 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;
}
}

View File

@@ -2,4 +2,7 @@
public static class GlobalVars { public static class GlobalVars {
public static bool Verbose = false; public static bool Verbose = false;
} public const string LibName = "YaeAchievementLib.dll";
public const string PipeName = "YaeAchievementPipe";
public static bool UnexpectedExit = true;
}

View File

@@ -5,22 +5,17 @@ namespace YaeAchievement;
public static class Injector { public static class Injector {
public static bool CreateProcess(string path, ref IntPtr phThread, ref IntPtr phProcess) { public static unsafe bool CreateProcess(string path, out IntPtr hProc, out IntPtr hThread, out uint pid) {
ProcessInformation pi; var si = new StartupInfo();
unsafe { SecurityAttributes* attr = null;
var si = new StartupInfo(); var result = Native.CreateProcess(
SecurityAttributes* attr = null; path, null, ref *attr, ref *attr, false,
var result = Native.CreateProcess( CreationFlags.CreateSuspended, IntPtr.Zero, null, ref si, out var pi
path, null, ref *attr, ref *attr, false, );
CreationFlags.CreateSuspended, IntPtr.Zero, null, ref si, out pi pid = pi.dwProcessID;
); hProc = pi.hProcess;
if (!result) { hThread = pi.hThread;
return false; return result;
}
}
phThread = pi.hThread;
phProcess = pi.hProcess;
return true;
} }
public static int LoadLibraryAndInject(IntPtr handle, string libPath) { public static int LoadLibraryAndInject(IntPtr handle, string libPath) {

View File

@@ -1,46 +1,66 @@
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using System.IO.Pipes; using System.IO.Pipes;
using YaeAchievement; using YaeAchievement;
using YaeAchievement.Events;
using YaeAchievement.Win32; using YaeAchievement.Win32;
var hThread = IntPtr.Zero; // ReSharper disable once UnusedLocalFunctionReturnValue
var hProcess = IntPtr.Zero; Thread StartAndWaitResult(string exePath, Func<IEventBase, bool> onEvent) {
if (!Injector.CreateProcess("exePath", ref hThread, ref hProcess)) { if (!Injector.CreateProcess(exePath, out var hProcess, out var hThread, out var pid)) {
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("ICreateProcess fail")); 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"));
} }
} if (Injector.LoadLibraryAndInject(hProcess, GlobalVars.LibName) != 0) {
if (Native.ResumeThread(hThread) == 0xFFFFFFFF) { if (!Native.TerminateProcess(hProcess, 0)) {
var e = new Win32Exception(); Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("TerminateProcess fail"));
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 (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();

View File

@@ -1,13 +1,14 @@
namespace YaeAchievement.Win32; namespace YaeAchievement.Win32;
public static class AllocationType { [Flags]
public const int Commit = 0x1000; public enum AllocationType : uint {
public const int Reserve = 0x2000; Commit = 0x1000,
public const int Decommit = 0x4000; Reserve = 0x2000,
public const int Release = 0x8000; Decommit = 0x4000,
public const int Reset = 0x80000; Release = 0x8000,
public const int Physical = 0x400000; Reset = 0x80000,
public const int TopDown = 0x100000; Physical = 0x400000,
public const int WriteWatch = 0x200000; TopDown = 0x100000,
public const int LargePages = 0x20000000; WriteWatch = 0x200000,
LargePages = 0x20000000
} }

View File

@@ -1,8 +1,9 @@
namespace YaeAchievement.Win32; namespace YaeAchievement.Win32;
public static class CreationFlags { [Flags]
public const int CreateSuspended = 0x00000004; public enum CreationFlags : uint {
public const int DetachedProcess = 0x00000008; CreateSuspended = 0x00000004,
public const int CreateNoWindow = 0x08000000; DetachedProcess = 0x00000008,
public const int ExtendedStartupInfoPresent = 0x00080000; CreateNoWindow = 0x08000000,
ExtendedStartupInfoPresent = 0x00080000
} }

View File

@@ -1,15 +1,16 @@
namespace YaeAchievement.Win32; namespace YaeAchievement.Win32;
public static class MemoryProtection { [Flags]
public const int Execute = 0x10; public enum MemoryProtection : uint {
public const int ExecuteRead = 0x20; Execute = 0x10,
public const int ExecuteReadWrite = 0x40; ExecuteRead = 0x20,
public const int ExecuteWriteCopy = 0x80; ExecuteReadWrite = 0x40,
public const int NoAccess = 0x01; ExecuteWriteCopy = 0x80,
public const int ReadOnly = 0x02; NoAccess = 0x01,
public const int ReadWrite = 0x04; ReadOnly = 0x02,
public const int WriteCopy = 0x08; ReadWrite = 0x04,
public const int GuardModifierFlag = 0x100; WriteCopy = 0x08,
public const int NoCacheModifierFlag = 0x200; GuardModifierFlag = 0x100,
public const int WriteCombineModifierFlag = 0x400; NoCacheModifierFlag = 0x200,
WriteCombineModifierFlag = 0x400
} }

View File

@@ -14,7 +14,7 @@ public static class Native {
ref SecurityAttributes lpProcessAttributes, ref SecurityAttributes lpProcessAttributes,
ref SecurityAttributes lpThreadAttributes, ref SecurityAttributes lpThreadAttributes,
bool bInheritHandles, bool bInheritHandles,
int dwCreationFlags, CreationFlags dwCreationFlags,
IntPtr lpEnvironment, IntPtr lpEnvironment,
string? lpCurrentDirectory, string? lpCurrentDirectory,
[In] ref StartupInfo lpStartupInfo, [In] ref StartupInfo lpStartupInfo,
@@ -46,12 +46,12 @@ public static class Native {
IntPtr hProcess, IntPtr hProcess,
IntPtr lpAddress, IntPtr lpAddress,
int dwSize, int dwSize,
int flAllocationType, AllocationType flAllocationType,
int flProtect MemoryProtection flProtect
); );
[DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)] [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)] [DllImport("kernel32.dll", SetLastError = true)]
public static extern uint ResumeThread(IntPtr hThread); public static extern uint ResumeThread(IntPtr hThread);

View File

@@ -9,6 +9,6 @@ namespace YaeAchievement.Win32;
public struct ProcessInformation { public struct ProcessInformation {
public IntPtr hProcess; public IntPtr hProcess;
public IntPtr hThread; public IntPtr hThread;
public int dwProcessId; public uint dwProcessID;
public int dwThreadId; public uint dwThreadID;
} }

View File

@@ -7,20 +7,20 @@ namespace YaeAchievement.Win32;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct StartupInfo { public struct StartupInfo {
public int cb; public uint cb;
public string lpReserved; public string lpReserved;
public string lpDesktop; public string lpDesktop;
public string lpTitle; public string lpTitle;
public int dwX; public uint dwX;
public int dwY; public uint dwY;
public int dwXSize; public uint dwXSize;
public int dwYSize; public uint dwYSize;
public int dwXCountChars; public uint dwXCountChars;
public int dwYCountChars; public uint dwYCountChars;
public int dwFillAttribute; public uint dwFillAttribute;
public int dwFlags; public uint dwFlags;
public short wShowWindow; public ushort wShowWindow;
public short cbReserved2; public ushort cbReserved2;
public IntPtr lpReserved2; public IntPtr lpReserved2;
public IntPtr hStdInput; public IntPtr hStdInput;
public IntPtr hStdOutput; public IntPtr hStdOutput;