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; const uint MAPVK_VSC_TO_VK_EX = 0x03;
// DInputKey is a scancode as is // 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); return VKeyToDKeyMap.GetValueOrDefault(virtualKey, DInputKey.Unknown);
} }

View File

@ -32,12 +32,12 @@ namespace BizHawk.Bizware.Input
private static readonly Lazy<IntPtr> _rawInputWindowAtom = new(() => private static readonly Lazy<IntPtr> _rawInputWindowAtom = new(() =>
{ {
var wc = default(WNDCLASS); var wc = default(WNDCLASSW);
wc.lpfnWndProc = _wndProc; wc.lpfnWndProc = _wndProc;
wc.hInstance = LoaderApiImports.GetModuleHandleW(null); wc.hInstance = LoaderApiImports.GetModuleHandleW(null);
wc.lpszClassName = "RawKeyInputClass"; wc.lpszClassName = "RawKeyInputClass";
var atom = RegisterClass(ref wc); var atom = RegisterClassW(ref wc);
if (atom == IntPtr.Zero) if (atom == IntPtr.Zero)
{ {
throw new InvalidOperationException("Failed to register RAWINPUT window class"); 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) 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) if (ud == IntPtr.Zero)
{ {
return DefWindowProc(hWnd, uMsg, wParam, lParam); return DefWindowProcW(hWnd, uMsg, wParam, lParam);
} }
if (uMsg != WM_INPUT) if (uMsg != WM_INPUT)
{ {
if (uMsg == WM_CLOSE) if (uMsg == WM_CLOSE)
{ {
SetWindowLongPtr(hWnd, GWLP_USERDATA, IntPtr.Zero); SetWindowLongPtrW(hWnd, GWLP_USERDATA, IntPtr.Zero);
GCHandle.FromIntPtr(ud).Free(); GCHandle.FromIntPtr(ud).Free();
} }
return DefWindowProc(hWnd, uMsg, wParam, lParam); return DefWindowProcW(hWnd, uMsg, wParam, lParam);
} }
if (GetRawInputData(lParam, RID.INPUT, IntPtr.Zero, if (GetRawInputData(lParam, RID.INPUT, IntPtr.Zero,
out var size, Marshal.SizeOf<RAWINPUTHEADER>()) == -1) 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 // 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, if (GetRawInputData(lParam, RID.INPUT, input,
ref size, Marshal.SizeOf<RAWINPUTHEADER>()) == -1) 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) 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() private static IntPtr CreateRawInputWindow()
{ {
const int WS_CHILD = 0x40000000; const int WS_CHILD = 0x40000000;
var window = CreateWindowEx( var window = CreateWindowExW(
dwExStyle: 0, dwExStyle: 0,
lpClassName: _rawInputWindowAtom.Value, lpClassName: _rawInputWindowAtom.Value,
lpWindowName: "RawKeyInput", lpWindowName: "RawKeyInput",
@ -170,7 +170,7 @@ namespace BizHawk.Bizware.Input
if (RawInputWindow != IntPtr.Zero) if (RawInputWindow != IntPtr.Zero)
{ {
// Can't use DestroyWindow, that's only allowed in the thread that created the window! // 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; RawInputWindow = IntPtr.Zero;
} }
} }
@ -184,15 +184,15 @@ namespace BizHawk.Bizware.Input
{ {
RawInputWindow = CreateRawInputWindow(); RawInputWindow = CreateRawInputWindow();
var handle = GCHandle.Alloc(this, GCHandleType.Normal); var handle = GCHandle.Alloc(this, GCHandleType.Normal);
SetWindowLongPtr(RawInputWindow, GWLP_USERDATA, GCHandle.ToIntPtr(handle)); SetWindowLongPtrW(RawInputWindow, GWLP_USERDATA, GCHandle.ToIntPtr(handle));
} }
HandleAltKbLayouts = handleAltKbLayouts; 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); TranslateMessage(ref msg);
DispatchMessage(ref msg); DispatchMessageW(ref msg);
} }
var ret = KeyEvents; 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) // similar code shouldn't be needed on other platforms (which have global message queues and not thread local message queues)
if (!OSTailoredCode.IsUnixHost) 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.TranslateMessage(ref msg);
WmImports.DispatchMessage(ref msg); WmImports.DispatchMessageW(ref msg);
} }
} }

View File

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

View File

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

View File

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

View File

@ -21,7 +21,7 @@ namespace BizHawk.Client.EmuHawk
{ {
const int SPI_GETSCREENSAVERTIMEOUT = 14; const int SPI_GETSCREENSAVERTIMEOUT = 14;
int value = default; int value = default;
Win32Imports.SystemParametersInfo(SPI_GETSCREENSAVERTIMEOUT, 0, ref value, 0); Win32Imports.SystemParametersInfoW(SPI_GETSCREENSAVERTIMEOUT, 0, ref value, 0);
return value; return value;
} }
set set
@ -29,7 +29,7 @@ namespace BizHawk.Client.EmuHawk
const int SPI_SETSCREENSAVERTIMEOUT = 15; const int SPI_SETSCREENSAVERTIMEOUT = 15;
const int SPIF_SENDWININICHANGE = 2; const int SPIF_SENDWININICHANGE = 2;
int nullVar = default; 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(); 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; var tp = tabctrlDetails.SelectedTab;
@ -886,7 +890,12 @@ namespace BizHawk.Client.EmuHawk
groupFreeze.ResumeLayout(); 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(); groupFreeze.Refresh();
} }

View File

@ -82,9 +82,9 @@ namespace BizHawk.Common.PathExtensions
if (File.Exists(path1.SubstringBefore('|'))) return FileAttributes.Normal; if (File.Exists(path1.SubstringBefore('|'))) return FileAttributes.Normal;
throw new FileNotFoundException(); throw new FileNotFoundException();
} }
var path = new StringBuilder(Win32Imports.MAX_PATH); var path = new char[Win32Imports.MAX_PATH];
return Win32Imports.PathRelativePathTo(path, fromPath, GetPathAttribute(fromPath), toPath, GetPathAttribute(toPath)) return Win32Imports.PathRelativePathToW(path, fromPath, GetPathAttribute(fromPath), toPath, GetPathAttribute(toPath))
? path.ToString() ? new string(path).TrimEnd('\0')
: throw new ArgumentException(message: "Paths must have a common prefix", paramName: nameof(toPath)); : 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> /// <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); 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(); 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); public static extern int AVIFileOpenW(ref IntPtr pAviFile, [MarshalAs(UnmanagedType.LPWStr)] string szFile, OpenFileStyle uMode, int lpHandler);
/// <summary>Release an open AVI stream</summary> /// <summary>Release an open AVI stream</summary>
[DllImport("avifil32.dll")] [DllImport("avifil32.dll", ExactSpelling = true)]
public static extern int AVIFileRelease(IntPtr pfile); 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> /// <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); 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> /// <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); public static extern unsafe int AVISaveOptions(IntPtr hwnd, int flags, int streams, void* ppAvi, void* plpOptions);
/// <inheritdoc cref="AVIFileRelease"/> /// <inheritdoc cref="AVIFileRelease"/>
[DllImport("avifil32.dll")] [DllImport("avifil32.dll", ExactSpelling = true)]
public static extern int AVIStreamRelease(IntPtr pavi); public static extern int AVIStreamRelease(IntPtr pavi);
/// <summary>Set the format of a stream at the specified position</summary> /// <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); 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)"/> /// <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); public static extern int AVIStreamSetFormat(IntPtr pavi, int lPos, ref WAVEFORMATEX lpFormat, int cbFormat);
/// <summary>Write data to a stream</summary> /// <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); 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> /// <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 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); 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); private static extern bool SetCurrentDirectoryW(string lpPathName);
public static bool Set(string newCWD) public static bool Set(string newCWD)

View File

@ -10,16 +10,19 @@ namespace BizHawk.Common
{ {
public static class CommctrlImports public static class CommctrlImports
{ {
public const int LVM_GETHEADER = 4127; public const int LVM_FIRST = 0x1000;
public const int HDM_GETITEM = 4619; public const int LVM_GETHEADER = LVM_FIRST + 31;
public const int HDM_SETITEM = 4620;
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)] [StructLayout(LayoutKind.Sequential)]
public struct HDITEM public struct HDITEMW
{ {
public Mask mask; public Mask mask;
public int cxy; public int cxy;
[MarshalAs(UnmanagedType.LPTStr)] [MarshalAs(UnmanagedType.LPWStr)]
public string pszText; public string pszText;
public IntPtr hbm; public IntPtr hbm;
public int cchTextMax; public int cchTextMax;
@ -38,20 +41,20 @@ namespace BizHawk.Common
public uint state; public uint state;
[Flags] [Flags]
public enum Mask public enum Mask : uint
{ {
Format = 0x4 Format = 0x4
} }
[Flags] [Flags]
public enum Format public enum Format : int
{ {
SortDown = 0x200, SortDown = 0x200,
SortUp = 0x400 SortUp = 0x400
} }
} }
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, ref HDITEM lParam); 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 public static class HeapApiImports
{ {
[DllImport("kernel32.dll", SetLastError = true)] [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetProcessHeap(); 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); 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> /// <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)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool HeapFree(IntPtr hHeap, uint dwFlags, IntPtr lpMem); public static extern bool HeapFree(IntPtr hHeap, uint dwFlags, IntPtr lpMem);
} }

View File

@ -1,24 +1,26 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// ReSharper disable UnusedMember.Global
namespace BizHawk.Common namespace BizHawk.Common
{ {
public static class LoaderApiImports 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); 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); 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)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool FreeLibrary(IntPtr hLibModule); 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); 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); public static extern IntPtr GetProcAddress(IntPtr hModule, IntPtr lpProcName);
} }
} }

View File

@ -37,11 +37,11 @@ namespace BizHawk.Common
WRITECOMBINE_Modifierflag = 0x400 WRITECOMBINE_Modifierflag = 0x400
} }
[DllImport("kernel32.dll", SetLastError = true)] [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
public static extern UIntPtr VirtualAlloc(UIntPtr lpAddress, UIntPtr dwSize, public static extern UIntPtr VirtualAlloc(UIntPtr lpAddress, UIntPtr dwSize,
AllocationType flAllocationType, MemoryProtection flProtect); AllocationType flAllocationType, MemoryProtection flProtect);
[DllImport("kernel32.dll", SetLastError = true)] [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool VirtualProtect( public static extern bool VirtualProtect(
UIntPtr lpAddress, UIntPtr lpAddress,
@ -56,7 +56,7 @@ namespace BizHawk.Common
Release = 0x8000, Release = 0x8000,
} }
[DllImport("kernel32.dll")] [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool VirtualFree(UIntPtr lpAddress, UIntPtr dwSize, FreeType dwFreeType); 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; 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); 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); 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); 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)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RegisterRawInputDevices(ref RAWINPUTDEVICE pRawInputDevice, uint uiNumDevices, int cbSize); 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)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevices, uint uiNumDevices, int cbSize); public static extern bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevices, uint uiNumDevices, int cbSize);
} }

View File

@ -2,122 +2,200 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
// ReSharper disable FieldCanBeMadeReadOnly.Global // ReSharper disable FieldCanBeMadeReadOnly.Global
// ReSharper disable UnusedMember.Global
namespace BizHawk.Common namespace BizHawk.Common
{ {
public static class ShellLinkImports public static class ShellLinkImports
{ {
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] [StructLayout(LayoutKind.Sequential)]
public struct WIN32_FIND_DATAW public struct WIN32_FIND_DATAW
{ {
public uint dwFileAttributes; public uint dwFileAttributes;
public long ftCreationTime; public FILETIME ftCreationTime;
public long ftLastAccessTime; public FILETIME ftLastAccessTime;
public long ftLastWriteTime; public FILETIME ftLastWriteTime;
public uint nFileSizeHigh; public uint nFileSizeHigh;
public uint nFileSizeLow; public uint nFileSizeLow;
public uint dwReserved0; public uint dwReserved0;
public uint dwReserved1; public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Win32Imports.MAX_PATH)]
public string cFileName; public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName; public string cAlternateFileName;
} // Obsolete fields
public uint dwFileType;
public uint dwCreatorType;
public int wFinderFlags;
[Flags] public struct FILETIME
public enum SLGP_FLAGS {
{ public uint dwLowDateTime;
} public uint dwHighDateTime;
}
[Flags]
public enum SLR_FLAGS
{
} }
/// <summary>The IShellLink interface allows Shell links to be created, modified, and resolved</summary> /// <summary>The IShellLink interface allows Shell links to be created, modified, and resolved</summary>
[ComImport] [StructLayout(LayoutKind.Sequential)]
[Guid("000214F9-0000-0000-C000-000000000046")] public unsafe struct IShellLinkW
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IShellLinkW
{ {
/// <summary>Retrieves the path and file name of a Shell link object</summary> public static readonly Guid Guid = new("000214F9-0000-0000-C000-000000000046");
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> [StructLayout(LayoutKind.Sequential)]
void GetIDList(out IntPtr ppidl); public struct IShellLinkWVtbl
/// <summary>Sets the pointer to an item identifier list (PIDL) for a Shell link object.</summary> {
void SetIDList(IntPtr pidl); // IUnknown functions
/// <summary>Retrieves the description string for a Shell link object</summary> public delegate* unmanaged[Stdcall]<IShellLinkW*, in Guid, out IntPtr, int> QueryInterface;
void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName); public delegate* unmanaged[Stdcall]<IShellLinkW*, uint> AddRef;
/// <summary>Sets the description for a Shell link object. The description can be any application-defined string</summary> public delegate* unmanaged[Stdcall]<IShellLinkW*, uint> Release;
void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); // IShellLinkW functions
/// <summary>Retrieves the name of the working directory for a Shell link object</summary> public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int, IntPtr, uint, int> GetPath;
void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath); public delegate* unmanaged[Stdcall]<IShellLinkW*, out IntPtr, int> GetIDList;
/// <summary>Sets the name of the working directory for a Shell link object</summary> public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int> SetIDList;
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int, int> GetDescription;
/// <summary>Retrieves the command-line arguments associated with a Shell link object</summary> public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int> SetDescription;
void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath); public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int, int> GetWorkingDirectory;
/// <summary>Sets the command-line arguments for a Shell link object</summary> public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int> SetWorkingDirectory;
void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int, int> GetArguments;
/// <summary>Retrieves the hot key for a Shell link object</summary> public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int> SetArguments;
void GetHotkey(out short pwHotkey); public delegate* unmanaged[Stdcall]<IShellLinkW*, out short, int> GetHotkey;
/// <summary>Sets a hot key for a Shell link object</summary> public delegate* unmanaged[Stdcall]<IShellLinkW*, short, int> SetHotkey;
void SetHotkey(short wHotkey); public delegate* unmanaged[Stdcall]<IShellLinkW*, out int, int> GetShowCmd;
/// <summary>Retrieves the show command for a Shell link object</summary> public delegate* unmanaged[Stdcall]<IShellLinkW*, int, int> SetShowCmd;
void GetShowCmd(out int piShowCmd); public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int, out int, int> GetIconLocation;
/// <summary>Sets the show command for a Shell link object. The show command sets the initial show state of the window.</summary> public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int, int> SetIconLocation;
void SetShowCmd(int iShowCmd); public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int, int> SetRelativePath;
/// <summary>Retrieves the location (path and index) of the icon for a Shell link object</summary> public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int, int> Resolve;
void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon); public delegate* unmanaged[Stdcall]<IShellLinkW*, IntPtr, int> SetPath;
/// <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> public IShellLinkWVtbl* lpVtbl;
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);
} }
[ComImport] [StructLayout(LayoutKind.Sequential)]
[Guid("0000010c-0000-0000-c000-000000000046")] public unsafe struct IPersist
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPersist
{ {
[PreserveSig] public static readonly Guid Guid = new("0000010c-0000-0000-C000-000000000046");
void GetClassID(out Guid pClassID);
[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] [StructLayout(LayoutKind.Sequential)]
[Guid("0000010b-0000-0000-C000-000000000046")] public unsafe struct IPersistFile
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPersistFile : IPersist
{ {
new void GetClassID(out Guid pClassID); public static readonly Guid Guid = new("0000010b-0000-0000-C000-000000000046");
[PreserveSig] [StructLayout(LayoutKind.Sequential)]
int IsDirty(); 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] public IPersistFileVtbl* lpVtbl;
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);
} }
/// <remarks>CLSID_ShellLink from ShlGuid.h</remarks> /// <remarks>CLSID_ShellLink from ShlGuid.h</remarks>
[ComImport] public unsafe class ShellLink : IDisposable
[Guid("00021401-0000-0000-C000-000000000046")]
public class ShellLink /* : IPersistFile, IShellLinkW */
{ {
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)] [UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate int BFFCALLBACK(IntPtr hwnd, uint uMsg, IntPtr lParam, IntPtr lpData); public delegate int BFFCALLBACK(IntPtr hwnd, uint uMsg, IntPtr lParam, IntPtr lpData);
[StructLayout(LayoutKind.Sequential, Pack = 8)] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct BROWSEINFO public struct BROWSEINFOW
{ {
public IntPtr hwndOwner; public IntPtr hwndOwner;
public IntPtr pidlRoot; public IntPtr pidlRoot;
public IntPtr pszDisplayName; public IntPtr pszDisplayName;
[MarshalAs(UnmanagedType.LPTStr)] [MarshalAs(UnmanagedType.LPWStr)]
public string lpszTitle; public string lpszTitle;
public FLAGS ulFlags; public FLAGS ulFlags;
[MarshalAs(UnmanagedType.FunctionPtr)] [MarshalAs(UnmanagedType.FunctionPtr)]
@ -78,16 +78,16 @@ namespace BizHawk.Common
void HeapMinimize(); void HeapMinimize();
} }
[DllImport("shell32.dll", CharSet = CharSet.Auto)] [DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
public static extern IntPtr SHBrowseForFolder(ref BROWSEINFO bi); public static extern IntPtr SHBrowseForFolderW(ref BROWSEINFOW bi);
[DllImport("shell32.dll")] [DllImport("shell32.dll", ExactSpelling = true)]
public static extern int SHGetMalloc(out IMalloc ppMalloc); public static extern int SHGetMalloc(out IMalloc ppMalloc);
[DllImport("shell32.dll", CharSet = CharSet.Auto)] [DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
public static extern int SHGetPathFromIDList(IntPtr pidl, StringBuilder pszPath); 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); 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 QS_ALLINPUT = 0x4FFU;
public const uint MWMO_INPUTAVAILABLE = 0x0004U; 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); 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); public static extern int WaitForSingleObject(SafeWaitHandle handle, uint milliseconds);
} }
} }

View File

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

View File

@ -224,19 +224,19 @@ namespace BizHawk.Common
int HandleMenuMsg(int uMsg, IntPtr wParam, IntPtr lParam); 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( public static extern IShellItem SHCreateItemFromParsingName(
[In] string pszPath, [In] string pszPath,
[In] IntPtr pbc, [In] IntPtr pbc,
[In, MarshalAs(UnmanagedType.LPStruct)] Guid riid); [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); 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); 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); public static extern int TrackPopupMenuEx(IntPtr hmenu, TPM fuFlags, int x, int y, IntPtr hwnd, IntPtr lptpm);
private IContextMenu ComInterface { get; } private IContextMenu ComInterface { get; }
@ -271,10 +271,11 @@ namespace BizHawk.Common
private ref struct TempMenu private ref struct TempMenu
{ {
[DllImport("user32.dll")] [DllImport("user32.dll", ExactSpelling = true)]
private static extern IntPtr CreatePopupMenu(); 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); private static extern bool DestroyMenu(IntPtr hMenu);
public IntPtr Handle { get; private set; } public IntPtr Handle { get; private set; }

View File

@ -23,13 +23,14 @@ namespace BizHawk.Common
public uint time; public uint time;
public int x; public int x;
public int y; public int y;
public uint lPrivate;
} }
[UnmanagedFunctionPointer(CallingConvention.Winapi)] [UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate IntPtr WNDPROC(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam); public delegate IntPtr WNDPROC(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WNDCLASS public struct WNDCLASSW
{ {
public uint style; public uint style;
public WNDPROC lpfnWndProc; public WNDPROC lpfnWndProc;
@ -43,47 +44,47 @@ namespace BizHawk.Common
public string lpszClassName; public string lpszClassName;
} }
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateWindowEx(int dwExStyle, IntPtr lpClassName, string lpWindowName, 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); 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)] [DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr DefWindowProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam); 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)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DestroyWindow(IntPtr hWnd); public static extern bool DestroyWindow(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr DispatchMessage([In] ref MSG lpMsg); public static extern IntPtr DispatchMessageW([In] ref MSG lpMsg);
[DllImport("user32.dll")] [DllImport("user32.dll", ExactSpelling = true)]
public static extern IntPtr GetActiveWindow(); public static extern IntPtr GetActiveWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex); public static extern IntPtr GetWindowLongPtrW(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")] [DllImport("user32.dll", ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool HideCaret(IntPtr hWnd); 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)] [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)] [DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); public static extern IntPtr PostMessageW(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr RegisterClass([In] ref WNDCLASS lpWndClass); public static extern IntPtr RegisterClassW([In] ref WNDCLASSW lpWndClass);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); public static extern IntPtr SendMessageW(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong); 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)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool TranslateMessage([In] ref MSG lpMsg); 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); nativeResult = ThreadHacks.MsgWaitForMultipleObjectsEx(count, waitHandles, 0xFFFFFFFF, QS_MASK, ThreadHacks.MWMO_INPUTAVAILABLE);
if (IsNativeWaitSuccessful(count, nativeResult, out int managedResult) || WaitHandle.WaitTimeout == managedResult) break; if (IsNativeWaitSuccessful(count, nativeResult, out int managedResult) || WaitHandle.WaitTimeout == managedResult) break;
// there is a message, pump and dispatch it // 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.TranslateMessage(ref msg);
WmImports.DispatchMessage(ref msg); WmImports.DispatchMessageW(ref msg);
} }
} }
// handle.WaitOne(); // handle.WaitOne();