Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Em alguns casos, um determinado nome de contrato de conjunto de API pode ser mapeado intencionalmente para um nome de módulo vazio em alguns dispositivos Windows. Os motivos para isso variam, mas um exemplo comum é que um recurso caro em termos de recursos do sistema pode ser removido do sistema operacional Windows quando configurado para um dispositivo com restrição de recurso. Isso representa um desafio para os aplicativos lidarem normalmente com recursos opcionais no nível da API.
A abordagem tradicional para testar se uma API Win32 está disponível é usar loadLibrary ou GetProcAddress. No entanto, esses não são um meio confiável para testar conjuntos de API devido ao encaminhamento reverso. Quando o encaminhamento reverso é aplicado a uma determinada API, LoadLibrary ou GetProcAddress podem resolver para um ponteiro de função válido mesmo nos casos em que a implementação interna foi removida. Nesse caso, o ponteiro da função apontará para uma função stub que simplesmente retorna um erro.
Para detectar esse caso, você pode usar a função IsApiSetImplemented para consultar a disponibilidade subjacente de uma determinada implementação de API. Esse teste informa se o conjunto de API está presente no esquema de conjunto de API composto no dispositivo em execução e se ele está mapeado para um módulo de implementação.
Importante
Uma consulta de disponibilidade bem-sucedida não é uma garantia de que uma chamada específica será bem-sucedida. Continue a lidar com erros de carregamento de módulo, exportações ausentes e os próprios resultados de falha documentados da API.
O exemplo de código a seguir demonstra como usar IsApiSetImplemented para determinar se o conjunto de API que contém WTSEnumerateSessionsW está disponível no dispositivo atual antes de chamá-lo.
#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 é declarado em apiquery2.h e o caminho de link público normal do SDK fornece-o do OneCore.lib. Essa biblioteca é separada de qualquer biblioteca de importação necessária para chamar a própria API de destino opcional.
O exemplo acima vincula Wtsapi32.lib para uma importação estática, o que mantém o exemplo curto. Um aplicativo de produção que deve ser executado onde o conjunto de API está ausente também deve aplicar as diretrizes em Manter o caminho de código opcional acessível.
Escolha o nome da consulta
Passe o nome do conjunto de API que você está testando. Os nomes de conjuntos de API são escritos convencionalmente sem sufixo .dll e os exemplos nesta página usam esse formulário. O sufixo não faz parte do nome do conjunto de API.
Para localizar o nome a ser passado, consulte a tabela Requisitos na página de referência da API que você deseja chamar. Se essa tabela tiver uma linha de conjunto de API , ela fornecerá o nome do contrato. Caso contrário, use a linha DLL , mas somente quando o nome houver um nome de contrato começando com api- ou ext-; um nome de módulo físico como Wtsapi32.dll não é um contrato e consultá-lo retornará FALSE.
A forma do nome depende de como a API é endereçada.
| Superfície da API | Formulário de consulta | Example |
|---|---|---|
| Grupo nomeado | <contract>~<group> |
api-win-core-samplefeature~AdvancedOperations |
| Grupo padrão | Alias de contrato, sem ~Default |
api-win-core-samplefeature |
| Contrato com versão | Nome completo do contrato com versão | ext-ms-win-core-samplefeature-l1-1-0 |
Os samplefeature nomes são nomes ilustrativos para um componente de Windows fictício. O prefixo de nome (api- ou ext-) não desempenha uma função no comportamento de disponibilidade.
Para um grupo nomeado, uma consulta bem-sucedida significa que o grupo existe, seu contrato é mapeado para um módulo de implementação, esse host é utilizável no ambiente de execução atual, o grupo não está desabilitado e qualquer recurso do sistema associado ao grupo está habilitado. Uma consulta que usa um alias de contrato aplica o contrato e verificações de host.
Se o cabeçalho público da API fornecer um Is<APIName>Present auxiliar, prefira esse auxiliar. Ele já contém o nome correto para o conjunto de API ou grupo que carrega a API.
O resultado de uma consulta é contrato ou grupo granular, não função granular. Dois auxiliares apoiados pelo mesmo grupo nomeado sempre retornam o mesmo resultado, mesmo que cada auxiliar seja nomeado para uma API diferente.
Manter o caminho do código opcional acessível
Uma verificação de disponibilidade não poderá proteger a inicialização do processo se a API opcional estiver vinculada como uma importação estática. O carregador resolve as importações estáticas antes da execução do código, portanto, um módulo ausente falha no processo antes que a execução atinja a verificação.
Use uma destas abordagens:
- Configure o módulo que carrega a API opcional para o carregamento de atraso. Atraso no carregamento é uma configuração do vinculador: especificar
/DELAYLOAD:<module>e vincular delayimp.lib. Especifique o nome do módulo que aparece na tabela de importação do binário, que pode ser o nome de DLL clássico em vez do nome do contrato do conjunto de API. Para o exemplo anterior, esse nome é WTSAPI32.dll. - Ou resolva o destino dinamicamente com LoadLibrary e GetProcAddress depois que a consulta de disponibilidade for bem-sucedida.
Não use LoadLibrary ou GetProcAddress como um substituto para a consulta de disponibilidade. Eles respondem perguntas de módulo e exportação, não avaliam o estado do grupo nomeado e podem resolver para um stub de encaminhamento reverso, conforme descrito anteriormente. Use-os após a consulta para manipular o módulo separado e as verificações de exportação.
Comportamento em versões anteriores do Windows
A implementação fornecida pelo OneCore.lib seleciona um mecanismo de consulta disponível em tempo de execução, de modo que um aplicativo que chama IsApiSetImplemented ainda pode ser executado em um sistema que predefini o suporte à consulta subjacente.
Em um sistema em que nenhum mecanismo de consulta está disponível:
- Um nome qualificado por grupo que contém
~retorna FALSE. Um sistema que não pode avaliar grupos nomeados não pode relatar que um grupo está disponível. - Um nome que não é qualificado por grupo pode retornar TRUE. Isso preserva a compatibilidade com aplicativos que forneceram suas próprias DLLs de encaminhador em versões iniciais de Windows, em que o contrato foi de fato atendido por esse encaminhador.
Não use uma consulta de disponibilidade de conjunto de API como uma verificação de segurança ou autorização.