Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In sommige gevallen kan een bepaalde naam van een API-setcontract opzettelijk worden toegewezen aan een lege modulenaam op sommige Windows apparaten. De redenen hiervoor variƫren, maar een veelvoorkomend voorbeeld is dat een dure functie in termen van systeemresources kan worden verwijderd uit het Windows besturingssysteem wanneer deze is geconfigureerd voor een apparaat met resourcebeperking. Dit vormt een uitdaging voor toepassingen om optioneel functies op API-niveau correct te verwerken.
De traditionele methode voor het testen of een Win32-API beschikbaar is, is om LoadLibrary- of GetProcAddress-te gebruiken. Dit is echter geen betrouwbare methode voor het testen van API-sets vanwege reverse forwarding. Wanneer reverse forwarding wordt toegepast op een bepaalde API, kan LoadLibrary of GetProcAddress worden omgezet in een geldige functieaanwijzer, zelfs in gevallen waarin de interne implementatie is verwijderd. In dit geval wijst de functieaanwijzer naar een stub-functie die gewoon een fout retourneert.
Als u dit geval wilt detecteren, kunt u de functie IsApiSetImplemented gebruiken om een query uit te voeren op de onderliggende beschikbaarheid van een bepaalde API-implementatie. Deze test rapporteert of de API-set aanwezig is in het samengestelde API-setschema op het actieve apparaat en of deze is toegewezen aan een implementatiemodule.
Important
Een geslaagde beschikbaarheidsquery is geen garantie dat een bepaalde aanroep slaagt. Ga door met het afhandelen van fouten bij het laden van modules, ontbrekende exports en de eigen gedocumenteerde foutresultaten van de API.
In het volgende codevoorbeeld ziet u hoe u IsApiSetImplemented gebruikt om te bepalen of de API-set die WTSEnumerateSessionsW bevat, beschikbaar is op het huidige apparaat voordat u deze aanroept.
#include <windows.h>
#include <apiquery2.h>
#include <stdio.h>
#include <wtsapi32.h>
#pragma comment(lib, "OneCore.lib")
#pragma comment(lib, "Wtsapi32.lib")
int __cdecl wmain(int /* argc */, PCWSTR /* argv */ [])
{
PWTS_SESSION_INFOW pInfo = nullptr;
DWORD count = 0;
if (!IsApiSetImplemented("ext-ms-win-session-wtsapi32-l1-1-0"))
{
wprintf(L"ext-ms-win-session-wtsapi32-l1-1-0 is not available.\n");
return 0;
}
if (WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pInfo, &count))
{
wprintf(L"SessionCount = %lu\n", count);
for (DWORD i = 0; i < count; i++)
{
PWTS_SESSION_INFOW pCurInfo = &pInfo[i];
wprintf(L" %ls: ID = %lu, state = %d\n", pCurInfo->pWinStationName,
pCurInfo->SessionId, static_cast<int>(pCurInfo->State));
}
WTSFreeMemory(pInfo);
}
else
{
wprintf(L"WTSEnumerateSessionsW failure: %lu\n", GetLastError());
}
return 0;
}
IsApiSetImplemented wordt gedeclareerd in apiquery2.h en het normale openbare SDK-koppelingspad levert dit vanuit OneCore.lib. Deze bibliotheek staat los van elke importbibliotheek die nodig is om de optionele doel-API zelf aan te roepen.
In het bovenstaande voorbeeld wordt Wtsapi32.lib gekoppeld voor een statische import, waardoor het voorbeeld kort blijft. Een productietoepassing die moet worden uitgevoerd waar de API-set afwezig is, moet ook de richtlijnen toepassen in Optionele codepad bereikbaar houden.
De naam van de query kiezen
Geef de naam door van de API-set die u wilt testen. API-setnamen worden conventioneel geschreven zonder achtervoegsel .dll en de voorbeelden op deze pagina gebruiken dat formulier. Het achtervoegsel maakt geen deel uit van de naam van de API-set.
Zie de tabel Vereisten op de referentiepagina voor de API die u wilt aanroepen om de naam te vinden die moet worden doorgegeven. Als deze tabel een API-setrij heeft, krijgt deze de naam van het contract. Gebruik anders de DLL-rij , maar alleen wanneer de naam er zelf een contractnaam is die begint met api- of ext-; een naam van een fysieke module, zoals Wtsapi32.dll geen contract is, en het uitvoeren van query's op ONWAAR.
De vorm van de naam is afhankelijk van de wijze waarop de API wordt geadresseerd.
| API-oppervlak | Queryformulier | Example |
|---|---|---|
| Benoemde groep | <contract>~<group> |
api-win-core-samplefeature~AdvancedOperations |
| Standaardgroep | Contractalias, zonder ~Default |
api-win-core-samplefeature |
| Versie-contract | Volledige naam van versie van contract | ext-ms-win-core-samplefeature-l1-1-0 |
De samplefeature namen zijn illustratieve namen voor een fictief Windows onderdeel. Het naamvoorvoegsel (api- of ext-) speelt geen rol in het beschikbaarheidsgedrag.
Voor een benoemde groep betekent een geslaagde query dat de groep bestaat, het contract is toegewezen aan een implementatiemodule, die host kan worden gebruikt in de huidige uitvoeringsomgeving, wordt de groep niet uitgeschakeld en wordt een systeemfunctie ingeschakeld die aan de groep is gekoppeld. Een query die gebruikmaakt van een contractalias past het contract en de hostcontroles toe.
Als de openbare header van de API een Is<APIName>Present helper levert, geeft u de voorkeur aan die helper. Deze bevat al de juiste naam voor de API-set of -groep die de API draagt.
Het resultaat van een query is contract- of groepsgranulatie, niet functiegranulatief. Twee helpers die worden ondersteund door dezelfde benoemde groep, retourneren altijd hetzelfde resultaat, ook al heeft elke helper een naam voor een andere API.
Het optionele codepad bereikbaar houden
Een beschikbaarheidscontrole kan het opstarten van processen niet beveiligen als de optionele API is gekoppeld als een statische import. Het laadprogramma lost statische importbewerkingen op voordat uw code wordt uitgevoerd, zodat een ontbrekende module het proces mislukt voordat de uitvoering de controle bereikt.
Gebruik een van deze methoden:
- Configureer de module die de optionele API bevat voor vertraging bij het laden. Vertraging laden is een linkerinstelling: geef op
/DELAYLOAD:<module>en link delayimp.lib. Geef de modulenaam op die wordt weergegeven in de importtabel van uw binaire bestand. Dit kan de klassieke DLL-naam zijn in plaats van de naam van het API-setcontract. In het voorgaande voorbeeld is die naam WTSAPI32.dll. - Of los het doel dynamisch op met LoadLibrary en GetProcAddress nadat de beschikbaarheidsquery is geslaagd.
Gebruik LoadLibrary of GetProcAddress niet als vervanging voor de beschikbaarheidsquery. Ze beantwoorden module en exporteren vragen, ze evalueren de status van de benoemde groep niet en ze kunnen worden omgezet in een stub voor reverse-forwarding zoals eerder beschreven. Gebruik deze na de query om de afzonderlijke module af te handelen en controles te exporteren.
Gedrag in eerdere versies van Windows
De implementatie die door OneCore.lib wordt geleverd, selecteert een beschikbaar querymechanisme tijdens runtime, dus een toepassing die IsApiSetImplemented aanroept, kan nog steeds worden uitgevoerd op een systeem dat voorafgaat aan de ondersteuning van de onderliggende query.
Op een systeem waar geen querymechanisme beschikbaar is:
- Een groepsgegekwalificeerde naam die ONWAAR retourneert
~. Een systeem dat benoemde groepen niet kan evalueren, kan niet rapporteren dat een groep beschikbaar is. - Een naam die niet is gegroepeerd, kan TRUE retourneren. Dit behoudt de compatibiliteit met toepassingen die hun eigen doorstuur-DLL's op vroege versies van Windows hebben geleverd, waarbij het contract in feite tevreden was met die doorstuurserver.
Gebruik geen API-set beschikbaarheidsquery als een beveiligings- of autorisatiecontrole.