The following snippet causes a STATUS_ACCESS_VIOLATION on exit. If I negate the conditional check, no error occurs. I can only assume that there is some kind of memory corruption occurring as a result of a controller actually being connected, but I'm at a loss as to why or how to fix it.
for i in 0..XUSER_MAX_COUNT {
let mut controller_state = unsafe { std::mem::zeroed::<XINPUT_STATE>() };
if unsafe { XInputGetState(i, &mut controller_state) == ERROR_SUCCESS.0 } {
println!("{} {:?}", i, controller_state);
} else {
// Controller is not connected.
}
}
Outputs:
0 XINPUT_STATE { dwPacketNumber: 11, Gamepad: XINPUT_GAMEPAD { wButtons: 0, bLeftTrigger: 0, bRightTrigger: 0, sThumbLX: -32768, sThumbLY: 0, sThumbRX: 0, sThumbRY: 0 } }
error: process didn't exit successfully: `target\debug\horizon.exe` (exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)
A full example is available, which is basically a window with a direct copy of the Getting Controller State example from the XInput docs. Is this a problem with the bindings or my use of them?
A quick check in C++ produces the same results, but as the docs are broken I have no idea whether the API is misbehaving or whether we're holding it wrong. @stevewhims may know what happened to the XInputGetState docs:
https://www.bing.com/search?q=XInputGetState
But as far as I can tell, the Rust bindings are not at fault.
Adding @karl-bridge-microsoft (and I sent him an email, too) as writer-owner of XInput.
@kennykerr, until the topics can be restored, you can see the content in the repo here: https://cpubwin.visualstudio.com/win32/_git/sdk-api?path=%2Fsdk-api-src%2Fcontent%2Fxinput.
Thanks Steve, looks like usage is also described here: https://docs.microsoft.com/en-us/windows/win32/xinput/getting-started-with-xinput
Anyway, this looks like an issue outside the scope of the Windows crate.
Thanks for confirming it's not a Windows crate issue. I've been able to get around the issue by loading XInput at runtime and creating a function pointer to XInputGetState. In case anyone else comes across this and want's a possible solution:
type XInputGetStateFn = extern "system" fn(u32, *mut XINPUT_STATE) -> u32;
extern "system" fn xinput_get_state_stub(_: u32, _: *mut XINPUT_STATE) -> u32 {
return ERROR_DEVICE_NOT_CONNECTED.0;
}
#[allow(non_upper_case_globals)]
static mut XInputGetState: XInputGetStateFn = xinput_get_state_stub;
unsafe fn load_xinput() {
let library = LoadLibraryW("xinput1_4.dll");
if !library.is_null() {
XInputGetState = std::mem::transmute(GetProcAddress(library, "XInputGetState"));
}
}
Do you know where is best to raise this issue with XInput?
Hopefully @Karl-Bridge-Microsoft can help.
@kennykerr, @ambye85 - an engineering fix has resolved the doc issue you reported.
For XBox developer support, please try the Xbox Developer Forums.