美文网首页
Rust实战——注册表之自定义Windows11任务栏位置(下)

Rust实战——注册表之自定义Windows11任务栏位置(下)

作者: L我是小学生 | 来源:发表于2021-10-13 07:39 被阅读0次

    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注册表】获取源码。

    相关文章

      网友评论

          本文标题:Rust实战——注册表之自定义Windows11任务栏位置(下)

          本文链接:https://www.haomeiwen.com/subject/nyrsoltx.html