Dual-STA Abfrage und Konfiguration
Anmerkung
Um die in diesem Thema beschriebenen Features zu entwickeln, ist das Windows 11 SDK (10.0.22000.194) und höher erforderlich.
Es gibt zwei Arten von Schnittstellen, die Adaptern zugeordnet sind, die duale Station (Dual-STA)-Verbindungen unterstützen– primäre STA-Schnittstellen und sekundäre STA-Schnittstellen. Alle Adapter stellen eine primäre STA-Schnittstelle zur Verfügung, aber nur Adapter, die die Dual-STA-Funktionalität unterstützen, machen sekundäre STA-Schnittstellen verfügbar.
Standardmäßig verbindet Windows nur die primäre STA-Schnittstelle. Windows stellt nur dann eine Verbindung mit der sekundären STA-Schnittstelle her, wenn alle folgenden Bedingungen erfüllt sind:
- Der Treiber gibt die Unterstützung für sekundäre STA-Schnittstellen in seinen Funktionen an.
- Es gibt keine Richtlinie, die sekundäre STA-Konnektivität verhindert.
- Es gibt mindestens eine Anwendung, die den WlanSetInterface- mit dem wlan_intf_opcode_secondary_sta_synchronized_connections Opcode aufgerufen hat, wobei der Parameter auf
TRUE
festgelegt ist.
Abfragen von Dual-STA-Schnittstellen
Um festzustellen, ob ein Adapter für Dual-STA konfiguriert ist und um die Liste der sekundären STA-Schnittstelle GUID-s abzurufen, muss Ihre Anwendung WlanQueryInterface- (wlanapi.h) mit dem wlan_intf_opcode_secondary_sta_interfaces opcode aufrufen.
Dieser Opcode verwendet als Parameter die GUID- der Primärstationsschnittstelle (STA), die durch einen Aufruf von WlanEnumInterfacesabgerufen werden kann, und es wird eine Liste der sekundären STA-Schnittstellen zurückgegeben, die dieser primären STA-Schnittstelle zugeordnet sind.
Hier ist ein Beispiel zum Abrufen der Liste der sekundären STA-Schnittstellen.
#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;
}
Abfragen des synchronisierten Verbindungszustands von dual-STA
Um festzustellen, ob ein Adapter automatisch über die sekundäre STA-Schnittstelle verbunden wird, nachdem eine Verbindung über die primäre STA-Schnittstelle hergestellt wurde, kann Ihre Anwendung den aktuellen Zustand abfragen, indem sie WlanQueryInterface- mit dem wlan_intf_opcode_secondary_sta_synchronized_connections Opcode aufruft.
Dieser Opcode gibt einen BOOL- Wert zurück, der angibt, ob die primären und sekundären STA-Verbindungen synchronisiert werden.
Hier ist ein Beispiel für das Abfragen dieses Zustands.
#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;
}
Aktivieren von Verbindungen auf der sekundären STA-Schnittstelle
Windows stellt keine Verbindung mit den sekundären STA-Schnittstellen her, es sei denn, eine Anwendung ist vorhanden, die die sekundäre STA-Verbindung verwendet. Um zu steuern, ob Windows eine Verbindung über die sekundäre STA-Schnittstelle herstellt, muss Ihre Anwendung WlanSetInterface- mit dem wlan_intf_opcode_secondary_sta_synchronized_connections Opcode aufrufen, wobei ein boOL--Parameter angegeben wird, der angibt, ob Verbindungen auf der sekundären STA-Schnittstelle aktiviert oder deaktiviert werden sollen. Ein Wert von TRUE
gibt an, dass Sie die sekundäre STA-Konnektivität aktivieren möchten, während ein Wert von FALSE
angibt, dass Sie keine sekundäre STA-Verbindung mehr benötigen.
Das Aufrufen der API mit dem gleichen Wert (TRUE
oder FALSE
) ist mehrfach redundant, und nur die erste Instanz eines neuen Werts bewirkt, dass sich die Funktionalität ändert.
Sobald Ihre Anwendung die sekundäre STA-Konnektivität aktiviert hat, müssen Sie den Handle für die Dauer geöffnet lassen, die Sie für die Verwendung der sekundären STA-Verbindung erwarten. Sobald Ihre Anwendung die sekundäre STA-Konnektivität explizit deaktiviert (entweder durch Aufrufen von WlanSetInterface mit dem opcode-wlan_intf_opcode_secondary_sta_synchronized_connections und dem Parameterwert von FALSE
oder durch Aufrufen von WlanCloseHandle) oder implizit (durch Beenden) deaktiviert Windows die Konnektivität über die sekundäre STA-Schnittstelle zu einem bestimmten Zeitpunkt danach.
Die sekundäre STA-Konnektivität bleibt aktiviert, solange die Anwendung sie anfordert.
Hier ist ein Beispiel, das zeigt, wie sekundäre STA-Konnektivität aktiviert oder deaktiviert wird.
#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;
}