fix: win com call

This commit is contained in:
xkeyC 2025-12-10 16:05:38 +08:00
parent df025319aa
commit da0bf8f4e7

View File

@ -29,8 +29,8 @@ pub fn send_notify(
/// Get system memory size in GB /// Get system memory size in GB
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub fn get_system_memory_size_gb() -> anyhow::Result<u64> { pub fn get_system_memory_size_gb() -> anyhow::Result<u64> {
use windows::Win32::System::SystemInformation::{GlobalMemoryStatusEx, MEMORYSTATUSEX};
use std::mem; use std::mem;
use windows::Win32::System::SystemInformation::{GlobalMemoryStatusEx, MEMORYSTATUSEX};
unsafe { unsafe {
let mut mem_status: MEMORYSTATUSEX = mem::zeroed(); let mut mem_status: MEMORYSTATUSEX = mem::zeroed();
@ -51,8 +51,8 @@ pub fn get_system_memory_size_gb() -> anyhow::Result<u64> {
/// Get number of logical processors /// Get number of logical processors
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub fn get_number_of_logical_processors() -> anyhow::Result<u32> { pub fn get_number_of_logical_processors() -> anyhow::Result<u32> {
use windows::Win32::System::SystemInformation::{GetSystemInfo, SYSTEM_INFO};
use std::mem; use std::mem;
use windows::Win32::System::SystemInformation::{GetSystemInfo, SYSTEM_INFO};
unsafe { unsafe {
let mut sys_info: SYSTEM_INFO = mem::zeroed(); let mut sys_info: SYSTEM_INFO = mem::zeroed();
@ -78,8 +78,8 @@ pub struct SystemInfo {
/// Get all system information at once /// Get all system information at once
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub fn get_system_info() -> anyhow::Result<SystemInfo> { pub fn get_system_info() -> anyhow::Result<SystemInfo> {
use wmi::{COMLibrary, WMIConnection};
use serde::Deserialize; use serde::Deserialize;
use wmi::WMIConnection;
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "Caption")] #[serde(rename = "Caption")]
@ -112,12 +112,12 @@ pub fn get_system_info() -> anyhow::Result<SystemInfo> {
size: Option<u64>, size: Option<u64>,
} }
let com_con = COMLibrary::new()?; let wmi_con = WMIConnection::new()?;
let wmi_con = WMIConnection::new(com_con)?;
// Get OS name using raw query // Get OS name using raw query
let os_name = match wmi_con.raw_query::<OsInfo>("SELECT Caption FROM Win32_OperatingSystem") { let os_name = match wmi_con.raw_query::<OsInfo>("SELECT Caption FROM Win32_OperatingSystem") {
Ok(results) => results.first() Ok(results) => results
.first()
.and_then(|os| os.caption.clone()) .and_then(|os| os.caption.clone())
.unwrap_or_default(), .unwrap_or_default(),
Err(_) => String::new(), Err(_) => String::new(),
@ -125,41 +125,48 @@ pub fn get_system_info() -> anyhow::Result<SystemInfo> {
// Get CPU name using raw query // Get CPU name using raw query
let cpu_name = match wmi_con.raw_query::<CpuInfo>("SELECT Name FROM Win32_Processor") { let cpu_name = match wmi_con.raw_query::<CpuInfo>("SELECT Name FROM Win32_Processor") {
Ok(results) => results.first() Ok(results) => results
.first()
.and_then(|cpu| cpu.name.clone()) .and_then(|cpu| cpu.name.clone())
.unwrap_or_default(), .unwrap_or_default(),
Err(_) => String::new(), Err(_) => String::new(),
}; };
// Get GPU info using raw query // Get GPU info using raw query
let gpu_info = match wmi_con.raw_query::<GpuInfo>("SELECT Name, AdapterRAM FROM Win32_VideoController") { let gpu_info =
Ok(results) => results.iter() match wmi_con.raw_query::<GpuInfo>("SELECT Name, AdapterRAM FROM Win32_VideoController") {
.filter_map(|gpu| { Ok(results) => results
gpu.name.as_ref().map(|name| { .iter()
let vram_gb = gpu.adapter_ram.unwrap_or(0) / (1024 * 1024 * 1024); .filter_map(|gpu| {
format!("{} ({} GB)", name, vram_gb) gpu.name.as_ref().map(|name| {
let vram_gb = gpu.adapter_ram.unwrap_or(0) / (1024 * 1024 * 1024);
format!("{} ({} GB)", name, vram_gb)
})
}) })
}) .collect::<Vec<_>>()
.collect::<Vec<_>>() .join("\n"),
.join("\n"), Err(_) => String::new(),
Err(_) => String::new(), };
};
// Get Disk info using raw query // Get Disk info using raw query
let disk_info = match wmi_con.raw_query::<DiskInfo>("SELECT MediaType, Model, Size FROM Win32_DiskDrive") { let disk_info =
Ok(results) => results.iter() match wmi_con.raw_query::<DiskInfo>("SELECT MediaType, Model, Size FROM Win32_DiskDrive") {
.filter(|disk| disk.model.is_some()) Ok(results) => results
.map(|disk| { .iter()
let size_gb = disk.size.unwrap_or(0) / (1024 * 1024 * 1024); .filter(|disk| disk.model.is_some())
format!("{}\t{}\t{} GB", .map(|disk| {
disk.media_type.as_deref().unwrap_or(""), let size_gb = disk.size.unwrap_or(0) / (1024 * 1024 * 1024);
disk.model.as_deref().unwrap_or(""), format!(
size_gb) "{}\t{}\t{} GB",
}) disk.media_type.as_deref().unwrap_or(""),
.collect::<Vec<_>>() disk.model.as_deref().unwrap_or(""),
.join("\n"), size_gb
Err(_) => String::new(), )
}; })
.collect::<Vec<_>>()
.join("\n"),
Err(_) => String::new(),
};
Ok(SystemInfo { Ok(SystemInfo {
os_name, os_name,
@ -182,15 +189,16 @@ pub fn get_system_info() -> anyhow::Result<SystemInfo> {
/// Get GPU info from registry (more accurate VRAM) /// Get GPU info from registry (more accurate VRAM)
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub fn get_gpu_info_from_registry() -> anyhow::Result<String> { pub fn get_gpu_info_from_registry() -> anyhow::Result<String> {
use windows::Win32::System::Registry::{
RegOpenKeyExW, RegQueryValueExW, RegEnumKeyExW, RegCloseKey,
HKEY_LOCAL_MACHINE, KEY_READ, REG_VALUE_TYPE,
};
use windows::core::{HSTRING, PCWSTR};
use std::mem; use std::mem;
use windows::core::{HSTRING, PCWSTR};
use windows::Win32::System::Registry::{
RegCloseKey, RegEnumKeyExW, RegOpenKeyExW, RegQueryValueExW, HKEY_LOCAL_MACHINE, KEY_READ,
REG_VALUE_TYPE,
};
let mut result = Vec::new(); let mut result = Vec::new();
let base_path = HSTRING::from(r"SYSTEM\ControlSet001\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}"); let base_path =
HSTRING::from(r"SYSTEM\ControlSet001\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}");
unsafe { unsafe {
let mut hkey = std::mem::zeroed(); let mut hkey = std::mem::zeroed();
@ -200,7 +208,9 @@ pub fn get_gpu_info_from_registry() -> anyhow::Result<String> {
Some(0), Some(0),
KEY_READ, KEY_READ,
&mut hkey, &mut hkey,
).is_err() { )
.is_err()
{
return Ok(String::new()); return Ok(String::new());
} }
@ -218,7 +228,9 @@ pub fn get_gpu_info_from_registry() -> anyhow::Result<String> {
None, None,
None, None,
None, None,
).is_err() { )
.is_err()
{
break; break;
} }
@ -238,7 +250,9 @@ pub fn get_gpu_info_from_registry() -> anyhow::Result<String> {
Some(0), Some(0),
KEY_READ, KEY_READ,
&mut subkey, &mut subkey,
).is_ok() { )
.is_ok()
{
// Read adapter string // Read adapter string
let adapter_name = HSTRING::from("HardwareInformation.AdapterString"); let adapter_name = HSTRING::from("HardwareInformation.AdapterString");
let mut adapter_buffer = [0u16; 512]; let mut adapter_buffer = [0u16; 512];
@ -252,7 +266,9 @@ pub fn get_gpu_info_from_registry() -> anyhow::Result<String> {
Some(&mut adapter_type), Some(&mut adapter_type),
Some(adapter_buffer.as_mut_ptr() as *mut u8), Some(adapter_buffer.as_mut_ptr() as *mut u8),
Some(&mut adapter_size), Some(&mut adapter_size),
).is_ok() { )
.is_ok()
{
let len = (adapter_size as usize / 2).saturating_sub(1); let len = (adapter_size as usize / 2).saturating_sub(1);
String::from_utf16_lossy(&adapter_buffer[..len]) String::from_utf16_lossy(&adapter_buffer[..len])
} else { } else {
@ -272,7 +288,9 @@ pub fn get_gpu_info_from_registry() -> anyhow::Result<String> {
Some(&mut mem_type), Some(&mut mem_type),
Some(&mut mem_value as *mut u64 as *mut u8), Some(&mut mem_value as *mut u64 as *mut u8),
Some(&mut mem_size), Some(&mut mem_size),
).is_ok() { )
.is_ok()
{
mem_value / (1024 * 1024 * 1024) mem_value / (1024 * 1024 * 1024)
} else { } else {
0 0
@ -303,13 +321,13 @@ pub fn get_gpu_info_from_registry() -> anyhow::Result<String> {
/// Resolve shortcut (.lnk) file to get target path /// Resolve shortcut (.lnk) file to get target path
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub fn resolve_shortcut(lnk_path: String) -> anyhow::Result<String> { pub fn resolve_shortcut(lnk_path: String) -> anyhow::Result<String> {
use windows::core::{HSTRING, Interface}; use windows::core::{Interface, HSTRING};
use windows::Win32::System::Com::IPersistFile;
use windows::Win32::System::Com::{ use windows::Win32::System::Com::{
CoCreateInstance, CoInitializeEx, CoUninitialize, CoCreateInstance, CoInitializeEx, CoUninitialize, CLSCTX_INPROC_SERVER,
CLSCTX_INPROC_SERVER, COINIT_APARTMENTTHREADED, STGM_READ, COINIT_APARTMENTTHREADED, STGM_READ,
}; };
use windows::Win32::UI::Shell::{IShellLinkW, ShellLink}; use windows::Win32::UI::Shell::{IShellLinkW, ShellLink};
use windows::Win32::System::Com::IPersistFile;
unsafe { unsafe {
// Initialize COM // Initialize COM
@ -317,11 +335,7 @@ pub fn resolve_shortcut(lnk_path: String) -> anyhow::Result<String> {
let result = (|| -> anyhow::Result<String> { let result = (|| -> anyhow::Result<String> {
// Create ShellLink instance // Create ShellLink instance
let shell_link: IShellLinkW = CoCreateInstance( let shell_link: IShellLinkW = CoCreateInstance(&ShellLink, None, CLSCTX_INPROC_SERVER)?;
&ShellLink,
None,
CLSCTX_INPROC_SERVER,
)?;
// Get IPersistFile interface // Get IPersistFile interface
let persist_file: IPersistFile = shell_link.cast()?; let persist_file: IPersistFile = shell_link.cast()?;
@ -332,14 +346,13 @@ pub fn resolve_shortcut(lnk_path: String) -> anyhow::Result<String> {
// Get target path // Get target path
let mut path_buffer = [0u16; 260]; let mut path_buffer = [0u16; 260];
shell_link.GetPath( shell_link.GetPath(&mut path_buffer, std::ptr::null_mut(), 0)?;
&mut path_buffer,
std::ptr::null_mut(),
0,
)?;
let path = String::from_utf16_lossy( let path = String::from_utf16_lossy(
&path_buffer[..path_buffer.iter().position(|&c| c == 0).unwrap_or(path_buffer.len())] &path_buffer[..path_buffer
.iter()
.position(|&c| c == 0)
.unwrap_or(path_buffer.len())],
); );
Ok(path) Ok(path)
@ -375,11 +388,13 @@ pub fn open_dir_with_explorer(path: &str, is_file: bool) -> anyhow::Result<()> {
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
pub fn open_dir_with_explorer(path: &str, is_file: bool) -> anyhow::Result<()> { pub fn open_dir_with_explorer(path: &str, is_file: bool) -> anyhow::Result<()> {
println!("open_dir_with_explorer (unix): {} is_file={}", path, is_file); println!(
"open_dir_with_explorer (unix): {} is_file={}",
path, is_file
);
Ok(()) Ok(())
} }
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub fn set_foreground_window(window_name: &str) -> anyhow::Result<bool> { pub fn set_foreground_window(window_name: &str) -> anyhow::Result<bool> {
use windows::core::{HSTRING, PCWSTR}; use windows::core::{HSTRING, PCWSTR};
@ -494,7 +509,8 @@ fn get_process_path(pid: u32) -> Option<String> {
use windows::core::PWSTR; use windows::core::PWSTR;
use windows::Win32::Foundation::{CloseHandle, MAX_PATH}; use windows::Win32::Foundation::{CloseHandle, MAX_PATH};
use windows::Win32::System::Threading::{ use windows::Win32::System::Threading::{
OpenProcess, QueryFullProcessImageNameW, PROCESS_NAME_WIN32, PROCESS_QUERY_LIMITED_INFORMATION, OpenProcess, QueryFullProcessImageNameW, PROCESS_NAME_WIN32,
PROCESS_QUERY_LIMITED_INFORMATION,
}; };
unsafe { unsafe {
@ -508,7 +524,10 @@ fn get_process_path(pid: u32) -> Option<String> {
PROCESS_NAME_WIN32, PROCESS_NAME_WIN32,
PWSTR::from_raw(path_buffer.as_mut_ptr()), PWSTR::from_raw(path_buffer.as_mut_ptr()),
&mut path_len, &mut path_len,
).is_ok() && path_len > 0 { )
.is_ok()
&& path_len > 0
{
Some(String::from_utf16_lossy(&path_buffer[..path_len as usize])) Some(String::from_utf16_lossy(&path_buffer[..path_len as usize]))
} else { } else {
None None
@ -563,14 +582,14 @@ pub fn kill_process_by_name(process_name: &str) -> anyhow::Result<u32> {
/// Get disk physical sector size for performance /// Get disk physical sector size for performance
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub fn get_disk_physical_sector_size(drive_letter: &str) -> anyhow::Result<u32> { pub fn get_disk_physical_sector_size(drive_letter: &str) -> anyhow::Result<u32> {
use std::mem;
use windows::core::HSTRING;
use windows::Win32::Foundation::CloseHandle;
use windows::Win32::Storage::FileSystem::{ use windows::Win32::Storage::FileSystem::{
CreateFileW, FILE_SHARE_READ, FILE_SHARE_WRITE, OPEN_EXISTING, CreateFileW, FILE_SHARE_READ, FILE_SHARE_WRITE, OPEN_EXISTING,
}; };
use windows::Win32::System::IO::DeviceIoControl;
use windows::Win32::System::Ioctl::IOCTL_STORAGE_QUERY_PROPERTY; use windows::Win32::System::Ioctl::IOCTL_STORAGE_QUERY_PROPERTY;
use windows::Win32::Foundation::CloseHandle; use windows::Win32::System::IO::DeviceIoControl;
use windows::core::HSTRING;
use std::mem;
// STORAGE_PROPERTY_QUERY structure // STORAGE_PROPERTY_QUERY structure
#[repr(C)] #[repr(C)]
@ -650,28 +669,30 @@ pub fn get_disk_physical_sector_size(drive_letter: &str) -> anyhow::Result<u32>
/// Create a desktop shortcut /// Create a desktop shortcut
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub fn create_desktop_shortcut(target_path: &str, shortcut_name: &str) -> anyhow::Result<()> { pub fn create_desktop_shortcut(target_path: &str, shortcut_name: &str) -> anyhow::Result<()> {
use windows::core::{HSTRING, Interface, BSTR}; use windows::core::{Interface, BSTR, HSTRING};
use windows::Win32::System::Com::{
CoCreateInstance, CoInitializeEx, CoUninitialize,
CLSCTX_INPROC_SERVER, COINIT_APARTMENTTHREADED,
};
use windows::Win32::UI::Shell::{IShellLinkW, ShellLink, SHGetKnownFolderPath, FOLDERID_Desktop};
use windows::Win32::System::Com::IPersistFile; use windows::Win32::System::Com::IPersistFile;
use windows::Win32::System::Com::{
CoCreateInstance, CoInitializeEx, CoUninitialize, CLSCTX_INPROC_SERVER,
COINIT_APARTMENTTHREADED,
};
use windows::Win32::UI::Shell::{
FOLDERID_Desktop, IShellLinkW, SHGetKnownFolderPath, ShellLink,
};
unsafe { unsafe {
let _ = CoInitializeEx(None, COINIT_APARTMENTTHREADED); let _ = CoInitializeEx(None, COINIT_APARTMENTTHREADED);
let result = (|| -> anyhow::Result<()> { let result = (|| -> anyhow::Result<()> {
// Get desktop path // Get desktop path
let desktop_path = SHGetKnownFolderPath(&FOLDERID_Desktop, windows::Win32::UI::Shell::KNOWN_FOLDER_FLAG(0), None)?; let desktop_path = SHGetKnownFolderPath(
&FOLDERID_Desktop,
windows::Win32::UI::Shell::KNOWN_FOLDER_FLAG(0),
None,
)?;
let desktop_str = desktop_path.to_string()?; let desktop_str = desktop_path.to_string()?;
// Create ShellLink instance // Create ShellLink instance
let shell_link: IShellLinkW = CoCreateInstance( let shell_link: IShellLinkW = CoCreateInstance(&ShellLink, None, CLSCTX_INPROC_SERVER)?;
&ShellLink,
None,
CLSCTX_INPROC_SERVER,
)?;
// Set target path // Set target path
let target_w = HSTRING::from(target_path); let target_w = HSTRING::from(target_path);
@ -697,7 +718,10 @@ pub fn create_desktop_shortcut(target_path: &str, shortcut_name: &str) -> anyhow
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
pub fn create_desktop_shortcut(target_path: &str, shortcut_name: &str) -> anyhow::Result<()> { pub fn create_desktop_shortcut(target_path: &str, shortcut_name: &str) -> anyhow::Result<()> {
println!("create_desktop_shortcut (unix): {} -> {}", target_path, shortcut_name); println!(
"create_desktop_shortcut (unix): {} -> {}",
target_path, shortcut_name
);
Ok(()) Ok(())
} }
@ -713,20 +737,16 @@ pub fn run_as_admin(program: &str, args: &str) -> anyhow::Result<()> {
let parameters = HSTRING::from(args); let parameters = HSTRING::from(args);
unsafe { unsafe {
let result = ShellExecuteW( let result = ShellExecuteW(None, &operation, &file, &parameters, None, SW_SHOWNORMAL);
None,
&operation,
&file,
&parameters,
None,
SW_SHOWNORMAL,
);
// ShellExecuteW returns a value > 32 on success // ShellExecuteW returns a value > 32 on success
if result.0 as usize > 32 { if result.0 as usize > 32 {
Ok(()) Ok(())
} else { } else {
Err(anyhow::anyhow!("ShellExecuteW failed with code: {}", result.0 as usize)) Err(anyhow::anyhow!(
"ShellExecuteW failed with code: {}",
result.0 as usize
))
} }
} }
} }
@ -742,9 +762,7 @@ pub fn run_as_admin(program: &str, args: &str) -> anyhow::Result<()> {
pub fn start_process(program: &str, args: Vec<String>) -> anyhow::Result<()> { pub fn start_process(program: &str, args: Vec<String>) -> anyhow::Result<()> {
use std::process::Command; use std::process::Command;
Command::new(program) Command::new(program).args(&args).spawn()?;
.args(&args)
.spawn()?;
Ok(()) Ok(())
} }
@ -764,11 +782,10 @@ const NVME_VALUE_NAME: &str = "ForcedPhysicalSectorSizeInBytes";
/// Check if NVME patch is applied /// Check if NVME patch is applied
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub fn check_nvme_patch_status() -> anyhow::Result<bool> { pub fn check_nvme_patch_status() -> anyhow::Result<bool> {
use windows::Win32::System::Registry::{
RegOpenKeyExW, RegQueryValueExW, RegCloseKey,
HKEY_LOCAL_MACHINE, KEY_READ, REG_VALUE_TYPE,
};
use windows::core::{HSTRING, PCWSTR}; use windows::core::{HSTRING, PCWSTR};
use windows::Win32::System::Registry::{
RegCloseKey, RegOpenKeyExW, RegQueryValueExW, HKEY_LOCAL_MACHINE, KEY_READ, REG_VALUE_TYPE,
};
unsafe { unsafe {
let path = HSTRING::from(NVME_REGISTRY_PATH); let path = HSTRING::from(NVME_REGISTRY_PATH);
@ -781,7 +798,9 @@ pub fn check_nvme_patch_status() -> anyhow::Result<bool> {
Some(0), Some(0),
KEY_READ, KEY_READ,
&mut hkey, &mut hkey,
).is_err() { )
.is_err()
{
return Ok(false); return Ok(false);
} }
@ -798,12 +817,15 @@ pub fn check_nvme_patch_status() -> anyhow::Result<bool> {
Some(&mut value_type), Some(&mut value_type),
Some(buffer.as_mut_ptr()), Some(buffer.as_mut_ptr()),
Some(&mut size), Some(&mut size),
).is_ok() { )
.is_ok()
{
// Check if the value contains "* 4095" // Check if the value contains "* 4095"
// REG_MULTI_SZ is stored as null-terminated wide strings // REG_MULTI_SZ is stored as null-terminated wide strings
let data = String::from_utf16_lossy( let data = String::from_utf16_lossy(std::slice::from_raw_parts(
std::slice::from_raw_parts(buffer.as_ptr() as *const u16, size as usize / 2) buffer.as_ptr() as *const u16,
); size as usize / 2,
));
data.contains("* 4095") data.contains("* 4095")
} else { } else {
false false
@ -822,11 +844,10 @@ pub fn check_nvme_patch_status() -> anyhow::Result<bool> {
/// Add NVME patch to registry /// Add NVME patch to registry
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub fn add_nvme_patch() -> anyhow::Result<()> { pub fn add_nvme_patch() -> anyhow::Result<()> {
use windows::Win32::System::Registry::{
RegOpenKeyExW, RegSetValueExW, RegCloseKey,
HKEY_LOCAL_MACHINE, KEY_WRITE, REG_MULTI_SZ,
};
use windows::core::{HSTRING, PCWSTR}; use windows::core::{HSTRING, PCWSTR};
use windows::Win32::System::Registry::{
RegCloseKey, RegOpenKeyExW, RegSetValueExW, HKEY_LOCAL_MACHINE, KEY_WRITE, REG_MULTI_SZ,
};
unsafe { unsafe {
let path = HSTRING::from(NVME_REGISTRY_PATH); let path = HSTRING::from(NVME_REGISTRY_PATH);
@ -841,7 +862,10 @@ pub fn add_nvme_patch() -> anyhow::Result<()> {
&mut hkey, &mut hkey,
); );
if open_result.is_err() { if open_result.is_err() {
return Err(anyhow::anyhow!("Failed to open registry key: {:?}", open_result)); return Err(anyhow::anyhow!(
"Failed to open registry key: {:?}",
open_result
));
} }
// Prepare the value: "* 4095" as REG_MULTI_SZ (double null terminated) // Prepare the value: "* 4095" as REG_MULTI_SZ (double null terminated)
@ -863,7 +887,10 @@ pub fn add_nvme_patch() -> anyhow::Result<()> {
let _ = RegCloseKey(hkey); let _ = RegCloseKey(hkey);
if result.is_err() { if result.is_err() {
return Err(anyhow::anyhow!("Failed to set registry value: {:?}", result)); return Err(anyhow::anyhow!(
"Failed to set registry value: {:?}",
result
));
} }
Ok(()) Ok(())
} }
@ -877,12 +904,11 @@ pub fn add_nvme_patch() -> anyhow::Result<()> {
/// Remove NVME patch from registry /// Remove NVME patch from registry
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub fn remove_nvme_patch() -> anyhow::Result<()> { pub fn remove_nvme_patch() -> anyhow::Result<()> {
use windows::Win32::System::Registry::{
RegOpenKeyExW, RegDeleteValueW, RegCloseKey,
HKEY_LOCAL_MACHINE, KEY_WRITE,
};
use windows::Win32::Foundation::ERROR_FILE_NOT_FOUND;
use windows::core::{HSTRING, PCWSTR}; use windows::core::{HSTRING, PCWSTR};
use windows::Win32::Foundation::ERROR_FILE_NOT_FOUND;
use windows::Win32::System::Registry::{
RegCloseKey, RegDeleteValueW, RegOpenKeyExW, HKEY_LOCAL_MACHINE, KEY_WRITE,
};
unsafe { unsafe {
let path = HSTRING::from(NVME_REGISTRY_PATH); let path = HSTRING::from(NVME_REGISTRY_PATH);
@ -897,21 +923,24 @@ pub fn remove_nvme_patch() -> anyhow::Result<()> {
&mut hkey, &mut hkey,
); );
if open_result.is_err() { if open_result.is_err() {
return Err(anyhow::anyhow!("Failed to open registry key: {:?}", open_result)); return Err(anyhow::anyhow!(
"Failed to open registry key: {:?}",
open_result
));
} }
let value_name = HSTRING::from(NVME_VALUE_NAME); let value_name = HSTRING::from(NVME_VALUE_NAME);
let result = RegDeleteValueW( let result = RegDeleteValueW(hkey, PCWSTR(value_name.as_ptr()));
hkey,
PCWSTR(value_name.as_ptr()),
);
let _ = RegCloseKey(hkey); let _ = RegCloseKey(hkey);
// It's OK if the value doesn't exist // It's OK if the value doesn't exist
if result.is_err() && result != ERROR_FILE_NOT_FOUND { if result.is_err() && result != ERROR_FILE_NOT_FOUND {
return Err(anyhow::anyhow!("Failed to delete registry value: {:?}", result)); return Err(anyhow::anyhow!(
"Failed to delete registry value: {:?}",
result
));
} }
Ok(()) Ok(())