IRP_MN_QUERY_INTERFACE

IRP_MN_QUERY_INTERFACE 요청을 사용하면 드라이버가 직접 호출 인터페이스를 다른 드라이버로 내보낼 수 있습니다.

인터페이스를 내보내는 버스 드라이버는 자식 디바이스(자식 PDO)에 대해 이 요청을 처리해야 합니다. 함수 및 필터는 필요에 따라 이 요청을 처리할 수 있습니다.

이 컨텍스트의 "인터페이스"는 드라이버 또는 드라이버 집합에서 내보낸 하나 이상의 루틴과 데이터로 구성됩니다. 인터페이스에는 해당 내용을 설명하는 구조체와 형식을 식별하는 GUID가 있습니다.

예를 들어 PCMCIA 버스 드라이버는 PCMCIA 메모리 카드 쓰기 보호 조건 가져오기와 같은 작업에 대한 루틴을 포함하는 GUID_PCMCIA_INTERFACE_STANDARD 형식의 인터페이스를 내보냅니다. 이러한 메모리 카드 대한 함수 드라이버는 부모 PCMCIA 버스 드라이버에 IRP_MN_QUERY_INTERFACE 요청을 보내 PCMCIA 인터페이스 루틴에 대한 포인터를 가져올 수 있습니다.

참고

기존 인터페이스의 새 버전을 도입할 때 INTERFACE 구조의크기 또는 버전 필드를 수정하는 대신 새 GUID를 만듭니다. 자세한 내용은 Driver-Defined 인터페이스 사용을 참조하세요.

이 섹션에서는 일반적인 메커니즘으로 쿼리 인터페이스 IRP에 대해 설명합니다. 인터페이스를 노출하는 드라이버는 특정 인터페이스에 대한 추가 정보를 제공해야 합니다.

0x08

주 코드

IRP_MJ_PNP

보낸 경우

드라이버 또는 시스템 구성 요소는 디바이스에 대해 드라이버에서 내보낸 인터페이스에 대한 정보를 가져오기 위해 이 IRP를 보냅니다.

드라이버 또는 시스템 구성 요소는 임의 스레드 컨텍스트에서 IRQL = PASSIVE_LEVEL 이 IRP를 보냅니다.

드라이버는 디바이스에 대해 드라이버의 AddDevice 루틴이 호출된 후 언제든지 이 IRP를 받을 수 있습니다. 이 IRP가 전송될 때 디바이스가 시작되거나 시작되지 않을 수 있습니다(즉, 드라이버가 디바이스에 대한 IRP_MN_START_DEVICE 요청을 성공적으로 완료했다고 가정할 수 없음).

입력 매개 변수

IO_STACK_LOCATION 구조체의 Parameters.QueryInterface 멤버 자체는 요청되는 인터페이스를 설명하는 구조체입니다. 구조체에는 다음 정보가 포함됩니다.

CONST GUID *InterfaceType;
USHORT Size;
USHORT Version;
PINTERFACE Interface;
PVOID InterfaceSpecificData

구조체의 멤버는 다음과 같이 정의됩니다.

InterfaceType
요청되는 인터페이스를 식별하는 GUID를 가리킵니다. GUID는 GUID_BUS_INTERFACE_STANDARD 같은 시스템 정의 인터페이스 또는 사용자 지정 인터페이스에 대한 것일 수 있습니다. 시스템 정의 인터페이스에 대한 GUID는 Wdmguid.h에 나열됩니다. 사용자 지정 인터페이스에 대한 GUID는 Uuidgen을 사용하여 생성해야 합니다.

크기
요청되는 인터페이스의 크기를 지정합니다. 이 IRP를 처리하는 드라이버는 크기 바이트보다 큰 INTERFACE 구조를 반환해서는 안 됩니다.

Version
요청되는 인터페이스의 버전을 지정합니다.

드라이버가 둘 이상의 인터페이스 버전을 지원하는 경우 드라이버는 요청된 버전을 초과하지 않고 지원되는 가장 가까운 버전을 반환합니다. IRP를 보낸 구성 요소는 반환된 Interface.Version 필드를 검사하고 해당 값에 따라 수행할 작업을 결정해야 합니다.

인터페이스
요청된 인터페이스를 반환할 구조를 가리킵니다. 이 구조체는 INTERFACE 구조를 첫 번째 멤버로 포함해야 합니다. IRP를 보내는 구성 요소는 페이징된 메모리에서 이 구조를 할당합니다.

인터페이스를 내보내는 드라이버는 인터페이스 구조체를 포함하는 새 구조체 형식과 인터페이스 의 루틴 및/또는 데이터에 대한 멤버를 정의합니다. (드라이버는 위의 InterfaceType 멤버에 설명된 대로 인터페이스에 대한 GUID도 정의합니다.)

인터페이스를 내보내는 드라이버는 루틴을 호출할 수 있는 IRQL 등을 포함하여 인터페이스의 각 루틴에 대한 실행 환경을 정의합니다.

InterfaceSpecificData
요청되는 인터페이스에 대한 추가 정보를 지정합니다.

일부 인터페이스의 경우 IRP를 보내는 구성 요소는 이 필드에 추가 정보를 지정합니다. 일반적으로 이 필드는 NULL 이고 InterfaceTypeVersion 은 요청되는 인터페이스를 식별하기에 충분합니다.

출력 매개 변수

성공하면 드라이버는 Parameters.QueryInterface.Interface 구조체의 멤버를 채웁니다.

I/O 상태 블록

드라이버는 Irp-IoStatus.Status>를 STATUS_SUCCESS 또는 적절한 오류 상태 설정합니다.

성공하면 버스 드라이버가 Irp-IoStatus.Information>를 0으로 설정합니다.

함수 또는 필터 드라이버가 이 IRP를 처리하지 않는 경우 IoSkipCurrentIrpStackLocation 을 호출하고 IRP를 다음 드라이버로 전달합니다. 이러한 드라이버는 Irp-IoStatus.Status>를 수정해서는 안 되며 IRP를 완료해서는 안 됩니다.

버스 드라이버가 요청된 인터페이스를 내보내지 않아 자식 PDO에 대해 이 IRP를 처리하지 않는 경우 버스 드라이버는 Irp-IoStatus.Status>를 있는 그대로 두고 IRP를 완료합니다.

작업

매개 변수가 드라이버에서 지원하는 인터페이스를 지정하는 경우 드라이버는 이 IRP를 처리합니다.

IRP가 드라이버에서 지원하지 않는 인터페이스를 요청하는 경우 드라이버는 이 IRP를 큐에 대기시키지 않아야 합니다. 드라이버는 IO_STACK_LOCATION 구조에서 Parameters.QueryInterface.InterfaceType을 검사 합니다. 인터페이스가 드라이버에서 지원하는 인터페이스가 아닌 경우 드라이버는 차단하지 않고 디바이스 스택의 다음 하위 드라이버에 IRP를 전달해야 합니다.

각 인터페이스 는 InterfaceReferenceInterfaceDereference 루틴을 제공해야 하며 인터페이스를 내보내는 드라이버는 INTERFACE 구조에서 이러한 루틴의 주소를 제공해야 합니다. 드라이버는 IRP에 대한 응답으로 인터페이스를 반환하기 전에 InterfaceReference 루틴을 호출하여 인터페이스의 참조 횟수를 증가시켜야 합니다. 인터페이스를 요청한 드라이버의 사용이 완료되면 해당 드라이버는 인터페이스의 InterfaceDereference 루틴을 호출하여 참조 수를 감소시켜야 합니다.

IRP(드라이버 x)를 보내는 드라이버가 나중에 인터페이스를 다른 드라이버(드라이버 y)에 전달하는 경우 드라이버 x 는 인터페이스의 참조 횟수를 증가시켜야 하며 드라이버 y 는 이를 감소시켜야 합니다.

이 IRP를 처리하는 드라이버는 요청된 인터페이스를 가져오기 위해 IRP를 다른 디바이스 스택에 전달하지 않아야 합니다. 이러한 디자인은 관리하기 어려운 디바이스 스택 간에 종속성을 만듭니다. 예를 들어 첫 번째 스택의 적절한 드라이버가 인터페이스를 역참조할 때까지 두 번째 디바이스 스택으로 표시되는 디바이스를 제거할 수 없습니다.

인터페이스는 버스별 또는 버스 독립적일 수 있습니다. 버스 관련 인터페이스는 해당 버스의 헤더 파일에 정의됩니다. 시스템은 표준 버스 인터페이스를 내보내기 위한 버스 독립적 인터페이스 인 BUS_INTERFACE_STANDARD 정의합니다.

플러그 앤 플레이 사소한 IRP를 처리하기 위한 일반 규칙은 플러그 앤 플레이 참조하세요.

이 IRP는 특히 디바이스의 계층화된 커널 모드 드라이버 간에 일상적인 진입점을 전달하는 데 사용됩니다. 이 IRP에서 노출하는 인터페이스를 디바이스 인터페이스와 혼동하지 마세요. 디바이스 인터페이스는 주로 사용자 모드 구성 요소 또는 다른 커널 구성 요소에서 사용하기 위해 디바이스에 대한 경로를 노출하는 데 사용됩니다. 디바이스 인터페이스에 대한 자세한 내용은 디바이스 인터페이스 클래스를 참조하세요.

이 IRP 보내기

IRP 전송에 대한 자세한 내용은 IRP 처리를 참조하세요. 다음 단계는 이 IRP에 특히 적용됩니다.

  • 페이징된 풀에서 INTERFACE 구조를 할당하고 0으로 초기화합니다. 인터페이스 계약을 기반으로 IRQL >= DISPATCH_LEVEL 인터페이스를 호출하는 경우 호출자는 페이지가 지정되지 않은 풀에서 할당된 메모리에 콘텐츠를 복사할 수 있습니다.

  • IRP의 다음 I/O 스택 위치에 있는 값을 설정합니다. MajorFunctionIRP_MJ_PNP 설정하고, MinorFunctionIRP_MN_QUERY_INTERFACE 설정하고, Parameters.QueryInterface에서 적절한 값을 설정합니다.

  • IoStatus.Status를 STATUS_NOT_SUPPORTED 초기화합니다.

  • 더 이상 필요하지 않은 경우 IRP 및 INTERFACE 구조체의 할당을 취소합니다.

  • 인터페이스 사양에 설명된 대로 인터페이스 루틴 및 컨텍스트 매개 변수를 사용합니다.

  • 인터페이스가 더 이상 필요하지 않은 경우 InterfaceDereference 루틴을 사용하여 참조 횟수를 감소합니다. 인터페이스를 역참조한 후에는 인터페이스 루틴을 호출하지 마세요.

일반적으로 드라이버는 이 IRP를 드라이버가 연결된 디바이스 스택의 맨 위로 보냅니다. 드라이버가 이 IRP를 다른 디바이스 스택으로 보내는 경우 다른 디바이스가 드라이버가 서비스하는 디바이스의 상위 디바이스가 아닌 경우 드라이버는 다른 디바이스에서 대상 디바이스 알림을 등록해야 합니다. 이러한 드라이버는 EventCategoryTargetDeviceChangeEventCategory를 사용하여 IoRegisterPlugPlayNotification을 호출합니다. 드라이버가 형식 GUID_TARGET_DEVICE_QUERY_REMOVE 알림을 받으면 드라이버는 인터페이스를 역참조해야 합니다. 드라이버는 후속 GUID_TARGET_DEVICE_REMOVE_CANCELLED 알림을 수신하는 경우 인터페이스에 대해 다시 쿼리할 수 있습니다.

요구 사항

헤더

Wdm.h(Wdm.h, Ntddk.h 또는 Ntifs.h 포함)

추가 정보

BUS_INTERFACE_STANDARD

인터페이스

IoRegisterPlugPlayNotification