You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Rust的windows-rs调用WlanGetAvailableNetworkList遇索引越界问题

问题描述

尝试通过WlanGetAvailableNetworkList获取所有可用网络列表,但根据dwNumberOfItems遍历网络数组时,仅能显示第一个网络,索引超过0时触发index out of bounds: the len is 1 but the index is 1错误,代码如下:

let mut w_handle: HANDLE = HANDLE::default();
let mut current_version: u32 = 0;

if WIN32_ERROR(WlanOpenHandle(2, None, &mut current_version, &mut w_handle)) != ERROR_SUCCESS {
  return;
}

let mut wlan_interface_info_list = std::ptr::null_mut();
if WIN32_ERROR(WlanEnumInterfaces(w_handle, None, &mut wlan_interface_info_list)) != ERROR_SUCCESS {
  return;
}

for i in 0..wlan_interface_info_list.as_ref().unwrap().dwNumberOfItems {
  let interface_info = wlan_interface_info_list.as_ref().unwrap().InterfaceInfo[i as usize];
  let interface_name = interface_info.strInterfaceDescription;

  let mut available_network_list = std::mem::zeroed();
  if WIN32_ERROR(WlanGetAvailableNetworkList(w_handle, &interface_info.InterfaceGuid, 0, None, &mut available_network_list)) != ERROR_SUCCESS {
    continue;
  }

  let list = available_network_list.as_ref().unwrap();
  println!("Number of available networks on {}: {}", String::from_utf16_lossy(&interface_name), list.dwNumberOfItems);

  for j in 0..list.dwNumberOfItems {
    let network_name = (*list).Network[j as usize].strProfileName; // <- Panicked
    println!("Network name: {}", String::from_utf16_lossy(&network_name));
  }
}

WlanCloseHandle(w_handle, None);
问题原因

Win32 API绑定中,WLAN_AVAILABLE_NETWORK_LIST结构体的Network字段被声明为[WLAN_AVAILABLE_NETWORK; 1],这是C语言可变长度数组的常见Rust表示方式——仅标记数组的起始位置,而非实际长度。Rust会将其视为固定长度为1的数组,所以直接用索引访问j >=1的位置会触发越界错误。

解决方法

需要将Network字段的起始指针转换为对应长度的Rust切片,再进行遍历,同时别忘了释放WlanGetAvailableNetworkList返回的内存(否则会造成内存泄漏)。

修改后的完整代码:

let mut w_handle: HANDLE = HANDLE::default();
let mut current_version: u32 = 0;

if WIN32_ERROR(WlanOpenHandle(2, None, &mut current_version, &mut w_handle)) != ERROR_SUCCESS {
  return;
}

let mut wlan_interface_info_list = std::ptr::null_mut();
if WIN32_ERROR(WlanEnumInterfaces(w_handle, None, &mut wlan_interface_info_list)) != ERROR_SUCCESS {
  return;
}

for i in 0..wlan_interface_info_list.as_ref().unwrap().dwNumberOfItems {
  let interface_info = wlan_interface_info_list.as_ref().unwrap().InterfaceInfo[i as usize];
  let interface_name = interface_info.strInterfaceDescription;

  let mut available_network_list = std::mem::zeroed();
  if WIN32_ERROR(WlanGetAvailableNetworkList(w_handle, &interface_info.InterfaceGuid, 0, None, &mut available_network_list)) != ERROR_SUCCESS {
    continue;
  }

  let list = available_network_list.as_ref().unwrap();
  println!("Number of available networks on {}: {}", String::from_utf16_lossy(&interface_name), list.dwNumberOfItems);

  // 将Network指针转换为指定长度的切片
  let networks = unsafe {
      std::slice::from_raw_parts(list.Network.as_ptr(), list.dwNumberOfItems as usize)
  };

  // 遍历切片获取所有网络
  for network in networks {
      let network_name = network.strProfileName;
      println!("Network name: {}", String::from_utf16_lossy(&network_name));
  }

  // 释放WlanGetAvailableNetworkList返回的内存
  unsafe {
      WlanFreeMemory(available_network_list as *mut _);
  }
}

// 释放WlanEnumInterfaces返回的接口列表内存
unsafe {
    WlanFreeMemory(wlan_interface_info_list as *mut _);
}

WlanCloseHandle(w_handle, None);

注:原代码遗漏了WlanEnumInterfaces返回列表的内存释放,已补充,避免内存泄漏。

内容的提问来源于stack exchange,提问作者ymgpwcca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 15:28:14