[PS-1469] Ensure the window is focused when prompting for biometrics (#3534)
This commit is contained in:
parent
8b73658e54
commit
d2736fe035
|
@ -30,6 +30,8 @@ windows = {version = "0.32.0", features = [
|
|||
"Win32_Foundation",
|
||||
"Win32_Security_Credentials",
|
||||
"Win32_System_WinRT",
|
||||
"Win32_UI_Input_KeyboardAndMouse",
|
||||
"Win32_UI_WindowsAndMessaging",
|
||||
]}
|
||||
|
||||
[target.'cfg(windows)'.dev-dependencies]
|
||||
|
|
|
@ -1,19 +1,33 @@
|
|||
use anyhow::Result;
|
||||
use windows::{
|
||||
core::factory, Foundation::IAsyncOperation, Security::Credentials::UI::*,
|
||||
Win32::Foundation::HWND, Win32::System::WinRT::IUserConsentVerifierInterop,
|
||||
core::{factory, HSTRING},
|
||||
Foundation::IAsyncOperation,
|
||||
Security::Credentials::UI::*,
|
||||
Win32::{
|
||||
Foundation::HWND,
|
||||
System::WinRT::IUserConsentVerifierInterop,
|
||||
UI::{
|
||||
Input::KeyboardAndMouse::{
|
||||
self, keybd_event, GetAsyncKeyState, SetFocus, KEYEVENTF_EXTENDEDKEY,
|
||||
KEYEVENTF_KEYUP, VK_MENU,
|
||||
},
|
||||
WindowsAndMessaging::{self, SetForegroundWindow},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
pub fn prompt(hwnd: Vec<u8>, message: String) -> Result<bool> {
|
||||
let interop = factory::<UserConsentVerifier, IUserConsentVerifierInterop>()?;
|
||||
|
||||
let h = isize::from_le_bytes(hwnd.try_into().unwrap());
|
||||
let h = isize::from_le_bytes(hwnd.clone().try_into().unwrap());
|
||||
let window = HWND(h);
|
||||
|
||||
let operation: IAsyncOperation<UserConsentVerificationResult> =
|
||||
unsafe { interop.RequestVerificationForWindowAsync(window, message)? };
|
||||
// The Windows Hello prompt is displayed inside the application window. For best result we
|
||||
// should set the window to the foreground and focus it.
|
||||
set_focus(window);
|
||||
|
||||
let result: UserConsentVerificationResult = operation.get()?;
|
||||
let interop = factory::<UserConsentVerifier, IUserConsentVerifierInterop>()?;
|
||||
let operation: IAsyncOperation<UserConsentVerificationResult> =
|
||||
unsafe { interop.RequestVerificationForWindowAsync(window, &HSTRING::from(message))? };
|
||||
let result = operation.get()?;
|
||||
|
||||
match result {
|
||||
UserConsentVerificationResult::Verified => Ok(true),
|
||||
|
@ -31,6 +45,31 @@ pub fn available() -> Result<bool> {
|
|||
}
|
||||
}
|
||||
|
||||
fn set_focus(window: HWND) {
|
||||
let mut pressed = false;
|
||||
|
||||
unsafe {
|
||||
// Simulate holding down Alt key to bypass windows limitations
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getasynckeystate#return-value
|
||||
// The most significant bit indicates if the key is currently being pressed. This means the
|
||||
// value will be negative if the key is pressed.
|
||||
if GetAsyncKeyState(VK_MENU.0 as i32) >= 0 {
|
||||
pressed = true;
|
||||
keybd_event(VK_MENU.0 as u8, 0, KEYEVENTF_EXTENDEDKEY, 0);
|
||||
}
|
||||
SetForegroundWindow(window);
|
||||
SetFocus(window);
|
||||
if pressed {
|
||||
keybd_event(
|
||||
VK_MENU.0 as u8,
|
||||
0,
|
||||
KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,
|
||||
0,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
Loading…
Reference in New Issue