OneCore をターゲットとしたビルド

Visual Studio を使用して Windows 10 のユーザー モード コードをビルドする場合、リンカー オプションをカスタマイズして、特定のバージョンの Windows をターゲットにすることができます。 次のような要素が考えられます。

  • ビルドされたバイナリは最新バージョンの Windows でのみ実行する必要がありますか? それとも、以前のバージョン (Windows 7 など) でも実行できますか。

  • プロジェクトに UWP の依存関係はありますか?

たとえば、新しい UMDF v2 ドライバー プロジェクトを作成した場合、Visual Studio は既定で OneCoreUAP.lib にリンクします。 これにより、最新バージョンの Windows で動作するバイナリが作成され、UWP 機能の追加が可能になります。

ただし、要件によっては、代わりに OneCore.lib をリンクすることができます。 次の表は、各ライブラリに対応するシナリオを示したものです。

ライブラリ シナリオ
OneCore.lib Windows 7 以降のすべてのエディション (UWP のサポートなし)
OneCoreUAP.lib Windows 7 以降、Windows 10 の UWP エディション (デスクトップ、IoT、HoloLens、ただし Nano Server は除く)

Note

Visual Studio でリンカー オプションを変更するには、プロジェクトのプロパティを選択して、[リンカー] -> [入力] -> [追加の依存ファイル] に移動します。

Windows API のサブセットは正常にコンパイルされますが、デスクトップ以外の OneCore エディション (モバイルや IoT など) ではランタイム エラーが返されます。

たとえば、InstallApplication 関数は、デスクトップ以外の OneCore エディションで ERROR_ NOT_SUPPORTED を返します。 これらの問題は ApiValidatorツールでも報告されます。 次のセクションでは、この問題を修正する方法について説明します。

IsApiSetImplemented を使用して ApiValidator のエラーを修正する

コードで非ユニバーサル API を呼び出すと、次の ApiValidator エラーが返される場合があります。

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

    アプリやベース ドライバーを Windows 10 と以前のバージョンの Windows で実行する必要がある場合は、上記のカテゴリの API 呼び出しを削除する必要があります。

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

    上記のカテゴリの API 呼び出しは正常にコンパイルされますが、対象のオペレーティング システムによっては、実行時に想定どおりの動作をしない可能性があります。 Windows ドライバーAPI レイヤー化要件をパスするには、IsApiSetImplemented を使用してこれらの呼び出しをラップします。

これにより、コードをエラーなくコンパイルすることができます。 その後の実行時に、ターゲット コンピューターに必要な API がない場合は、IsApiSetImplemented で FALSE が返されます。

次のコード サンプルは、これを行う方法を説明したものです。

コードサンプル: 存在を評価せずに API を直接使用する

このコードは Windows 10 より前のバージョンの Windows では正常に動作しますが、Windows 10 の OneCore エディションで実行すると WTSEnumerateSessions エラーが発生します。78 または ERROR_CALL_NOT_IMPLEMENTED 120 (0x78)。

このコード サンプルは、Windows ドライバーの API レイヤー化要件を満たさず、次の 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

のコードを次に示します。

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

コードサンプル: 存在を評価した後の API の直接使用

このサンプルは、IsApiSetImplemented を呼び出す方法を示したものです。 このサンプルは、Windows ドライバーの API レイヤー化要件を満たし、次の ApiValidator 出力が表示されます。

ApiValidation: All binaries are Universal

のコードを次に示します。

#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;
}
  • 上記のリンカー オプションを確認し、それに応じて Visual Studio プロジェクトを更新します。
  • WDK の ApiValidator ツールを使用します。 このツールは、Visual Studio でドライバーをビルドするときに自動的に実行されます。
  • ランタイム テストを使用して、ユーザー モード コードがデスクトップ以外の OneCore エディションで期待どおりに実行されることを確認します。 スタブ化された API は異なるエラー コードを生成する可能性があることに注意してください。

参照