diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsAddress.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsAddress.cs index ceaafabd..a5f3c1e8 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsAddress.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsAddress.cs @@ -21,7 +21,6 @@ internal static class GameFpsAddress int offsetToUserAssembly = IndexOfPattern(localModule.UserAssembly.AsSpan()); HutaoException.ThrowIfNot(offsetToUserAssembly >= 0, SH.ServiceGameUnlockerInterestedPatternNotFound); - // Register Instruction Pointer nuint rip = localModule.UserAssembly.Address + (uint)offsetToUserAssembly; rip += 5U; rip += (nuint)(*(int*)(rip + 2U) + 6); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs index 2b0cb141..afa83023 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs @@ -3,8 +3,8 @@ using Snap.Hutao.Core.ExceptionService; using Snap.Hutao.Win32.Foundation; +using Snap.Hutao.Win32.System.LibraryLoader; using System.Diagnostics; -using System.Runtime.InteropServices; using static Snap.Hutao.Win32.Kernel32; namespace Snap.Hutao.Service.Game.Unlocker; @@ -76,9 +76,9 @@ internal sealed class GameFpsUnlocker : IGameFpsUnlocker { string gameFoler = gameFileSystem.GameDirectory; string dataFoler = gameFileSystem.DataDirectory; - - nint unityPlayerAddress = NativeLibrary.Load(System.IO.Path.Combine(gameFoler, "UnityPlayer.dll")); - nint userAssemblyAddress = NativeLibrary.Load(System.IO.Path.Combine(dataFoler, "Native", "UserAssembly.dll")); + LOAD_LIBRARY_FLAGS flags = LOAD_LIBRARY_FLAGS.LOAD_LIBRARY_AS_IMAGE_RESOURCE; + HMODULE unityPlayerAddress = LoadLibraryExW(System.IO.Path.Combine(gameFoler, "UnityPlayer.dll"), default, flags); + HMODULE userAssemblyAddress = LoadLibraryExW(System.IO.Path.Combine(dataFoler, "Native", "UserAssembly.dll"), default, flags); return new(unityPlayerAddress, userAssemblyAddress); } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/RequiredLocalModule.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/RequiredLocalModule.cs index 1ea58a8e..5863567c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/RequiredLocalModule.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/RequiredLocalModule.cs @@ -4,7 +4,6 @@ using Snap.Hutao.Win32.Foundation; using Snap.Hutao.Win32.System.ProcessStatus; using System.Diagnostics; -using System.Runtime.InteropServices; using static Snap.Hutao.Win32.Kernel32; namespace Snap.Hutao.Service.Game.Unlocker; @@ -15,21 +14,21 @@ internal readonly struct RequiredLocalModule : IDisposable public readonly Module UnityPlayer; public readonly Module UserAssembly; - public RequiredLocalModule(nint unityPlayerAddress, nint userAssemblyAddress) + public RequiredLocalModule(in HMODULE unityPlayer, in HMODULE userAssembly) { HasValue = true; HANDLE process = Process.GetCurrentProcess().Handle; - K32GetModuleInformation(process, unityPlayerAddress, out MODULEINFO upInfo); - UnityPlayer = new((nuint)unityPlayerAddress, upInfo.SizeOfImage); + K32GetModuleInformation(process, unityPlayer, out MODULEINFO upInfo); + UnityPlayer = new((nuint)(nint)unityPlayer, upInfo.SizeOfImage); - K32GetModuleInformation(process, userAssemblyAddress, out MODULEINFO uaInfo); - UserAssembly = new((nuint)userAssemblyAddress, uaInfo.SizeOfImage); + K32GetModuleInformation(process, userAssembly, out MODULEINFO uaInfo); + UserAssembly = new((nuint)(nint)userAssembly, uaInfo.SizeOfImage); } public void Dispose() { - NativeLibrary.Free((nint)UnityPlayer.Address); - NativeLibrary.Free((nint)UserAssembly.Address); + FreeLibrary((nint)UnityPlayer.Address); + FreeLibrary((nint)UserAssembly.Address); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/Foundation/HMODULE.cs b/src/Snap.Hutao/Snap.Hutao/Win32/Foundation/HMODULE.cs index 6b1317be..999be25c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Win32/Foundation/HMODULE.cs +++ b/src/Snap.Hutao/Snap.Hutao/Win32/Foundation/HMODULE.cs @@ -10,4 +10,6 @@ internal readonly struct HMODULE public readonly nint Value; public static unsafe implicit operator HMODULE(nint value) => *(HMODULE*)&value; + + public static unsafe implicit operator nint(HMODULE module) => *(nint*)&module; } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/Kernel32.cs b/src/Snap.Hutao/Snap.Hutao/Win32/Kernel32.cs index 2a870d3a..5bd46763 100644 --- a/src/Snap.Hutao/Snap.Hutao/Win32/Kernel32.cs +++ b/src/Snap.Hutao/Snap.Hutao/Win32/Kernel32.cs @@ -4,6 +4,7 @@ using Snap.Hutao.Win32.Foundation; using Snap.Hutao.Win32.Security; using Snap.Hutao.Win32.System.Console; +using Snap.Hutao.Win32.System.LibraryLoader; using Snap.Hutao.Win32.System.ProcessStatus; using System.Diagnostics; using System.Runtime.InteropServices; @@ -41,6 +42,10 @@ internal static class Kernel32 [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] public static extern BOOL FreeConsole(); + [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true, SetLastError = true)] + [SupportedOSPlatform("windows5.1.2600")] + public static extern BOOL FreeLibrary(HMODULE hLibModule); + [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] public static unsafe extern BOOL GetConsoleMode(HANDLE hConsoleHandle, CONSOLE_MODE* lpMode); @@ -96,6 +101,19 @@ internal static class Kernel32 } } + [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] + [SupportedOSPlatform("windows5.1.2600")] + public static extern HMODULE LoadLibraryExW(PCWSTR lpLibFileName, [AllowNull] HANDLE hFile, LOAD_LIBRARY_FLAGS dwFlags); + + [DebuggerStepThrough] + public static unsafe HMODULE LoadLibraryExW(ReadOnlySpan libFileName, [AllowNull] HANDLE hFile, LOAD_LIBRARY_FLAGS dwFlags) + { + fixed (char* lpLibFileName = libFileName) + { + return LoadLibraryExW(lpLibFileName, hFile, dwFlags); + } + } + [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] [SupportedOSPlatform("windows5.1.2600")] public static unsafe extern BOOL ReadProcessMemory(HANDLE hProcess, void* lpBaseAddress, void* lpBuffer, nuint nSize, [MaybeNull] nuint* lpNumberOfBytesRead); diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/System/LibraryLoader/Class1.cs b/src/Snap.Hutao/Snap.Hutao/Win32/System/LibraryLoader/Class1.cs new file mode 100644 index 00000000..eaf02667 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Win32/System/LibraryLoader/Class1.cs @@ -0,0 +1,23 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Win32.System.LibraryLoader; + +[Flags] +internal enum LOAD_LIBRARY_FLAGS : uint +{ + DONT_RESOLVE_DLL_REFERENCES = 1u, + LOAD_LIBRARY_AS_DATAFILE = 2u, + LOAD_WITH_ALTERED_SEARCH_PATH = 8u, + LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x10u, + LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x20u, + LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x40u, + LOAD_LIBRARY_REQUIRE_SIGNED_TARGET = 0x80u, + LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x100u, + LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x200u, + LOAD_LIBRARY_SEARCH_USER_DIRS = 0x400u, + LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x800u, + LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x1000u, + LOAD_LIBRARY_SAFE_CURRENT_DIRS = 0x2000u, + LOAD_LIBRARY_SEARCH_SYSTEM32_NO_FORWARDER = 0x4000u +}