Erkennen der Verfügbarkeit von API-Sätze
In einigen Fällen kann ein bestimmter API-Satz-Vertragsname absichtlich einem leeren Modulnamen auf einigen Windows-Geräten zugeordnet werden. Die Gründe hierfür variieren, aber ein häufiges Beispiel ist, dass ein teures Feature in Bezug auf Systemressourcen möglicherweise aus dem Windows-Betriebssystem entfernt werden kann, wenn es für ein ressourceneinschränktes Gerät konfiguriert ist. Dies stellt eine Herausforderung für Anwendungen dar, optionale Features auf API-Ebene ordnungsgemäß zu behandeln.
Der herkömmliche Ansatz zum Testen, ob eine Win32-API verfügbar ist, besteht darin, LoadLibrary oder GetProcAddresszu verwenden. Dies ist jedoch kein zuverlässiges Mittel zum Testen von API-Sätzen aufgrund der Reverse forwarding Unterstützung in Windows 10 und höher. Wenn die Reverseweiterleitung auf eine bestimmte API angewendet wird, kann LoadLibrary oder GetProcAddress- zu einem gültigen Funktionszeiger aufgelöst werden, auch wenn die interne Implementierung entfernt wurde. In diesem Fall zeigt der Funktionszeiger auf eine Stubfunktion, die einfach einen Fehler zurückgibt.
Um diesen Fall zu erkennen, können Sie die IsApiSetImplemented--Funktion verwenden, um die zugrunde liegende Verfügbarkeit einer bestimmten API-Implementierung abzufragen. Dieser Test überprüft, ob das Aufrufen dieser Funktion dazu führt, dass eine funktionale Implementierung der API ausgeführt wird.
Im folgenden Codebeispiel wird veranschaulicht, wie IsApiSetImplemented- verwendet wird, um zu bestimmen, ob die WTSEnumerateSessions--Funktion auf dem aktuellen Gerät verfügbar ist, bevor sie aufgerufen wird.
#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;
}