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 10의 Windows 7 이상, UWP 버전(데스크톱, IoT, HoloLens, Nano Server 아님) |
참고 항목
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)이 발생합니다.
이 코드 샘플은 다음과 같은 ApiValidator 오류로 Windows 드라이버의 API 계층화 요구 사항에 실패합니다.
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를 호출하는 방법을 보여 줍니다. 이 샘플은 다음 ApiValidator 출력을 사용하여 Windows 드라이버의 API 계층화 요구 사항을 전달합니다.
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는 다른 오류 코드를 생성할 수 있습니다.