diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index e7dc101..d670d8f 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -22,4 +22,4 @@ chrono = "0.4" anyhow = "1" [target.'cfg(windows)'.dependencies] -winapi = { version = "0.3", features = ["winuser", "sysinfoapi", "windef", "winreg", "shellapi"] } +winapi = { version = "0.3", features = ["winuser", "sysinfoapi", "windef", "shellapi"] } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index e5a6614..2e14d9f 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -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 { 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() {