デュアル STA クエリと構成
Note
このトピックで説明する機能を開発するには、Windows 11 SDK (10.0.22000.194) 以降が必要です。
デュアル ステーション (デュアル STA) 接続をサポートするアダプターに関連付けられているインターフェイスには、プライマリ STA インターフェイスとセカンダリ STA インターフェイスの 2 種類があります。 すべてのアダプターはプライマリ STA インターフェイスを公開しますが、デュアル STA 機能をサポートするアダプターのみがセカンダリ STA インターフェイスを公開します。
既定では、Windows はプライマリ STA インターフェイスでのみ接続します。 Windows は、次のすべての条件が満たされている場合にのみ、セカンダリ STA インターフェイスで接続します。
- ドライバーは、その機能におけるセカンダリ STA インターフェイスのサポートを示します。
- セカンダリ STA 接続を妨げるポリシーはありません。
- パラメーターが に
TRUE
設定されたwlan_intf_opcode_secondary_sta_synchronized_connectionsオペコードを使用して WlanSetInterface を呼び出したアプリケーションが少なくとも 1 つあります。
デュアル STA インターフェイスのクエリ
アダプターがデュアル STA 用に構成されているかどうかを確認し、セカンダリ STA インターフェイス GUIDの一覧を取得するには、アプリケーションで wlan_intf_opcode_secondary_sta_interfaces オペコードを使用して WlanQueryInterface (wlanapi.h) を呼び出す必要があります。
このオペコードは、パラメーターとしてプライマリ ステーション (STA) インターフェイスの GUID ( WlanEnumInterfaces の呼び出しによって取得できます) を受け取り、そのプライマリ STA インターフェイスに関連付けられているセカンダリ STA インターフェイスの一覧を返します。
セカンダリ STA インターフェイスの一覧を取得する方法の例を次に示します。
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <wlanapi.h>
#include <Windot11.h> // for DOT11_SSID struct
#include <objbase.h>
#include <wtypes.h>
#include <stdio.h>
#include <stdlib.h>
// Need to link with Wlanapi.lib and Ole32.lib
#pragma comment(lib, "wlanapi.lib")
#pragma comment(lib, "ole32.lib")
DWORD QueryDualStaInterfaces()
{
HANDLE hClient;
DWORD version;
DWORD dwResult = WlanOpenHandle(WLAN_API_VERSION_2_0, nullptr, &version, &hClient);
if (dwResult != ERROR_SUCCESS)
{
wprintf(L"WlanOpenHandle failed with error: %u\n", dwResult);
return dwResult;
}
PWLAN_INTERFACE_INFO_LIST pPrimaryIntfList = nullptr;
dwResult = WlanEnumInterfaces(hClient, nullptr, &pPrimaryIntfList);
if (dwResult != ERROR_SUCCESS)
{
wprintf(L"WlanEnumInterfaces FAILed, error = %u\n", dwResult);
WlanCloseHandle(hClient, NULL);
return dwResult;
}
wprintf(L"There are %u primary interfaces in the system\n", pPrimaryIntfList->dwNumberOfItems);
for (UINT i = 0; i < pPrimaryIntfList->dwNumberOfItems; i++)
{
WCHAR* strPrimaryUuid = nullptr;
if (UuidToStringW(&pPrimaryIntfList->InterfaceInfo[i].InterfaceGuid, reinterpret_cast<RPC_WSTR*>(&strPrimaryUuid)) != RPC_S_OK)
{
strPrimaryUuid = nullptr;
}
DWORD dwDataSize = 0;
PWLAN_INTERFACE_INFO_LIST pSecondaryIntfList = nullptr;
dwResult = WlanQueryInterface(
hClient,
&pPrimaryIntfList->InterfaceInfo[i].InterfaceGuid,
wlan_intf_opcode_secondary_sta_interfaces,
NULL,
&dwDataSize,
reinterpret_cast<PVOID*>(&pSecondaryIntfList),
NULL);
if (dwResult == ERROR_SUCCESS)
{
wprintf(
L"\t[%d]\tInterface %ws (State = %d) has %u Secondary interfaces\n",
i,
strPrimaryUuid ? strPrimaryUuid : L"Unknown",
pPrimaryIntfList->InterfaceInfo[i].isState,
pSecondaryIntfList->dwNumberOfItems);
for (UINT j = 0; j < pSecondaryIntfList->dwNumberOfItems; j++)
{
WCHAR* strSecondaryUuid = nullptr;
if (UuidToStringW(&pSecondaryIntfList->InterfaceInfo[j].InterfaceGuid, reinterpret_cast<RPC_WSTR*>(&strSecondaryUuid)) == RPC_S_OK)
{
wprintf(
L"\t\t[%d]\tSecondary Interface GUID: %ws, (State = %d)\n",
j,
strSecondaryUuid,
pSecondaryIntfList->InterfaceInfo[j].isState);
RpcStringFreeW(reinterpret_cast<RPC_WSTR*>(&strSecondaryUuid));
}
}
WlanFreeMemory(pSecondaryIntfList);
}
else
{
wprintf(L"\t[%d]\tInterface %ws has 0 Secondary interfaces, error = %u\n", i, strPrimaryUuid ? strPrimaryUuid : L"Unknown", dwResult);
}
if (strPrimaryUuid)
{
RpcStringFreeW(reinterpret_cast<RPC_WSTR*>(&strPrimaryUuid));
}
}
WlanFreeMemory(pPrimaryIntfList);
WlanCloseHandle(hClient, NULL);
return dwResult;
}
デュアル STA 同期接続の状態のクエリ
プライマリ STA インターフェイス経由の接続に従って、アダプターがセカンダリ STA インターフェイス経由で自動的に接続するかどうかを判断するために、アプリケーションは、wlan_intf_opcode_secondary_sta_synchronized_connectionsオペコードを使用して WlanQueryInterface を呼び出すことによって、現在の状態に対してクエリを実行できます。
このオペコードは、プライマリとセカンダリの STA 接続が同期されているかどうかを示す BOOL 値を返します。
この状態を照会する方法の例を次に示します。
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <wlanapi.h>
#include <Windot11.h> // for DOT11_SSID struct
#include <objbase.h>
#include <wtypes.h>
#include <stdio.h>
#include <stdlib.h>
// Need to link with Wlanapi.lib and Ole32.lib
#pragma comment(lib, "wlanapi.lib")
#pragma comment(lib, "ole32.lib")
DWORD QueryDualStaConnectivity()
{
HANDLE hClient;
DWORD version;
DWORD dwResult = WlanOpenHandle(WLAN_API_VERSION_2_0, nullptr, &version, &hClient);
if (dwResult != ERROR_SUCCESS)
{
wprintf(L"WlanOpenHandle failed with error: %u\n", dwResult);
return dwResult;
}
PWLAN_INTERFACE_INFO_LIST pPrimaryIntfList = nullptr;
dwResult = WlanEnumInterfaces(hClient, nullptr, &pPrimaryIntfList);
if (dwResult != ERROR_SUCCESS)
{
wprintf(L"WlanEnumInterfaces FAILed, error = %u\n", dwResult);
WlanCloseHandle(hClient, NULL);
return dwResult;
}
//
// Need to call the API only once to query/change the state.
//
if (pPrimaryIntfList->dwNumberOfItems)
{
WCHAR* strPrimaryUuid = nullptr;
if (UuidToStringW(&pPrimaryIntfList->InterfaceInfo[0].InterfaceGuid, reinterpret_cast<RPC_WSTR*>(&strPrimaryUuid)) != RPC_S_OK)
{
strPrimaryUuid = nullptr;
}
DWORD dwDataSize = 0;
PBOOL bQueriedValue = NULL;
dwResult = WlanQueryInterface(
hClient,
&pPrimaryIntfList->InterfaceInfo[0].InterfaceGuid,
wlan_intf_opcode_secondary_sta_synchronized_connections,
NULL,
&dwDataSize,
(PVOID*)&bQueriedValue,
NULL);
if (dwResult == ERROR_SUCCESS)
{
wprintf(L"Secondary Sta Synchronized connections is currently %ws\n", *bQueriedValue ? L"Enabled" : L"Disabled");
WlanFreeMemory(bQueriedValue);
}
else
{
wprintf(L"Failed to query Secondary Sta Synchronized connections - error = %u\n", dwResult);
}
if (strPrimaryUuid)
{
RpcStringFreeW(reinterpret_cast<RPC_WSTR*>(&strPrimaryUuid));
}
}
WlanFreeMemory(pPrimaryIntfList);
WlanCloseHandle(hClient, NULL);
return dwResult;
}
セカンダリ STA インターフェイスでの接続の有効化
セカンダリ STA 接続を使用するアプリケーションが存在しない限り、Windows はセカンダリ STA インターフェイスで接続しません。 Windows がセカンダリ STA インターフェイスで接続するかどうかを制御するには、アプリケーションで、セカンダリ STA インターフェイスで接続を有効または無効にするかどうかを指定する BOOL パラメーターを使用して、wlan_intf_opcode_secondary_sta_synchronized_connectionsオペコードを使用して WlanSetInterface を呼び出す必要があります。 の TRUE
値はセカンダリ STA 接続を有効にすることを示し、 の FALSE
値はセカンダリ STA 接続が不要であることを示します。
同じ値 (TRUE
または FALSE
) を複数回使用して API を呼び出すことは冗長であり、新しい値の最初のインスタンスのみが機能を変更します。
アプリケーションでセカンダリ STA 接続が有効になったら、セカンダリ STA 接続を使用する予定の間、サービスへのハンドルを開いたままにする必要があります。 アプリケーションがセカンダリ STA 接続を明示的に無効にすると (オペコード wlan_intf_opcode_secondary_sta_synchronized_connectionsとパラメーター値FALSE
を使用して WlanSetInterface を呼び出すか、WlanCloseHandle を呼び出すか、暗黙的に (終了することによって) その後のある時点でセカンダリ STA インターフェイス経由の接続が無効になります。
セカンダリ STA 接続は、アプリケーションが要求する少なくとも 1 回限り有効なままになります。
セカンダリ STA 接続を有効または無効にする方法を示す例を次に示します。
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <wlanapi.h>
#include <Windot11.h> // for DOT11_SSID struct
#include <objbase.h>
#include <wtypes.h>
#include <stdio.h>
#include <stdlib.h>
// Need to link with Wlanapi.lib and Ole32.lib
#pragma comment(lib, "wlanapi.lib")
#pragma comment(lib, "ole32.lib")
DWORD SetDualStaConnectivity(BOOL bEnable)
{
HANDLE hClient;
DWORD version;
DWORD dwResult = WlanOpenHandle(WLAN_API_VERSION_2_0, nullptr, &version, &hClient);
if (dwResult != ERROR_SUCCESS)
{
wprintf(L"WlanOpenHandle failed with error: %u\n", dwResult);
return dwResult;
}
PWLAN_INTERFACE_INFO_LIST pPrimaryIntfList = nullptr;
dwResult = WlanEnumInterfaces(hClient, nullptr, &pPrimaryIntfList);
if (dwResult != ERROR_SUCCESS)
{
wprintf(L"WlanEnumInterfaces FAILed, error = %u\n", dwResult);
WlanCloseHandle(hClient, NULL);
return dwResult;
}
//
// Only need to call the API once to query/change the state
//
if (pPrimaryIntfList->dwNumberOfItems)
{
WCHAR* strPrimaryUuid = nullptr;
if (UuidToStringW(&pPrimaryIntfList->InterfaceInfo[0].InterfaceGuid, reinterpret_cast<RPC_WSTR*>(&strPrimaryUuid)) != RPC_S_OK)
{
strPrimaryUuid = nullptr;
}
dwResult = WlanSetInterface(
hClient,
&pPrimaryIntfList->InterfaceInfo[0].InterfaceGuid,
wlan_intf_opcode_secondary_sta_synchronized_connections,
sizeof(bEnable),
reinterpret_cast<PBYTE>(&bEnable),
NULL);
if (dwResult == ERROR_SUCCESS)
{
wprintf(L"Successfully set Sec Sta opcode = %x on Primary Interface %ws\n", bEnable, strPrimaryUuid);
}
else
{
wprintf(L"FAILed set Sec Sta opcode = %x on Primary Interface %ws -- error = %u\n", bEnable, strPrimaryUuid, dwResult);
}
if (strPrimaryUuid)
{
RpcStringFreeW(reinterpret_cast<RPC_WSTR*>(&strPrimaryUuid));
}
}
WlanFreeMemory(pPrimaryIntfList);
// Close the handle only when the app no longer needs the dual-sta connection
//
WlanCloseHandle(hClient, NULL);
return dwResult;
}