Partager via


Compilation pour OneCore

Lorsque vous utilisez Visual Studio pour créer du code en mode utilisateur pour Windows 10, vous pouvez personnaliser les options de l’éditeur de liens pour cibler des versions spécifiques de Windows. Considérons les facteurs suivants :

  • Le binaire généré doit-il uniquement fonctionner sur la version la plus récente de Windows ? Ou doit-il fonctionner sur des versions antérieures, telles que Windows 7 ?

  • Votre projet a-t-il des dépendances UWP ?

Par exemple, lorsque vous créez un nouveau projet de pilote UMDF v2, Visual Studio se lie à OneCoreUAP.lib par défaut. Cela donne un binaire qui fonctionne sur la version la plus récente de Windows, et permet l’ajout de fonctionnalités UWP.

Cependant, selon vos besoins, vous pouvez choisir de vous lier à OneCore.lib à la place. Le tableau suivant montre les scénarios applicables à chaque bibliothèque :

Bibliothèque Scénario
OneCore.lib Toutes les éditions de Windows 7 et ultérieures, sans support UWP
OneCoreUAP.lib Windows 7 et ultérieures, éditions UWP (Desktop, IoT, HoloLens, mais pas Nano Server) de Windows 10

Remarque

Pour modifier les options de l’éditeur de liens dans Visual Studio, choisissez les propriétés du projet et accédez à Linker->Input->Additional Dependencies.

Un sous-ensemble des API Windows compile sans problème, mais renvoie des erreurs d’exécution sur les éditions OneCore non-Desktop (par exemple Mobile ou IoT).

Par exemple, la fonction InstallApplication renvoie ERROR_ NOT_SUPPORTED sur les éditions OneCore non-Desktop. L’outil ApiValidator signale également ces problèmes. La section suivante décrit comment les corriger.

Correction des erreurs ApiValidator en utilisant IsApiSetImplemented

Si votre code appelle des API non universelles, vous pourriez voir les erreurs ApiValidator suivantes :

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

    Si votre application ou pilote de base doit fonctionner sur Windows 10 ainsi que sur des versions antérieures de Windows, vous devez supprimer les appels d’API dans la catégorie ci-dessus.

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

    Les appels d’API dans la catégorie ci-dessus se compilent correctement, mais peuvent ne pas se comporter comme prévu à l’exécution, selon le système d’exploitation cible. Pour satisfaire à l’exigence API Layering pour les pilotes Windows, encapsulez ces appels avec IsApiSetImplemented.

Cela vous permet de compiler votre code sans erreurs. Puis, à l’exécution, si la machine cible ne dispose pas de l’API requise, IsApiSetImplemented renvoie FALSE.

Les exemples de code suivants illustrent comment faire cela.

Exemple de code : Utilisation directe de l’API, sans évaluation de son existence

Ce code fonctionne bien sur les versions de Windows antérieures à Windows 10, mais son exécution sur une édition OneCore de Windows 10 entraîne un échec de WTSEnumerateSessions : 78 ou ERROR_CALL_NOT_IMPLEMENTED 120 (0x78).

Cet exemple de code échoue à l’exigence API Layering pour les pilotes Windows avec les erreurs ApiValidator suivantes :

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

Voici le code  :

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

Exemple de code : Utilisation directe de l’API, après évaluation de son existence

Cet exemple montre comment appeler IsApiSetImplemented. Cet exemple satisfait à l’exigence API Layering pour les pilotes Windows avec la sortie ApiValidator suivante :

ApiValidation: All binaries are Universal

Voici le code  :

#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;
}
  • Examinez les options de l’éditeur de liens ci-dessus et mettez à jour votre projet Visual Studio en conséquence.
  • Utilisez l’outil ApiValidator dans le WDK. Cet outil s’exécute automatiquement lorsque vous construisez un pilote dans Visual Studio.
  • Utilisez des tests d’exécution pour vérifier que votre code en mode utilisateur fonctionne comme prévu sur les éditions OneCore non-Desktop. Notez que les API factices peuvent générer des codes d’erreur différents.

Voir aussi