Skip to content

Commit

Permalink
Add VT_UNKNOWN support for VARIANT and PROPVARIANT (#2788)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr authored Jan 11, 2024
1 parent e69e8e6 commit f3b9ca3
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 4 deletions.
2 changes: 1 addition & 1 deletion crates/libs/core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ impl From<std::string::FromUtf8Error> for Error {

impl From<std::num::TryFromIntError> for Error {
fn from(_: std::num::TryFromIntError) -> Self {
Self { code: HRESULT(crate::imp::E_INVALIDARG), info: None }
Self { code: crate::imp::E_INVALIDARG, info: None }
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/libs/core/src/imp/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,6 @@ impl ::core::clone::Clone for EXCEPINFO {
*self
}
}
pub const E_INVALIDARG: HRESULT = -2147024809i32;
pub type FARPROC = ::core::option::Option<unsafe extern "system" fn() -> isize>;
#[repr(C)]
pub struct FILETIME {
Expand Down Expand Up @@ -999,5 +998,6 @@ pub const VT_UI1: VARENUM = 17u16;
pub const VT_UI2: VARENUM = 18u16;
pub const VT_UI4: VARENUM = 19u16;
pub const VT_UI8: VARENUM = 21u16;
pub const VT_UNKNOWN: VARENUM = 13u16;
pub type WAIT_EVENT = u32;
pub type WIN32_ERROR = u32;
2 changes: 2 additions & 0 deletions crates/libs/core/src/imp/com_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ impl ::core::default::Default for DateTime {
}
}
pub const E_BOUNDS: ::windows_core::HRESULT = ::windows_core::HRESULT(-2147483637i32);
pub const E_INVALIDARG: ::windows_core::HRESULT = ::windows_core::HRESULT(-2147024809i32);
pub const E_NOINTERFACE: ::windows_core::HRESULT = ::windows_core::HRESULT(-2147467262i32);
pub const E_OUTOFMEMORY: ::windows_core::HRESULT = ::windows_core::HRESULT(-2147024882i32);
::windows_core::imp::com_interface!(IAgileObject, IAgileObject_Vtbl, 0x94ea2b94_e9cc_49e0_c0ff_ee64ca8f5b90);
Expand Down Expand Up @@ -1225,6 +1226,7 @@ impl ::core::default::Default for Size {
unsafe { ::core::mem::zeroed() }
}
}
pub const TYPE_E_TYPEMISMATCH: ::windows_core::HRESULT = ::windows_core::HRESULT(-2147316576i32);
#[repr(C)]
pub struct TimeSpan {
pub Duration: i64,
Expand Down
50 changes: 50 additions & 0 deletions crates/libs/core/src/variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,56 @@ impl TryFrom<&PROPVARIANT> for VARIANT {
}
}

// VT_UNKNOWN

impl From<IUnknown> for VARIANT {
fn from(value: IUnknown) -> Self {
Self(imp::VARIANT {
Anonymous: imp::VARIANT_0 {
Anonymous: imp::VARIANT_0_0 { vt: imp::VT_UNKNOWN, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::VARIANT_0_0_0 { punkVal: value.into_raw() } },
},
})
}
}

impl From<IUnknown> for PROPVARIANT {
fn from(value: IUnknown) -> Self {
Self(imp::PROPVARIANT {
Anonymous: imp::PROPVARIANT_0 {
Anonymous: imp::PROPVARIANT_0_0 { vt: imp::VT_UNKNOWN, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::PROPVARIANT_0_0_0 { punkVal: value.into_raw() } },
},
})
}
}

impl TryFrom<&VARIANT> for IUnknown {
type Error = Error;
fn try_from(from: &VARIANT) -> Result<Self> {
unsafe {
if from.0.Anonymous.Anonymous.vt == imp::VT_UNKNOWN && !from.0.Anonymous.Anonymous.Anonymous.punkVal.is_null() {
let unknown: &IUnknown = std::mem::transmute(&from.0.Anonymous.Anonymous.Anonymous.punkVal);
Ok(unknown.clone())
} else {
Err(Error { code: imp::TYPE_E_TYPEMISMATCH, info: None })
}
}
}
}

impl TryFrom<&PROPVARIANT> for IUnknown {
type Error = Error;
fn try_from(from: &PROPVARIANT) -> Result<Self> {
unsafe {
if from.0.Anonymous.Anonymous.vt == imp::VT_UNKNOWN && !from.0.Anonymous.Anonymous.Anonymous.punkVal.is_null() {
let unknown: &IUnknown = std::mem::transmute(&from.0.Anonymous.Anonymous.Anonymous.punkVal);
Ok(unknown.clone())
} else {
Err(Error { code: imp::TYPE_E_TYPEMISMATCH, info: None })
}
}
}
}

// VT_BSTR

impl From<BSTR> for VARIANT {
Expand Down
7 changes: 7 additions & 0 deletions crates/tests/variant/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,10 @@ publish = false

[dependencies.windows-core]
path = "../../libs/core"

[dependencies.windows]
path = "../../libs/windows"
features = [
"Foundation",
"Win32_Foundation",
]
26 changes: 26 additions & 0 deletions crates/tests/variant/tests/tests.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use windows::Foundation::Uri;
use windows::Win32::Foundation::TYPE_E_TYPEMISMATCH;
use windows_core::*;

#[test]
Expand Down Expand Up @@ -69,6 +71,18 @@ fn test_variant() -> Result<()> {
assert_eq!(VARIANT::from(3.5f64), VARIANT::from(3.5f64));
assert_ne!(VARIANT::from(3.5f64), VARIANT::from(0.0f64));

let unknown: IUnknown = Uri::CreateUri(h!("https://github.com/"))?.into();
let v = VARIANT::from(unknown);
let unknown = IUnknown::try_from(&v)?;
assert_eq!(unknown.cast::<Uri>()?.Domain()?, "github.com");
assert_eq!(i32::try_from(&v).unwrap_err().code(), TYPE_E_TYPEMISMATCH);
assert_eq!(
IUnknown::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 @@ -168,6 +182,18 @@ fn test_propvariant() -> Result<()> {
assert_eq!(PROPVARIANT::from(3.5f64), PROPVARIANT::from(3.5f64));
assert_ne!(PROPVARIANT::from(3.5f64), PROPVARIANT::from(0.0f64));

let unknown: IUnknown = Uri::CreateUri(h!("https://github.com/"))?.into();
let v = PROPVARIANT::from(unknown);
let unknown = IUnknown::try_from(&v)?;
assert_eq!(unknown.cast::<Uri>()?.Domain()?, "github.com");
assert_eq!(i32::try_from(&v).unwrap_err().code(), TYPE_E_TYPEMISMATCH);
assert_eq!(
IUnknown::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
2 changes: 1 addition & 1 deletion crates/tools/core/bindings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

--filter
Windows.Win32.Foundation.CloseHandle
Windows.Win32.Foundation.E_INVALIDARG
Windows.Win32.Foundation.ERROR_NO_UNICODE_TRANSLATION
Windows.Win32.Foundation.FreeLibrary
Windows.Win32.Foundation.GetLastError
Expand Down Expand Up @@ -67,3 +66,4 @@
Windows.Win32.System.Variant.VT_UI2
Windows.Win32.System.Variant.VT_UI4
Windows.Win32.System.Variant.VT_UI8
Windows.Win32.System.Variant.VT_UNKNOWN
4 changes: 3 additions & 1 deletion crates/tools/core/com_bindings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
Windows.Win32.Foundation.CLASS_E_CLASSNOTAVAILABLE
Windows.Win32.Foundation.CO_E_NOTINITIALIZED
Windows.Win32.Foundation.E_BOUNDS
Windows.Win32.Foundation.E_INVALIDARG
Windows.Win32.Foundation.E_NOINTERFACE
Windows.Win32.Foundation.E_OUTOFMEMORY
Windows.Win32.Foundation.JSCRIPT_E_CANTEXECUTE
Windows.Win32.Foundation.RPC_E_DISCONNECTED
Windows.Win32.Foundation.TYPE_E_TYPEMISMATCH
Windows.Win32.System.Com.CoCreateGuid
Windows.Win32.System.Com.GetErrorInfo
Windows.Win32.System.Com.IAgileObject
Expand All @@ -24,4 +26,4 @@
Windows.Win32.System.WinRT.ILanguageExceptionErrorInfo2
Windows.Win32.System.WinRT.IRestrictedErrorInfo
Windows.Win32.System.WinRT.IWeakReferenceSource
Windows.Win32.System.WinRT.RoGetAgileReference
Windows.Win32.System.WinRT.RoGetAgileReference

0 comments on commit f3b9ca3

Please sign in to comment.