如何使用Rust和winapi板条箱为Windows中的事件创建订阅?

如何使用Rust和winapi板条箱为Windows中的事件创建订阅?,winapi,rust,Winapi,Rust,我正在尝试使用从订阅Windows事件,但得到了错误\u无效\u参数 我找不到铁锈的例子,但确实找到了一个 生成错误\u无效\u参数的我的代码: fn main() { unsafe { let mut callback: winapi::um::winevt::EVT_SUBSCRIBE_CALLBACK = None; let mut session = std::ptr::null_mut(); let mut signal_even

我正在尝试使用从订阅Windows事件,但得到了
错误\u无效\u参数

我找不到铁锈的例子,但确实找到了一个

生成
错误\u无效\u参数的我的代码

fn main() {
    unsafe {
        let mut callback: winapi::um::winevt::EVT_SUBSCRIBE_CALLBACK = None;
        let mut session = std::ptr::null_mut();
        let mut signal_event = std::ptr::null_mut();

        let mut bookmark = std::ptr::null_mut();
        let mut context = std::ptr::null_mut();
        let channel_path = "Security";
        let channel_path: winnt::LPWSTR = to_wchar(channel_path);
        let query = "Event/System[EventID=4624]";
        let query: winnt::LPWSTR = to_wchar(query);

        let event_handle = winevt::EvtSubscribe(
            session,
            signal_event,
            channel_path,
            query,
            bookmark,
            context,
            callback,
            winevt::EvtSubscribeStartAtOldestRecord,
        );

        //println!("{:?}", &event_handle);
        println!("{:?}", &winapi::um::errhandlingapi::GetLastError());
    } //unsafe end
}

fn to_vec(str: &str) -> Vec<u16> {
    return OsStr::new(str)
        .encode_wide()
        .chain(Some(0).into_iter())
        .collect();
}

fn to_wchar(str: &str) -> *mut u16 {
    return to_vec(str).as_mut_ptr();
}
fn main(){
不安全{
让mut回调:winapi::um::winevt::EVT\u SUBSCRIBE\u callback=None;
让mut session=std::ptr::null_mut();
让mut signal_event=std::ptr::null_mut();
让mut bookmark=std::ptr::null_mut();
让mut context=std::ptr::null_mut();
让通道_path=“安全”;
让通道路径:winnt::LPWSTR=to_wchar(通道路径);
让query=“事件/系统[EventID=4624]”;
let query:winnt::LPWSTR=to_wchar(查询);
让事件句柄=winevt::EvtSubscribe(
一场
信号灯事件,
英吉利海峡,
查询
书签,
上下文
回拨,
winevt::EVT订阅StartOldEstrecord,
);
//println!(“{:?}”和事件句柄);
println!(“{:?},&winapi::um::errhandlingapi::GetLastError());
}//不安全端
}
fn到_vec(str:&str)->vec{
返回OsStr::新建(str)
.encode_wide()
.chain(一些(0).into_iter())
.收集();
}
fn至_wchar(str:&str)->*mut u16{
返回到_vec(str).as_mut_ptr();
}
各州的文件:

SignalEvent

[…]如果
回调
参数不可用,则此参数必须为
NULL
NULL

回调

[…]如果
SignalEvent
参数为空,则此参数必须为
NULL
NULL

此处未说明的含义是必须提供这些参数中的一个。显式地不允许同时传递这两个事件,但同时传递这两个事件都没有意义,否则代码将无法接收事件

传递其中一个值将导致代码开始工作

编辑上,这是一个很好的例子,说明Rust枚举是一种更好的API建模方法。这将清楚地表明这两种选择是相互排斥的,需要一种:

enum Subscriber {
    EventObject(HANDLE),
    Callback(EVT_SUBSCRIBE_CALLBACK),
}

顺便说一句,您对_wchar的
实现不正确,可能会导致内存不安全
to_vec
分配内存,您获取一个指向它的指针,然后释放该内存,创建一个悬空指针。坏指针由
unsafe
块内的C代码读取-需要部分原因
unsafe

您要么需要使用
mem::forget
,如中所示(然后需要以某种方式防止内存泄漏),要么需要引用数据而不是原始指针。

状态文档:

SignalEvent

[…]如果
回调
参数不可用,则此参数必须为
NULL
NULL

回调

[…]如果
SignalEvent
参数为空,则此参数必须为
NULL
NULL

此处未说明的含义是必须提供这些参数中的一个。显式地不允许同时传递这两个事件,但同时传递这两个事件都没有意义,否则代码将无法接收事件

传递其中一个值将导致代码开始工作

编辑上,这是一个很好的例子,说明Rust枚举是一种更好的API建模方法。这将清楚地表明这两种选择是相互排斥的,需要一种:

enum Subscriber {
    EventObject(HANDLE),
    Callback(EVT_SUBSCRIBE_CALLBACK),
}

顺便说一句,您对_wchar
实现不正确,可能会导致内存不安全
to_vec
分配内存,您获取一个指向它的指针,然后释放该内存,创建一个悬空指针。坏指针由
unsafe
块内的C代码读取-需要部分原因
unsafe


您要么需要使用
mem::forget
,如中所示(然后您需要以某种方式防止内存泄漏),要么需要引用数据,而不是原始指针。

您的
位于
println是不需要的(),并且助手中显式的
返回
是非惯用的,并且
.chain(一些(0))
就足够了。您的
println中是不需要的(),并且助手中显式的
返回
s是非惯用的,并且
.chain(一些(0))
就足够了。