Criar para OneCore

Ao usar o Visual Studio para criar códigos de modo de usuário para Windows 10, você pode personalizar as opções do vinculador para direcionar versões específicas do Windows. Considere os seguintes fatores:

  • O binário criado deve ser executado somente na versão mais recente do Windows? Ou deve ser executado em versões anteriores, como o Windows 7?

  • Seu projeto tem alguma dependência UWP?

Por exemplo, quando você cria um novo projeto de driver UMDF v2, o Visual Studio é vinculado a OneCoreUAP.lib por padrão. Isso resulta em um binário que é executado na versão mais recente do Windows e permite a adição da funcionalidade UWP.

No entanto, dependendo dos seus requisitos, você pode optar por vincular à OneCore.lib. A tabela a seguir mostra os cenários aplicáveis a cada biblioteca:

Biblioteca Cenário
OneCore.lib Todas as edições do Windows 7 e posteriores, sem suporte para UWP
OneCoreUAP.lib Windows 7 e versões posteriores, edições UWP (Desktop, IoT, HoloLens, mas não Nano Server) do Windows 10

Observação

Para alterar as opções do vinculador no Visual Studio, escolha as propriedades do projeto e navegue até Dependências adicionais de> entrada> do vinculador.

Um subconjunto de APIs do Windows é compilado corretamente, mas retorna erros de runtime em edições OneCore que não são Desktop (por exemplo, Mobile ou IoT).

Por exemplo, a função InstallApplication retorna ERROR_ NOT_SUPPORTED em edições OneCore não Desktop. A ferramenta ApiValidator também relata esses problemas. A próxima seção descreve como corrigi-los.

Corrigir erros do ApiValidator usando IsApiSetImplemented

Se o código chamar APIs não universais, você poderá ver os seguintes erros do ApiValidator:

  • Error: <Binary Name> has unsupported API call to <Module Name><Api Name>

    Se o aplicativo ou driver base precisar ser executado no Windows 10, bem como em versões anteriores do Windows, você deverá remover as chamadas de API na categoria acima.

  • Error: <Binary Name> has a dependency on <Module Name><Api Name> but is missing: IsApiSetImplemented("<contract-name-for-Module>)

    As chamadas de API na categoria acima são compiladas corretamente, mas podem não se comportar conforme o esperado no tempo de execução, dependendo do sistema operacional de destino. Para passar o requisito de camadas de API para drivers do Windows, encapsule essas chamadas com IsApiSetImplemented.

Isso permite que você compile seu código sem erros. Em seguida, no tempo de execução, se o computador de destino não tiver a API necessária, IsApiSetImplemented retornará FALSE.

Os exemplos de código a seguir ilustram como fazer isso.

Exemplo de código: uso direto da API, sem avaliar a existência

Esse código é executado corretamente em versões do Windows anteriores ao Windows 10, mas executá-lo em uma edição OneCore do Windows 10 resulta em falha WTSEnumerateSessions: 78 ou ERROR_CALL_NOT_IMPLEMENTED 120 (0x78).

Este exemplo de código falha no requisito de camadas de API dos drivers do Windows com os seguintes erros do ApiValidator:

ApiValidation: Error: FlexLinkTest.exe has a dependency on 'wtsapi32.dll!WTSEnumerateSessionsW' but is missing: IsApiSetImplemented("ext-ms-win-session-wtsapi32-l1-1-0")
ApiValidation: Error: FlexLinkTest.exe has a dependency on 'wtsapi32.dll!WTSFreeMemory' but is missing: IsApiSetImplemented("ext-ms-win-session-wtsapi32-l1-1-0")
ApiValidation: NOT all binaries are Universal

Este é o código :

#include <windows.h>
#include <stdio.h>
#include <Wtsapi32.h>

int __cdecl wmain(int /* argc */, PCWSTR /* argv */ [])
{
    PWTS_SESSION_INFO pInfo = {};
    DWORD count = 0;

    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;
}

Exemplo de código: uso direto da API, depois de avaliar a existência

Este exemplo mostra como chamar IsApiSetImplemented. Este exemplo passa o requisito de camadas de API dos drivers do Windows com a seguinte saída do ApiValidator:

ApiValidation: All binaries are Universal

Este é o código :

#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;
}
  • Analise as opções do vinculador acima e atualize seu projeto do Visual Studio adequadamente.
  • Use a ferramenta ApiValidator no WDK. Essa ferramenta é executada automaticamente quando você cria um driver no Visual Studio.
  • Use o teste de tempo de execução para verificar se o código do modo de usuário é executado conforme o esperado em edições OneCore que não são Desktop. As APIs de amostra podem gerar códigos de erro diferentes.

Confira também