RtmRegisterEntity 访问冲突

问题描述 投票:0回答:1

总结

我尝试实现此示例:使用路由表管理器注册,但出现错误:

Exception has occurred: W32/0xC0000005
Unhandled exception at 0x00007FFCFACEBCE4 (rtm.dll) in clash-rs.exe: 0xC0000005: Access violation writing location 0x0000000000000000.

我也对

windows::Win32::NetworkManagement::Rras::RTM_ENTITY_ID
和嵌入式
Anonymous
RTM_ENTITY_ID_0_0
的东西感到有点困惑。 这是由于定义成为工会吗?

typedef struct _RTM_ENTITY_ID {
  union {
    struct {
      ULONG EntityProtocolId;
      ULONG EntityInstanceId;
    };
    ULONGLONG EntityId;
  };
} RTM_ENTITY_ID, *PRTM_ENTITY_ID;

这就是映射到 Rust 的样子?

我不确定是否与指针问题有关。

板条箱清单

[target.'cfg(windows)'.dependencies]
windows = { version = "0.58", features = [
    "Win32_Networking_WinSock",
    "Win32_Foundation",
    "Win32_NetworkManagement_Rras",
]}

箱子代码

let address_family = match dest {
        IpNet::V4(_) => AF_INET,
        IpNet::V6(_) => AF_INET6,
    };

    let rtm_reg_handle: HANDLE = null_mut();
    let mut rtm_entity_info = RTM_ENTITY_INFO::default();
    let mut rtm_regn_profile = RTM_REGN_PROFILE::default();

    rtm_entity_info.RtmInstanceId = 0;
    rtm_entity_info.AddressFamily = address_family.0;
    rtm_entity_info
        .EntityId
        .Anonymous
        .Anonymous
        .EntityProtocolId = PROTO_IP_RIP.0.try_into().unwrap();
    rtm_entity_info
        .EntityId
        .Anonymous
        .Anonymous
        .EntityInstanceId = protocol_id(
        PROTO_TYPE_UCAST,
        PROTO_VENDOR_ID,
        PROTO_IP_RIP.0.try_into().unwrap(),
    );
    let rv = unsafe {
        RtmRegisterEntity(
            &mut rtm_entity_info,
            null_mut(),
            None,
            false,
            &mut rtm_regn_profile,
            rtm_reg_handle as *mut _,
        )
    };

    if rv != ERROR_SUCCESS.0 {
        let err = unsafe { GetLastError().to_hresult().message() };
        error!("failed to register entity: {}", err);
        return Err(new_io_error(err));
    }

评论更新

let address_family = match dest {
        IpNet::V4(_) => AF_INET,
        IpNet::V6(_) => AF_INET6,
    };

    let mut rtm_reg_handle: isize = 0;
    let mut rtm_entity_info = RTM_ENTITY_INFO::default();
    let mut rtm_regn_profile = RTM_REGN_PROFILE::default();

    rtm_entity_info.RtmInstanceId = 0;
    rtm_entity_info.AddressFamily = address_family.0;
    rtm_entity_info
        .EntityId
        .Anonymous
        .Anonymous
        .EntityProtocolId = PROTO_IP_RIP.0.try_into().unwrap();
    rtm_entity_info
        .EntityId
        .Anonymous
        .Anonymous
        .EntityInstanceId = protocol_id(
        PROTO_TYPE_UCAST,
        PROTO_VENDOR_ID,
        PROTO_IP_RIP.0.try_into().unwrap(),
    );
    let rv = unsafe {
        RtmRegisterEntity(
            &mut rtm_entity_info,
            null_mut(),
            None,
            false,
            &mut rtm_regn_profile,
            &mut rtm_reg_handle,
        )
    };
windows winapi rust windows-rs
1个回答
0
投票

docs来看,handle参数不应该为null。放弃 Rust 签名,你想这样做:

let mut rtm_reg_handle: isize = 0;

...

let rv = unsafe {
    RtmRegisterEntity(
        ...
        &mut rtm_reg_handle,
    )
};

0: isize 和 null_mut() 的返回值有什么区别,因为它们看起来都是指向零的地址?

该函数需要一个非空指针,这就是

null_mut()
创建的。上面发生的事情是我们在堆栈上创建一个变量并向其传递一个pointer(该变量不会为空)。
rtm_reg_handle
的实际值并不重要,重要的是它可能是 42069,因为它只需要存在并且
RtmRegisterEntity
调用将覆盖它。

© www.soinside.com 2019 - 2024. All rights reserved.