Fix WebView2 detection - use loader API instead of registry
Registry check gave false negatives on systems where WebView2 is installed through Edge rather than EdgeUpdate. Now calls GetAvailableCoreWebView2BrowserVersionString (statically linked) which detects all installation methods.
This commit is contained in:
@@ -14,59 +14,38 @@ fn main() {
|
||||
#[cfg(windows)]
|
||||
mod webview2_check {
|
||||
use std::ptr;
|
||||
use winapi::shared::minwindef::{HKEY, MAX_PATH};
|
||||
use winapi::um::winnt::{KEY_READ, REG_SZ};
|
||||
use winapi::um::winreg::{RegOpenKeyExW, RegQueryValueExW, RegCloseKey, HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER};
|
||||
use winapi::um::winuser::{MessageBoxW, MB_OK, MB_ICONWARNING};
|
||||
use winapi::um::shellapi::ShellExecuteW;
|
||||
|
||||
const WEBVIEW2_GUID: &str = r"SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BEB-E15AB5810CD5}";
|
||||
const WEBVIEW2_GUID_USER: &str = r"Software\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BEB-E15AB5810CD5}";
|
||||
// Statically linked from WebView2LoaderStatic.lib via msvc_compat shims
|
||||
extern "system" {
|
||||
fn GetAvailableCoreWebView2BrowserVersionString(
|
||||
browser_executable_folder: *const u16,
|
||||
version_info: *mut *mut u16,
|
||||
) -> i32;
|
||||
}
|
||||
|
||||
extern "system" {
|
||||
fn CoTaskMemFree(pv: *mut std::ffi::c_void);
|
||||
}
|
||||
|
||||
fn to_wide(s: &str) -> Vec<u16> {
|
||||
s.encode_utf16().chain(std::iter::once(0)).collect()
|
||||
}
|
||||
|
||||
fn check_registry_key(root: HKEY, subkey: &str) -> bool {
|
||||
unsafe {
|
||||
let subkey_w = to_wide(subkey);
|
||||
let value_name = to_wide("pv");
|
||||
let mut hkey: HKEY = ptr::null_mut();
|
||||
|
||||
let status = RegOpenKeyExW(root, subkey_w.as_ptr(), 0, KEY_READ, &mut hkey);
|
||||
if status != 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut data = [0u16; MAX_PATH];
|
||||
let mut data_size = (data.len() * 2) as u32;
|
||||
let mut data_type = 0u32;
|
||||
|
||||
let status = RegQueryValueExW(
|
||||
hkey,
|
||||
value_name.as_ptr(),
|
||||
ptr::null_mut(),
|
||||
&mut data_type,
|
||||
data.as_mut_ptr() as *mut u8,
|
||||
&mut data_size,
|
||||
);
|
||||
|
||||
RegCloseKey(hkey);
|
||||
|
||||
if status != 0 || data_type != REG_SZ {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Convert to string and check it's not empty or "0.0.0.0"
|
||||
let len = (data_size as usize / 2).saturating_sub(1); // exclude null terminator
|
||||
let version = String::from_utf16_lossy(&data[..len]);
|
||||
!version.is_empty() && version != "0.0.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_webview2_installed() -> bool {
|
||||
check_registry_key(HKEY_LOCAL_MACHINE, WEBVIEW2_GUID)
|
||||
|| check_registry_key(HKEY_CURRENT_USER, WEBVIEW2_GUID_USER)
|
||||
unsafe {
|
||||
let mut version_info: *mut u16 = ptr::null_mut();
|
||||
let hr = GetAvailableCoreWebView2BrowserVersionString(
|
||||
ptr::null(),
|
||||
&mut version_info,
|
||||
);
|
||||
let installed = hr == 0 && !version_info.is_null();
|
||||
if !version_info.is_null() {
|
||||
CoTaskMemFree(version_info as *mut _);
|
||||
}
|
||||
installed
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show_missing_dialog() {
|
||||
|
||||
Reference in New Issue
Block a user