Condividi tramite


Rilevare la disponibilità di un set di API

In alcuni casi, un determinato nome di contratto del set di API può essere intenzionalmente mappato a un nome di modulo vuoto in alcuni dispositivi Windows. I motivi di questo problema variano, ma un esempio comune è che una funzionalità costosa in termini di risorse di sistema può essere rimossa dal sistema operativo Windows quando configurata per un dispositivo con vincoli di risorse. Ciò comporta una sfida per le applicazioni di gestire normalmente le funzionalità facoltative a livello di API.

L'approccio tradizionale per verificare se è disponibile un'API Win32 consiste nell'usare LoadLibrary o GetProcAddress. Tuttavia, questi non sono un mezzo affidabile per il test dei set di API a causa del supporto dell'inoltro inverso in Windows 10 e versioni successive. Quando l'inoltro inverso viene applicato a una determinata API, LoadLibrary o GetProcAddress può risolversi in un puntatore a funzione valido anche nei casi in cui l'implementazione interna è stata rimossa. In questo caso, il puntatore alla funzione punterà a una funzione stub che restituisce semplicemente un errore.

Per rilevare questo caso, è possibile usare la funzione IsApiSetImplemented per eseguire una query sulla disponibilità sottostante di una determinata implementazione dell'API. Questo test convalida che la chiamata a questa funzione comporterà l'esecuzione di un'implementazione funzionale dell'API.

Nell'esempio di codice seguente viene illustrato come usare IsApiSetImplemented per determinare se la funzione WT edizione Standard numerateSessions è disponibile nel dispositivo corrente prima di chiamarla.

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