From 18a088d83b1dbb08f8425d4060ed85d25ecc4ab7 Mon Sep 17 00:00:00 2001 From: Lightczx <1686188646@qq.com> Date: Wed, 19 Jun 2024 17:14:23 +0800 Subject: [PATCH] Use All Access Handle --- .../Service/Game/Unlocker/GameFpsAddress.cs | 6 +-- .../Service/Game/Unlocker/GameFpsUnlocker.cs | 6 ++- .../Game/Unlocker/GameFpsUnlockerContext.cs | 3 ++ .../Game/Unlocker/GameProcessModule.cs | 2 +- src/Snap.Hutao/Snap.Hutao/Win32/AdvApi32.cs | 2 +- src/Snap.Hutao/Snap.Hutao/Win32/Kernel32.cs | 49 ++++++++++--------- src/Snap.Hutao/Snap.Hutao/Win32/Ole32.cs | 6 +-- .../System/Threading/PROCESS_ACCESS_RIGHTS.cs | 30 ++++++++++++ src/Snap.Hutao/Snap.Hutao/Win32/User32.cs | 8 +-- 9 files changed, 76 insertions(+), 36 deletions(-) create mode 100644 src/Snap.Hutao/Snap.Hutao/Win32/System/Threading/PROCESS_ACCESS_RIGHTS.cs 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 c35cebf9..86843162 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsAddress.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsAddress.cs @@ -27,7 +27,7 @@ internal static class GameFpsAddress nuint remoteVirtualAddress = remoteModule.UserAssembly.Address + (rip - localModule.UserAssembly.Address); nuint ptr = 0; - SpinWait.SpinUntil(() => UnsafeReadProcessMemory(context.GameProcess, remoteVirtualAddress, out ptr) && ptr != 0); + SpinWait.SpinUntil(() => UnsafeReadProcessMemory(context.AllAccess, remoteVirtualAddress, out ptr) && ptr != 0); nuint localVirtualAddress = ptr - remoteModule.UnityPlayer.Address + localModule.UnityPlayer.Address; @@ -48,10 +48,10 @@ internal static class GameFpsAddress return memory.IndexOf(part); } - private static unsafe bool UnsafeReadProcessMemory(Process process, nuint baseAddress, out nuint value) + private static unsafe bool UnsafeReadProcessMemory(HANDLE processId, nuint baseAddress, out nuint value) { value = 0; - bool result = ReadProcessMemory((HANDLE)process.Handle, (void*)baseAddress, ref value, out _); + bool result = ReadProcessMemory(processId, (void*)baseAddress, ref value, out _); HutaoException.ThrowIfNot(result, SH.ServiceGameUnlockerReadProcessMemoryPointerAddressFailed); return result; } 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 7b0ff055..93a2e506 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs @@ -4,6 +4,7 @@ using Snap.Hutao.Core.ExceptionService; using Snap.Hutao.Win32.Foundation; using Snap.Hutao.Win32.System.LibraryLoader; +using Snap.Hutao.Win32.System.Threading; using System.Diagnostics; using static Snap.Hutao.Win32.Kernel32; @@ -24,6 +25,7 @@ internal sealed class GameFpsUnlocker : IGameFpsUnlocker launchOptions = serviceProvider.GetRequiredService(); context.GameProcess = gameProcess; + context.AllAccess = OpenProcess(PROCESS_ACCESS_RIGHTS.PROCESS_ALL_ACCESS, false, (uint)gameProcess.Id); context.Options = options; context.Progress = progress; } @@ -73,9 +75,9 @@ internal sealed class GameFpsUnlocker : IGameFpsUnlocker } } - private static unsafe bool UnsafeWriteProcessMemory(Process process, nuint baseAddress, int value) + private static unsafe bool UnsafeWriteProcessMemory(System.Diagnostics.Process process, nuint baseAddress, int value) { - return WriteProcessMemory((HANDLE)process.Handle, (void*)baseAddress, ref value, out _); + return WriteProcessMemory((Win32.Foundation.HANDLE)process.Handle, (void*)baseAddress, ref value, out _); } private static RequiredLocalModule LoadRequiredLocalModule(GameFileSystem gameFileSystem) diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlockerContext.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlockerContext.cs index dcf5778a..bbb7e847 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlockerContext.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlockerContext.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Win32.Foundation; using System.Diagnostics; namespace Snap.Hutao.Service.Game.Unlocker; @@ -22,6 +23,8 @@ internal sealed class GameFpsUnlockerContext public Process GameProcess { get; set; } = default!; + public HANDLE AllAccess { get; set; } + public IProgress Progress { get; set; } = default!; public void Report() diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameProcessModule.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameProcessModule.cs index cc9dc030..29144ce0 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameProcessModule.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameProcessModule.cs @@ -19,7 +19,7 @@ internal static class GameProcessModule { while (await timer.WaitForNextTickAsync().ConfigureAwait(false)) { - FindModuleResult result = UnsafeGetGameModuleInfo((HANDLE)state.GameProcess.Handle, out RequiredRemoteModule gameModule); + FindModuleResult result = UnsafeGetGameModuleInfo(state.AllAccess, out RequiredRemoteModule gameModule); if (result == FindModuleResult.Ok) { return new(FindModuleResult.Ok, gameModule); diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/AdvApi32.cs b/src/Snap.Hutao/Snap.Hutao/Win32/AdvApi32.cs index cb33d947..f2f41933 100644 --- a/src/Snap.Hutao/Snap.Hutao/Win32/AdvApi32.cs +++ b/src/Snap.Hutao/Snap.Hutao/Win32/AdvApi32.cs @@ -51,7 +51,7 @@ internal static class AdvApi32 [DllImport("ADVAPI32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] [SupportedOSPlatform("windows5.0")] - public static extern WIN32_ERROR RegNotifyChangeKeyValue(HKEY hKey, BOOL bWatchSubtree, REG_NOTIFY_FILTER dwNotifyFilter, [AllowNull] HANDLE hEvent, BOOL fAsynchronous); + public static extern WIN32_ERROR RegNotifyChangeKeyValue(HKEY hKey, BOOL bWatchSubtree, REG_NOTIFY_FILTER dwNotifyFilter, [AllowNull] Foundation.HANDLE hEvent, BOOL fAsynchronous); [DllImport("ADVAPI32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] [SupportedOSPlatform("windows5.0")] diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/Kernel32.cs b/src/Snap.Hutao/Snap.Hutao/Win32/Kernel32.cs index 3ae4bd26..448dc862 100644 --- a/src/Snap.Hutao/Snap.Hutao/Win32/Kernel32.cs +++ b/src/Snap.Hutao/Snap.Hutao/Win32/Kernel32.cs @@ -6,6 +6,7 @@ using Snap.Hutao.Win32.Security; using Snap.Hutao.Win32.System.Console; using Snap.Hutao.Win32.System.LibraryLoader; using Snap.Hutao.Win32.System.ProcessStatus; +using Snap.Hutao.Win32.System.Threading; using System.Diagnostics; using System.Runtime.InteropServices; using System.Runtime.Versioning; @@ -21,14 +22,14 @@ internal static class Kernel32 [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] [SupportedOSPlatform("windows5.0")] - public static extern BOOL CloseHandle(HANDLE hObject); + public static extern BOOL CloseHandle(Foundation.HANDLE hObject); [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] [SupportedOSPlatform("windows5.1.2600")] - public static unsafe extern HANDLE CreateEventW([AllowNull] SECURITY_ATTRIBUTES* lpEventAttributes, BOOL bManualReset, BOOL bInitialState, [AllowNull] PCWSTR lpName); + public static unsafe extern Foundation.HANDLE CreateEventW([AllowNull] SECURITY_ATTRIBUTES* lpEventAttributes, BOOL bManualReset, BOOL bInitialState, [AllowNull] PCWSTR lpName); [DebuggerStepThrough] - public static unsafe HANDLE CreateEventW(ref readonly SECURITY_ATTRIBUTES eventAttributes, BOOL bManualReset, BOOL bInitialState, [AllowNull] ReadOnlySpan name) + public static unsafe Foundation.HANDLE CreateEventW(ref readonly SECURITY_ATTRIBUTES eventAttributes, BOOL bManualReset, BOOL bInitialState, [AllowNull] ReadOnlySpan name) { fixed (SECURITY_ATTRIBUTES* lpEventAttributes = &eventAttributes) { @@ -47,11 +48,11 @@ internal static class Kernel32 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); + public static unsafe extern BOOL GetConsoleMode(Foundation.HANDLE hConsoleHandle, CONSOLE_MODE* lpMode); [SuppressMessage("", "SH002")] [DebuggerStepThrough] - public static unsafe BOOL GetConsoleMode(HANDLE hConsoleHandle, out CONSOLE_MODE mode) + public static unsafe BOOL GetConsoleMode(Foundation.HANDLE hConsoleHandle, out CONSOLE_MODE mode) { fixed (CONSOLE_MODE* lpMode = &mode) { @@ -64,13 +65,13 @@ internal static class Kernel32 public static extern WIN32_ERROR GetLastError(); [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] - public static extern HANDLE GetStdHandle(STD_HANDLE nStdHandle); + public static extern Foundation.HANDLE GetStdHandle(STD_HANDLE nStdHandle); [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] - public static unsafe extern BOOL K32EnumProcessModules(HANDLE hProcess, HMODULE* lphModule, uint cb, uint* lpcbNeeded); + public static unsafe extern BOOL K32EnumProcessModules(Foundation.HANDLE hProcess, HMODULE* lphModule, uint cb, uint* lpcbNeeded); [DebuggerStepThrough] - public static unsafe BOOL K32EnumProcessModules(HANDLE hProcess, Span hModules, out uint cbNeeded) + public static unsafe BOOL K32EnumProcessModules(Foundation.HANDLE hProcess, Span hModules, out uint cbNeeded) { fixed (HMODULE* lphModule = hModules) { @@ -82,10 +83,10 @@ internal static class Kernel32 } [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] - public static extern uint K32GetModuleBaseNameW(HANDLE hProcess, [AllowNull] HMODULE hModule, PWSTR lpBaseName, uint nSize); + public static extern uint K32GetModuleBaseNameW(Foundation.HANDLE hProcess, [AllowNull] HMODULE hModule, PWSTR lpBaseName, uint nSize); [DebuggerStepThrough] - public static unsafe uint K32GetModuleBaseNameW(HANDLE hProcess, [AllowNull] HMODULE hModule, Span baseName) + public static unsafe uint K32GetModuleBaseNameW(Foundation.HANDLE hProcess, [AllowNull] HMODULE hModule, Span baseName) { fixed (char* lpBaseName = baseName) { @@ -94,10 +95,10 @@ internal static class Kernel32 } [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] - public static unsafe extern BOOL K32GetModuleInformation(HANDLE hProcess, HMODULE hModule, MODULEINFO* lpmodinfo, uint cb); + public static unsafe extern BOOL K32GetModuleInformation(Foundation.HANDLE hProcess, HMODULE hModule, MODULEINFO* lpmodinfo, uint cb); [DebuggerStepThrough] - public static unsafe BOOL K32GetModuleInformation(HANDLE hProcess, HMODULE hModule, out MODULEINFO modinfo) + public static unsafe BOOL K32GetModuleInformation(Foundation.HANDLE hProcess, HMODULE hModule, out MODULEINFO modinfo) { fixed (MODULEINFO* lpmodinfo = &modinfo) { @@ -107,10 +108,10 @@ 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); + public static extern HMODULE LoadLibraryExW(PCWSTR lpLibFileName, [AllowNull] Foundation.HANDLE hFile, LOAD_LIBRARY_FLAGS dwFlags); [DebuggerStepThrough] - public static unsafe HMODULE LoadLibraryExW(ReadOnlySpan libFileName, [AllowNull] HANDLE hFile, LOAD_LIBRARY_FLAGS dwFlags) + public static unsafe HMODULE LoadLibraryExW(ReadOnlySpan libFileName, [AllowNull] Foundation.HANDLE hFile, LOAD_LIBRARY_FLAGS dwFlags) { fixed (char* lpLibFileName = libFileName) { @@ -120,10 +121,14 @@ internal static class Kernel32 [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); + public static extern Foundation.HANDLE OpenProcess(PROCESS_ACCESS_RIGHTS dwDesiredAccess, BOOL bInheritHandle, uint dwProcessId); + + [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] + [SupportedOSPlatform("windows5.1.2600")] + public static unsafe extern BOOL ReadProcessMemory(Foundation.HANDLE hProcess, void* lpBaseAddress, void* lpBuffer, nuint nSize, [MaybeNull] nuint* lpNumberOfBytesRead); [DebuggerStepThrough] - public static unsafe BOOL ReadProcessMemory(HANDLE hProcess, void* lpBaseAddress, Span buffer, [MaybeNull] out nuint numberOfBytesRead) + public static unsafe BOOL ReadProcessMemory(Foundation.HANDLE hProcess, void* lpBaseAddress, Span buffer, [MaybeNull] out nuint numberOfBytesRead) { fixed (byte* lpBuffer = buffer) { @@ -135,7 +140,7 @@ internal static class Kernel32 } [DebuggerStepThrough] - public static unsafe BOOL ReadProcessMemory(HANDLE hProcess, void* lpBaseAddress, ref T buffer, [MaybeNull] out nuint numberOfBytesRead) + public static unsafe BOOL ReadProcessMemory(Foundation.HANDLE hProcess, void* lpBaseAddress, ref T buffer, [MaybeNull] out nuint numberOfBytesRead) where T : unmanaged { fixed (T* lpBuffer = &buffer) @@ -148,7 +153,7 @@ internal static class Kernel32 } [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] - public static extern BOOL SetConsoleMode(HANDLE hConsoleHandle, CONSOLE_MODE dwMode); + public static extern BOOL SetConsoleMode(Foundation.HANDLE hConsoleHandle, CONSOLE_MODE dwMode); [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] public static extern BOOL SetConsoleTitleW(PCWSTR lpConsoleTitle); @@ -164,14 +169,14 @@ internal static class Kernel32 [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] [SupportedOSPlatform("windows5.1.2600")] - public static extern BOOL SetEvent(HANDLE hEvent); + public static extern BOOL SetEvent(Foundation.HANDLE hEvent); [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] [SupportedOSPlatform("windows5.1.2600")] - public static unsafe extern BOOL WriteProcessMemory(HANDLE hProcess, void* lpBaseAddress, void* lpBuffer, nuint nSize, nuint* lpNumberOfBytesWritten); + public static unsafe extern BOOL WriteProcessMemory(Foundation.HANDLE hProcess, void* lpBaseAddress, void* lpBuffer, nuint nSize, nuint* lpNumberOfBytesWritten); [DebuggerStepThrough] - public static unsafe BOOL WriteProcessMemory(HANDLE hProcess, void* lpBaseAddress, ReadOnlySpan buffer, out nuint numberOfBytesWritten) + public static unsafe BOOL WriteProcessMemory(Foundation.HANDLE hProcess, void* lpBaseAddress, ReadOnlySpan buffer, out nuint numberOfBytesWritten) { fixed (byte* lpBuffer = buffer) { @@ -183,7 +188,7 @@ internal static class Kernel32 } [DebuggerStepThrough] - public static unsafe BOOL WriteProcessMemory(HANDLE hProcess, void* lpBaseAddress, ref readonly T buffer, out nuint numberOfBytesWritten) + public static unsafe BOOL WriteProcessMemory(Foundation.HANDLE hProcess, void* lpBaseAddress, ref readonly T buffer, out nuint numberOfBytesWritten) where T : unmanaged { fixed (T* lpBuffer = &buffer) diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/Ole32.cs b/src/Snap.Hutao/Snap.Hutao/Win32/Ole32.cs index 5df50ed1..416ad61f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Win32/Ole32.cs +++ b/src/Snap.Hutao/Snap.Hutao/Win32/Ole32.cs @@ -39,13 +39,13 @@ internal static class Ole32 public static unsafe extern void CoTaskMemFree([AllowNull] void* pv); [DllImport("OLE32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] - public static unsafe extern HRESULT CoWaitForMultipleObjects(uint dwFlags, uint dwTimeout, uint cHandles, HANDLE* pHandles, uint* lpdwindex); + public static unsafe extern HRESULT CoWaitForMultipleObjects(uint dwFlags, uint dwTimeout, uint cHandles, Foundation.HANDLE* pHandles, uint* lpdwindex); [SuppressMessage("", "SH002")] [DebuggerStepThrough] - public static unsafe HRESULT CoWaitForMultipleObjects(CWMO_FLAGS dwFlags, uint dwTimeout, ReadOnlySpan handles, out uint dwindex) + public static unsafe HRESULT CoWaitForMultipleObjects(CWMO_FLAGS dwFlags, uint dwTimeout, ReadOnlySpan handles, out uint dwindex) { - fixed (HANDLE* pHandles = handles) + fixed (Foundation.HANDLE* pHandles = handles) { fixed (uint* lpdwindex = &dwindex) { diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/System/Threading/PROCESS_ACCESS_RIGHTS.cs b/src/Snap.Hutao/Snap.Hutao/Win32/System/Threading/PROCESS_ACCESS_RIGHTS.cs new file mode 100644 index 00000000..0f8f5d97 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Win32/System/Threading/PROCESS_ACCESS_RIGHTS.cs @@ -0,0 +1,30 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Win32.System.Threading; + +[Flags] +public enum PROCESS_ACCESS_RIGHTS : uint +{ + PROCESS_TERMINATE = 1U, + PROCESS_CREATE_THREAD = 2U, + PROCESS_SET_SESSIONID = 4U, + PROCESS_VM_OPERATION = 8U, + PROCESS_VM_READ = 0x10U, + PROCESS_VM_WRITE = 0x20U, + PROCESS_DUP_HANDLE = 0x40U, + PROCESS_CREATE_PROCESS = 0x80U, + PROCESS_SET_QUOTA = 0x100U, + PROCESS_SET_INFORMATION = 0x200U, + PROCESS_QUERY_INFORMATION = 0x400U, + PROCESS_SUSPEND_RESUME = 0x800U, + PROCESS_QUERY_LIMITED_INFORMATION = 0x1000U, + PROCESS_SET_LIMITED_INFORMATION = 0x2000U, + PROCESS_ALL_ACCESS = 0x1FFFFFU, + PROCESS_DELETE = 0x10000U, + PROCESS_READ_CONTROL = 0x20000U, + PROCESS_WRITE_DAC = 0x40000U, + PROCESS_WRITE_OWNER = 0x80000U, + PROCESS_SYNCHRONIZE = 0x100000U, + PROCESS_STANDARD_RIGHTS_REQUIRED = 0xF0000U, +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/User32.cs b/src/Snap.Hutao/Snap.Hutao/Win32/User32.cs index e09b933a..28f7713c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Win32/User32.cs +++ b/src/Snap.Hutao/Snap.Hutao/Win32/User32.cs @@ -214,10 +214,10 @@ internal static class User32 [DllImport("USER32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] [SupportedOSPlatform("windows5.0")] - public static extern HANDLE RemovePropW(HWND hWnd, PCWSTR lpString); + public static extern Foundation.HANDLE RemovePropW(HWND hWnd, PCWSTR lpString); [DebuggerStepThrough] - public static unsafe HANDLE RemovePropW(HWND hWnd, string @string) + public static unsafe Foundation.HANDLE RemovePropW(HWND hWnd, string @string) { fixed (char* lpString = @string) { @@ -248,10 +248,10 @@ internal static class User32 [DllImport("USER32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] [SupportedOSPlatform("windows5.0")] - public static extern BOOL SetPropW(HWND hWnd, PCWSTR lpString, [AllowNull] HANDLE hData); + public static extern BOOL SetPropW(HWND hWnd, PCWSTR lpString, [AllowNull] Foundation.HANDLE hData); [DebuggerStepThrough] - public static unsafe BOOL SetPropW(HWND hWnd, string @string, [AllowNull] HANDLE hData) + public static unsafe BOOL SetPropW(HWND hWnd, string @string, [AllowNull] Foundation.HANDLE hData) { fixed (char* lpString = @string) {