DeviceIoControl错误87为OID_802_11_BSSID_LIST

问题描述:

我试图从网络GUID获得可用的接入点,但我总是得到DeviceIoControl()错误87(错误的参数)。这让我发疯了一段时间,因为我不知道哪个参数错了!我一直在谷歌搜索几个小时,并找不到解决方案。代码如下: “\\。\ {8D36491D-C393-4D71-B10A-153C4FA69AEE}”DeviceIoControl错误87为OID_802_11_BSSID_LIST

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这是博通802.11n网络适配器。

编辑:我试着在Win7工作。我知道它已被弃用(所以我也为WlanGetNetworkBssList()的更新版本添加了可移植性,并且它运行良好)。在调试老版本时(在这个相同的win7工作站中),我得到了错误,也许问题是:如果代码是正确的,NDIS IOCTL它仍然在Win7和更高版本中工作?

+0

您必须改用NDIS_802_11_BSSID_LIST_EX。 15是任意的,太低,实际结构要大得多。 –

+0

@HansPassant谢谢,也试过用NDIS_802_11_BSSID_LIST_EX和相同的结果:错误87.关于15,如果我没有错,我应该得到ERROR_INSUFFICIENT_BUFFER或ERROR_MORE_DATA,直到我达到正确的缓冲区大小,不是吗?无论如何,我已经尝试过20,100,1000,并且在DeviceIoControl的第一次调用时我总是得到错误87。 – Miquel

像这样的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结构。