Megosztás a következőn keresztül:


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:

  1. Az illesztőprogram támogatja a másodlagos STA-interfészeket a képességeiben.
  2. Nincs olyan házirend, amely megakadályozná a másodlagos STA-kapcsolatot.
  3. Legalább egy olyan alkalmazás van, amely a WlanSetInterface a wlan_intf_opcode_secondary_sta_synchronized_connections opcode-nal és a TRUEparamé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 FALSEopcode 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;
}