检测 API 集可用性

在某些情况下,给定的 API 集协定名称可能会有意映射到某些Windows 10设备上的空模块名称。 原因各不相同,但一个常见示例是,在为资源受限设备配置时,系统资源方面的昂贵功能可能会从 Windows OS 中删除。 这给应用程序带来了一个挑战,即在 API 级别正常处理可选功能。

用于测试 Win32 API 是否可用的传统方法是使用 LoadLibraryGetProcAddress。 但是,由于Windows 10中的反向转发支持,这些不是测试 API 集的可靠方法。 当反向转发应用于给定 API 时,即使删除了内部实现, LoadLibraryGetProcAddress 也可以解析为有效的函数指针。 在这种情况下,函数指针将指向仅返回错误的存根函数。

为了检测这种情况,可以使用 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;
}