Dual-STA lekérdezés és konfiguráció
Jegyzet
A jelen témakörben ismertetett funkciók fejlesztéséhez a Windows 11 SDK -ra (10.0.22000.194) és újabb verziókra van szükség.
A kettős állomású (kettős STA) kapcsolatokat támogató adapterekhez kétféle illesztő tartozik: az elsődleges STA-adapterekhez és a másodlagos STA-adapterekhez. Minden adapter elsődleges STA-felületet tesz elérhetővé, de csak a kettős STA funkciót támogató adapterek teszik elérhetővé a másodlagos STA-interfészeket.
Alapértelmezés szerint a Windows csak az elsődleges STA-felületen csatlakozik. A Windows csak akkor csatlakozik a másodlagos STA-adapterhez, ha az alábbi feltételek teljesülnek:
- Az illesztőprogram támogatja a másodlagos STA-interfészeket a képességeiben.
- Nincs olyan házirend, amely megakadályozná a másodlagos STA-kapcsolatot.
- Legalább egy olyan alkalmazás van, amely a WlanSetInterface a wlan_intf_opcode_secondary_sta_synchronized_connections opcode-nal és a
TRUE
paraméterrel.
Kettős STA-interfészek lekérdezése
Annak megállapításához, hogy egy adapter kettős sta-ra van-e konfigurálva, és hogy lekérje a másodlagos STA-interfész GUIDs listáját, az alkalmazásnak meg kell hívnia WlanQueryInterface (wlanapi.h) wlan_intf_opcode_secondary_sta_interfaces opcode-ot.
Ez az opcode paraméterként az elsődleges állomás (STA) interfészének GUID (amely a WlanEnumInterfaceshívásával érhető el), és visszaadja az elsődleges STA-adapterhez társított másodlagos STA-adapterek listáját.
Íme egy példa a másodlagos STA-adapterek listájának lekérésére.
#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;
}
Kettős STA szinkronizált kapcsolatok állapotának lekérdezése
Annak megállapításához, hogy egy adapter automatikusan csatlakozik-e a másodlagos STA-adapterhez az elsődleges STA-adapteren keresztüli kapcsolat után, az alkalmazás le tudja kérdezni az aktuális állapotot WlanQueryInterface meghívásával az wlan_intf_opcode_secondary_sta_synchronized_connections opcode-jával.
Ez az opcode egy BOOL értéket ad vissza, amely jelzi, hogy az elsődleges és a másodlagos STA-kapcsolatok szinkronizálva vannak-e.
Íme egy példa az állapot lekérdezésére.
#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;
}
Kapcsolatok engedélyezése a másodlagos STA-felületen
A Windows csak akkor csatlakozik a másodlagos STA-felületekhez, ha létezik olyan alkalmazás, amely a másodlagos STA-kapcsolatot fogja használni. Annak szabályozásához, hogy a Windows a másodlagos STA-felületen csatlakozik-e, az alkalmazásnak meg kell hívnia WlanSetInterface a wlan_intf_opcode_secondary_sta_synchronized_connections opcode-jával, és egy BOOL paraméterrel kell megadnia, hogy engedélyezi vagy letiltsa-e a kapcsolatokat a másodlagos STA-felületen. A TRUE
értéke azt jelzi, hogy engedélyezni szeretné a másodlagos STA-kapcsolatot, míg a FALSE
értéke azt jelzi, hogy már nincs szüksége másodlagos sta-kapcsolatra.
Az API többször is redundáns, ha ugyanazt a értéket (TRUE
vagy FALSE
) hívja meg az API-t, és csak az új érték első példánya okozza a funkció módosítását.
Ha az alkalmazás engedélyezi a másodlagos STA-kapcsolatot, a leírót nyitva kell tartania a szolgáltatás számára a másodlagos STA-kapcsolat várhatóan használni kívánt időtartamára. Ha az alkalmazás explicit módon letiltja a másodlagos STA-kapcsolatot (vagy a WlanSetInterface meghívásával a FALSE
opcode wlan_intf_opcode_secondary_sta_synchronized_connections és paraméterértékével, vagy a WlanCloseHandlemeghívásával), vagy implicit módon (kilépéssel), a Windows letiltja a kapcsolatot a másodlagos sta interfészen keresztül, egy későbbi időpontban.
A másodlagos sta-kapcsolat mindaddig engedélyezve marad, amíg az alkalmazás legalább egyszer kéri.
Íme egy példa a másodlagos sta-kapcsolat engedélyezésére vagy letiltására.
#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;
}