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");
}