【问题标题】:DeviceIoControl error 87 for OID_802_11_BSSID_LISTOID_802_11_BSSID_LIST 的 DeviceIoControl 错误 87
【发布时间】:2014-03-02 07:24:07
【问题描述】:

我正在尝试从网络 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 及更高版本中工作?

【问题讨论】:

  • 您必须改用 NDIS_802_11_BSSID_LIST_EX。 15是任意的,太低了,实际结构要大很多。
  • @HansPassant 谢谢,也尝试了 NDIS_802_11_BSSID_LIST_EX 和相同的结果:错误 87。关于 15,如果我没有错,我应该得到 ERROR_INSUFFICIENT_BUFFER 或 ERROR_MORE_DATA 直到我达到正确的缓冲区大小,不是它?无论如何,我已经尝试过 20、100、1000,但在第一次调用 DeviceIoControl 时总是收到错误 87。

标签: c++ windows ndis deviceiocontrol


【解决方案1】:

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

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

如果您必须在没有 API 的 Windows XP 上工作,那么您可能需要使用其他技术。但是IOCTL_NDIS_QUERY_GLOBAL_STATS 不会有帮助,因为 ioctl 发出 query OID,而 OID_802_11_BSSID_LISTmethod OID。

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

【讨论】:

    猜你喜欢
    • 2017-08-14
    • 2018-01-07
    • 2017-03-21
    • 2017-07-22
    • 1970-01-01
    • 2020-07-06
    • 1970-01-01
    • 1970-01-01
    • 2016-11-07
    相关资源
    最近更新 更多