Change a lot of CharSet.Auto's to CharSet.Unicode, explicitly put W postfix on relevant winapi functions/structs, put ExactSpelling = true for winapi functions.

We don't care for ANSI functions (no way somebody is going to run BizHawk on Windows 98/ME), and ExactSpelling = false (default) has a minor runtime cost, so this should be slightly more performant.
Also, replace ShellLink COM usage with custom COM interaction code. See https://github.com/TASEmulators/BizHawk/issues/3767. The same is yet to be done for the two other COM usages.
This commit is contained in:
CasualPokePlayer 2023-11-15 11:24:35 -08:00
parent 391190b6d4
commit 956af3577e
24 changed files with 371 additions and 220 deletions

View File

@ -90,7 +90,7 @@ namespace BizHawk.Bizware.Input
{
const uint MAPVK_VSC_TO_VK_EX = 0x03;
// DInputKey is a scancode as is
var virtualKey = MapVirtualKey((uint) key, MAPVK_VSC_TO_VK_EX);
var virtualKey = MapVirtualKeyW((uint) key, MAPVK_VSC_TO_VK_EX);
return VKeyToDKeyMap.GetValueOrDefault(virtualKey, DInputKey.Unknown);
}

View File

@ -32,12 +32,12 @@ namespace BizHawk.Bizware.Input
private static readonly Lazy<IntPtr> _rawInputWindowAtom = new(() =>
{
var wc = default(WNDCLASS);
var wc = default(WNDCLASSW);
wc.lpfnWndProc = _wndProc;
wc.hInstance = LoaderApiImports.GetModuleHandleW(null);
wc.lpszClassName = "RawKeyInputClass";
var atom = RegisterClass(ref wc);
var atom = RegisterClassW(ref wc);
if (atom == IntPtr.Zero)
{
throw new InvalidOperationException("Failed to register RAWINPUT window class");
@ -48,27 +48,27 @@ namespace BizHawk.Bizware.Input
private static unsafe IntPtr WndProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam)
{
var ud = GetWindowLongPtr(hWnd, GWLP_USERDATA);
var ud = GetWindowLongPtrW(hWnd, GWLP_USERDATA);
if (ud == IntPtr.Zero)
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
if (uMsg != WM_INPUT)
{
if (uMsg == WM_CLOSE)
{
SetWindowLongPtr(hWnd, GWLP_USERDATA, IntPtr.Zero);
SetWindowLongPtrW(hWnd, GWLP_USERDATA, IntPtr.Zero);
GCHandle.FromIntPtr(ud).Free();
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
if (GetRawInputData(lParam, RID.INPUT, IntPtr.Zero,
out var size, Marshal.SizeOf<RAWINPUTHEADER>()) == -1)
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
// don't think size should ever be this big, but just in case
@ -83,7 +83,7 @@ namespace BizHawk.Bizware.Input
if (GetRawInputData(lParam, RID.INPUT, input,
ref size, Marshal.SizeOf<RAWINPUTHEADER>()) == -1)
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
if (input->header.dwType == RAWINPUTHEADER.RIM_TYPE.KEYBOARD && input->data.keyboard.Flags <= RAWKEYBOARD.RIM_KEY.E1)
@ -116,7 +116,7 @@ namespace BizHawk.Bizware.Input
private static IntPtr CreateRawInputWindow()
{
const int WS_CHILD = 0x40000000;
var window = CreateWindowEx(
var window = CreateWindowExW(
dwExStyle: 0,
lpClassName: _rawInputWindowAtom.Value,
lpWindowName: "RawKeyInput",
@ -170,7 +170,7 @@ namespace BizHawk.Bizware.Input
if (RawInputWindow != IntPtr.Zero)
{
// Can't use DestroyWindow, that's only allowed in the thread that created the window!
PostMessage(RawInputWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
PostMessageW(RawInputWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
RawInputWindow = IntPtr.Zero;
}
}
@ -184,15 +184,15 @@ namespace BizHawk.Bizware.Input
{
RawInputWindow = CreateRawInputWindow();
var handle = GCHandle.Alloc(this, GCHandleType.Normal);
SetWindowLongPtr(RawInputWindow, GWLP_USERDATA, GCHandle.ToIntPtr(handle));
SetWindowLongPtrW(RawInputWindow, GWLP_USERDATA, GCHandle.ToIntPtr(handle));
}
HandleAltKbLayouts = handleAltKbLayouts;
while (PeekMessage(out var msg, RawInputWindow, 0, 0, PM_REMOVE))
while (PeekMessageW(out var msg, RawInputWindow, 0, 0, PM_REMOVE))
{
TranslateMessage(ref msg);
DispatchMessage(ref msg);
DispatchMessageW(ref msg);
}
var ret = KeyEvents;

View File

@ -46,10 +46,10 @@ namespace BizHawk.Bizware.Input
// similar code shouldn't be needed on other platforms (which have global message queues and not thread local message queues)
if (!OSTailoredCode.IsUnixHost)
{
while (WmImports.PeekMessage(out var msg, IntPtr.Zero, 0, 0, WmImports.PM_REMOVE))
while (WmImports.PeekMessageW(out var msg, IntPtr.Zero, 0, 0, WmImports.PM_REMOVE))
{
WmImports.TranslateMessage(ref msg);
WmImports.DispatchMessage(ref msg);
WmImports.DispatchMessageW(ref msg);
}
}

View File

@ -23,8 +23,8 @@ namespace BizHawk.Client.EmuHawk
/// </remarks>
public sealed class FolderBrowserEx : Component
{
private const BROWSEINFO.FLAGS BrowseOptions = BROWSEINFO.FLAGS.RestrictToFilesystem | BROWSEINFO.FLAGS.RestrictToDomain |
BROWSEINFO.FLAGS.NewDialogStyle | BROWSEINFO.FLAGS.ShowTextBox;
private const BROWSEINFOW.FLAGS BrowseOptions = BROWSEINFOW.FLAGS.RestrictToFilesystem | BROWSEINFOW.FLAGS.RestrictToDomain |
BROWSEINFOW.FLAGS.NewDialogStyle | BROWSEINFOW.FLAGS.ShowTextBox;
public string Description = "Please select a folder below:";
@ -41,7 +41,7 @@ namespace BizHawk.Client.EmuHawk
var str = Marshal.StringToHGlobalUni(SelectedPath);
try
{
WmImports.SendMessage(hwnd, BFFM_SETSELECTIONW, new(1), str);
WmImports.SendMessageW(hwnd, BFFM_SETSELECTIONW, new(1), str);
}
finally
{
@ -62,14 +62,14 @@ namespace BizHawk.Client.EmuHawk
var browseOptions = BrowseOptions;
if (ApartmentState.MTA == Application.OleRequired())
{
browseOptions &= ~BROWSEINFO.FLAGS.NewDialogStyle;
browseOptions &= ~BROWSEINFOW.FLAGS.NewDialogStyle;
}
var pidlRet = IntPtr.Zero;
try
{
var buffer = Marshal.AllocHGlobal(Win32Imports.MAX_PATH);
var bi = new BROWSEINFO
var bi = new BROWSEINFOW
{
hwndOwner = hWndOwner,
pidlRoot = pidlRoot,
@ -79,20 +79,20 @@ namespace BizHawk.Client.EmuHawk
lpfn = Callback
};
pidlRet = SHBrowseForFolder(ref bi);
pidlRet = SHBrowseForFolderW(ref bi);
Marshal.FreeHGlobal(buffer);
if (pidlRet == IntPtr.Zero)
{
return DialogResult.Cancel; // user clicked Cancel
}
var path = new StringBuilder(Win32Imports.MAX_PATH);
if (SHGetPathFromIDList(pidlRet, path) == 0)
var path = new char[Win32Imports.MAX_PATH];
if (SHGetPathFromIDListW(pidlRet, path) == 0)
{
return DialogResult.Cancel;
}
SelectedPath = path.ToString();
SelectedPath = new string(path).TrimEnd('\0');
}
finally
{

View File

@ -1,7 +1,7 @@
using System;
using System.IO;
using System.Security.Principal;
using System.Text;
using BizHawk.Common;
namespace BizHawk.Client.EmuHawk
@ -15,17 +15,24 @@ namespace BizHawk.Client.EmuHawk
/// <remarks>http://stackoverflow.com/questions/139010/how-to-resolve-a-lnk-in-c-sharp</remarks>
public static string ResolveShortcut(string filename)
{
if (filename.Contains("|") || OSTailoredCode.IsUnixHost || !".lnk".Equals(Path.GetExtension(filename), StringComparison.OrdinalIgnoreCase)) return filename; // archive internal files are never shortcuts (and choke when analyzing any further)
var link = new ShellLinkImports.ShellLink();
if (filename.Contains("|") || OSTailoredCode.IsUnixHost ||
!".lnk".Equals(Path.GetExtension(filename), StringComparison.OrdinalIgnoreCase))
{
return filename; // archive internal files are never shortcuts (and choke when analyzing any further)
}
using var link = new ShellLinkImports.ShellLink();
const uint STGM_READ = 0;
((ShellLinkImports.IPersistFile) link).Load(filename, STGM_READ);
link.Load(filename, STGM_READ);
#if false
// TODO: if I can get hold of the hwnd call resolve first. This handles moved and renamed files.
((ShellLinkImports.IShellLinkW) link).Resolve(hwnd, 0);
link.Resolve(hwnd, 0);
#endif
var sb = new StringBuilder(Win32Imports.MAX_PATH);
((ShellLinkImports.IShellLinkW) link).GetPath(sb, sb.Capacity, out _, 0);
return sb.Length == 0 ? filename : sb.ToString(); // maybe? what if it's invalid?
link.GetPath(out var path, Win32Imports.MAX_PATH + 1, out _, 0);
return path;
}
}
}

View File

@ -191,34 +191,34 @@ namespace BizHawk.Client.EmuHawk
return;
}
var columnHeader = WmImports.SendMessage(listViewControl.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);
var columnHeader = WmImports.SendMessageW(listViewControl.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);
for (int columnNumber = 0, l = listViewControl.Columns.Count; columnNumber < l; columnNumber++)
{
var columnPtr = new IntPtr(columnNumber);
var item = new HDITEM { mask = HDITEM.Mask.Format };
if (SendMessage(columnHeader, HDM_GETITEM, columnPtr, ref item) == IntPtr.Zero)
var item = new HDITEMW { mask = HDITEMW.Mask.Format };
if (SendMessageW(columnHeader, HDM_GETITEMW, columnPtr, ref item) == IntPtr.Zero)
{
throw new Win32Exception();
}
if (columnNumber != columnIndex || order == SortOrder.None)
{
item.fmt &= ~HDITEM.Format.SortDown & ~HDITEM.Format.SortUp;
item.fmt &= ~HDITEMW.Format.SortDown & ~HDITEMW.Format.SortUp;
}
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
else switch (order)
{
case SortOrder.Ascending:
item.fmt &= ~HDITEM.Format.SortDown;
item.fmt |= HDITEM.Format.SortUp;
item.fmt &= ~HDITEMW.Format.SortDown;
item.fmt |= HDITEMW.Format.SortUp;
break;
case SortOrder.Descending:
item.fmt &= ~HDITEM.Format.SortUp;
item.fmt |= HDITEM.Format.SortDown;
item.fmt &= ~HDITEMW.Format.SortUp;
item.fmt |= HDITEMW.Format.SortDown;
break;
}
if (SendMessage(columnHeader, HDM_SETITEM, columnPtr, ref item) == IntPtr.Zero)
if (SendMessageW(columnHeader, HDM_SETITEMW, columnPtr, ref item) == IntPtr.Zero)
{
throw new Win32Exception();
}

View File

@ -21,7 +21,7 @@ namespace BizHawk.Client.EmuHawk
{
const int SPI_GETSCREENSAVERTIMEOUT = 14;
int value = default;
Win32Imports.SystemParametersInfo(SPI_GETSCREENSAVERTIMEOUT, 0, ref value, 0);
Win32Imports.SystemParametersInfoW(SPI_GETSCREENSAVERTIMEOUT, 0, ref value, 0);
return value;
}
set
@ -29,7 +29,7 @@ namespace BizHawk.Client.EmuHawk
const int SPI_SETSCREENSAVERTIMEOUT = 15;
const int SPIF_SENDWININICHANGE = 2;
int nullVar = default;
Win32Imports.SystemParametersInfo(SPI_SETSCREENSAVERTIMEOUT, value, ref nullVar, SPIF_SENDWININICHANGE);
Win32Imports.SystemParametersInfoW(SPI_SETSCREENSAVERTIMEOUT, value, ref nullVar, SPIF_SENDWININICHANGE);
}
}
}

View File

@ -868,7 +868,11 @@ namespace BizHawk.Client.EmuHawk
{
groupFreeze.SuspendLayout();
WmImports.SendMessage(groupFreeze.Handle, 11, (IntPtr)0, IntPtr.Zero); //WM_SETREDRAW false
if (!OSTailoredCode.IsUnixHost)
{
// WM_SETREDRAW false
WmImports.SendMessageW(groupFreeze.Handle, 11, (IntPtr)0, IntPtr.Zero);
}
var tp = tabctrlDetails.SelectedTab;
@ -886,7 +890,12 @@ namespace BizHawk.Client.EmuHawk
groupFreeze.ResumeLayout();
WmImports.SendMessage(groupFreeze.Handle, 11, (IntPtr)1, IntPtr.Zero); //WM_SETREDRAW true
if (!OSTailoredCode.IsUnixHost)
{
// WM_SETREDRAW true
WmImports.SendMessageW(groupFreeze.Handle, 11, (IntPtr)1, IntPtr.Zero);
}
groupFreeze.Refresh();
}

View File

@ -82,9 +82,9 @@ namespace BizHawk.Common.PathExtensions
if (File.Exists(path1.SubstringBefore('|'))) return FileAttributes.Normal;
throw new FileNotFoundException();
}
var path = new StringBuilder(Win32Imports.MAX_PATH);
return Win32Imports.PathRelativePathTo(path, fromPath, GetPathAttribute(fromPath), toPath, GetPathAttribute(toPath))
? path.ToString()
var path = new char[Win32Imports.MAX_PATH];
return Win32Imports.PathRelativePathToW(path, fromPath, GetPathAttribute(fromPath), toPath, GetPathAttribute(toPath))
? new string(path).TrimEnd('\0')
: throw new ArgumentException(message: "Paths must have a common prefix", paramName: nameof(toPath));
}

View File

@ -101,41 +101,41 @@ namespace BizHawk.Common
}
/// <summary>Create a new stream in an existing file and creates an interface to the new stream</summary>
[DllImport("avifil32.dll")]
[DllImport("avifil32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
public static extern int AVIFileCreateStreamW(IntPtr pfile, out IntPtr ppavi, ref AVISTREAMINFOW psi);
[DllImport("avifil32.dll", SetLastError = true)]
[DllImport("avifil32.dll", ExactSpelling = true)]
public static extern void AVIFileInit();
[DllImport("avifil32.dll", SetLastError = true)]
[DllImport("avifil32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern int AVIFileOpenW(ref IntPtr pAviFile, [MarshalAs(UnmanagedType.LPWStr)] string szFile, OpenFileStyle uMode, int lpHandler);
/// <summary>Release an open AVI stream</summary>
[DllImport("avifil32.dll")]
[DllImport("avifil32.dll", ExactSpelling = true)]
public static extern int AVIFileRelease(IntPtr pfile);
/// <summary>Create a compressed stream from an uncompressed stream and a compression filter, and returns the address of a pointer to the compressed stream</summary>
[DllImport("avifil32.dll")]
[DllImport("avifil32.dll", ExactSpelling = true)]
public static extern int AVIMakeCompressedStream(out IntPtr ppsCompressed, IntPtr psSource, ref AVICOMPRESSOPTIONS lpOptions, IntPtr pclsidHandler);
/// <summary>Retrieve the save options for a file and returns them in a buffer</summary>
[DllImport("avifil32.dll")]
[DllImport("avifil32.dll", ExactSpelling = true)]
public static extern unsafe int AVISaveOptions(IntPtr hwnd, int flags, int streams, void* ppAvi, void* plpOptions);
/// <inheritdoc cref="AVIFileRelease"/>
[DllImport("avifil32.dll")]
[DllImport("avifil32.dll", ExactSpelling = true)]
public static extern int AVIStreamRelease(IntPtr pavi);
/// <summary>Set the format of a stream at the specified position</summary>
[DllImport("avifil32.dll")]
[DllImport("avifil32.dll", ExactSpelling = true)]
public static extern int AVIStreamSetFormat(IntPtr pavi, int lPos, ref BITMAPINFOHEADER lpFormat, int cbFormat);
/// <inheritdoc cref="AVIStreamSetFormat(System.IntPtr,int,ref BizHawk.Common.AVIWriterImports.BITMAPINFOHEADER,int)"/>
[DllImport("avifil32.dll")]
[DllImport("avifil32.dll", ExactSpelling = true)]
public static extern int AVIStreamSetFormat(IntPtr pavi, int lPos, ref WAVEFORMATEX lpFormat, int cbFormat);
/// <summary>Write data to a stream</summary>
[DllImport("avifil32.dll")]
[DllImport("avifil32.dll", ExactSpelling = true)]
public static extern int AVIStreamWrite(IntPtr pavi, int lStart, int lSamples, IntPtr lpBuffer, int cbBuffer, int dwFlags, IntPtr plSampWritten, out int plBytesWritten);
}
}

View File

@ -6,10 +6,10 @@ namespace BizHawk.Common
/// <summary>Gets/Sets the current working directory while bypassing the security checks triggered by the public API (<see cref="Environment.CurrentDirectory"/>).</summary>
public static class CWDHacks
{
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
private static extern unsafe int GetCurrentDirectoryW(int nBufferLength, char* lpBuffer);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
private static extern bool SetCurrentDirectoryW(string lpPathName);
public static bool Set(string newCWD)

View File

@ -10,16 +10,19 @@ namespace BizHawk.Common
{
public static class CommctrlImports
{
public const int LVM_GETHEADER = 4127;
public const int HDM_GETITEM = 4619;
public const int HDM_SETITEM = 4620;
public const int LVM_FIRST = 0x1000;
public const int LVM_GETHEADER = LVM_FIRST + 31;
public const int HDM_FIRST = 0x1200;
public const int HDM_GETITEMW = HDM_FIRST + 11;
public const int HDM_SETITEMW = HDM_FIRST + 12;
[StructLayout(LayoutKind.Sequential)]
public struct HDITEM
public struct HDITEMW
{
public Mask mask;
public int cxy;
[MarshalAs(UnmanagedType.LPTStr)]
[MarshalAs(UnmanagedType.LPWStr)]
public string pszText;
public IntPtr hbm;
public int cchTextMax;
@ -38,20 +41,20 @@ namespace BizHawk.Common
public uint state;
[Flags]
public enum Mask
public enum Mask : uint
{
Format = 0x4
}
[Flags]
public enum Format
public enum Format : int
{
SortDown = 0x200,
SortUp = 0x400
}
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, ref HDITEM lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr SendMessageW(IntPtr hWnd, uint msg, IntPtr wParam, ref HDITEMW lParam);
}
}

View File

@ -8,14 +8,14 @@ namespace BizHawk.Common
{
public static class HeapApiImports
{
[DllImport("kernel32.dll", SetLastError = true)]
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetProcessHeap();
[DllImport("kernel32.dll", SetLastError = false)]
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = false)]
public static extern IntPtr HeapAlloc(IntPtr hHeap, uint dwFlags, int dwBytes);
/// <remarks>used in <c>#if false</c> code in <c>AviWriter.CodecToken.DeallocateAVICOMPRESSOPTIONS</c>, don't delete it</remarks>
[DllImport("kernel32.dll", SetLastError = true)]
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool HeapFree(IntPtr hHeap, uint dwFlags, IntPtr lpMem);
}

View File

@ -1,24 +1,26 @@
using System;
using System.Runtime.InteropServices;
// ReSharper disable UnusedMember.Global
namespace BizHawk.Common
{
public static class LoaderApiImports
{
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetModuleHandleW(string? lpModuleName);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr LoadLibraryW(string lpLibFileName);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool FreeLibrary(IntPtr hLibModule);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, IntPtr lpProcName);
}
}

View File

@ -37,11 +37,11 @@ namespace BizHawk.Common
WRITECOMBINE_Modifierflag = 0x400
}
[DllImport("kernel32.dll", SetLastError = true)]
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
public static extern UIntPtr VirtualAlloc(UIntPtr lpAddress, UIntPtr dwSize,
AllocationType flAllocationType, MemoryProtection flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool VirtualProtect(
UIntPtr lpAddress,
@ -56,7 +56,7 @@ namespace BizHawk.Common
Release = 0x8000,
}
[DllImport("kernel32.dll")]
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool VirtualFree(UIntPtr lpAddress, UIntPtr dwSize, FreeType dwFreeType);
}

View File

@ -0,0 +1,50 @@
using System;
using System.Runtime.InteropServices;
// ReSharper disable UnusedMember.Global
namespace BizHawk.Common
{
public static class Ole32Imports
{
public enum CLSCTX : uint
{
INPROC_SERVER = 0x1,
INPROC_HANDLER = 0x2,
LOCAL_SERVER = 0x4,
INPROC_SERVER16 = 0x8,
REMOTE_SERVER = 0x10,
INPROC_HANDLER16 = 0x20,
RESERVED1 = 0x40,
RESERVED2 = 0x80,
RESERVED3 = 0x100,
RESERVED4 = 0x200,
NO_CODE_DOWNLOAD = 0x400,
RESERVED5 = 0x800,
NO_CUSTOM_MARSHAL = 0x1000,
ENABLE_CODE_DOWNLOAD = 0x2000,
NO_FAILURE_LOG = 0x4000,
DISABLE_AAA = 0x8000,
ENABLE_AAA = 0x10000,
FROM_DEFAULT_CONTEXT = 0x20000,
ACTIVATE_X86_SERVER = 0x40000,
ACTIVATE_32_BIT_SERVER,
ACTIVATE_64_BIT_SERVER = 0x80000,
ENABLE_CLOAKING = 0x100000,
APPCONTAINER = 0x400000,
ACTIVATE_AAA_AS_IU = 0x800000,
RESERVED6 = 0x1000000,
ACTIVATE_ARM32_SERVER = 0x2000000,
ALLOW_LOWER_TRUST_REGISTRATION,
PS_DLL = 0x80000000
}
[DllImport("Ole32.dll", ExactSpelling = true)]
public static extern int CoCreateInstance(
[In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
IntPtr pUnkOuter,
CLSCTX dwClsContext,
[In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
out IntPtr ppv);
}
}

View File

@ -129,20 +129,20 @@ namespace BizHawk.Common
public RAWINPUTDATA data;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
public static extern unsafe IntPtr DefRawInputProc(RAWINPUT* paRawInput, int nInput, int cbSizeHeader);
[DllImport("user32.dll")]
[DllImport("user32.dll", ExactSpelling = true)]
public static extern int GetRawInputData(IntPtr hRawInput, RID uiCommand, IntPtr pData, out int bSize, int cbSizeHeader);
[DllImport("user32.dll")]
[DllImport("user32.dll", ExactSpelling = true)]
public static extern unsafe int GetRawInputData(IntPtr hRawInput, RID uiCommand, RAWINPUT* pData, ref int bSize, int cbSizeHeader);
[DllImport("user32.dll", SetLastError = true)]
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RegisterRawInputDevices(ref RAWINPUTDEVICE pRawInputDevice, uint uiNumDevices, int cbSize);
[DllImport("user32.dll", SetLastError = true)]
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevices, uint uiNumDevices, int cbSize);
}

View File

@ -2,122 +2,200 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
// ReSharper disable FieldCanBeMadeReadOnly.Global
// ReSharper disable UnusedMember.Global
namespace BizHawk.Common
{
public static class ShellLinkImports
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
[StructLayout(LayoutKind.Sequential)]
public struct WIN32_FIND_DATAW
{
public uint dwFileAttributes;
public long ftCreationTime;
public long ftLastAccessTime;
public long ftLastWriteTime;
public FILETIME ftCreationTime;
public FILETIME ftLastAccessTime;
public FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Win32Imports.MAX_PATH)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
}
// Obsolete fields
public uint dwFileType;
public uint dwCreatorType;
public int wFinderFlags;
[Flags]
public enum SLGP_FLAGS
{
}
[Flags]
public enum SLR_FLAGS
{
public struct FILETIME
{
public uint dwLowDateTime;
public uint dwHighDateTime;
}
}
/// <summary>The IShellLink interface allows Shell links to be created, modified, and resolved</summary>
[ComImport]
[Guid("000214F9-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IShellLinkW
[StructLayout(LayoutKind.Sequential)]
public unsafe struct IShellLinkW
{
/// <summary>Retrieves the path and file name of a Shell link object</summary>
void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out WIN32_FIND_DATAW pfd, SLGP_FLAGS fFlags);
/// <summary>Retrieves the list of item identifiers for a Shell link object</summary>
void GetIDList(out IntPtr ppidl);
/// <summary>Sets the pointer to an item identifier list (PIDL) for a Shell link object.</summary>
void SetIDList(IntPtr pidl);
/// <summary>Retrieves the description string for a Shell link object</summary>
void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
/// <summary>Sets the description for a Shell link object. The description can be any application-defined string</summary>
void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
/// <summary>Retrieves the name of the working directory for a Shell link object</summary>
void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
/// <summary>Sets the name of the working directory for a Shell link object</summary>
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
/// <summary>Retrieves the command-line arguments associated with a Shell link object</summary>
void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
/// <summary>Sets the command-line arguments for a Shell link object</summary>
void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
/// <summary>Retrieves the hot key for a Shell link object</summary>
void GetHotkey(out short pwHotkey);
/// <summary>Sets a hot key for a Shell link object</summary>
void SetHotkey(short wHotkey);
/// <summary>Retrieves the show command for a Shell link object</summary>
void GetShowCmd(out int piShowCmd);
/// <summary>Sets the show command for a Shell link object. The show command sets the initial show state of the window.</summary>
void SetShowCmd(int iShowCmd);
/// <summary>Retrieves the location (path and index) of the icon for a Shell link object</summary>
void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
/// <summary>Sets the location (path and index) of the icon for a Shell link object</summary>
void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
/// <summary>Sets the relative path to the Shell link object</summary>
void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved);
/// <summary>Attempts to find the target of a Shell link, even if it has been moved or renamed</summary>
void Resolve(IntPtr hwnd, SLR_FLAGS fFlags);
/// <summary>Sets the path and file name of a Shell link object</summary>
void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
public static readonly Guid Guid = new("000214F9-0000-0000-C000-000000000046");
[StructLayout(LayoutKind.Sequential)]
public struct IShellLinkWVtbl
{
// IUnknown functions
public delegate* unmanaged[Stdcall]<IShellLinkW*, in Guid, out IntPtr, int> QueryInterface;
public delegate* unmanaged[Stdcall]<IShellLinkW*, uint> AddRef;
public delegate* unmanaged[Stdcall]<IShellLinkW*, uint> Release;
// IShellLinkW functions
public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int, IntPtr, uint, int> GetPath;
public delegate* unmanaged[Stdcall]<IShellLinkW*, out IntPtr, int> GetIDList;
public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int> SetIDList;
public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int, int> GetDescription;
public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int> SetDescription;
public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int, int> GetWorkingDirectory;
public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int> SetWorkingDirectory;
public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int, int> GetArguments;
public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int> SetArguments;
public delegate* unmanaged[Stdcall]<IShellLinkW*, out short, int> GetHotkey;
public delegate* unmanaged[Stdcall]<IShellLinkW*, short, int> SetHotkey;
public delegate* unmanaged[Stdcall]<IShellLinkW*, out int, int> GetShowCmd;
public delegate* unmanaged[Stdcall]<IShellLinkW*, int, int> SetShowCmd;
public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int, out int, int> GetIconLocation;
public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int, int> SetIconLocation;
public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int, int> SetRelativePath;
public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int, int> Resolve;
public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int> SetPath;
}
public IShellLinkWVtbl* lpVtbl;
}
[ComImport]
[Guid("0000010c-0000-0000-c000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPersist
[StructLayout(LayoutKind.Sequential)]
public unsafe struct IPersist
{
[PreserveSig]
void GetClassID(out Guid pClassID);
public static readonly Guid Guid = new("0000010c-0000-0000-C000-000000000046");
[StructLayout(LayoutKind.Sequential)]
public struct IPersistVtbl
{
// IUnknown functions
public delegate* unmanaged[Stdcall]<IPersist*, in Guid, out IntPtr, int> QueryInterface;
public delegate* unmanaged[Stdcall]<IPersist*, uint> AddRef;
public delegate* unmanaged[Stdcall]<IPersist*, uint> Release;
// IPersist functions
public delegate* unmanaged[Stdcall]<IPersist*, out Guid, int> GetClassID;
}
public IPersistVtbl* lpVtbl;
}
[ComImport]
[Guid("0000010b-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPersistFile : IPersist
[StructLayout(LayoutKind.Sequential)]
public unsafe struct IPersistFile
{
new void GetClassID(out Guid pClassID);
public static readonly Guid Guid = new("0000010b-0000-0000-C000-000000000046");
[PreserveSig]
int IsDirty();
[StructLayout(LayoutKind.Sequential)]
public struct IPersistFileVtbl
{
// IUnknown functions
public delegate* unmanaged[Stdcall]<IPersistFile*, in Guid, out IntPtr, int> QueryInterface;
public delegate* unmanaged[Stdcall]<IPersistFile*, uint> AddRef;
public delegate* unmanaged[Stdcall]<IPersistFile*, uint> Release;
// IPersist functions
public delegate* unmanaged[Stdcall]<IPersistFile*, out Guid, int> GetClassID;
// IPersistFile functions
public delegate* unmanaged[Stdcall]<IPersistFile*, int> IsDirty;
public delegate* unmanaged[Stdcall]<IPersistFile*, IntPtr, uint, int> Load;
public delegate* unmanaged[Stdcall]<IPersistFile*, IntPtr, bool, int> Save;
public delegate* unmanaged[Stdcall]<IPersistFile*, IntPtr, int> SaveCompleted;
public delegate* unmanaged[Stdcall]<IPersistFile*, out IntPtr, int> GetCurFile;
}
[PreserveSig]
void Load([In, MarshalAs(UnmanagedType.LPWStr)]string pszFileName, uint dwMode);
[PreserveSig]
void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, [In, MarshalAs(UnmanagedType.Bool)] bool fRemember);
[PreserveSig]
void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName);
[PreserveSig]
void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName);
public IPersistFileVtbl* lpVtbl;
}
/// <remarks>CLSID_ShellLink from ShlGuid.h</remarks>
[ComImport]
[Guid("00021401-0000-0000-C000-000000000046")]
public class ShellLink /* : IPersistFile, IShellLinkW */
public unsafe class ShellLink : IDisposable
{
public static readonly Guid Guid = new("00021401-0000-0000-C000-000000000046");
private IShellLinkW* SLI;
private IPersistFile* PFI;
public ShellLink()
{
var hr = Ole32Imports.CoCreateInstance(Guid, IntPtr.Zero, Ole32Imports.CLSCTX.INPROC_SERVER, IShellLinkW.Guid, out var psl);
Marshal.ThrowExceptionForHR(hr);
var sli = (IShellLinkW*)psl;
hr = sli->lpVtbl->QueryInterface(sli, in IPersist.Guid, out var ppf);
var hrEx = Marshal.GetExceptionForHR(hr);
if (hrEx != null)
{
sli->lpVtbl->Release(sli);
throw hrEx;
}
SLI = sli;
PFI = (IPersistFile*)ppf;
}
public void Dispose()
{
if (PFI != null)
{
PFI->lpVtbl->Release(PFI);
PFI = null;
}
if (SLI != null)
{
SLI->lpVtbl->Release(SLI);
SLI = null;
}
}
public void GetPath(out string pszFile, int cch, out WIN32_FIND_DATAW pfd, uint fFlags)
{
var pszFile_ = Marshal.AllocCoTaskMem(cch * sizeof(char));
#if false // should we do this? we don't need pfd (NULL is valid), and we could delete the WIN32_FIND_DATAW definition by doing this
var hr = SLI->lpVtbl->GetPath(SLI, pszFile_, cch, IntPtr.Zero, fFlags);
#else
var pfd_ = Marshal.AllocCoTaskMem(Marshal.SizeOf<WIN32_FIND_DATAW>());
var hr = SLI->lpVtbl->GetPath(SLI, pszFile_, cch, pfd_, fFlags);
#endif
try
{
Marshal.ThrowExceptionForHR(hr);
pszFile = Marshal.PtrToStringUni(pszFile_);
pfd = Marshal.PtrToStructure<WIN32_FIND_DATAW>(pfd_);
}
finally
{
Marshal.FreeCoTaskMem(pszFile_);
Marshal.FreeCoTaskMem(pfd_);
}
}
#if false
public void Resolve(IntPtr hwnd, int fFlags)
{
var hr = SLI->lpVtbl->Resolve(SLI, hwnd, fFlags);
Marshal.ThrowExceptionForHR(hr);
}
#endif
public void Load(string pszFileName, uint dwMode)
{
var pszFileName_ = Marshal.StringToCoTaskMemUni(pszFileName);
var hr = PFI->lpVtbl->Load(PFI, pszFileName_, dwMode);
Marshal.FreeCoTaskMem(pszFileName_);
Marshal.ThrowExceptionForHR(hr);
}
}
}
}

View File

@ -17,13 +17,13 @@ namespace BizHawk.Common
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate int BFFCALLBACK(IntPtr hwnd, uint uMsg, IntPtr lParam, IntPtr lpData);
[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct BROWSEINFO
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct BROWSEINFOW
{
public IntPtr hwndOwner;
public IntPtr pidlRoot;
public IntPtr pszDisplayName;
[MarshalAs(UnmanagedType.LPTStr)]
[MarshalAs(UnmanagedType.LPWStr)]
public string lpszTitle;
public FLAGS ulFlags;
[MarshalAs(UnmanagedType.FunctionPtr)]
@ -78,16 +78,16 @@ namespace BizHawk.Common
void HeapMinimize();
}
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SHBrowseForFolder(ref BROWSEINFO bi);
[DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
public static extern IntPtr SHBrowseForFolderW(ref BROWSEINFOW bi);
[DllImport("shell32.dll")]
[DllImport("shell32.dll", ExactSpelling = true)]
public static extern int SHGetMalloc(out IMalloc ppMalloc);
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
public static extern int SHGetPathFromIDList(IntPtr pidl, StringBuilder pszPath);
[DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
public static extern int SHGetPathFromIDListW(IntPtr pidl, char[] pszPath);
[DllImport("shell32.dll")]
[DllImport("shell32.dll", ExactSpelling = true)]
public static extern int SHGetSpecialFolderLocation(IntPtr hwndOwner, int nFolder, out IntPtr ppidl);
}
}

View File

@ -16,10 +16,10 @@ namespace BizHawk.Common
public const uint QS_ALLINPUT = 0x4FFU;
public const uint MWMO_INPUTAVAILABLE = 0x0004U;
[DllImport("user32.dll", SetLastError = true)]
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
public static extern uint MsgWaitForMultipleObjectsEx(uint nCount, IntPtr[] pHandles, uint dwMilliseconds, uint dwWakeMask, uint dwFlags);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
public static extern int WaitForSingleObject(SafeWaitHandle handle, uint milliseconds);
}
}

View File

@ -13,19 +13,19 @@ namespace BizHawk.Common
{
public const int MAX_PATH = 260;
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)]
public static extern bool DeleteFileW([MarshalAs(UnmanagedType.LPWStr)] string lpFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern bool DeleteFileW(string lpFileName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern uint MapVirtualKey(uint uCode, uint uMapType);
[DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
public static extern uint MapVirtualKeyW(uint uCode, uint uMapType);
[DllImport("shlwapi.dll", CharSet = CharSet.Auto)]
public static extern bool PathRelativePathTo([Out] StringBuilder pszPath, [In] string pszFrom, [In] FileAttributes dwAttrFrom, [In] string pszTo, [In] FileAttributes dwAttrTo);
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
public static extern bool PathRelativePathToW([Out] char[] pszPath, [In] string pszFrom, [In] FileAttributes dwAttrFrom, [In] string pszTo, [In] FileAttributes dwAttrTo);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool SystemParametersInfo(int uAction, int uParam, ref int lpvParam, int flags);
[DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
public static extern bool SystemParametersInfoW(int uAction, int uParam, ref int lpvParam, int flags);
[DllImport("winmm.dll")]
[DllImport("winmm.dll", ExactSpelling = true)]
public static extern uint timeBeginPeriod(uint uMilliseconds);
}
}

View File

@ -224,19 +224,19 @@ namespace BizHawk.Common
int HandleMenuMsg(int uMsg, IntPtr wParam, IntPtr lParam);
}
[DllImport("shell32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
[DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)]
public static extern IShellItem SHCreateItemFromParsingName(
[In] string pszPath,
[In] IntPtr pbc,
[In, MarshalAs(UnmanagedType.LPStruct)] Guid riid);
[DllImport("shell32.dll", PreserveSig = false)]
[DllImport("shell32.dll", ExactSpelling = true, PreserveSig = false)]
public static extern IntPtr SHGetIDListFromObject([In, MarshalAs(UnmanagedType.IUnknown)] object punk);
[DllImport("shell32.dll", EntryPoint = "#16")]
[DllImport("shell32.dll", EntryPoint = "#16", ExactSpelling = true)]
public static extern IntPtr ILFindLastID(IntPtr pidl);
[DllImport("user32.dll")]
[DllImport("user32.dll", ExactSpelling = true)]
public static extern int TrackPopupMenuEx(IntPtr hmenu, TPM fuFlags, int x, int y, IntPtr hwnd, IntPtr lptpm);
private IContextMenu ComInterface { get; }
@ -271,10 +271,11 @@ namespace BizHawk.Common
private ref struct TempMenu
{
[DllImport("user32.dll")]
[DllImport("user32.dll", ExactSpelling = true)]
private static extern IntPtr CreatePopupMenu();
[DllImport("user32.dll", SetLastError = true)]
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DestroyMenu(IntPtr hMenu);
public IntPtr Handle { get; private set; }

View File

@ -23,13 +23,14 @@ namespace BizHawk.Common
public uint time;
public int x;
public int y;
public uint lPrivate;
}
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate IntPtr WNDPROC(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct WNDCLASS
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WNDCLASSW
{
public uint style;
public WNDPROC lpfnWndProc;
@ -43,47 +44,47 @@ namespace BizHawk.Common
public string lpszClassName;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateWindowEx(int dwExStyle, IntPtr lpClassName, string lpWindowName,
[DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateWindowExW(int dwExStyle, IntPtr lpClassName, string lpWindowName,
int dwStyle, int X, int Y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr DefWindowProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr DefWindowProcW(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DestroyWindow(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr DispatchMessage([In] ref MSG lpMsg);
[DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr DispatchMessageW([In] ref MSG lpMsg);
[DllImport("user32.dll")]
[DllImport("user32.dll", ExactSpelling = true)]
public static extern IntPtr GetActiveWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetWindowLongPtrW(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
[DllImport("user32.dll", ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool HideCaret(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool PeekMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg);
public static extern bool PeekMessageW(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr PostMessageW(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr RegisterClass([In] ref WNDCLASS lpWndClass);
[DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr RegisterClassW([In] ref WNDCLASSW lpWndClass);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr SendMessageW(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr SetWindowLongPtrW(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool TranslateMessage([In] ref MSG lpMsg);
}

View File

@ -796,10 +796,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
nativeResult = ThreadHacks.MsgWaitForMultipleObjectsEx(count, waitHandles, 0xFFFFFFFF, QS_MASK, ThreadHacks.MWMO_INPUTAVAILABLE);
if (IsNativeWaitSuccessful(count, nativeResult, out int managedResult) || WaitHandle.WaitTimeout == managedResult) break;
// there is a message, pump and dispatch it
if (WmImports.PeekMessage(out msg, IntPtr.Zero, 0, 0, WmImports.PM_REMOVE))
if (WmImports.PeekMessageW(out msg, IntPtr.Zero, 0, 0, WmImports.PM_REMOVE))
{
WmImports.TranslateMessage(ref msg);
WmImports.DispatchMessage(ref msg);
WmImports.DispatchMessageW(ref msg);
}
}
// handle.WaitOne();