You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
use std::ffi::OsString;use std::os::windows::ffi::OsStringExt;use std::path::PathBuf;use winreg::enums::HKEY_CURRENT_USER;use winreg::RegKey;fnmain(){let base = RegKey::predef(HKEY_CURRENT_USER);let desktop = base.open_subkey(r#"Control Panel\Desktop"#).unwrap();// read using OsStringlet wallpaper:OsString = desktop.get_value("WallPaper").unwrap();let path = PathBuf::from(wallpaper);println!("Wallpaper exists? {}, path is {:?}", path.exists(), path);// read using Stringlet wallpaper:String = desktop.get_value("WallPaper").unwrap();let path = PathBuf::from(wallpaper);println!("Wallpaper exists? {}, path is {:?}", path.exists(), path);// read manuallylet wallpaper = desktop.get_raw_value("WallPaper").unwrap();letmut raw:Vec<u16> = wallpaper
.bytes.chunks_exact(2).into_iter().map(|c| u16::from_le_bytes([c[0], c[1]])).collect();while raw.ends_with(&[0]){
raw.pop();}let path = PathBuf::from(OsString::from_wide(&raw));println!("Wallpaper exists? {}, path is {:?}", path.exists(), path);}
On my machine this prints:
Wallpaper exists? false, path is "C:\\Users\\X\\AppData\\Local\\Packages\\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\\LocalState\\Assets\\0659d89079d32d12eab382d73089f7997f00ee80d8d6c053dc879e956600804b\u{0}"
Wallpaper exists? true, path is "C:\\Users\\X\\AppData\\Local\\Packages\\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\\LocalState\\Assets\\0659d89079d32d12eab382d73089f7997f00ee80d8d6c053dc879e956600804b"
Wallpaper exists? true, path is "C:\\Users\\X\\AppData\\Local\\Packages\\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\\LocalState\\Assets\\0659d89079d32d12eab382d73089f7997f00ee80d8d6c053dc879e956600804b"
(these may all print false on your machine as internally it caches elsewhere; I just needed a simpler repro)
The null terminator on the OsString causes the PathBuf to have a path to a non-existent file. As a result, I have to choose between using a String (lossy if Unicode is ill-formed) or manually turning the registry's bytes into an OsString (lossless but complex, not sure my method is 100% correct).
OsString and OsStr bridge this gap by simultaneously representing Rust and platform-native string values, and in particular allowing a Rust string to be converted into an "OS" string with no cost if possible. A consequence of this is that OsString instances are not NUL terminated; in order to pass to e.g., Unix system call, you should create a CStr.
The text was updated successfully, but these errors were encountered:
I specifically intended OsString to be NUL terminated and be a replacement for CString, which cannot be used with WinAPI functions because they use UTF-16. widestring crate could probably be used for that but that's an additional dependency. And I also haven't found any clean way to get rid of NULs in OsString. Seems like they're not intended to be editable.
Example code:
On my machine this prints:
(these may all print false on your machine as internally it caches elsewhere; I just needed a simpler repro)
The null terminator on the OsString causes the PathBuf to have a path to a non-existent file. As a result, I have to choose between using a String (lossy if Unicode is ill-formed) or manually turning the registry's bytes into an OsString (lossless but complex, not sure my method is 100% correct).
From the OsString docs:
The text was updated successfully, but these errors were encountered: