使用windows crate调用Windows API读取注册表键时出现参数错误
解决Rust调用Windows API读取注册表时的0x80070057参数错误
你遇到的0x80070057(参数不正确)错误,直接原因是第二次调用RegGetValueW时违反了Windows API的参数规则:当传入数据缓冲区(lpData参数)时,必须同时传入缓冲区的大小指针(lpcbData参数),API需要通过这个参数确认缓冲区容量,否则会返回参数错误。
你的代码中第二次调用RegGetValueW时最后一个参数传的是None,这就是问题的核心。
修正后的代码
use std::alloc::{alloc, dealloc, Layout}; use windows::Win32::System::Registry::{RegGetValueW, HKEY, REG_ROUTINE_FLAGS}; use windows::core::{HSTRING, PCWSTR, Error}; use std::os::raw::c_void; pub fn get_registry_key<'a>(hkey: HKEY, subkey: &'a str, key: &'a str, flags: REG_ROUTINE_FLAGS) -> Result<(*mut c_void, u32), Error> { unsafe { let mut data_length: u32 = 0; let subkey_hstring = HSTRING::from(subkey); let key_hstring = HSTRING::from(key); // 第一次调用获取数据长度 RegGetValueW( hkey, PCWSTR(subkey_hstring.as_ptr()), PCWSTR(key_hstring.as_ptr()), flags, None, None, Some(&mut data_length), )?; println!("Length: {}", data_length); // 分配内存,使用4字节对齐适配多数注册表数据类型(如REG_DWORD、REG_SZ等) let layout = Layout::from_size_align(data_length as usize, 4).unwrap(); let data = alloc(layout) as *mut c_void; // 第二次调用必须传入数据缓冲区和长度指针 RegGetValueW( hkey, PCWSTR(subkey_hstring.as_ptr()), PCWSTR(key_hstring.as_ptr()), flags, None, Some(data), Some(&mut data_length), // 此处不能为None )?; // 返回数据指针和实际写入的长度,方便后续处理与内存释放 Ok((data, data_length)) } } // 使用示例(记得手动释放内存): // fn main() -> Result<(), Error> { // let (data, len) = get_registry_key(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductName", REG_ROUTINE_FLAGS(0))?; // // 处理数据... // unsafe { dealloc(data as *mut u8, Layout::from_size_align(len as usize, 4).unwrap()); } // Ok(()) // }
关键说明
- 参数约束:
RegGetValueW明确规定,若lpData不为空,lpcbData必须指向一个DWORD变量,用于传入缓冲区大小并接收实际写入的数据长度。 - 内存对齐:将内存对齐值从1改为4,适配注册表常见数据类型的对齐要求,避免潜在的未定义行为。
- 内存安全:函数返回数据指针后,需要手动调用
dealloc释放内存,否则会造成内存泄漏。
内容的提问来源于stack exchange,提问作者nrp
相关产品推荐
相关产品推荐

