rust winapi的DWORD问题记录
最近使用rust 调用winapi发现DWORD映射到rust u32十分不妥,且出现溢出现象。故作记录
在使用winapi 获得期望的数据时 DWORD最终可能会导致数值溢出。
如下面代码获取pIpForwardTable 会导致获取的dwNumEntries溢出,解决方法是自定义一个u32按字节序列读取即可
use std::env;
// TODO 没法用不工作,请用别的方法
#[cfg(windows)]
#[allow(non_snake_case)]
fn add_route_api(ipaddr :&str,mask :&str,gw :&str,ifstr :&str) -> bool {
use std::ptr::null_mut;
use std::io::Write;
use winapi::um::iphlpapi::{GetIpForwardTable};
use winapi::shared::ipmib::{PMIB_IPFORWARDTABLE,PMIB_IPFORWARDROW,MIB_IPFORWARDTABLE};
use winapi::shared::winerror::{ERROR_SUCCESS,ERROR_INSUFFICIENT_BUFFER};
use winapi::shared::minwindef::*;
use std::{mem, ptr};
use std::convert::TryInto;
let mut dwStatus :u32;
let mut ipRow :PMIB_IPFORWARDROW;
let mut pIpForwardTable :PMIB_IPFORWARDTABLE = null_mut();
let mut dwSize :u32 = 0;
let bOrder :i32 = 1;
unsafe
{
dwStatus = GetIpForwardTable(null_mut(), &mut dwSize, bOrder);
if dwStatus == ERROR_INSUFFICIENT_BUFFER
{
// Allocate the memory for the table
println!("### 1.{}\n",dwSize);
let mut v = vec![0u8; dwSize as usize];
pIpForwardTable = v.as_mut_ptr() as PMIB_IPFORWARDTABLE ;
println!("### 2. v.size:{} \n",v.len());
// Now get the table.
dwStatus = GetIpForwardTable( pIpForwardTable , &mut dwSize, bOrder);
println!("### 3. dwStatus: {}\n" ,dwStatus);
println!("### 4. data vec: {:X?}\n" ,v);
//单独取出解析
let v1 : [u8;4] = v[0..4].try_into().expect("slice with incorrect length");
let dwEntityNum = u32::from_le_bytes(v1); //小端序列
(*pIpForwardTable).dwNumEntries = dwEntityNum as DWORD;
println!("### 5 dwEntityNum: {}" , (*pIpForwardTable).dwNumEntries);
}
if dwStatus != ERROR_SUCCESS {
return false;
}
println!("### 5 dwEntityNum: {}" , (*pIpForwardTable).dwNumEntries);
//test
let mut v2: Vec<u8> = Vec::new();
let view = pIpForwardTable as *const _ as *const u8;
let slice = std::slice::from_raw_parts(view, dwSize as usize) ;
v2.write(slice).expect("Unable to write");
println!("{:X?}", v2);
// let ff :u32 = u32::from_be_bytes( mem::transmute(pIpForwardTable) );
println!("### 6. status:{} , {}\n" , dwStatus, (*pIpForwardTable).dwNumEntries);
}
println!("### 7.\n");
true
}
fn main() {
let args: Vec<String> = env::args().collect();
println!("{:?}", args);
// print_message("hello world你好世界");
add_route_api("10.12.233.233", "255.255.255.255", "10.12.1.1", "1");
}