Detección de disponibilidad del conjunto de API
En algunos casos, un nombre de contrato de conjunto de API determinado se puede asignar intencionadamente a un nombre de módulo vacío en algunos dispositivos Windows. Las razones de esto varían, pero un ejemplo común es que una característica costosa en términos de recursos del sistema se puede quitar del sistema operativo Windows cuando se configura para un dispositivo restringido por recursos. Esto supone un desafío para que las aplicaciones controlen correctamente las características opcionales en el nivel de API.
El enfoque tradicional para probar si hay disponible una API de Win32 es usar LoadLibrary o GetProcAddress. Sin embargo, no son un medio confiable para probar conjuntos de API debido a la compatibilidad con el reenvío inverso en Windows 10 y versiones posteriores. Cuando se aplica el reenvío inverso a una API determinada, LoadLibrary o GetProcAddress pueden resolverse en un puntero de función válido incluso en los casos en los que se ha quitado la implementación interna. En este caso, el puntero de función apuntará a una función de código auxiliar que simplemente devuelve un error.
Para detectar este caso, puede usar la función IsApiSetImplemented para consultar la disponibilidad subyacente de una implementación de API determinada. Esta prueba valida que llamar a esta función dará lugar a la ejecución de una implementación funcional de la API.
En el ejemplo de código siguiente se muestra cómo usar IsApiSetImplemented para determinar si la función WTSEnumerateSessions está disponible en el dispositivo actual antes de llamarla.
#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;
}