在 Rust 中实现 IWbemObjectSink 接口
Implement IWbemObjectSink interface in Rust
我希望能够在 Rust 中调用 SWbemServices 的 ExecQueryAsync,如 C++ 中的示例所示:
https://docs.microsoft.com/fr-fr/windows/win32/wmisdk/example--getting-wmi-data-from-the-local-computer-asynchronously
我的问题是它需要 IWbemObjectSink 的实现,并且 none 在 winapi 中可用。 winapi crates 提供 an interface definition in Rust,但我应该如何在 Rust 中“实现”它?
我可以编写一个尊重接口的结构,我可以从 winapi crate 导入接口,但我如何将两者粘合在一起?
我还用 com-rs crate 做了一些实验,因为它提供了 an example to implement an interface with the com::class! macro
但我能做的是创建另一个 IWbemObjectSink 接口并实现它,而不是从 winapi::um::wbemcli:IWbemObjectSink 开始并实现它...
感谢您的见解
如果有人试图实现像 IWbemObjectSink 这样的 winapi 板条箱的 COM 接口,WMI 没有为其提供实现,这里有一个方法可以实现。
不要使用 Microsoft 维护的 com-rs crate,只要他们不添加对 winapi crate 的支持。更喜欢 com-impl 箱子,结合 wio ComPtr(不是必需的,但很方便)。
use winapi::{
um::wbemcli::{
{IWbemClassObject,IWbemObjectSink, IWbemObjectSinkVtbl},
WBEM_S_NO_ERROR,
},
shared::{
ntdef::HRESULT,
wtypes::BSTR,
},
ctypes::{
c_long,
},
};
use com_impl::{ComImpl, VTable, Refcount};
use wio::com::ComPtr;
#[repr(C)]
#[derive(ComImpl)]
#[interfaces(IWbemObjectSink)]
pub struct QuerySink {
vtbl: VTable<IWbemObjectSinkVtbl>,
refcount: Refcount,
}
impl QuerySink {
pub fn new() -> ComPtr<IWbemObjectSink> {
let ptr = QuerySink::create_raw();
let ptr = ptr as *mut IWbemObjectSink;
unsafe { ComPtr::from_raw(ptr) }
}
}
// AddRef and Release methods are provided by com_impl
#[com_impl::com_impl]
unsafe impl IWbemObjectSink for QuerySink2 {
pub unsafe fn indicate(
&self,
_lObjectCount: c_long,
_apObjArray: *mut *mut IWbemClassObject
) -> HRESULT {
WBEM_S_NO_ERROR as i32
}
pub unsafe fn set_status(
&self,
_lFlags: c_long,
_hResult: HRESULT,
_strParam: BSTR,
_pObjParam: *mut IWbemClassObject
) -> HRESULT {
WBEM_S_NO_ERROR as i32
}
}
其他一些有用的信息:
如果您需要将成员添加到您的 class(此处为 yolo
和 swag
),请按以下步骤操作:
#[repr(C)]
#[derive(ComImpl)]
#[interfaces(IWbemObjectSink)]
pub struct QuerySink2 {
vtbl: VTable<IWbemObjectSinkVtbl>,
refcount: Refcount,
yolo: i32,
swag: u8,
}
impl QuerySink2 {
pub fn new(param1: i32, param2: u8) -> ComPtr<IWbemObjectSink> {
let ptr = QuerySink2::create_raw(param1, param2);
let ptr = ptr as *mut IWbemObjectSink;
unsafe { ComPtr::from_raw(ptr) }
}
}
方法名称由 com-impl 从 snake_case 转换为 PascalCase。
这就是我的 QuerySink 使用 set_status
和 indicate
的原因,它们映射到 SetStatus
和 Indicate
。 com-impl 提供了一个 #[com_name = "..."]
属性,如果你想按照自己的方式去做的话。了解细节的最好方法是查看 https://github.com/Connicpu/com-impl/blob/master/derive-com-impl/src/lib.rs
中的评论
我希望能够在 Rust 中调用 SWbemServices 的 ExecQueryAsync,如 C++ 中的示例所示: https://docs.microsoft.com/fr-fr/windows/win32/wmisdk/example--getting-wmi-data-from-the-local-computer-asynchronously
我的问题是它需要 IWbemObjectSink 的实现,并且 none 在 winapi 中可用。 winapi crates 提供 an interface definition in Rust,但我应该如何在 Rust 中“实现”它? 我可以编写一个尊重接口的结构,我可以从 winapi crate 导入接口,但我如何将两者粘合在一起?
我还用 com-rs crate 做了一些实验,因为它提供了 an example to implement an interface with the com::class! macro 但我能做的是创建另一个 IWbemObjectSink 接口并实现它,而不是从 winapi::um::wbemcli:IWbemObjectSink 开始并实现它...
感谢您的见解
如果有人试图实现像 IWbemObjectSink 这样的 winapi 板条箱的 COM 接口,WMI 没有为其提供实现,这里有一个方法可以实现。
不要使用 Microsoft 维护的 com-rs crate,只要他们不添加对 winapi crate 的支持。更喜欢 com-impl 箱子,结合 wio ComPtr(不是必需的,但很方便)。
use winapi::{
um::wbemcli::{
{IWbemClassObject,IWbemObjectSink, IWbemObjectSinkVtbl},
WBEM_S_NO_ERROR,
},
shared::{
ntdef::HRESULT,
wtypes::BSTR,
},
ctypes::{
c_long,
},
};
use com_impl::{ComImpl, VTable, Refcount};
use wio::com::ComPtr;
#[repr(C)]
#[derive(ComImpl)]
#[interfaces(IWbemObjectSink)]
pub struct QuerySink {
vtbl: VTable<IWbemObjectSinkVtbl>,
refcount: Refcount,
}
impl QuerySink {
pub fn new() -> ComPtr<IWbemObjectSink> {
let ptr = QuerySink::create_raw();
let ptr = ptr as *mut IWbemObjectSink;
unsafe { ComPtr::from_raw(ptr) }
}
}
// AddRef and Release methods are provided by com_impl
#[com_impl::com_impl]
unsafe impl IWbemObjectSink for QuerySink2 {
pub unsafe fn indicate(
&self,
_lObjectCount: c_long,
_apObjArray: *mut *mut IWbemClassObject
) -> HRESULT {
WBEM_S_NO_ERROR as i32
}
pub unsafe fn set_status(
&self,
_lFlags: c_long,
_hResult: HRESULT,
_strParam: BSTR,
_pObjParam: *mut IWbemClassObject
) -> HRESULT {
WBEM_S_NO_ERROR as i32
}
}
其他一些有用的信息:
如果您需要将成员添加到您的 class(此处为 yolo
和 swag
),请按以下步骤操作:
#[repr(C)]
#[derive(ComImpl)]
#[interfaces(IWbemObjectSink)]
pub struct QuerySink2 {
vtbl: VTable<IWbemObjectSinkVtbl>,
refcount: Refcount,
yolo: i32,
swag: u8,
}
impl QuerySink2 {
pub fn new(param1: i32, param2: u8) -> ComPtr<IWbemObjectSink> {
let ptr = QuerySink2::create_raw(param1, param2);
let ptr = ptr as *mut IWbemObjectSink;
unsafe { ComPtr::from_raw(ptr) }
}
}
方法名称由 com-impl 从 snake_case 转换为 PascalCase。
这就是我的 QuerySink 使用 set_status
和 indicate
的原因,它们映射到 SetStatus
和 Indicate
。 com-impl 提供了一个 #[com_name = "..."]
属性,如果你想按照自己的方式去做的话。了解细节的最好方法是查看 https://github.com/Connicpu/com-impl/blob/master/derive-com-impl/src/lib.rs