-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from TotemArts/dinput8_fix
Work around dinput8.dll not existing in System32 by using COM
- Loading branch information
Showing
4 changed files
with
51 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,52 @@ | ||
//! This module handles functionality related to the original dinput8.dll | ||
use lazy_static::lazy_static; | ||
use libloading::Library; | ||
|
||
lazy_static! { | ||
static ref DINPUT8_DLL: Library = unsafe { Library::new("C:\\Windows\\System32\\dinput8.dll") }.unwrap(); | ||
static ref DINPUT8CREATE_PTR: libloading::Symbol<'static, unsafe extern "C" fn(usize, u32, usize, usize, usize) -> u32> = | ||
unsafe { DINPUT8_DLL.get(b"DirectInput8Create\0") }.unwrap(); | ||
} | ||
use windows::{ | ||
core::{IUnknown, Interface, GUID, HRESULT}, | ||
Win32::{ | ||
Devices::HumanInterfaceDevice::{CLSID_DirectInput8, IDirectInput8A, IDirectInput8W}, | ||
Foundation::{E_NOINTERFACE, HINSTANCE, S_OK}, | ||
System::Com::{CoCreateInstance, CLSCTX_INPROC_SERVER}, | ||
}, | ||
}; | ||
|
||
/// This function simply redirects the one and only DirectInput8Create call to the real dinput8 DLL. | ||
#[no_mangle] | ||
#[export_name = "DirectInput8Create"] | ||
pub unsafe extern "C" fn directinput8_create( | ||
hinst: usize, | ||
hinst: HINSTANCE, | ||
dwversion: u32, | ||
riid: usize, | ||
out: usize, | ||
outer: usize, | ||
) -> u32 { | ||
(DINPUT8CREATE_PTR)(hinst, dwversion, riid, out, outer) | ||
riid: *const GUID, | ||
out: *mut Option<IUnknown>, | ||
_outer: Option<IUnknown>, | ||
) -> HRESULT { | ||
// Instead of trying to load the original dinput8.dll and calling the original `DirectInput8Create`, | ||
// we can simply load the dinput8 interface via COM and return it up to our caller. This is basically | ||
// what DirectInput8Create does noawadays anyway. | ||
// | ||
// Reference: https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ee416756(v=vs.85) | ||
let f = || -> Result<IUnknown, windows::core::Error> { | ||
match unsafe { riid.as_ref() } { | ||
Some(&IDirectInput8A::IID) => { | ||
let dinput: IDirectInput8A = | ||
CoCreateInstance(&CLSID_DirectInput8, None, CLSCTX_INPROC_SERVER)?; | ||
|
||
dinput.Initialize(hinst, dwversion)?; | ||
Ok(dinput.cast()?) | ||
} | ||
Some(&IDirectInput8W::IID) => { | ||
let dinput: IDirectInput8W = | ||
CoCreateInstance(&CLSID_DirectInput8, None, CLSCTX_INPROC_SERVER)?; | ||
|
||
dinput.Initialize(hinst, dwversion)?; | ||
Ok(dinput.cast()?) | ||
} | ||
_ => return Err(E_NOINTERFACE.into()), | ||
} | ||
}; | ||
|
||
*out = match f() { | ||
Ok(v) => Some(v), | ||
Err(e) => return e.code(), | ||
}; | ||
|
||
S_OK | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters