Skip to content

Commit

Permalink
Add Windows shell sample illustrating VARIANT support (#2789)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr authored Jan 12, 2024
1 parent f3b9ca3 commit 8eeb18e
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 1 deletion.
1 change: 1 addition & 0 deletions .github/workflows/clippy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ jobs:
cargo clippy -p sample_privileges &&
cargo clippy -p sample_privileges_sys &&
cargo clippy -p sample_rss &&
cargo clippy -p sample_shell &&
cargo clippy -p sample_simple &&
cargo clippy -p sample_spellchecker &&
cargo clippy -p sample_thread_pool_work &&
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ jobs:
cargo test -p sample_privileges &&
cargo test -p sample_privileges_sys &&
cargo test -p sample_rss &&
cargo test -p sample_shell &&
cargo test -p sample_simple &&
cargo test -p sample_spellchecker &&
cargo test -p sample_thread_pool_work &&
Expand Down Expand Up @@ -100,8 +101,8 @@ jobs:
cargo test -p test_enums &&
cargo test -p test_error &&
cargo test -p test_event &&
cargo test -p test_extensions &&
cargo clean &&
cargo test -p test_extensions &&
cargo test -p test_handles &&
cargo test -p test_helpers &&
cargo test -p test_implement &&
Expand Down
12 changes: 12 additions & 0 deletions crates/libs/core/src/variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,18 @@ impl From<BSTR> for PROPVARIANT {
}
}

impl From<&str> for VARIANT {
fn from(value: &str) -> Self {
BSTR::from(value).into()
}
}

impl From<&str> for PROPVARIANT {
fn from(value: &str) -> Self {
BSTR::from(value).into()
}
}

impl TryFrom<&VARIANT> for BSTR {
type Error = Error;
fn try_from(from: &VARIANT) -> Result<Self> {
Expand Down
14 changes: 14 additions & 0 deletions crates/samples/windows/shell/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "sample_shell"
version = "0.0.0"
edition = "2021"
publish = false

[dependencies.windows]
path = "../../../libs/windows"
features = [
"Win32_System_Com",
"Win32_System_Ole",
"Win32_UI_Shell",
"Win32_UI_WindowsAndMessaging",
]
63 changes: 63 additions & 0 deletions crates/samples/windows/shell/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use windows::{
core::*, Win32::System::Com::*, Win32::UI::Shell::*, Win32::UI::WindowsAndMessaging::*,
};

fn main() -> Result<()> {
unsafe { CoInitialize(None)? };

shell_execute_from_explorer(
"https://github.com/microsoft/windows-rs",
"",
"",
"",
SW_SHOWNORMAL,
)
}

// Ported from https://devblogs.microsoft.com/oldnewthing/20131118-00/?p=2643
fn shell_execute_from_explorer(
file: &str,
args: &str,
directory: &str,
operation: &str,
show: SHOW_WINDOW_CMD,
) -> Result<()> {
unsafe {
let view: IShellView = find_desktop_folder_view()?;
let background: IDispatch = view.GetItemObject(SVGIO_BACKGROUND)?;
let folder: IShellFolderViewDual = background.cast()?;
let shell: IShellDispatch2 = folder.Application()?.cast()?;

shell.ShellExecute(
&BSTR::from(file),
&VARIANT::from(args),
&VARIANT::from(directory),
&VARIANT::from(operation),
&VARIANT::from(show.0),
)
}
}

// Ported from https://devblogs.microsoft.com/oldnewthing/20130318-00/?p=4933
fn find_desktop_folder_view<T: Interface>() -> Result<T> {
unsafe {
let windows: IShellWindows = CoCreateInstance(&ShellWindows, None, CLSCTX_ALL)?;
let mut dispatch = None;
let mut handle = 0;

// TODO: find out why this retval isn't kicking in
windows.FindWindowSW(
&VARIANT::from(CSIDL_DESKTOP),
&VARIANT::default(),
SWC_DESKTOP,
&mut handle,
SWFO_NEEDDISPATCH,
&mut dispatch,
)?;

let provider: IServiceProvider = dispatch.unwrap().cast()?;
let browser: IShellBrowser = provider.QueryService(&SID_STopLevelBrowser)?;
let view = browser.QueryActiveShellView()?;
view.cast()
}
}
10 changes: 10 additions & 0 deletions crates/tests/variant/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ fn test_variant() -> Result<()> {
VARIANT::from(BSTR::from("goodbye"))
);

let v = VARIANT::from("hello");
assert_eq!(BSTR::try_from(&v)?, "hello");
assert_eq!(VARIANT::from("hello"), VARIANT::from("hello"));
assert_ne!(VARIANT::from("hello"), VARIANT::from("goodbye"));

let v = VARIANT::from(3.5f64);
assert_eq!(BSTR::try_from(&v)?, "3.5");

Expand Down Expand Up @@ -205,6 +210,11 @@ fn test_propvariant() -> Result<()> {
PROPVARIANT::from(BSTR::from("goodbye"))
);

let v = PROPVARIANT::from("hello");
assert_eq!(BSTR::try_from(&v)?, "hello");
assert_eq!(PROPVARIANT::from("hello"), PROPVARIANT::from("hello"));
assert_ne!(PROPVARIANT::from("hello"), PROPVARIANT::from("goodbye"));

let v = PROPVARIANT::from(3.5f64);
assert_eq!(BSTR::try_from(&v)?, "3.5");

Expand Down

0 comments on commit 8eeb18e

Please sign in to comment.