diff --git a/crates/libs/core/src/lib.rs b/crates/libs/core/src/lib.rs index 25708a4c6d..9b0579e189 100644 --- a/crates/libs/core/src/lib.rs +++ b/crates/libs/core/src/lib.rs @@ -8,7 +8,7 @@ Learn more about Rust for Windows here: >(&self, path: T) -> Result { let mut handle = core::ptr::null_mut(); - let result = - unsafe { RegOpenKeyExW(self.0, pcwstr(path).as_ptr(), 0, KEY_READ, &mut handle) }; + let result = unsafe { + RegOpenKeyExW( + self.0, + encode_utf16(path).as_ptr(), + 0, + KEY_READ, + &mut handle, + ) + }; win32_error(result).map(|_| Self(handle)) } @@ -61,13 +68,13 @@ impl Key { /// Removes the registry keys and values of the specified key recursively. pub fn remove_tree>(&self, path: T) -> Result<()> { - let result = unsafe { RegDeleteTreeW(self.0, pcwstr(path).as_ptr()) }; + let result = unsafe { RegDeleteTreeW(self.0, encode_utf16(path).as_ptr()) }; win32_error(result) } /// Removes the registry value. pub fn remove_value>(&self, name: T) -> Result<()> { - let result = unsafe { RegDeleteValueW(self.0, pcwstr(name).as_ptr()) }; + let result = unsafe { RegDeleteValueW(self.0, encode_utf16(name).as_ptr()) }; win32_error(result) } @@ -93,7 +100,7 @@ impl Key { /// Sets the name and value in the registry key. pub fn set_string>(&self, name: T, value: T) -> Result<()> { - let value = pcwstr(value); + let value = encode_utf16(value); unsafe { self.set_value(name, REG_SZ, value.as_ptr() as _, value.len() * 2) } } @@ -101,7 +108,7 @@ impl Key { /// Sets the name and value in the registry key. pub fn set_multi_string>(&self, name: T, value: &[T]) -> Result<()> { let mut packed = value.iter().fold(vec![0u16; 0], |mut packed, value| { - packed.append(&mut pcwstr(value)); + packed.append(&mut encode_utf16(value)); packed }); @@ -117,7 +124,7 @@ impl Key { /// Gets the type for the name in the registry key. pub fn get_type>(&self, name: T) -> Result { - let name = pcwstr(name); + let name = encode_utf16(name); let mut ty = 0; let result = unsafe { @@ -145,7 +152,7 @@ impl Key { /// Gets the value for the name in the registry key. pub fn get_value>(&self, name: T) -> Result { - let name = pcwstr(name); + let name = encode_utf16(name); let mut ty = 0; let mut len = 0; @@ -280,7 +287,7 @@ impl Key { /// Gets the value for the name in the registry key. pub fn get_bytes>(&self, name: T) -> Result> { - let name = pcwstr(name); + let name = encode_utf16(name); let mut len = 0; let result = unsafe { @@ -320,6 +327,48 @@ impl Key { } } + /// Sets the name and value in the registry key. + #[cfg(feature = "std")] + pub fn set_os_string, V: AsRef>( + &self, + name: N, + value: V, + ) -> Result<()> { + let value = encode_wide(value); + + unsafe { self.set_value(name, REG_SZ, value.as_ptr() as _, value.len() * 2) } + } + + /// Gets the value for the name in the registry key. + #[cfg(feature = "std")] + pub fn get_os_string>(&self, name: T) -> Result { + let name = encode_utf16(name); + let mut ty = 0; + let mut len = 0; + + let result = unsafe { + RegQueryValueExW(self.0, name.as_ptr(), null(), &mut ty, null_mut(), &mut len) + }; + + win32_error(result)?; + let mut value = vec![0u16; len as usize / 2]; + + let result = unsafe { + RegQueryValueExW( + self.0, + name.as_ptr(), + null(), + null_mut(), + value.as_mut_ptr() as _, + &mut len, + ) + }; + + win32_error(result)?; + use std::os::windows::prelude::*; + Ok(std::ffi::OsString::from_wide(trim(&value))) + } + unsafe fn set_value>( &self, name: T, @@ -327,7 +376,14 @@ impl Key { ptr: *const u8, len: usize, ) -> Result<()> { - let result = RegSetValueExW(self.0, pcwstr(name).as_ptr(), 0, ty, ptr, len.try_into()?); + let result = RegSetValueExW( + self.0, + encode_utf16(name).as_ptr(), + 0, + ty, + ptr, + len.try_into()?, + ); win32_error(result) } diff --git a/crates/libs/registry/src/lib.rs b/crates/libs/registry/src/lib.rs index 1d11207d5d..04eb095003 100644 --- a/crates/libs/registry/src/lib.rs +++ b/crates/libs/registry/src/lib.rs @@ -2,7 +2,7 @@ Learn more about Rust for Windows here: */ -#![cfg_attr(not(test), no_std)] +#![cfg_attr(all(not(feature = "std")), no_std)] #[macro_use] extern crate alloc; @@ -45,7 +45,7 @@ pub const LOCAL_MACHINE: &Key = &Key(HKEY_LOCAL_MACHINE); /// The predefined `HKEY_USERS` registry key. pub const USERS: &Key = &Key(HKEY_USERS); -fn pcwstr>(value: T) -> Vec { +fn encode_utf16>(value: T) -> Vec { value .as_ref() .encode_utf16() @@ -53,6 +53,16 @@ fn pcwstr>(value: T) -> Vec { .collect() } +#[cfg(feature = "std")] +fn encode_wide>(value: T) -> Vec { + use std::os::windows::prelude::*; + value + .as_ref() + .encode_wide() + .chain(core::iter::once(0)) + .collect() +} + fn trim(mut value: &[u16]) -> &[u16] { while value.last() == Some(&0) { value = &value[..value.len() - 1]; diff --git a/crates/libs/result/Cargo.toml b/crates/libs/result/Cargo.toml index a255606833..f553397c3c 100644 --- a/crates/libs/result/Cargo.toml +++ b/crates/libs/result/Cargo.toml @@ -9,7 +9,6 @@ description = "Windows error handling" repository = "https://github.com/microsoft/windows-rs" readme = "readme.md" categories = ["os::windows-apis"] -exclude = ["tests"] [features] default = ["std"] diff --git a/crates/libs/result/src/lib.rs b/crates/libs/result/src/lib.rs index df5cd6d97f..8eb6ddbeeb 100644 --- a/crates/libs/result/src/lib.rs +++ b/crates/libs/result/src/lib.rs @@ -6,7 +6,7 @@ Learn more about Rust for Windows here: */ -#![cfg_attr(not(test), no_std)] +#![no_std] mod bindings; use bindings::*; diff --git a/crates/tests/registry/tests/bad_string.rs b/crates/tests/registry/tests/bad_string.rs index 412d8c33a4..a070adce66 100644 --- a/crates/tests/registry/tests/bad_string.rs +++ b/crates/tests/registry/tests/bad_string.rs @@ -32,5 +32,9 @@ fn bad_string() -> Result<()> { let value_as_bytes = key.get_bytes("name")?; assert_eq!(value_as_bytes, bad_string_bytes); + + let value_as_os_string = key.get_os_string("name")?; + assert_eq!(value_as_os_string.to_string_lossy(), "�ā"); + Ok(()) } diff --git a/crates/tests/registry/tests/values.rs b/crates/tests/registry/tests/values.rs index d78256d3b4..ff3022d7d2 100644 --- a/crates/tests/registry/tests/values.rs +++ b/crates/tests/registry/tests/values.rs @@ -10,12 +10,14 @@ fn values() -> Result<()> { key.set_u32("u32", 123)?; key.set_u64("u64", 456)?; key.set_string("string", "hello")?; + key.set_os_string("os_string", "hello os")?; key.set_bytes("bytes", &[1u8, 2u8, 2u8])?; key.set_multi_string("multi", &["hello", "world"])?; assert_eq!(key.get_u32("u32")?, 123u32); assert_eq!(key.get_u64("u64")?, 456u64); assert_eq!(key.get_string("string")?, "hello".to_string()); + assert_eq!(&key.get_os_string("os_string")?, "hello os"); assert_eq!(key.get_bytes("bytes")?, vec![1u8, 2u8, 2u8]); assert_eq!( key.get_multi_string("multi")?, @@ -43,6 +45,10 @@ fn values() -> Result<()> { ("u32".to_string(), Value::U32(123)), ("u64".to_string(), Value::U64(456)), ("string".to_string(), Value::String("hello".to_string())), + ( + "os_string".to_string(), + Value::String("hello os".to_string()) + ), ("bytes".to_string(), Value::Bytes(vec![1u8, 2u8, 2u8])), ( "multi".to_string(), @@ -52,6 +58,7 @@ fn values() -> Result<()> { ); key.remove_value("string")?; + key.remove_value("os_string")?; key.remove_value("multi")?; let names: Vec<_> = key.values()?.collect();