GraveDollの備忘録ブログ

勉強したことや捗るグッズの備忘録です。

Native Wifiを使ってみた その2

前回、Native Wifiを使って利用可能なネットワークのスキャンをおこないました。
gravedoll.hatenablog.com


今回は無線アクセスポイントに接続する処理を実装してみたいと思います。
サンプルコードはこちら。無線アクセスポイントのSSIDとセキュリティキーを入力し、接続するようになっています。
github.com


以下、接続までの処理についてのメモです。

接続時のパラメータを設定する

//接続パラメータ設定
ZeroMemory(&wlanConnectionParams, sizeof(WLAN_CONNECTION_PARAMETERS));
wlanConnectionParams.wlanConnectionMode = wlan_connection_mode_profile;//接続形式の指定(今回は接続する際にプロファイルを使う形式を指定)
wlanConnectionParams.strProfile = ssid;//接続するプロファイル名を指定(今回はSSID名を指定)
wlanConnectionParams.pDot11Ssid = &dot11Ssid;//接続するAPのSSIDを指定
wlanConnectionParams.pDesiredBssidList = NULL;//BSSリストの指定(今回は使用しない)
wlanConnectionParams.dot11BssType = dot11_BSS_type_infrastructure;//BSSタイプの指定(普通にAPに接続するならインフラストラクチャを指定する)
wlanConnectionParams.dwFlags = 0;//フラグの指定(ステルスのネットワーク接続するかどうかなどが指定できる)

今回は無線アクセスポイントに接続するために、SSID、セキュリティキー、暗号化方式などが含まれるプロファイルを作成・保存し、そのプロファイルをもとに接続をおこなうようパラメータを指定しています。
wlanConnectionModeをwlan_connection_mode_temporary_profileにすればプロファイルを保存せずに接続ができるっぽいのですが、私はうまくできませんでした(;´Д`)

WLAN_CONNECTION_PARAMETERSのドキュメントはこちらです。
WLAN_CONNECTION_PARAMETERS structure (Windows)

プロファイルを作成する

プロファイルはXML形式で作成します。
暗号化方式別のサンプルが用意されているので、こちらを参考にプロファイルを作成します。
Wireless Profile Samples (Windows)

私は今回以下のようにXMLをベタ打ちしていますw

wchar_t strXml[1024];
LPCWSTR key = securityKey;
wchar_t profileFormat[] = L"<?xml version=\"1.0\" encoding=\"US-ASCII\"?>"
	L"<WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\">\n"
	L"<name>%s</name>\n"
	L"<SSIDConfig>\n"
	L"<SSID>\n"
	L"<name>%s</name>\n"
	L"</SSID>\n"
	L"</SSIDConfig>\n"
	L"<connectionType>ESS</connectionType>\n"
	L"<connectionMode>auto</connectionMode>\n"
	L"<autoSwitch>false</autoSwitch>\n"
	L"<MSM>\n"
	L"<security>\n"
	L"<authEncryption>\n"
	L"<authentication>WPA2PSK</authentication>\n"
	L"<encryption>AES</encryption>\n"
	L"<useOneX>false</useOneX>\n"
	L"</authEncryption>\n"
	L"<sharedKey>\n"
	L"<keyType>passPhrase</keyType>\n"
	L"<protected>false</protected>\n"
	L"<keyMaterial>%s</keyMaterial>\n"
	L"</sharedKey>\n"
	L"</security>\n"
	L"</MSM>\n"
	L"</WLANProfile>\n";
_snwprintf_s(strXml, _countof(strXml), profileFormat, ssid, ssid, key);

プロファイルを登録する

WlanSetProfileで先ほど作成したプロファイルを登録します。

WlanSetProfile function (Windows)

WlanSetProfile(hClient, guid, 0, strXml, 0, true, NULL, &dwReasonCode);

という感じで、第四引数にプロファイルを指定しています。

ここで登録されたプロファイルは、Windows10の場合、[ネットワーク設定] - [既知のネットワークの管理]で確認できると思います。
Windows7は[ネットワークと共有センター] - [ワイヤレスネットワークの管理]で確認できます。

無線アクセスポイントに接続する

やっと接続処理ですが、WlanConnectを使います。
WlanConnect function (Windows)

WlanConnect(hClient, guid, &wlanConnectionParams, NULL);

第三引数で最初に設定した接続パラメータを指定しています。

注意点

WlanConnectがエラーを返さなかったとしても接続が成功したとは限りません。
信頼性を高めるためにはIPが当たっているかを確認したり、通知を見て接続エラー判定したりといった処理が別途必要だと思います。