Partager via


Détecter la disponibilité du groupe d’API

Dans certains cas, un nom de contrat d’ensemble d’API donné peut être mappé intentionnellement à un nom de module vide sur certains appareils Windows. Les raisons de cette variation, 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 limité aux ressources. 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 de tester les ensembles d’API en raison de la prise en charge de de transfert inverse dans Windows 10 et versions ultérieures. Lorsque le transfert inverse est appliqué à une API donnée, LoadLibrary ou GetProcAddress peut être résolu en pointeur de fonction valide même si 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;
}