SW 개발

[winCE/WM] NDISUIO 를 이용하여 무선랜의 상태얻기 예제

. . . 2014. 8. 29. 12:20
반응형
  • NDISUIO 를 이용하면 무선랜의 각종 상태 및 정보를 얻을수있다.
  • 사용하고있는 무선랜 드라이버가 WM / CE 의 표준으로 작성되었다면 아래의 인터페이스들이 정상적으로 동작할것이다.

실제 예제소스

NDISUIO.cpp NDISUIO.h

NDISUIO 의 초기화

NDISUIO::NDISUIO()
{
  m_hNDISUIO = CreateFile(
              NDISUIO_DEVICE_NAME,              //  Object name.
              0x00,                     //  Desired access.
              0x00,                     //  Share Mode.
              NULL,                     //  Security Attr
              OPEN_EXISTING,                  //  Creation Disposition.
              FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, //  Flag and Attributes..
              (HANDLE)INVALID_HANDLE_VALUE );

  if ( m_hNDISUIO == INVALID_HANDLE_VALUE )
    RETAILMSG(1, (TEXT("CreateFile Error....\r\n"))); 
}

디바이스 이름 얻기

BOOL NDISUIO::GetDeviceName(LPWSTR lpszAdapterName)
{
  char                    Buffer[1024];
    PNDISUIO_QUERY_BINDING  pQueryBinding;
    DWORD                   dwOutSize, i = 0x00;

  pQueryBinding = (PNDISUIO_QUERY_BINDING)&Buffer[0];

  memset(pQueryBinding, 0x00, sizeof(NDISUIO_QUERY_BINDING));

  //BTPAN이 index 0 에 있는 경우도 있으므로, BTPAN은 제외하고 찾는다.
  while(1)
  {
    pQueryBinding->BindingIndex = i;

    if (!DeviceIoControl(
        m_hNDISUIO,
        IOCTL_NDISUIO_QUERY_BINDING,
        pQueryBinding,
        sizeof(NDISUIO_QUERY_BINDING),
        pQueryBinding,
        1024,
        &dwOutSize,
        NULL))
    {
      RETAILMSG( 1, ( TEXT( "## IOCTL_NDISUIO_QUERY_BINDING FAIL(CWirelessLan) errnum  %d \r\n" ),GetLastError() ) );
      return FALSE;
    }

    //
    //  Make sure it's terminated..
    //

    memset( lpszAdapterName, 0x00 , MAXLEN);
    memcpy( lpszAdapterName , &Buffer[pQueryBinding->DeviceNameOffset] , (pQueryBinding->DeviceNameLength -  1));
    lpszAdapterName[(pQueryBinding->DeviceNameLength ) - 1] = 0x00;

    if(wcsncmp(lpszAdapterName,L"BTPAN",wcslen(L"BTPAN")) == 0)
    {
      i++;
      continue;
    }
    else
    {
      break;
    }   
  }
  return TRUE;
}

맥 어드레스 얻기

BOOL NDISUIO::GetMacAddr( UCHAR* pMacAddr )
{
    CHAR            cBuffer[1024];  
    PNDISUIO_QUERY_OID      pstQueryOid;
    DWORD           dwReturned = 0;
    BOOL            ret;
    INT             i;

    memset(cBuffer,0,sizeof(cBuffer));
    pstQueryOid = (PNDISUIO_QUERY_OID)cBuffer;
    pstQueryOid->Oid = OID_802_11_BSSID;  
  pstQueryOid->ptcDeviceName = m_lpszAdapterName;

    ret = DeviceIoControl(  m_hNDISUIO,
    IOCTL_NDISUIO_QUERY_OID_VALUE,
    (LPVOID)cBuffer,
    sizeof(cBuffer),
    (LPVOID)cBuffer,
    sizeof(cBuffer),
    &dwReturned,
    NULL);
    if (! ret) return FALSE;                        

    for ( i = 0; i < 6; i++ ) {
        pMacAddr[i] = pstQueryOid->Data[i];  
//    RETAILMSG(1, (TEXT("%02x"), (DWORD)pstQueryOid->Data[i] ));
    }

//  RETAILMSG(1, (TEXT("\r\n")));

    return TRUE;
}

현재 연결되어있는 AP 의 RSSI 얻기

BOOL NDISUIO::GetRSSI( DWORD & dwStrength )
{ 
  PNDISUIO_QUERY_OID    pQueryOid   = NULL;
  DWORD         dwBytesReturned = 0;
  DWORD         BufferSize = sizeof(NDISUIO_QUERY_OID)+sizeof(DWORD);
  UCHAR         QueryBuffer[sizeof(NDISUIO_QUERY_OID)+sizeof(DWORD)];


  // Get Signal strength
  memset(QueryBuffer, 0x00, BufferSize);

  pQueryOid = (PNDISUIO_QUERY_OID)QueryBuffer;  
  pQueryOid->ptcDeviceName = m_lpszAdapterName;
  pQueryOid->Oid = OID_802_11_RSSI;

  BOOL bRet = DeviceIoControl(
                m_hNDISUIO,
                IOCTL_NDISUIO_QUERY_OID_VALUE,
                (LPVOID) pQueryOid,
                sizeof(NDISUIO_QUERY_OID) + sizeof(DWORD),
                (LPVOID) pQueryOid,
                sizeof(NDISUIO_QUERY_OID) + sizeof(DWORD),
                &dwBytesReturned,
                NULL );

  if ( bRet )
  {
    dwStrength = *(DWORD *)&pQueryOid->Data;
//    RETAILMSG(1, (TEXT("Strength : %d\r\n"), dwStrength ));   
    return TRUE;
  }

  return FALSE;
}

현재 연결되어있는 AP의 SSID 얻기

BOOL NDISUIO::GetSSID(LPWSTR pszSSID)
{
    CHAR                cBuffer[1024];  
    PNDISUIO_QUERY_OID  pstQueryOid;
    DWORD               dwReturned = 0;
    BOOL                ret;
    PNDIS_802_11_SSID   pstSSID;
    INT                 i;

    pszSSID[0] = 0;                                 

    memset(cBuffer,0,sizeof(cBuffer));

    pstQueryOid = (PNDISUIO_QUERY_OID)cBuffer;
    pstQueryOid->Oid = OID_802_11_SSID;               
  pstQueryOid->ptcDeviceName = m_lpszAdapterName;

    ret = DeviceIoControl(  m_hNDISUIO,
    IOCTL_NDISUIO_QUERY_OID_VALUE,
    (LPVOID)cBuffer,
    sizeof(cBuffer),
    (LPVOID)cBuffer,
    sizeof(cBuffer),
    &dwReturned,
    NULL);
    if (! ret) return FALSE;                          

    pstSSID = (PNDIS_802_11_SSID)pstQueryOid->Data;

    for ( i = 0; i < (INT)pstSSID->SsidLength; i++ ) 
        pszSSID[i] = (TCHAR)pstSSID->Ssid[i];           
    pszSSID[i] = 0;

    return TRUE;
}

현재 시점에서의 AP list 얻기

BOOL NDISUIO::GetBSSIDList( BYTE *pstBSSIDList )
{
  DWORD           BufferSize = sizeof(NDISUIO_QUERY_OID)+sizeof(NDIS_802_11_BSSID_LIST)*30;
  UCHAR           QueryBuffer[sizeof(NDISUIO_QUERY_OID)+sizeof(NDIS_802_11_BSSID_LIST)*30]; 
    PNDISUIO_QUERY_OID      pstQueryOid;
    DWORD           dwReturned = 0;
    BOOL            ret;    

    memset(QueryBuffer,0,sizeof(QueryBuffer));

    pstQueryOid = (PNDISUIO_QUERY_OID)QueryBuffer;
    pstQueryOid->Oid = OID_802_11_BSSID_LIST;               
  pstQueryOid->ptcDeviceName = m_lpszAdapterName;

    ret = DeviceIoControl(  m_hNDISUIO,
    IOCTL_NDISUIO_QUERY_OID_VALUE,
    (LPVOID)pstQueryOid,
    BufferSize,
    (LPVOID)pstQueryOid,
    BufferSize,
    &dwReturned,
    NULL);
    if (! ret) return FALSE;                          

    memcpy( (void*)pstBSSIDList, (void*)pstQueryOid->Data, BufferSize );

    return TRUE;
}

## 주변 AP 강제 스캔

```cpp
BOOL NDISUIO::BroadcastScanList()
{
  RETAILMSG( 1, ( TEXT( "## BroadcastScanMessage\r\n" ) ) );

  // LIST_SCAN
  PNDISUIO_SET_OID  pSetOid;
  TCHAR       QueryBuffer[1024];
  DWORD       dwBytesReturned = 0;
  BOOL        ret;

  pSetOid = (PNDISUIO_SET_OID) &QueryBuffer[0];
  pSetOid->ptcDeviceName = m_lpszAdapterName;
  pSetOid->Oid = OID_802_11_BSSID_LIST_SCAN;


  ret = DeviceIoControl(
        m_hNDISUIO,
        IOCTL_NDISUIO_SET_OID_VALUE,
        (LPVOID) pSetOid,
        sizeof(OID_802_11_BSSID_LIST_SCAN) + sizeof(QueryBuffer) ,
        (LPVOID) pSetOid,
        1024* sizeof(TCHAR),
        &dwBytesReturned,
        NULL);

  if (!ret)
  {
    RETAILMSG (1, (TEXT("LIST_SCAN ERROR :: %d\r\n"), GetLastError()));
    return FALSE;
  }

  return TRUE;
}
반응형