I'm using the IDesktopWallpaper::SetWallpaper
method from the windows crate. The second argument to this method is a PCWSTR
(pointer) to the full path of an image that's meant to be set as the wallpaper. The problem is that the PCWSTR
object is meant to be of type *const u16
not *const String
. How can I get a PCWSTR
object from a Path/String?
let path = "Path_to_image.jpg".to_string();
let ptr = &path as *const String;
let wallpaper = PCWSTR::from_raw(ptr);
// ^^^ expected raw pointer `*const u16`
// found raw pointer `*const String`
unsafe { desktop.SetWallpaper(None, wallpaper)};
Regarding strings, Rust and Windows couldn't possibly disagree more. There are always going to be conversions involved when using Rust on Windows, and the best you can hope for is a crate that does this for you.
The windows crate doesn't just provide Rust mappings for Windows' API surface, it also contains a tiny library that addresses common issues when programming Windows with Rust, amongst which is string handling. A lot of thought went into string handling, and the result may seem somewhat anticlimactic: All string constants can be represented as HSTRING
instances.
Consequently, HSTRING
is the pivot point for string conversions in Rust for Windows. Its implementation has a sleuth of From
trait implementations for Rust string types (all, I believe), with From
implementations of all other Windows string types for HSTRING
.
In this case, if path
is of type Path
, you can construct an HSTRING
from it and pass it by reference. Everything else happens due to implicit From
trait invocations (namely From<&HSTRING> for PCWSTR
):
unsafe { desktop.SetWallpaper(None, &HSTRING::from(path.as_os_str())) };
v0.44.0 (released 2023-01-12) introduced an impl From<&Path> for HSTRING
, allowing us to further simplify the code:
unsafe { desktop.SetWallpaper(None, &HSTRING::from(&path)) };
This is purely for convenience. Internally, From<&Path>
calls as_os_str()
on our behalf and subsequently delegates to the From<&OsStr>
implementation.