Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Nota
Para desenvolver para os recursos descritos neste tópico, o SDK do Windows 11 (10.0.22000.194) e posterior é necessário.
Há dois tipos de interfaces associadas a adaptadores que dão suporte a conexões de estação dupla (sta dupla) – interfaces STA primárias e interfaces STA secundárias. Todos os adaptadores expõem uma interface STA primária, mas apenas adaptadores que dão suporte à funcionalidade de STA dupla expõem interfaces STA secundárias.
Por padrão, o Windows se conecta somente na interface de STA primária. O Windows se conectará na interface sta secundária somente se todas as seguintes condições forem atendidas:
- O driver indica suporte para interfaces STA secundárias em suas funcionalidades.
- Não há nenhuma política que impeça a conectividade de STA secundária.
- Há pelo menos um aplicativo que chamou o WlanSetInterface com o wlan_intf_opcode_secondary_sta_synchronized_connections opcode com o parâmetro definido como
TRUE.
Consultando interfaces de STA duplo
Para determinar se um adaptador está configurado para STA duplo e para obter a lista de de GUIDinterface STA secundária, seu aplicativo deve chamar WlanQueryInterface (wlanapi.h) com o opcode wlan_intf_opcode_secondary_sta_interfaces.
Esse opcode usa como parâmetro o GUID da interface STA (estação primária) (que pode ser obtida por uma chamada para WlanEnumInterfaces) e retorna uma lista de interfaces STA secundárias associadas a essa interface sta primária.
Aqui está um exemplo de como obter a lista de interfaces STA secundárias.
#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;
}
Consultando o estado de conexões sincronizadas de STA duplo
Para determinar se um adaptador se conectará automaticamente pela interface sta secundária após uma conexão pela interface sta primária, seu aplicativo pode consultar o estado atual chamando WlanQueryInterface com o wlan_intf_opcode_secondary_sta_synchronized_connections opcode.
Esse opcode retorna um valor BOOL indicando se as conexões STA primárias e secundárias são sincronizadas.
Aqui está um exemplo de como consultar esse estado.
#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;
}
Habilitando conexões na interface sta secundária
O Windows não se conectará nas interfaces STA secundárias, a menos que exista um aplicativo que use a conexão STA secundária. Para controlar se o Windows se conecta na interface STA secundária, seu aplicativo deve chamar WlanSetInterface com o opcode wlan_intf_opcode_secondary_sta_synchronized_connections, com um parâmetro bool especificando se deseja habilitar ou desabilitar conexões na interface sta secundária. Um valor de TRUE indica que você gostaria de habilitar a conectividade de STA secundária, enquanto um valor de FALSE indica que você não precisa mais de conectividade sta secundária.
Chamar a API com a mesmo valor de (TRUE ou FALSE) várias vezes é redundante e apenas a primeira instância de um novo valor faz com que a funcionalidade seja alterada.
Depois que seu aplicativo habilitar a conectividade sta secundária, você deve manter o identificador para o serviço aberto durante a duração que você espera usar a conexão STA secundária. Depois que seu aplicativo desabilitar explicitamente a conectividade sta secundária (chamando WlanSetInterface com o wlan_intf_opcode_secondary_sta_synchronized_connections de opcode e o valor do parâmetro de FALSE, ou chamando WlanCloseHandle) ou implicitamente (saindo), o Windows desabilitará a conectividade pela interface sta secundária em algum momento depois disso.
A conectividade secundária do STA permanecerá habilitada desde que pelo menos uma vez o aplicativo a solicite.
Aqui está um exemplo mostrando como habilitar ou desabilitar a conectividade de STA secundária.
#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;
}