2007-09-06

NDIS経由で無線LANの状態を取得してみる

無線LANの状態をまじめに取得してみようと格闘中です。
 
とりあえず NDIS経由で 情報取得できるんだろうなぁということは想像できるのですが、 意味がわからない上にドキュメントの分量も多いので ちょっと挫折気味です。
 
とりあえず斜め読みして理解できた範囲の事を書いておきます。
  1. NDISのハンドルは CreateFileに NDISUIO_DEVICE_NAMEを指定して開く。
    NDISUIO_DEVICE_NAMEは uuiouser.hで "UIO1:"として定義されています。
  2.  
  3. NDISに対する操作は DeviceIoControlに いろいろな制御コードを指定して行う。
 
試しに接続中のSSIDを取得するサンプルを作ってみました。
 
DeviceIoContorolに IOCTL_NDISUIO_QUERY_OID_VALUEを指定することで、 いろいろな情報を取得できるみたいです。 問い合わせたい内容は対象とするデバイス名と一緒に NDISUIO_QUERY_OIDに指定します。
 
サンプルはデバイス名に "GSPI86861"をハードコーディングしている時点でアドエス専用確定ですが...。
 
尚、取得した SSIDはそのままでは表示できないので、UNICODEに変換してやる必要があります。  
static BOOL GetSsid_Test()
{
    HANDLE              hNdis;
    UCHAR               cBuffer[1024];
    PNDISUIO_QUERY_OID  pNdisQueryOid   = (PNDISUIO_QUERY_OID)&cBuffer[0];
    NDIS_802_11_SSID    ndisSsid        = { 0 };
    BOOL                bRet            = TRUE;
    DWORD               dwBytesReturned = 0,
                        dwError;
    CString             strSsid;
    INT                 iLen;

    // NDISのハンドル取得
    hNdis = CreateFile(
        NDISUIO_DEVICE_NAME                         ,
        GENERIC_ALL                                 ,
        0                                           ,
        NULL                                        ,
        OPEN_EXISTING                               ,
        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
        (HANDLE)INVALID_HANDLE_VALUE);
    if (hNdis == INVALID_HANDLE_VALUE) {
        return FALSE;
    }

    // SSID取得
    pNdisQueryOid->Oid = OID_802_11_SSID;
    pNdisQueryOid->ptcDeviceName = _T("GSPI86861");

    if (DeviceIoControl(
            hNdis                                   ,
            IOCTL_NDISUIO_QUERY_OID_VALUE           ,
            (LPVOID)&cBuffer[0]                     ,
            sizeof(cBuffer)                         ,
            (LPVOID)&cBuffer[0]                     ,
            sizeof(cBuffer)                         ,
            &dwBytesReturned                        ,
            NULL)) {

        memcpy_s(&ndisSsid, sizeof(NDIS_802_11_SSID), &pNdisQueryOid->Data[0], sizeof(NDIS_802_11_SSID));
        
        // UNICODEに変換してから表示
        iLen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPCSTR)ndisSsid.Ssid, -1, NULL, 0);
        if (iLen > 0) {
            MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPCSTR)ndisSsid.Ssid, -1, strSsid.GetBuffer(iLen), iLen);
            strSsid.ReleaseBuffer();
            MessageBox(NULL, strSsid, _T("SSIDを取得してみるテスト"), MB_OK);
        }

    } else {
        dwError = GetLastError();
        bRet  = FALSE;
    }

    //
    CloseHandle(hNdis);
    hNdis = INVALID_HANDLE_VALUE;
    return bRet;
}
 
この方法でSSID以外にもいろいろな情報を取得できそうです。
もう少し整理して WifiInfoに反映したいですね。
 

0 件のコメント: