Freigeben über


Dual-STA-Abfrage und Konfiguration

Hinweis

Für die Entwicklung für die in diesem Thema beschriebenen Features ist das Windows 11 SDK (10.0.22000.194) und höher erforderlich.

Adaptern sind zwei Arten von Schnittstellen zugeordnet, die Dual-STA-Verbindungen (Dual-STA) unterstützen: primäre STA-Schnittstellen und sekundäre STA-Schnittstellen. Alle Adapter machen eine primäre STA-Schnittstelle verfügbar, aber nur Adapter, die die Dual-STA-Funktionalität unterstützen, machen sekundäre STA-Schnittstellen verfügbar.

Windows stellt standardmäßig nur eine Verbindung über die primäre STA-Schnittstelle her. Windows stellt nur dann eine Verbindung mit der sekundären STA-Schnittstelle her, wenn alle folgenden Bedingungen erfüllt sind:

  1. Der Treiber gibt die Unterstützung für sekundäre STA-Schnittstellen in seinen Funktionen an.
  2. Es gibt keine Richtlinie, die sekundäre STA-Konnektivität verhindert.
  3. Es gibt mindestens eine Anwendung, die das WlanSetInterface mit dem wlan_intf_opcode_secondary_sta_synchronized_connections opcode aufgerufen hat, wobei der Parameter auf TRUEfestgelegt ist.

Abfragen von Dual-STA-Schnittstellen

Um zu ermitteln, ob ein Adapter für Dual-STA konfiguriert ist, und um die Liste der sekundären STA-Schnittstellen-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 STA-Schnittstelle (Primary Station), die durch einen Aufruf von WlanEnumInterfaces abgerufen werden kann, und gibt eine Liste der sekundären STA-Schnittstellen zurück, die dieser primären STA-Schnittstelle zugeordnet sind.

Hier sehen Sie ein Beispiel für das 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 Zustands synchronisierter Dual-STA-Verbindungen

Um zu bestimmen, ob ein Adapter nach einer Verbindung über die primäre STA-Schnittstelle automatisch eine Verbindung über die sekundäre STA-Schnittstelle herstellt, 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 sind.

Hier sehen Sie ein Beispiel für die Abfrage 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 über die sekundären STA-Schnittstellen her, es sei denn, es ist eine Anwendung 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 angibt, ob Verbindungen auf der sekundären STA-Schnittstelle aktiviert oder deaktiviert werden sollen. Der Wert von TRUE gibt an, dass Sie die sekundäre STA-Konnektivität aktivieren möchten, während der Wert von FALSE angibt, dass Sie keine sekundäre STA-Konnektivität mehr benötigen.

Das mehrfache Aufrufen der API mit demselben Wert (TRUE oder FALSE) ist redundant, und nur die erste instance eines neuen Werts bewirkt, dass sich die Funktionalität ändert. Sobald Ihre Anwendung die sekundäre STA-Konnektivität aktiviert hat, müssen Sie das Handle für den Dienst für die Dauer geöffnet lassen, für die Sie erwarten, dass sie die sekundäre STA-Verbindung verwenden wird. 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 Parameterwert oder durch Aufrufen von FALSEWlanCloseHandle) 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 sie mindestens einmal von der Anwendung angefordert wird.

Hier sehen Sie ein Beispiel zum Aktivieren oder Deaktivieren der sekundären STA-Konnektivität.

#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;
}