0x00 写在前面的话
上节课了解了使用Rust才操作注册表的一些常用方法,这节课我们就用这些方法来实现“Windows11自定义任务栏位置”这个小工具。
0x01 &str转LPCWSTR
上节介绍的方法中,所有参数都存在的一个LPCWSTR
类型的参数。我们看源码可知,LPWSTR
类型其实就是WCHAR
类型的指针。WCHAR
又是wchar_t
类型,再继续看发现wchar_t
原来就是一个无符号16位整数了。(下面内容截取自源码)
pub type LPCWSTR = *const WCHAR;
pub type WCHAR = wchar_t;
pub type wchar_t = u16;
其实这也是winapi
里面带W
方法所常用的Unicode
编码类型了。那我们如何将&str
类型转为所需的LPCWSTR
类型呢。这就需要借助Rust提供的OsStr
类型了。转换代码如下:
unsafe fn str_to_lpcwstr(str: &str) -> Vec<u16> {
let result: Vec<u16> = OsStr::new(str).encode_wide().chain(once(0)).collect();
return result;
}
具体原理可以参见这篇来自知乎的文章“https://zhuanlan.zhihu.com/p/367190469”。这篇文章介绍的比较详细了,我在这里就不再赘述了。
0x02 封装注册表操作方法
为了便于操作注册表,在这里对相应的方法简单封装下。
打开注册表
/// 打开注册表
/// [`main_hkey`] 是一个HKEY值,默认接收[`HKEY_CURRENT_USER`]等值
/// [`sub_key`] HKEY的子健
/// # Examples
/// Basic usage:
/// ```
/// let sub_key = "Software\\360\\333";
/// let hkey_result = reg_util::reg_open(HKEY_CURRENT_USER, sub_key);
/// ```
pub(crate) fn reg_open(main_hkey: HKEY, sub_key: &str) -> Result<HKEY, String> {
unsafe {
let mut hkey: HKEY = null_mut();
let status = RegOpenKeyW(main_hkey,
str_to_lpcwstr(sub_key).as_ptr(),
&mut hkey);
if status == SEC_E_OK {
return Result::Ok(hkey);
}
return Result::Err(format!("status == {}", status));
}
}
查询REG_BINARY的值
/// 查询注册表的REG_BINARY的值
pub(crate) fn reg_query_binary(hkey: &HKEY, key_name: &str) -> Vec<u8> {
unsafe {
let mut dword: DWORD = 0;
let mut dtype: DWORD = 0;
//查询
let status = RegQueryValueExW(*hkey,
str_to_lpcwstr(key_name).as_ptr(),
null_mut(),
&mut dtype,
null_mut(),
&mut dword);
let mut data_binary: Vec<u8> = vec![0; dword as usize];
if status == SEC_E_OK {
// 存在值
RegQueryValueExW(*hkey,
str_to_lpcwstr(key_name).as_ptr(),
null_mut(),
&mut dtype,
data_binary.as_mut_ptr(),
&mut dword);
}
return data_binary;
}
}
保存REG_SZ类型的数据
/// 保存REG_SZ类型的数据
pub(crate) fn reg_save_binary(hkey: &HKEY, key_name: &str, value: &mut Vec<u8>) -> LSTATUS {
unsafe {
let status = RegSetValueExW(*hkey,
str_to_lpcwstr(key_name).as_ptr(),
0,
REG_BINARY,
value.as_mut_ptr(),
value.len() as u32);
return status;
}
}
0x03 开始编写小工具
打开注册表
首先,我们先打开相应的注册表。
const SUB_KEY: &str = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StuckRects3";
// 打开注册表
let hkey_result = reg_util::reg_open(HKEY_CURRENT_USER, SUB_KEY);
如果打开成功。我们再去查询当前的值。
查询注册表
我们即将查找的注册表是二进制值,判断第12个数据,如果是0x00 则表示左,0x01 则表示上,0x02 则表示右,0x03 则表示下。
let mut reg_value = reg_util::reg_query_binary(&hkey, ITEM_KEY);
let position_option = reg_value.get(12);
match position_option {
Some(LEFT) => {
println!("【当前任务栏的位置在屏幕左侧!】");
}
Some(RIGHT) => {
println!("【当前任务栏的位置在屏幕右侧!】");
}
Some(UP) => {
println!("【当前任务栏的位置在屏幕上方!】");
}
Some(DOWN) => {
println!("【当前任务栏的位置在屏幕下方!】");
}
Some(_) => {
println!("【读取任务栏的位置失败!UNKNOWN】");
return;
}
None => {
println!("【读取任务栏的位置失败!NONE】");
return;
}
}
修改注册表
我们接收键盘输入的数字,来修改注册表的值。这里仅接收0,1,2,3四个值。
let position = input_task_bar_position();
if position > 3 {
println!("输入错误!");
return;
}
// 正确输入,构建二进制值
reg_value[12] = position;
// 保存注册表
let status = reg_util::reg_save_binary(&hkey, ITEM_KEY, &mut reg_value);
if status == SEC_E_OK {
println!("修改成功!正在重启资源管理器......");
reboot_explorer();
println!("重启资源管理器成功!");
exit(0);
} else {
println!("修改失败!");
}
0x04 小结
至此,整个小工具就结束了。其实这里仅仅借此小工具来练习下使用Rust操作注册表。其实只要掌握如何使用Rust操作注册表的基本技巧,你们windows注册表的各种设置都不在话下了。
0x05 源码
关注公众号:《Rust学习日记》回复:【win11注册表】获取源码。
网友评论