Partager via


Détecter la disponibilité des ensembles d’API

Dans certains cas, un nom de contrat d’ensemble d’API donné peut être intentionnellement mappé à un nom de module vide sur certains appareils Windows. Les raisons de cela varient, mais un exemple courant est qu’une fonctionnalité coûteuse en termes de ressources système peut être supprimée du système d’exploitation Windows lorsqu’elle est configurée pour un appareil à ressources limitées. Cela pose un défi pour les applications de gérer correctement les fonctionnalités facultatives au niveau de l’API.

L’approche traditionnelle pour tester si une API Win32 est disponible consiste à utiliser LoadLibrary ou GetProcAddress. Toutefois, il ne s’agit pas d’un moyen fiable pour tester les ensembles d’API en raison de la prise en charge du transfert inverse dans Windows 10 et versions ultérieures. Lorsque le transfert inverse est appliqué à une API donnée, LoadLibrary ou GetProcAddress peut se résoudre en pointeur de fonction valide, même dans les cas où l’implémentation interne a été supprimée. Dans ce cas, le pointeur de fonction pointe vers une fonction stub qui retourne simplement une erreur.

Pour détecter ce cas, vous pouvez utiliser la fonction IsApiSetImplemented pour interroger la disponibilité sous-jacente d’une implémentation d’API donnée. Ce test valide que l’appel de cette fonction entraîne l’exécution d’une implémentation fonctionnelle de l’API.

L’exemple de code suivant montre comment utiliser IsApiSetImplemented pour déterminer si la fonction WTSEnumerateSessions est disponible sur l’appareil actuel avant de l’appeler.

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