Skip to content

Commit

Permalink
Support additional VARIANT types (#2892)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr authored Feb 27, 2024
1 parent cf65494 commit 380df19
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 1 deletion.
1 change: 1 addition & 0 deletions crates/libs/bindgen/src/rust/extensions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub fn gen_mod(writer: &Writer, namespace: &str) -> TokenStream {
"Windows.Win32.Foundation" => concat!(include_str!("mod/Win32/Foundation/BOOL.rs"), include_str!("mod/Win32/Foundation/BOOLEAN.rs"), include_str!("mod/Win32/Foundation/NTSTATUS.rs"), include_str!("mod/Win32/Foundation/VARIANT_BOOL.rs"), include_str!("mod/Win32/Foundation/WIN32_ERROR.rs"),),
"Windows.Win32.Networking.WinSock" => concat!(include_str!("mod/Win32/Networking/WinSock/IN_ADDR.rs"), include_str!("mod/Win32/Networking/WinSock/IN6_ADDR.rs"), include_str!("mod/Win32/Networking/WinSock/SOCKADDR_IN.rs"), include_str!("mod/Win32/Networking/WinSock/SOCKADDR_IN6.rs"), include_str!("mod/Win32/Networking/WinSock/SOCKADDR_INET.rs"),),
"Windows.Win32.System.Rpc" => include_str!("mod/Win32/System/Rpc/RPC_STATUS.rs"),
"Windows.Win32.System.Com" => include_str!("mod/Win32/System/Com/IDispatch.rs"),
"Windows.Win32.UI.WindowsAndMessaging" => {
include_str!("mod/Win32/UI/WindowsAndMessaging/WindowLong.rs")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
impl From<IDispatch> for ::windows_core::VARIANT {
fn from(value: IDispatch) -> Self {
unsafe {
Self::from_raw(::windows_core::imp::VARIANT {
Anonymous: ::windows_core::imp::VARIANT_0 {
Anonymous: ::windows_core::imp::VARIANT_0_0 {
vt: 9,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: ::windows_core::imp::VARIANT_0_0_0 { pdispVal: ::std::mem::transmute(value) },
},
},
})
}
}
}

impl From<IDispatch> for ::windows_core::PROPVARIANT {
fn from(value: IDispatch) -> Self {
unsafe {
Self::from_raw(::windows_core::imp::PROPVARIANT {
Anonymous: ::windows_core::imp::PROPVARIANT_0 {
Anonymous: ::windows_core::imp::PROPVARIANT_0_0 {
vt: 9,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: ::windows_core::imp::PROPVARIANT_0_0_0 { pdispVal: ::std::mem::transmute(value) },
},
},
})
}
}
}

impl TryFrom<&::windows_core::VARIANT> for IDispatch {
type Error = ::windows_core::Error;
fn try_from(from: &::windows_core::VARIANT) -> ::windows_core::Result<Self> {
let from = from.as_raw();
unsafe {
if from.Anonymous.Anonymous.vt == 9 && !from.Anonymous.Anonymous.Anonymous.pdispVal.is_null() {
let dispatch: &IDispatch = std::mem::transmute(&from.Anonymous.Anonymous.Anonymous.pdispVal);
Ok(dispatch.clone())
} else {
Err(::windows_core::Error::from_hresult(::windows_core::imp::TYPE_E_TYPEMISMATCH))
}
}
}
}

impl TryFrom<&::windows_core::PROPVARIANT> for IDispatch {
type Error = ::windows_core::Error;
fn try_from(from: &::windows_core::PROPVARIANT) -> ::windows_core::Result<Self> {
let from = from.as_raw();
unsafe {
if from.Anonymous.Anonymous.vt == 9 && !from.Anonymous.Anonymous.Anonymous.pdispVal.is_null() {
let dispatch: &IDispatch = std::mem::transmute(&from.Anonymous.Anonymous.Anonymous.pdispVal);
Ok(dispatch.clone())
} else {
Err(::windows_core::Error::from_hresult(::windows_core::imp::TYPE_E_TYPEMISMATCH))
}
}
}
}
28 changes: 28 additions & 0 deletions crates/libs/core/src/variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,20 @@ impl VARIANT {
pub const fn is_empty(&self) -> bool {
unsafe { self.0.Anonymous.Anonymous.vt == imp::VT_EMPTY }
}

/// Creates a `VARIANT` by taking ownership of the raw data.
///
/// # Safety
///
/// The raw data must be owned by the caller and represent a valid `VARIANT` data structure.
pub unsafe fn from_raw(raw: imp::VARIANT) -> Self {
Self(raw)
}

/// Returns the underlying raw data for the `VARIANT`.
pub fn as_raw(&self) -> &imp::VARIANT {
&self.0
}
}

impl PROPVARIANT {
Expand All @@ -157,6 +171,20 @@ impl PROPVARIANT {
pub const fn is_empty(&self) -> bool {
unsafe { self.0.Anonymous.Anonymous.vt == imp::VT_EMPTY }
}

/// Creates a `PROPVARIANT` by taking ownership of the raw data.
///
/// # Safety
///
/// The raw data must be owned by the caller and represent a valid `PROPVARIANT` data structure.
pub unsafe fn from_raw(raw: imp::PROPVARIANT) -> Self {
Self(raw)
}

/// Returns the underlying raw data for the `PROPVARIANT`.
pub fn as_raw(&self) -> &imp::PROPVARIANT {
&self.0
}
}

impl TryFrom<&VARIANT> for PROPVARIANT {
Expand Down
53 changes: 53 additions & 0 deletions crates/libs/windows/src/Windows/Win32/System/Com/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8137,5 +8137,58 @@ pub type LPEXCEPFINO_DEFERRED_FILLIN = ::core::option::Option<unsafe extern "sys
pub type LPFNCANUNLOADNOW = ::core::option::Option<unsafe extern "system" fn() -> ::windows_core::HRESULT>;
pub type LPFNGETCLASSOBJECT = ::core::option::Option<unsafe extern "system" fn(param0: *const ::windows_core::GUID, param1: *const ::windows_core::GUID, param2: *mut *mut ::core::ffi::c_void) -> ::windows_core::HRESULT>;
pub type PFNCONTEXTCALL = ::core::option::Option<unsafe extern "system" fn(pparam: *mut ComCallData) -> ::windows_core::HRESULT>;
impl From<IDispatch> for ::windows_core::VARIANT {
fn from(value: IDispatch) -> Self {
unsafe {
Self::from_raw(::windows_core::imp::VARIANT {
Anonymous: ::windows_core::imp::VARIANT_0 {
Anonymous: ::windows_core::imp::VARIANT_0_0 { vt: 9, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: ::windows_core::imp::VARIANT_0_0_0 { pdispVal: ::std::mem::transmute(value) } },
},
})
}
}
}

impl From<IDispatch> for ::windows_core::PROPVARIANT {
fn from(value: IDispatch) -> Self {
unsafe {
Self::from_raw(::windows_core::imp::PROPVARIANT {
Anonymous: ::windows_core::imp::PROPVARIANT_0 {
Anonymous: ::windows_core::imp::PROPVARIANT_0_0 { vt: 9, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: ::windows_core::imp::PROPVARIANT_0_0_0 { pdispVal: ::std::mem::transmute(value) } },
},
})
}
}
}

impl TryFrom<&::windows_core::VARIANT> for IDispatch {
type Error = ::windows_core::Error;
fn try_from(from: &::windows_core::VARIANT) -> ::windows_core::Result<Self> {
let from = from.as_raw();
unsafe {
if from.Anonymous.Anonymous.vt == 9 && !from.Anonymous.Anonymous.Anonymous.pdispVal.is_null() {
let dispatch: &IDispatch = std::mem::transmute(&from.Anonymous.Anonymous.Anonymous.pdispVal);
Ok(dispatch.clone())
} else {
Err(::windows_core::Error::from_hresult(::windows_core::imp::TYPE_E_TYPEMISMATCH))
}
}
}
}

impl TryFrom<&::windows_core::PROPVARIANT> for IDispatch {
type Error = ::windows_core::Error;
fn try_from(from: &::windows_core::PROPVARIANT) -> ::windows_core::Result<Self> {
let from = from.as_raw();
unsafe {
if from.Anonymous.Anonymous.vt == 9 && !from.Anonymous.Anonymous.Anonymous.pdispVal.is_null() {
let dispatch: &IDispatch = std::mem::transmute(&from.Anonymous.Anonymous.Anonymous.pdispVal);
Ok(dispatch.clone())
} else {
Err(::windows_core::Error::from_hresult(::windows_core::imp::TYPE_E_TYPEMISMATCH))
}
}
}
}
#[cfg(feature = "implement")]
::core::include!("impl.rs");
1 change: 1 addition & 0 deletions crates/tests/variant/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ path = "../../libs/windows"
features = [
"Foundation",
"Win32_Foundation",
"Win32_System_Com_Events",
]
33 changes: 32 additions & 1 deletion crates/tests/variant/tests/tests.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use windows::Foundation::Uri;
use windows::Win32::Foundation::TYPE_E_TYPEMISMATCH;
use windows::Win32::Foundation::{E_INVALIDARG, TYPE_E_TYPEMISMATCH};
use windows::Win32::System::Com;
use windows_core::*;

#[test]
fn test_variant() -> Result<()> {
unsafe { Com::CoIncrementMTAUsage()? };

let empty: VARIANT = VARIANT::new();
assert!(empty.is_empty());

Expand Down Expand Up @@ -83,6 +86,19 @@ fn test_variant() -> Result<()> {
TYPE_E_TYPEMISMATCH
);

let dispatch: Com::IDispatch =
unsafe { Com::CoCreateInstance(&Com::Events::CEventSystem, None, Com::CLSCTX_ALL)? };
let v = VARIANT::from(dispatch);
let dispatch = Com::IDispatch::try_from(&v)?;
dispatch.cast::<Com::Events::IEventSystem>()?;
assert_eq!(i32::try_from(&v).unwrap_err().code(), E_INVALIDARG);
assert_eq!(
Com::IDispatch::try_from(&VARIANT::from(3.5f64))
.unwrap_err()
.code(),
TYPE_E_TYPEMISMATCH
);

let v = VARIANT::from(BSTR::from("hello"));
assert_eq!(BSTR::try_from(&v)?, "hello");
assert_eq!(
Expand Down Expand Up @@ -115,6 +131,8 @@ fn test_variant() -> Result<()> {

#[test]
fn test_propvariant() -> Result<()> {
unsafe { Com::CoIncrementMTAUsage()? };

let empty: PROPVARIANT = PROPVARIANT::new();
assert!(empty.is_empty());

Expand Down Expand Up @@ -200,6 +218,19 @@ fn test_propvariant() -> Result<()> {
TYPE_E_TYPEMISMATCH
);

let dispatch: Com::IDispatch =
unsafe { Com::CoCreateInstance(&Com::Events::CEventSystem, None, Com::CLSCTX_ALL)? };
let v = PROPVARIANT::from(dispatch);
let dispatch = Com::IDispatch::try_from(&v)?;
dispatch.cast::<Com::Events::IEventSystem>()?;
assert_eq!(i32::try_from(&v).unwrap_err().code(), E_INVALIDARG);
assert_eq!(
Com::IDispatch::try_from(&PROPVARIANT::from(3.5f64))
.unwrap_err()
.code(),
TYPE_E_TYPEMISMATCH
);

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

0 comments on commit 380df19

Please sign in to comment.