OID_802_11_BSSID_LIST的DeviceIoControl错误87

时间:2014-02-05 17:38:29

标签: c++ windows ndis deviceiocontrol

我正在尝试从网络GUID获取可用的访问点,但我总是收到DeviceIoControl()的错误87(错误的参数)。这让我疯了一会儿,因为我不知道哪个参数错了!我一直在谷歌搜索几个小时,无法找到解决方案。代码如下:

PNDIS_802_11_BSSID_LIST getBssidList(wstring wsGuid, HANDLE & hNetAdapter, DWORD & dwMemSize) {
  DWORD dwBytesReturned = 0;
  DWORD oid = OID_802_11_BSSID_LIST;
  PNDIS_802_11_BSSID_LIST pBssList;

  wsGuid= L"\\\\.\\" + wsGuid;
  hNetAdapter = CreateFileW(wsGuid.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, INVALID_HANDLE_VALUE) ;

  if (hNetAdapter == INVALID_HANDLE_VALUE) {
    return NULL;
  }

  // allocate temporary memory to check the number of AP entries
  dwMemSize = sizeof(NDIS_802_11_BSSID_LIST) * 15;
  pBssList = (NDIS_802_11_BSSID_LIST *) VirtualAlloc(NULL, dwMemSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
  memset(pBssList, 0, dwMemSize);

  // call get AP list
  while (!DeviceIoControl(hNetAdapter, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof(oid), (ULONG *) pBssList, dwMemSize, &dwBytesReturned, NULL)) {
    DWORD error = 0;
    error = GetLastError();
    if (error == ERROR_GEN_FAILURE ||  // Returned by some Intel cards.
        error == ERROR_INSUFFICIENT_BUFFER ||
        error == ERROR_MORE_DATA ||
        error == NDIS_STATUS_INVALID_LENGTH ||
        error == NDIS_STATUS_BUFFER_TOO_SHORT ) {

      // free memory allocation and realloc
      VirtualFree(pBssList, dwMemSize, MEM_RELEASE | MEM_DECOMMIT);

      if (dwBytesReturned > dwMemSize) { 
        dwMemSize = dwBytesReturned;
      } else {
        dwMemSize *= 2;
      }
      pBssList = (NDIS_802_11_BSSID_LIST *) VirtualAlloc(NULL, dwMemSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
      memset(pBssList, 0, dwMemSize);

    } else {
      // free memory allocation
      VirtualFree(pBssList, dwMemSize, MEM_RELEASE | MEM_DECOMMIT);
      CloseHandle(hNetAdapter);
      pBssList = NULL;
      break;
    }
  }

  return pBssList;
}

我正在尝试使用wsGuid = L“\\。\ {8D36491D-C393-4D71-B10A-153C4FA69AEE}”获取此列表,这是一个Broadcom 802.11n网络适配器。

编辑:我正在Win7工作中尝试它。我知道它已被弃用(因此我也为WlanGetNetworkBssList()的更高版本添加了可移植性,并且它运行良好)。我在调试旧版本时遇到错误(在同一个win7工作站中),可能问题是:如果代码是正确的,NDIS IOCTL是否仍然可以在Win7及更高版本中运行?

1 个答案:

答案 0 :(得分:2)

这样的OID是操作系统和NIC驱动程序之间合同的一部分。它们通常不适用于应用程序。正确的解决方案是调用应用程序级API,如WlanGetNetworkBssList

发生的事情是较旧的NDIS 5无线驱动程序将使用OID_802_11_BSSID_LIST与操作系统进行通信。但是较新的NDIS 6驱动程序使用不同的机制。因此旧的OID在发送到较新的微型端口驱动程序时失败。像这样的驱动程序模型的更改被隔离在应用程序API之后。

如果您必须使用无法使用API​​的Windows XP,那么您可能需要使用其他技术。但IOCTL_NDIS_QUERY_GLOBAL_STATS无效,因为ioctl会发出查询 OID,而OID_802_11_BSSID_LIST方法 OID。

您可以尝试在WMI类MSNdis_80211_BSSIList上进行尝试,但如果我没记错,Windows XP上的MOF定义存在一些问题,因此您需要手动将原始字节转换为NDIS结构