fix ordinal loading (im pretty sure what was being done before only actually worked for dllimport and not getprocaddress)
cleanup some more win32 imports (new LoaderApiImports, although it isn't used for OSTailoredCode to avoid hard dep on BizHawk.Common, probably want to use same hack on LoaderApiImports)
This commit is contained in:
parent
195846f2f3
commit
b1f16cf437
|
@ -32,29 +32,24 @@ namespace BizHawk.Bizware.Input
|
|||
IsAvailable = XInput.Version != XInputVersion.Invalid;
|
||||
if (IsAvailable)
|
||||
{
|
||||
var llManager = OSTailoredCode.LinkedLibManager;
|
||||
var libHandle = XInput.Version switch
|
||||
{
|
||||
XInputVersion.Version14 => llManager.LoadOrThrow("xinput1_4.dll"),
|
||||
XInputVersion.Version13 => llManager.LoadOrThrow("xinput1_3.dll"),
|
||||
XInputVersion.Version14 => LoaderApiImports.GetModuleHandleW("xinput1_4.dll"),
|
||||
XInputVersion.Version13 => LoaderApiImports.GetModuleHandleW("xinput1_3.dll"),
|
||||
_ => IntPtr.Zero // unofficial API isn't available for 9.1.0
|
||||
};
|
||||
|
||||
if (libHandle != IntPtr.Zero)
|
||||
{
|
||||
var fptr = llManager.GetProcAddrOrZero(libHandle, "#100");
|
||||
var fptr = LoaderApiImports.GetProcAddress(libHandle, new IntPtr(100));
|
||||
if (fptr != IntPtr.Zero)
|
||||
{
|
||||
XInputGetStateExProc =
|
||||
Marshal.GetDelegateForFunctionPointer<XInputGetStateExProcDelegate>(fptr);
|
||||
}
|
||||
|
||||
// nb: this doesn't actually free the library here, rather it will just decrement the reference count
|
||||
llManager.FreeByPtr(libHandle);
|
||||
}
|
||||
|
||||
// don't remove this code. it's important to catch errors on systems with broken xinput installs.
|
||||
|
||||
_ = XInputGetStateExProc?.Invoke(0, out _);
|
||||
_ = XInput.GetState(0, out _);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ using System.Runtime.InteropServices;
|
|||
|
||||
using BizHawk.Client.Common;
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Common.CollectionExtensions;
|
||||
|
||||
using static BizHawk.Common.RawInputImports;
|
||||
using static BizHawk.Common.WmImports;
|
||||
|
@ -35,7 +34,7 @@ namespace BizHawk.Bizware.Input
|
|||
{
|
||||
var wc = default(WNDCLASS);
|
||||
wc.lpfnWndProc = _wndProc;
|
||||
wc.hInstance = Win32Imports.GetModuleHandle(null);
|
||||
wc.hInstance = LoaderApiImports.GetModuleHandleW(null);
|
||||
wc.lpszClassName = "RawKeyInputClass";
|
||||
|
||||
var atom = RegisterClass(ref wc);
|
||||
|
@ -128,7 +127,7 @@ namespace BizHawk.Bizware.Input
|
|||
nHeight: 1,
|
||||
hWndParent: HWND_MESSAGE,
|
||||
hMenu: IntPtr.Zero,
|
||||
hInstance: Win32Imports.GetModuleHandle(null),
|
||||
hInstance: LoaderApiImports.GetModuleHandleW(null),
|
||||
lpParam: IntPtr.Zero);
|
||||
|
||||
if (window == IntPtr.Zero)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<PropertyGroup>
|
||||
<ApplicationIcon>discohawk.ico</ApplicationIcon>
|
||||
<Nullable>disable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
|
|
|
@ -119,6 +119,8 @@ namespace BizHawk.Common
|
|||
|
||||
private class UnixMonoLLManager : ILinkedLibManager
|
||||
{
|
||||
private const int RTLD_NOW = 2;
|
||||
|
||||
[DllImport("libdl.so.2")]
|
||||
private static extern int dlclose(IntPtr handle);
|
||||
|
||||
|
@ -155,40 +157,24 @@ namespace BizHawk.Common
|
|||
public string GetErrorMessage()
|
||||
{
|
||||
var errCharPtr = dlerror();
|
||||
return errCharPtr == IntPtr.Zero ? "No error present" : Marshal.PtrToStringAnsi(errCharPtr);
|
||||
return errCharPtr == IntPtr.Zero ? "No error present" : Marshal.PtrToStringAnsi(errCharPtr)!;
|
||||
}
|
||||
|
||||
private const int RTLD_NOW = 2;
|
||||
}
|
||||
|
||||
private class WindowsLLManager : ILinkedLibManager
|
||||
{
|
||||
// comments reference extern functions removed from SevenZip.NativeMethods
|
||||
// functions taken from LoaderApiImports
|
||||
// TODO: Should we apply the same EXE_PROJECT hack to that file?
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern bool FreeLibrary(IntPtr hModule); // return type was annotated MarshalAs(UnmanagedType.Bool)
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
|
||||
private static extern IntPtr LoadLibraryW(string lpLibFileName);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern uint GetLastError();
|
||||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool FreeLibrary(IntPtr hLibModule);
|
||||
|
||||
private enum FORMAT_MESSAGE : uint
|
||||
{
|
||||
ALLOCATE_BUFFER = 0x00000100,
|
||||
IGNORE_INSERTS = 0x00000200,
|
||||
FROM_SYSTEM = 0x00001000,
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern int FormatMessageA(FORMAT_MESSAGE flags, IntPtr source, uint messageId, uint languageId, out IntPtr outMsg, int size, IntPtr args);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern IntPtr LocalFree(IntPtr hMem); // use this to free a message from FORMAT_MESSAGE.ALLOCATE_BUFFER
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)] // had BestFitMapping = false, ThrowOnUnmappableChar = true
|
||||
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName); // param procName was annotated `[MarshalAs(UnmanagedType.LPStr)]`
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)] // had BestFitMapping = false, ThrowOnUnmappableChar = true
|
||||
private static extern IntPtr LoadLibrary(string dllToLoad); // param dllToLoad was annotated `[MarshalAs(UnmanagedType.LPStr)]`
|
||||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
|
||||
private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
|
||||
|
||||
public int FreeByPtr(IntPtr hModule) => FreeLibrary(hModule) ? 0 : 1;
|
||||
|
||||
|
@ -197,25 +183,30 @@ namespace BizHawk.Common
|
|||
public IntPtr GetProcAddrOrThrow(IntPtr hModule, string procName)
|
||||
{
|
||||
var ret = GetProcAddrOrZero(hModule, procName);
|
||||
return ret != IntPtr.Zero ? ret : throw new InvalidOperationException($"got null pointer from {nameof(GetProcAddress)}, error code: {GetLastError()}");
|
||||
return ret != IntPtr.Zero ? ret : throw new InvalidOperationException($"got null pointer from {nameof(GetProcAddress)}, {GetErrorMessage()}");
|
||||
}
|
||||
|
||||
public IntPtr LoadOrZero(string dllToLoad) => LoadLibrary(dllToLoad);
|
||||
public IntPtr LoadOrZero(string dllToLoad) => LoadLibraryW(dllToLoad);
|
||||
|
||||
public IntPtr LoadOrThrow(string dllToLoad)
|
||||
{
|
||||
var ret = LoadOrZero(dllToLoad);
|
||||
return ret != IntPtr.Zero ? ret : throw new InvalidOperationException($"got null pointer from {nameof(LoadLibrary)}, error code: {GetLastError()}");
|
||||
return ret != IntPtr.Zero ? ret : throw new InvalidOperationException($"got null pointer from {nameof(LoadLibraryW)}, {GetErrorMessage()}");
|
||||
}
|
||||
|
||||
public string GetErrorMessage()
|
||||
[DllImport("kernel32.dll", ExactSpelling = true)]
|
||||
private static extern uint GetLastError();
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
|
||||
private static extern unsafe int FormatMessageW(int flags, IntPtr source, uint messageId, uint languageId, char* outMsg, int size, IntPtr args);
|
||||
|
||||
public unsafe string GetErrorMessage()
|
||||
{
|
||||
var errCode = GetLastError();
|
||||
var sz = FormatMessageA(FORMAT_MESSAGE.ALLOCATE_BUFFER | FORMAT_MESSAGE.FROM_SYSTEM | FORMAT_MESSAGE.IGNORE_INSERTS,
|
||||
IntPtr.Zero, errCode, 0, out var buffer, 1024, IntPtr.Zero);
|
||||
var ret = Marshal.PtrToStringAnsi(buffer, sz);
|
||||
_ = LocalFree(buffer);
|
||||
return ret;
|
||||
var buffer = stackalloc char[1024];
|
||||
const int FORMAT_MESSAGE_FROM_SYSTEM = 0x1000;
|
||||
var sz = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, IntPtr.Zero, errCode, 0, buffer, 1024, IntPtr.Zero);
|
||||
return $"error code: 0x{errCode:X8}, error message: {new string(buffer, 0, sz)}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BizHawk.Common
|
||||
{
|
||||
public static class LoaderApiImports
|
||||
{
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
|
||||
public static extern IntPtr GetModuleHandleW(string? lpModuleName);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
|
||||
public static extern IntPtr LoadLibraryW(string lpLibFileName);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool FreeLibrary(IntPtr hLibModule);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
|
||||
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
|
||||
public static extern IntPtr GetProcAddress(IntPtr hModule, IntPtr lpProcName);
|
||||
}
|
||||
}
|
|
@ -17,9 +17,6 @@ namespace BizHawk.Common
|
|||
[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.Auto, SetLastError = true)]
|
||||
public static extern IntPtr GetModuleHandle(string lpModuleName);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||
public static extern uint MapVirtualKey(uint uCode, uint uMapType);
|
||||
|
||||
|
|
Loading…
Reference in New Issue