检测 API 集可用性
在某些情况下,给定的 API 集协定名称可能会有意映射到某些 Windows 设备上的空模块名称。 原因各不相同,但一个常见示例是,在为资源受限的设备配置时,可能会从 Windows 操作系统中删除系统资源方面的昂贵功能。 这对应用程序在 API 级别正常处理可选功能提出了挑战。
用于测试 Win32 API 是否可用的传统方法是使用 LoadLibrary 或 GetProcAddress。 但是,由于 Windows 10 及更高版本中的反向转发支持,因此这些不是测试 API 集的可靠方法。 当反向转发应用于给定 API 时,LoadLibrary 或 GetProcAddress 可以解析为有效的函数指针,即使在内部实现已被删除的情况下也是如此。 在这种情况下,函数指针将指向一个只返回错误的存根函数。
为了检测这种情况,可以使用 IsApiSetImplemented 函数查询给定 API 实现的基础可用性。 此测试验证调用此函数是否将导致执行 API 的函数实现。
以下代码示例显示如何在调用 WTSEnumerateSessions 函数之前,使用 IsApiSetImplemented 来确定该函数在当前设备上是否可用。
#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;
}