我尝试实现此示例:使用路由表管理器注册,但出现错误:
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,
)
};
从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
调用将覆盖它。