mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
optimize Win32 calls
This commit is contained in:
@@ -15,6 +15,8 @@ namespace Snap.Hutao.Core.LifeCycle;
|
||||
[HighQuality]
|
||||
internal static class AppInstanceExtension
|
||||
{
|
||||
private static readonly WaitCallback RunActionWaitCallback = new(RunAction);
|
||||
|
||||
// Hold the reference here to prevent memory corruption.
|
||||
private static HANDLE redirectEventHandle = HANDLE.Null;
|
||||
|
||||
@@ -29,13 +31,14 @@ internal static class AppInstanceExtension
|
||||
redirectEventHandle = CreateEvent(default(SECURITY_ATTRIBUTES*), true, false, null);
|
||||
|
||||
// use ThreadPool.UnsafeQueueUserWorkItem to cancel stacktrace
|
||||
ThreadPool.UnsafeQueueUserWorkItem(new(RunAction), () =>
|
||||
// like ExecutionContext.SuppressFlow
|
||||
ThreadPool.UnsafeQueueUserWorkItem(RunActionWaitCallback, () =>
|
||||
{
|
||||
appInstance.RedirectActivationToAsync(args).AsTask().Wait();
|
||||
SetEvent(redirectEventHandle);
|
||||
});
|
||||
|
||||
ReadOnlySpan<HANDLE> handles = new(in redirectEventHandle);
|
||||
ReadOnlySpan<HANDLE> handles = new(redirectEventHandle);
|
||||
CoWaitForMultipleObjects((uint)CWMO_FLAGS.CWMO_DEFAULT, INFINITE, handles, out uint _);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/microsoft/CsWin32/main/src/Microsoft.Windows.CsWin32/settings.schema.json",
|
||||
"allowMarshaling": true,
|
||||
"useSafeHandles": false
|
||||
"useSafeHandles": false,
|
||||
"emitSingleFile": true
|
||||
}
|
||||
@@ -1,16 +1,4 @@
|
||||
// Const value
|
||||
INFINITE
|
||||
WM_GETMINMAXINFO
|
||||
WM_NCRBUTTONDOWN
|
||||
WM_NCRBUTTONUP
|
||||
WM_NULL
|
||||
|
||||
// Type & Enum definition
|
||||
CWMO_FLAGS
|
||||
MINMAXINFO
|
||||
LPTHREAD_START_ROUTINE
|
||||
|
||||
// COMCTL32
|
||||
// COMCTL32
|
||||
DefSubclassProc
|
||||
RemoveWindowSubclass
|
||||
SetWindowSubclass
|
||||
@@ -23,10 +11,11 @@ DwmSetWindowAttribute
|
||||
GetDeviceCaps
|
||||
|
||||
// KERNEL32
|
||||
CreateEvent
|
||||
CloseHandle
|
||||
CreateEventW
|
||||
CreateRemoteThread
|
||||
CreateToolhelp32Snapshot
|
||||
GetModuleHandle
|
||||
GetModuleHandleW
|
||||
GetProcAddress
|
||||
Module32First
|
||||
Module32Next
|
||||
@@ -44,14 +33,32 @@ CoWaitForMultipleObjects
|
||||
|
||||
// USER32
|
||||
AttachThreadInput
|
||||
FindWindowEx
|
||||
FindWindowExW
|
||||
GetDC
|
||||
GetDpiForWindow
|
||||
GetForegroundWindow
|
||||
GetWindowPlacement
|
||||
GetWindowThreadProcessId
|
||||
SetForegroundWindow
|
||||
ReleaseDC
|
||||
SetForegroundWindow
|
||||
|
||||
// WinRT
|
||||
IMemoryBufferByteAccess
|
||||
IMemoryBufferByteAccess
|
||||
|
||||
// Const value
|
||||
INFINITE
|
||||
WM_GETMINMAXINFO
|
||||
WM_NCRBUTTONDOWN
|
||||
WM_NCRBUTTONUP
|
||||
WM_NULL
|
||||
|
||||
// Type & Enum definition
|
||||
|
||||
// System.Threading
|
||||
LPTHREAD_START_ROUTINE
|
||||
|
||||
// UI.WindowsAndMessaging
|
||||
MINMAXINFO
|
||||
|
||||
// System.Com
|
||||
CWMO_FLAGS
|
||||
@@ -12,7 +12,7 @@
|
||||
<Identity
|
||||
Name="60568DGPStudio.SnapHutao"
|
||||
Publisher="CN=35C8E923-85DF-49A7-9172-B39DC6312C52"
|
||||
Version="1.6.3.0" />
|
||||
Version="1.6.4.0" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>Snap Hutao</DisplayName>
|
||||
|
||||
@@ -116,7 +116,6 @@ internal static class ProcessInterop
|
||||
hLoadLibraryAThread = CreateRemoteThread(hProcess, default, 0, lpThreadLoadLibraryA, pNativeLibraryPath, 0);
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetLastPInvokeError());
|
||||
|
||||
// What are we waiting for?
|
||||
WaitForSingleObject(hLoadLibraryAThread, 2000);
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetLastPInvokeError());
|
||||
}
|
||||
|
||||
@@ -93,14 +93,15 @@ internal sealed class GameFpsUnlocker : IGameFpsUnlocker
|
||||
|
||||
private static unsafe MODULEENTRY32 UnsafeFindModule(int processId, in ReadOnlySpan<byte> moduleName)
|
||||
{
|
||||
HANDLE snapshot = CreateToolhelp32Snapshot(CREATE_TOOLHELP_SNAPSHOT_FLAGS.TH32CS_SNAPMODULE, (uint)processId);
|
||||
CREATE_TOOLHELP_SNAPSHOT_FLAGS flags = CREATE_TOOLHELP_SNAPSHOT_FLAGS.TH32CS_SNAPMODULE | CREATE_TOOLHELP_SNAPSHOT_FLAGS.TH32CS_SNAPMODULE32;
|
||||
HANDLE snapshot = CreateToolhelp32Snapshot(flags, (uint)processId);
|
||||
try
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetLastPInvokeError());
|
||||
foreach (MODULEENTRY32 entry in StructMarshal.EnumerateModuleEntry32(snapshot))
|
||||
{
|
||||
ReadOnlySpan<byte> szModuleLocal = MemoryMarshal.CreateReadOnlySpanFromNullTerminated((byte*)&entry.szModule);
|
||||
if (entry.th32ProcessID == processId && szModuleLocal.SequenceEqual(moduleName))
|
||||
ReadOnlySpan<byte> szModuleNameLocal = MemoryMarshal.CreateReadOnlySpanFromNullTerminated((byte*)&entry.szModule);
|
||||
if (entry.th32ProcessID == processId && szModuleNameLocal.SequenceEqual(moduleName))
|
||||
{
|
||||
return entry;
|
||||
}
|
||||
@@ -199,7 +200,7 @@ internal sealed class GameFpsUnlocker : IGameFpsUnlocker
|
||||
using (localMemory)
|
||||
{
|
||||
int offset = IndexOfPattern(localMemory.GetBuffer()[(int)moduleEntryInfo.UnityPlayer.modBaseSize..]);
|
||||
Must.Range(offset > 0, "未匹配到FPS字节");
|
||||
Must.Range(offset >= 0, "未匹配到FPS字节");
|
||||
|
||||
byte* pLocalMemory = (byte*)localMemory.Pointer;
|
||||
MODULEENTRY32 unityPlayer = moduleEntryInfo.UnityPlayer;
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
<CommandBar.Content>
|
||||
<shcp:PanelSelector x:Name="ItemsPanelSelector" Margin="8,8,0,0"/>
|
||||
</CommandBar.Content>
|
||||
<AppBarButton Icon="{shcm:FontIcon Glyph=}" Label="搜索提示"/>
|
||||
<!--<AppBarButton Icon="{shcm:FontIcon Glyph=}" Label="搜索提示"/>-->
|
||||
<AppBarElementContainer>
|
||||
<AutoSuggestBox
|
||||
Width="240"
|
||||
|
||||
@@ -24,7 +24,7 @@ internal static class StructMarshal
|
||||
/// <returns>新的实例</returns>
|
||||
public static unsafe MODULEENTRY32 MODULEENTRY32()
|
||||
{
|
||||
return new() { dwSize = unchecked((uint)sizeof(MODULEENTRY32)) };
|
||||
return new() { dwSize = SizeOf<MODULEENTRY32>() };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -33,7 +33,19 @@ internal static class StructMarshal
|
||||
/// <returns>新的实例</returns>
|
||||
public static unsafe WINDOWPLACEMENT WINDOWPLACEMENT()
|
||||
{
|
||||
return new() { length = unchecked((uint)sizeof(WINDOWPLACEMENT)) };
|
||||
return new() { length = SizeOf<WINDOWPLACEMENT>() };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取结构的大小
|
||||
/// </summary>
|
||||
/// <typeparam name="TStruct">结构类型</typeparam>
|
||||
/// <returns>结构的大小</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe uint SizeOf<TStruct>()
|
||||
where TStruct : unmanaged
|
||||
{
|
||||
return unchecked((uint)sizeof(TStruct));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -44,11 +56,7 @@ internal static class StructMarshal
|
||||
public static unsafe Windows.UI.Color Color(uint value)
|
||||
{
|
||||
Unsafe.SkipInit(out Windows.UI.Color color);
|
||||
|
||||
// *(uint*)&color = BinaryPrimitives.ReverseEndianness(value);
|
||||
// How .NET store struct in BE host?
|
||||
Span<byte> colorSpan = new(&color, sizeof(uint));
|
||||
BinaryPrimitives.WriteUInt32BigEndian(colorSpan, value);
|
||||
*(uint*)&color = BinaryPrimitives.ReverseEndianness(value);
|
||||
return color;
|
||||
}
|
||||
|
||||
@@ -90,29 +98,18 @@ internal static class StructMarshal
|
||||
/// <param name="snapshot">快照</param>
|
||||
/// <returns>模块枚举</returns>
|
||||
[SuppressMessage("", "SH002")]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static IEnumerable<MODULEENTRY32> EnumerateModuleEntry32(HANDLE snapshot)
|
||||
{
|
||||
MODULEENTRY32 entry = MODULEENTRY32();
|
||||
|
||||
if (!Module32First(snapshot, ref entry))
|
||||
if (Module32First(snapshot, ref entry))
|
||||
{
|
||||
yield break;
|
||||
do
|
||||
{
|
||||
yield return entry;
|
||||
}
|
||||
while (Module32Next(snapshot, ref entry));
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
yield return entry;
|
||||
}
|
||||
while (Module32Next(snapshot, ref entry));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断结构实例是否为默认结构
|
||||
/// </summary>
|
||||
/// <param name="moduleEntry32">待测试的结构</param>
|
||||
/// <returns>是否为默认结构</returns>
|
||||
public static bool IsDefault(MODULEENTRY32 moduleEntry32)
|
||||
{
|
||||
return moduleEntry32.dwSize == 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user