diff --git a/Cargo.toml b/Cargo.toml index db4191e..23d5f27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,8 @@ default = ["chrono"] test = [] [target.'cfg(target_os = "windows")'.dependencies] -windows = { version = "0.52", features = [ +windows-core = { version = "0.58" } +windows = { version = "0.58", features = [ "implement", "Win32_Foundation", "Win32_Security", diff --git a/src/connection.rs b/src/connection.rs index 1c6f2da..8d907c6 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -63,7 +63,7 @@ impl COMLibrary { /// `CoInitialize`s the COM library for use by the calling thread, but without setting the security context. /// pub fn without_security() -> WMIResult { - unsafe { CoInitializeEx(None, COINIT_MULTITHREADED)? } + unsafe { CoInitializeEx(None, COINIT_MULTITHREADED).ok()? } let instance = Self { _phantom: PhantomData, diff --git a/src/query_sink.rs b/src/query_sink.rs index 85706ca..849238f 100644 --- a/src/query_sink.rs +++ b/src/query_sink.rs @@ -145,7 +145,7 @@ pub struct QuerySink { /// receives asynchronously the result of the query, through Indicate calls. /// When finished,the SetStatus method is called. /// # -impl IWbemObjectSink_Impl for QuerySink { +impl IWbemObjectSink_Impl for QuerySink_Impl { fn Indicate( &self, lObjectCount: i32, @@ -209,7 +209,7 @@ mod tests { use super::*; use crate::tests::fixtures::*; use futures::StreamExt; - use windows::core::{ComInterface, IUnknown, Interface}; + use windows::core::{IUnknown, Interface}; #[async_std::test] async fn async_it_should_send_result() { diff --git a/src/result_enumerator.rs b/src/result_enumerator.rs index 94fd172..356e9cf 100644 --- a/src/result_enumerator.rs +++ b/src/result_enumerator.rs @@ -9,8 +9,9 @@ use serde::{ Serialize, }; use std::ptr; +use windows::core::VARIANT; use windows::Win32::System::Ole::SafeArrayDestroy; -use windows::Win32::System::Variant::{VariantClear, VARIANT}; +use windows::Win32::System::Variant::VariantClear; use windows::Win32::System::Wmi::{ IEnumWbemClassObject, IWbemClassObject, CIMTYPE_ENUMERATION, WBEM_FLAG_ALWAYS, WBEM_FLAG_NONSYSTEM_ONLY, WBEM_INFINITE, diff --git a/src/variant.rs b/src/variant.rs index 6fa7ef4..2f9af39 100644 --- a/src/variant.rs +++ b/src/variant.rs @@ -3,8 +3,8 @@ use crate::{ }; use serde::Serialize; use std::convert::TryFrom; -use windows::core::{ComInterface, IUnknown, BSTR}; -use windows::Win32::Foundation::{VARIANT_FALSE, VARIANT_TRUE}; +use windows::core::{IUnknown, Interface, BSTR, VARIANT}; +use windows::Win32::Foundation::{VARIANT_BOOL, VARIANT_FALSE, VARIANT_TRUE}; use windows::Win32::System::Variant::*; use windows::Win32::System::Wmi::{self, IWbemClassObject, CIMTYPE_ENUMERATION}; @@ -79,15 +79,19 @@ impl Variant { /// /// This function is unsafe as it is the caller's responsibility to ensure that the VARIANT is correctly initialized. pub fn from_variant(vt: &VARIANT) -> WMIResult { + let vt = vt.as_raw(); let variant_type = unsafe { vt.Anonymous.Anonymous.vt }; // variant_type has two 'forms': // 1. A simple type like `VT_BSTR` . // 2. An array of certain type like `VT_ARRAY | VT_BSTR`. - if variant_type.0 & VT_ARRAY.0 == VT_ARRAY.0 { - let array = unsafe { vt.Anonymous.Anonymous.Anonymous.parray }; + if variant_type & VT_ARRAY.0 == VT_ARRAY.0 { + let array = unsafe { + vt.Anonymous.Anonymous.Anonymous.parray + as *const windows::Win32::System::Com::SAFEARRAY + }; - let item_type = VARENUM(variant_type.0 & VT_TYPEMASK.0); + let item_type = VARENUM(variant_type & VT_TYPEMASK.0); return Ok(Variant::Array(unsafe { safe_array_to_vec(&*array, item_type)? @@ -97,11 +101,13 @@ impl Variant { // See https://msdn.microsoft.com/en-us/library/cc237865.aspx for more info. // Rust can infer the return type of `vt.*Val()` calls, // but it's easier to read when the type is named explicitly. - let variant_value = match variant_type { + let variant_value = match VARENUM(variant_type) { VT_BSTR => { - let bstr_ptr: &BSTR = unsafe { &vt.Anonymous.Anonymous.Anonymous.bstrVal }; - - Variant::String(bstr_ptr.try_into()?) + let bstr_ptr = unsafe { BSTR::from_raw(vt.Anonymous.Anonymous.Anonymous.bstrVal) }; + let bstr_as_str = bstr_ptr.to_string(); + // We don't want to be the ones freeing the BSTR. + let _ = bstr_ptr.into_raw(); + Variant::String(bstr_as_str) } VT_I1 => { let num = unsafe { vt.Anonymous.Anonymous.Anonymous.cVal }; @@ -136,10 +142,10 @@ impl Variant { VT_BOOL => { let value = unsafe { vt.Anonymous.Anonymous.Anonymous.boolVal }; - match value { + match VARIANT_BOOL(value) { VARIANT_FALSE => Variant::Bool(false), VARIANT_TRUE => Variant::Bool(true), - _ => return Err(WMIError::ConvertBoolError(value.0)), + _ => return Err(WMIError::ConvertBoolError(value)), } } VT_UI1 => { @@ -165,11 +171,13 @@ impl Variant { VT_EMPTY => Variant::Empty, VT_NULL => Variant::Null, VT_UNKNOWN => { - let unk = unsafe { &vt.Anonymous.Anonymous.Anonymous.punkVal }; - let ptr = unk.as_ref().ok_or(WMIError::NullPointerResult)?; - Variant::Unknown(IUnknownWrapper::new(ptr.clone())) + let ptr = unsafe { + IUnknown::from_raw_borrowed(&vt.Anonymous.Anonymous.Anonymous.punkVal) + }; + let ptr = ptr.cloned().ok_or(WMIError::NullPointerResult)?; + Variant::Unknown(IUnknownWrapper::new(ptr)) } - _ => return Err(WMIError::ConvertError(variant_type.0)), + _ => return Err(WMIError::ConvertError(variant_type)), }; Ok(variant_value)