optimize Win32 calls

This commit is contained in:
Lightczx
2023-05-29 20:47:57 +08:00
parent 099c5d3f6d
commit 5b35167908
8 changed files with 61 additions and 53 deletions

View File

@@ -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 _);
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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>

View File

@@ -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());
}

View File

@@ -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;

View File

@@ -74,7 +74,7 @@
<CommandBar.Content>
<shcp:PanelSelector x:Name="ItemsPanelSelector" Margin="8,8,0,0"/>
</CommandBar.Content>
<AppBarButton Icon="{shcm:FontIcon Glyph=&#xE946;}" Label="搜索提示"/>
<!--<AppBarButton Icon="{shcm:FontIcon Glyph=&#xE946;}" Label="搜索提示"/>-->
<AppBarElementContainer>
<AutoSuggestBox
Width="240"

View File

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