Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add VT_UNKNOWN support for VARIANT and PROPVARIANT #2788

Merged
merged 1 commit into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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