0

I'm trying to get the available access points from a network GUID but I'm always getting error 87 (wrong param) for DeviceIoControl(). It's getting me crazy for a while, as I don't know which param is wrong! I've been googling for hours and can't find the solution. The code is the following:

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

I'm trying to get this list with wsGuid = L"\\.\{8D36491D-C393-4D71-B10A-153C4FA69AEE}" which is a Broadcom 802.11n Network Adapter.

EDIT: I'm trying it in a Win7 worksation. I know it is deprecated (and so I also added portability for later versions with WlanGetNetworkBssList() and it's working well). I'm getting the error when debugging for older versions (in this same win7 workstation), maybe the question is: If the code is correct, is NDIS IOCTL it still working in Win7 and later?

Miquel
  • 8,339
  • 11
  • 59
  • 82
  • You must use NDIS_802_11_BSSID_LIST_EX instead. 15 is arbitrary and too low, the actual structure is a lot bigger. – Hans Passant Feb 05 '14 at 18:14
  • @HansPassant thanks, also tried with NDIS_802_11_BSSID_LIST_EX and same result: error 87. Regarding to 15, if I'm not wrong I should get ERROR_INSUFFICIENT_BUFFER or ERROR_MORE_DATA until I reach the correct buffer size, isn't it? Anyway I've tried with 20, 100, 1000 and I always get error 87 at the first call of DeviceIoControl. – Miquel Feb 05 '14 at 18:31

1 Answers1

2

OIDs like this are part of the contract between the OS and the NIC driver. They aren't generally meant for applications to jump on. The right solution is to call application-level APIs like WlanGetNetworkBssList.

What's happening is that older NDIS 5 wireless drivers will use OID_802_11_BSSID_LIST to communicate with the OS. But newer NDIS 6 drivers use a different mechanism. So the old OID fails when sent to a newer miniport driver. Changes in the driver model like this are isolated behind the application APIs.

If you have to work on Windows XP, where the API is not available, then you might need to ding around with other techniques. But IOCTL_NDIS_QUERY_GLOBAL_STATS won't help, because that ioctl issues a query OID, while OID_802_11_BSSID_LIST is a method OID.

You can try poking at the WMI class MSNdis_80211_BSSIList, but if I remember right, there's some problem with the MOF definition on Windows XP, and so you'll need to manually cast the raw bytes to the NDIS structures.

Jeffrey Tippet
  • 3,146
  • 1
  • 14
  • 15