중요하다
이 항목의 정보는 모든 버전의 Windows 10 이상에 적용됩니다. 여기서는 이러한 버전을 "Windows"라고 하며 필요한 경우 예외를 호출합니다.
API 집합은 라이브러리 로더의 OS 지원을 사용하여 라이브러리 바인딩 프로세스에 모듈 네임스페이스 리디렉션을 도입합니다. API 집합 계약 이름은 파일 이름을 지정하지 않습니다. 로더는 해당 계약 이름에서 구현이 포함된 호스트 이진 파일로 런타임 리디렉션을 수행합니다.
로더가 런타임에 API 집합에 대한 종속성을 발견하면 이미지의 구성 데이터를 참조하여 해당 API 집합에 대한 호스트 이진 파일을 식별합니다. 이 구성 데이터를 API 집합 스키마호출합니다. 스키마는 OS의 속성으로 어셈블되며 지정된 디바이스에 포함된 이진 파일에 따라 API 집합과 이진 파일 간의 매핑이 다를 수 있습니다. 스키마를 사용하면 구현을 호스트하는 모듈의 이름이 변경되거나 분할되거나 리팩터링된 경우에도 단일 이진 파일의 가져온 함수를 다른 디바이스에서 올바르게 라우팅할 수 있습니다.
가져오기가 구현에 도달하는 방법
이진 파일은 가져오기 테이블의 이름으로 결정되는 두 가지 방법으로 API 집합 구현에 도달할 수 있습니다.
- 직접 API 집합 가져오기. 이진 파일은 API 집합 계약 이름을 가져옵니다. 로더는 API 집합 스키마를 통해 해당 이름을 현재 디바이스의 호스트 이진 파일로 확인합니다.
- 레거시 모듈 가져오기. 이진 파일은 samplefeature.dll같은 레거시 Windows 모듈 이름을 가져옵니다. 해당 모듈을 제공하는 버전에서 로더는 해당 모듈에 직접 바인딩합니다. 이를 대체한 버전에서 동일한 이름을 가진 역방향 전달자는 가져오기를 API 집합으로 리디렉션합니다. 그러면 로더가 스키마를 통해 확인됩니다.
이러한 이름 중 가져오기 테이블에서 끝나는 이름은 일반적으로 작성하는 원본이 아닌 연결하는 라이브러리에 의해 결정됩니다. Windows 우산 라이브러리를 참조하세요.
현재 버전의 Windows 대상으로 하는 코드에 API 집합 계약 이름을 사용하는 것이 좋습니다. 로더는 전달자 없이 호스트로 바로 확인합니다. API 집합이 존재하기 전에 릴리스된 Windows 버전에서도 실행되는 단일 이진 파일이 필요한 경우 레거시 모듈 이름을 가져옵니다. 역방향 전달은 레거시 모듈이 교체된 버전에서 이진 작업을 유지합니다.
직접 API 집합 가져오기
해결 방법은 3단계 시퀀스입니다.
- 이진 파일이 API 집합 계약 이름을 가져오거나 LoadLibrary에 전달합니다.
- 로더는 현재 디바이스의 API 집합 스키마에서 계약을 조회하고 스키마가 매핑하는 호스트 이진 파일을 찾습니다.
- 로더는 이진 파일을 호스트하고 가져온 함수를 호스트의 내보내기로 바인딩합니다.
매핑은 파일 시스템이 아닌 스키마에 있으므로 동일한 가져오기는 다른 디바이스의 다른 이진 파일로 확인할 수 있습니다.
| 디바이스 |
api-win-core-samplefeature 에 매핑 |
|---|---|
| 기능을 포함하는 디바이스 | samplefeature.dll |
| 리팩터링된 구현을 제공하는 디바이스 | samplefeaturecore.dll |
| 기능을 포함하지 않는 디바이스 | 매핑되지 않음 |
samplefeature 여기서 사용되는 이름은 가상의 Windows 구성 요소에 대한 설명 이름입니다.
사용되는 이진 파일은 바인딩된 호스트를 인식하지 못합니다. 이것이 바로 메커니즘의 포인트입니다. 계약은 안정적이며, 계약을 구현하는 모듈은 한 디바이스에서 다음 디바이스로 자유롭게 변경할 수 있습니다.
계약 이름의 가져오기는 중간 전달자 모듈이 없는 단일 작업에서 확인됩니다. 가장 효율적인 형식이며 API 집합에 대해 작성된 코드의 일반 경로입니다.
API 집합 이름 및 .dll 접미사
매핑은 디스크가 아닌 스키마에 유지되므로 .dll 끝나는 API 집합 이름은 해당 이름의 파일을 참조하지 않습니다. .dll 부분은 모듈 이름이 가져오기 테이블에서 철자되는 방식에서 전달되는 명명 규칙일 뿐입니다. API 집합 이름은 실제 DLL 파일의 별칭 또는 가상 이름과 비슷합니다.
로더 작업이 시작 api- 하거나 ext-로더가 스키마를 통해 계약을 확인하는 로더의 확장인 API 집합 런타임으로 라우팅하는 이름을 수신하는 경우 API 집합 런타임은 파일 이름이 아닌 API 집합 명명 규칙을 기준으로 이름을 구문 분석하므로 .dll 접미사는 확인되는 계약 이름의 일부가 아닙니다. 가져오기 테이블에 나타나는 이름에서 작업할 때 접미사를 포함합니다. 그렇지 않으면 해제할 수 있습니다.
로더는 동일한 스키마를 통해 두 가지 형태의 계약 이름, 버전이 지정된 계약 이름 및 계약 별칭을 모두 확인합니다. 이러한 이름을 제어하는 규칙은 API 집합 계약 이름을 참조하세요.
이름 안정성이 가용성과 동일하지 않음
API 집합 이름은 동일한 이름이 인식되는 모든 위치에서 항상 동일한 계약을 식별한다는 점에서 Windows 디바이스에서 안정적입니다. 이는 특정 디바이스에 대한 보장이 아니라 네임스페이스의 속성입니다.
지정된 계약이 디바이스에 없거나 호스트에 매핑되지 않을 수 있습니다. 이름에 대해 아무 것도 알려주지 않습니다. 구현이 실제로 있는지 확인하려면 API 집합 가용성 검색을 참조하세요.
필요한 해결 방법
구현에 도달하기 위해 API 집합을 통한 호출의 경우 다음을 모두 보유해야 합니다.
- 계약은 현재 디바이스의 스키마에 있습니다.
- 스키마는 계약을 호스트 이진 파일에 매핑하고 해당 호스트를 로드할 수 있습니다.
- 호스트는 이진 파일이 호출하는 특정 함수를 내보냅니다.
이러한 항목 중 하나가 유지되지 않는 경우 실패 화면은 API 집합을 가져온 방법에 따라 달라집니다.
| 가져오기 스타일 | 계약을 확인할 수 없는 경우의 동작 |
|---|---|
| 정적 가져오기 | 프로세스가 시작되지 않습니다. 로더는 코드가 실행되기 전에 정적 가져오기를 확인합니다. |
| 지연 로드 가져오기 | 프로세스가 정상적으로 시작됩니다. 해결 방법은 코드에서 오류를 처리할 수 있는 API에 대한 첫 번째 호출로 지연됩니다. |
누락된 내보내기는 누락된 계약과 별도로 보고됩니다. 호스트가 내보내지 않는 함수를 가져오는 이진 파일은 진입점 오류가 누락된 상태에서 실패합니다.
로드가 성공하지 못하는 내용
해결 방법은 계약을 호스트에 바인딩합니다. 해당 계약 내에서 개별 기능의 상태를 평가하지 않습니다.
계약은 개별적으로 사용 가능한 기능을 명명된 그룹으로 구성할 수 있습니다. 로더가 계약 세분성으로 바인딩되고 바인딩할 때 그룹 상태를 참조하지 않기 때문에 디바이스를 전달하는 계약이 정상적으로 확인되더라도 디바이스에서 그룹을 사용할 수 없습니다. 즉, 호스트 바인딩을 거부하는 것은 정적 가져오기에 치명적이므로 로더는 허용 경로를 사용하고 호출자에게 더 미세한 질문을 남깁니다.
코드의 결과는 로드 성공 또는 LoadLibrary 호출이 특정 기능을 사용할 수 있다는 증거가 아니라는 것입니다. 가용성 쿼리를 사용하여 명시적으로 해당 질문을 합니다. API 집합 가용성 검색을 참조하세요.
선택적 API 집합 및 지연 로드
애플리케이션이 존재하지 않을 수 있는 API 집합을 호출하는 경우 가용성 검사만으로는 충분하지 않습니다. 정적 가져오기를 사용하면 프로세스가 시작되지 않으므로 실행이 검사에 도달하지 않습니다.
선택적 코드 경로에 연결할 수 있도록 하려면 지연 로드를 위해 선택적 API를 전달하는 모듈을 구성하거나 가용성 쿼리가 성공한 후 LoadLibrary 및 GetProcAddress 를 사용하여 대상을 동적으로 확인합니다. 두 방법 모두에 대한 자세한 내용은 API 집합 가용성 검색을 참조하세요.
역방향 전달
API 집합 이름은 디바이스에서 모듈에 안정적인 네임스페이스를 제공하지만 모든 이진 파일을 이 시스템으로 변환하는 것이 항상 실용적인 것은 아닙니다. 애플리케이션은 몇 년 동안 일반적으로 사용되었을 수 있으며 이진 파일을 다시 컴파일하는 것은 불가능할 수 있습니다. 또한 일부 애플리케이션은 특정 API 집합이 도입되기 전에 빌드된 시스템에서 계속 실행되어야 합니다.
이를 수용하기 위해 원래 모듈을 포함하지 않는 버전에는 원래 Windows PC에 도입된 모듈 이름을 전달하고 내보내기를 API 집합으로 리디렉션하는 호환성 이진 파일과 같은 역방향 전달자 집합이 포함됩니다.
전체 데스크톱 버전은 원래 모듈을 제공합니다. 따라서 레거시 모듈 이름의 가져오기는 항상 모듈에 바인딩됩니다. 해당 모듈을 대체한 버전에서 동일한 이름을 사용하는 역방향 전달자가 간격을 덮습니다.
로더 작업은 다음과 같이 작동합니다.
- 로더는 디바이스에 없는 레거시 Windows PC 모듈 이름에 대한 종속성을 제공합니다.
- 로더는 해당 모듈 이름을 전달하는 역방향 전달자를 찾아 로드합니다.
- 역방향 전달자는 가져온 함수를 API 집합으로 리디렉션합니다.
- 로더는 이 항목의 앞부분에서 설명한 대로 스키마를 통해 API가 설정된 것을 확인합니다.
개념적으로 매핑은 다음과 같습니다.
가져온 DLL: samplefeature.dll
- 원래 모듈이 있는 버전에서 samplefeature.dll
- 그것을 대체 한 버전에서 : samplefeature.dll 역방향 전달자 ->
api-win-core-samplefeature->samplefeaturecore.dll
이 경로의 제한은 내보내기 적용 범위입니다. 역방향 전달자는 API 집합이 동일한 내보내기만 전달하므로 원래 모듈에서 수행했던 모든 함수를 반드시 내보내지는 않습니다. 역방향 전달자가 전달하지 않는 함수를 가져오는 이진 파일은 진입점 오류가 누락되어 로드되지 않습니다.
역방향 전달은 성공적인 해결을 구현이 있다는 증거로 처리하지 않는 이유이기도 합니다. 레거시 모듈 이름에 대한 GetProcAddress 호출은 오류를 반환하는 스텁으로 확인되는 유효한 함수 포인터를 반환할 수 있습니다. 대신 가용성을 명시적으로 쿼리합니다. API 집합 가용성 검색을 참조하세요.
메모
역방향 전달은 Win32 API 표면의 하위 집합만 포함합니다. 데스크톱 버전의 Windows 대상으로 하는 애플리케이션은 모든 Windows 디바이스에서 실행할 수 없습니다. 이진 파일이 현재 버전의 Windows 대상으로 하는 경우 API 집합 계약 이름이 더 직접적인 선택입니다.