Delen via


Beschikbaarheid van API-set detecteren

In sommige gevallen kan een bepaalde naam van een API-setcontract opzettelijk worden toegewezen aan een lege modulenaam op sommige Windows-apparaten. De redenen hiervoor variƫren, maar een veelvoorkomend voorbeeld is dat een dure functie in termen van systeembronnen kan worden verwijderd uit het Windows-besturingssysteem wanneer deze is geconfigureerd voor een apparaat met beperkte resources. Dit vormt een uitdaging voor toepassingen om optioneel functies op API-niveau correct te verwerken.

De traditionele methode voor het testen of een Win32-API beschikbaar is, is om LoadLibrary- of GetProcAddress-te gebruiken. Dit is echter geen betrouwbare methode voor het testen van API-sets vanwege de reverse forwarding ondersteuning in Windows 10 en hoger. Wanneer reverse forwarding wordt toegepast op een bepaalde API, kan LoadLibrary of GetProcAddress worden omgezet in een geldige functieaanwijzer, zelfs in gevallen waarin de interne implementatie is verwijderd. In dit geval wijst de functieaanwijzer naar een stub-functie die gewoon een fout retourneert.

Als u dit geval wilt detecteren, kunt u de functie IsApiSetImplemented gebruiken om een query uit te voeren op de onderliggende beschikbaarheid van een bepaalde API-implementatie. Met deze test wordt gevalideerd dat het aanroepen van deze functie resulteert in het uitvoeren van een functionele implementatie van de API.

In het volgende codevoorbeeld ziet u hoe u IsApiSetImplemented kunt gebruiken om te bepalen of de WTSEnumerateSessions functie beschikbaar is op het huidige apparaat voordat u deze aanroept.

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