検出 API セットの可用性

場合によっては、特定の API セット コントラクト名が、一部の Windows デバイスの空のモジュール名に意図的にマップされる場合があります。 この理由はさまざまですが、一般的な例として、リソースに制約のあるデバイス用に構成されている場合、システム リソースに関してコストの高い機能が Windows OS から削除される可能性があります。 これにより、アプリケーションが API レベルでオプション機能を適切に処理することが困難になります。

Win32 API を使用できるかどうかをテストするための従来のアプローチは、LoadLibrary または GetProcAddress を使用することです。 ただし、これらは、Windows 10 以降での逆転送サポートのため 、API セットをテストする上で信頼できる手段ではありません。 特定の API に逆転送を適用すると、内部実装が削除された場合でも、 LoadLibrary または GetProcAddress が有効な関数ポインターに解決される可能性があります。 この場合、関数ポインターは、単にエラーを返すスタブ関数を指します。

このケースを検出するために、IsApiSetImplemented 関数を使用して、特定の API 実装の基になる可用性をクエリできます。 このテストでは、この関数を呼び出すと API の機能実装が実行されることを検証します。

次のコード例では、IsApiSetImplemented を使用して、WTSEnumerateSessions 関数を呼び出す前に現在のデバイスで使用できるかどうかを判断する方法を示します。

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