From 6eb1db0f5de1543f28abc644986ff84113bb4c79 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Sun, 29 Jun 2025 16:49:20 +0700 Subject: [PATCH] Switch to the windows crate --- Cargo.lock | 2 +- Cargo.toml | 2 +- qt/launcher/Cargo.toml | 2 +- qt/launcher/src/platform/windows.rs | 67 ++++++++++++++++------------- 4 files changed, 40 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 04e7c6c76..3e8f381d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3548,7 +3548,7 @@ dependencies = [ "embed-resource", "libc", "libc-stdhandle", - "winapi", + "windows 0.61.3", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 2c6eee2af..0ff7289b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -139,7 +139,7 @@ unicode-normalization = "0.1.24" walkdir = "2.5.0" which = "8.0.0" winapi = { version = "0.3", features = ["wincon", "winreg"] } -windows = { version = "0.61.3", features = ["Media_SpeechSynthesis", "Media_Core", "Foundation_Collections", "Storage_Streams"] } +windows = { version = "0.61.3", features = ["Media_SpeechSynthesis", "Media_Core", "Foundation_Collections", "Storage_Streams", "Win32_System_Console", "Win32_System_Registry", "Win32_Foundation"] } wiremock = "0.6.3" xz2 = "0.1.7" zip = { version = "4.1.0", default-features = false, features = ["deflate", "time"] } diff --git a/qt/launcher/Cargo.toml b/qt/launcher/Cargo.toml index 735cd892e..5584e5296 100644 --- a/qt/launcher/Cargo.toml +++ b/qt/launcher/Cargo.toml @@ -15,7 +15,7 @@ camino.workspace = true dirs.workspace = true [target.'cfg(windows)'.dependencies] -winapi.workspace = true +windows.workspace = true libc.workspace = true libc-stdhandle.workspace = true diff --git a/qt/launcher/src/platform/windows.rs b/qt/launcher/src/platform/windows.rs index 8a64de9c2..ded968938 100644 --- a/qt/launcher/src/platform/windows.rs +++ b/qt/launcher/src/platform/windows.rs @@ -8,14 +8,21 @@ use std::process::Command; use anyhow::Context; use anyhow::Result; -use winapi::shared::minwindef::HKEY; -use winapi::um::wincon; -use winapi::um::winnt::KEY_READ; -use winapi::um::winreg; +use windows::core::PCWSTR; +use windows::Win32::System::Registry::HKEY_CURRENT_USER; +use windows::Win32::System::Console::AttachConsole; +use windows::Win32::System::Console::GetConsoleWindow; +use windows::Win32::System::Console::ATTACH_PARENT_PROCESS; +use windows::Win32::System::Registry::RegCloseKey; +use windows::Win32::System::Registry::RegOpenKeyExW; +use windows::Win32::System::Registry::RegQueryValueExW; +use windows::Win32::System::Registry::HKEY; +use windows::Win32::System::Registry::KEY_READ; +use windows::Win32::System::Registry::REG_SZ; pub fn ensure_terminal_shown() -> Result<()> { unsafe { - if !wincon::GetConsoleWindow().is_null() { + if !GetConsoleWindow().is_invalid() { // We already have a console, no need to spawn anki-console.exe return Ok(()); } @@ -51,12 +58,12 @@ pub fn ensure_terminal_shown() -> Result<()> { pub fn attach_to_parent_console() -> bool { unsafe { - if !wincon::GetConsoleWindow().is_null() { + if !GetConsoleWindow().is_invalid() { // we have a console already return false; } - if wincon::AttachConsole(wincon::ATTACH_PARENT_PROCESS) != 0 { + if AttachConsole(ATTACH_PARENT_PROCESS).is_ok() { // successfully attached to parent reconnect_stdio_to_console(); true @@ -136,7 +143,7 @@ fn get_uninstaller_path() -> Option { fn read_registry_install_dir() -> Option { unsafe { - let mut hkey: HKEY = std::ptr::null_mut(); + let mut hkey = HKEY::default(); // Convert the registry path to wide string let subkey: Vec = OsStr::new("SOFTWARE\\Anki") @@ -145,15 +152,15 @@ fn read_registry_install_dir() -> Option { .collect(); // Open the registry key - let result = winreg::RegOpenKeyExW( - winreg::HKEY_CURRENT_USER, - subkey.as_ptr(), - 0, + let result = RegOpenKeyExW( + HKEY_CURRENT_USER, + PCWSTR(subkey.as_ptr()), + Some(0), KEY_READ, &mut hkey, ); - if result != 0 { + if result.is_err() { return None; } @@ -163,38 +170,38 @@ fn read_registry_install_dir() -> Option { .chain(std::iter::once(0)) .collect(); - let mut value_type = 0u32; + let mut value_type = REG_SZ; let mut data_size = 0u32; // First call to get the size - let result = winreg::RegQueryValueExW( + let result = RegQueryValueExW( hkey, - value_name.as_ptr(), - std::ptr::null_mut(), - &mut value_type, - std::ptr::null_mut(), - &mut data_size, + PCWSTR(value_name.as_ptr()), + None, + Some(&mut value_type), + None, + Some(&mut data_size), ); - if result != 0 || data_size == 0 { - winreg::RegCloseKey(hkey); + if result.is_err() || data_size == 0 { + let _ = RegCloseKey(hkey); return None; } // Allocate buffer and read the value let mut buffer: Vec = vec![0; (data_size / 2) as usize]; - let result = winreg::RegQueryValueExW( + let result = RegQueryValueExW( hkey, - value_name.as_ptr(), - std::ptr::null_mut(), - &mut value_type, - buffer.as_mut_ptr() as *mut u8, - &mut data_size, + PCWSTR(value_name.as_ptr()), + None, + Some(&mut value_type), + Some(buffer.as_mut_ptr() as *mut u8), + Some(&mut data_size), ); - winreg::RegCloseKey(hkey); + let _ = RegCloseKey(hkey); - if result == 0 { + if result.is_ok() { // Convert wide string back to PathBuf let len = buffer.iter().position(|&x| x == 0).unwrap_or(buffer.len()); let path_str = String::from_utf16_lossy(&buffer[..len]);