Detectar disponibilidade do conjunto de API
Em alguns casos, um determinado nome de contrato de conjunto de API pode ser intencionalmente mapeado para um nome de módulo vazio em alguns dispositivos Windows. As razões para isso variam, mas um exemplo comum é que um recurso caro em termos de recursos do sistema pode ser removido do sistema operacional Windows quando configurado para um dispositivo com restrição de recursos. Isso representa um desafio para os aplicativos lidarem normalmente com recursos opcionais no nível da API.
A abordagem tradicional para testar se uma API Win32 está disponível é usar LoadLibrary ou GetProcAddress. No entanto, esses não são um meio confiável para testar conjuntos de API devido ao suporte de encaminhamento reverso no Windows 10 e posterior. Quando o encaminhamento reverso é aplicado a uma determinada API, LoadLibrary ou GetProcAddress pode resolver para um ponteiro de função válido, mesmo nos casos em que a implementação interna foi removida. Nesse caso, o ponteiro da função estará apontando para uma função stub que simplesmente retorna um erro.
Para detectar esse caso, você pode usar a função IsApiSetImplemented para consultar a disponibilidade subjacente de uma determinada implementação de API. Esse teste valida que chamar essa função resultará na execução de uma implementação funcional da API.
O exemplo de código a seguir demonstra como usar IsApiSetImplemented para determinar se a função WTSEnumerateSessions está disponível no dispositivo atual antes de chamá-lo.
#include <windows.h>
#include <stdio.h>
#include <Wtsapi32.h>
int __cdecl wmain(int /* argc */, PCWSTR /* argv */ [])
{
PWTS_SESSION_INFO pInfo = {};
DWORD count = 0;
if (!IsApiSetImplemented("ext-ms-win-session-wtsapi32-l1-1-0"))
{
wprintf(L"IsApiSetImplemented on ext-ms-win-session-wtsapi32-l1-1-0 returns FALSE\n");
}
else
{
if (WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pInfo, &count))
{
wprintf(L"SessionCount = %d\n", count);
for (ULONG i = 0; i < count; i++)
{
PWTS_SESSION_INFO pCurInfo = &pInfo[i];
wprintf(L" %s: ID = %d, state = %d\n", pCurInfo->pWinStationName,
pCurInfo->SessionId, pCurInfo->State);
}
WTSFreeMemory(pInfo);
}
else
{
wprintf(L"WTSEnumerateSessions failure : %x\n", GetLastError());
}
}
return 0;
}