IRP_MN_QUERY_DEVICE_RELATIONS

PnP 관리자는 디바이스 간의 특정 관계를 확인하기 위해 이 요청을 보냅니다. 다음 유형의 드라이버가 이 요청을 처리합니다.

  • 버스 드라이버는 어댑터 또는 컨트롤러(버스 FDO)에 대한 BusRelations 요청을 처리해야 합니다. 필터 드라이버는 BusRelations 요청을 처리할 수 있습니다.

  • 버스 드라이버는 자식 디바이스(자식 PDO)에 대한 TargetDeviceRelation 요청을 처리해야 합니다.

  • 함수 및 필터 드라이버는 RemovalRelationsPowerRelations 요청을 처리할 수 있습니다.

  • 버스 드라이버는 자식 디바이스(자식 PDO)에 대한 EjectionRelations 요청을 처리할 수 있습니다.

0x07

주 코드

IRP_MJ_PNP

보낸 경우

PnP 관리자는 지정된 디바이스와 관계가 있는 디바이스에 대한 정보를 수집하기 위해 이 IRP를 보냅니다.

PnP 관리자는 디바이스가 열거될 때와 디바이스가 활성 상태일 때(예: 드라이버가 IoInvalidateDeviceRelations 루틴을 호출하여 자식 디바이스가 도착하거나 출발했음을 나타내는 경우)를 쿼리합니다.

PnP 관리자는 디바이스의 드라이버를 제거하기 전에 디바이스의 RemoveRelations 를 쿼리합니다. PnP 관리자는 디바이스를 꺼내기 전에 RemovalRelationsEjectionRelations 를 쿼리합니다.

PnP 관리자는 드라이버 또는 사용자 모드 애플리케이션이 디바이스에서 EventCategoryTargetDeviceChange의 PnP 알림을 등록할 때 디바이스의 TargetDeviceRelation을 쿼리합니다. PnP 관리자는 특정 파일 개체와 연결된 디바이스를 쿼리합니다. IRP_MN_QUERY_DEVICE_RELATIONS 유효한 파일 개체 매개 변수가 있는 유일한 PnP IRP입니다. 드라이버는 TargetDeviceRelation에 대한 디바이스 스택을 쿼리할 수 있습니다. 드라이버는 TargetDeviceRelation 쿼리를 보낼 때 파일 개체를 제공할 필요가 없습니다.

PnP 관리자는 디바이스용 드라이버가 IoInvalidateDeviceRelations를 호출할 때 디바이스의 PowerRelations를 쿼리하여 이 디바이스에 암시적 전원 관리 관계가 있는 디바이스 집합이 변경되었음을 나타냅니다. PowerRelations 요청은 Windows 7부터 지원됩니다.

BusRelations, RemovalRelations, EjectionRelationsPowerRelations 요청의 경우 PnP 관리자는 시스템 스레드의 컨텍스트에서 IRQL = PASSIVE_LEVEL IRP_MN_QUERY_DEVICE_RELATIONS 보냅니다.

TargetDeviceRelation 요청의 경우 PnP 관리자는 임의 스레드 컨텍스트에서 IRQL = PASSIVE_LEVEL 이 IRP를 보냅니다.

입력 매개 변수

IO_STACK_LOCATION 구조체의 Parameters.QueryDeviceRelations.Type 멤버는 쿼리되는 관계의 형식을 지정합니다. 가능한 값으로 는 BusRelations, EjectionRelations, RemovalRelations, TargetDeviceRelationPowerRelations가 있습니다.

현재 IO_STACK_LOCATION 구조체의 FileObject 멤버는 Parameters.QueryDeviceRelations.Type이 TargetDeviceRelation인 경우에만 유효한 파일 개체 가리킵니다.

출력 매개 변수

I/O 상태 블록에서 반환됩니다.

I/O 상태 블록

드라이버는 Irp-IoStatus.Status>를 STATUS_SUCCESS 또는 STATUS_INSUFFICIENT_RESOURCES 같은 오류 상태 설정합니다.

성공하면 드라이버는 Irp-IoStatus.Information>를 요청된 관계 정보를 가리키는 PDEVICE_RELATIONS 포인터로 설정합니다. DEVICE_RELATIONS 구조체는 다음과 같이 정의됩니다.

typedef struct _DEVICE_RELATIONS {
  ULONG  Count;
  PDEVICE_OBJECT  Objects[1];  // variable length
} DEVICE_RELATIONS, *PDEVICE_RELATIONS;

작업

드라이버가 이 IRP_MN_QUERY_DEVICE_RELATIONS 대한 응답으로 관계를 반환하는 경우 드라이버는 페이징된 메모리에서 개수와 적절한 수의 디바이스 개체 포인터를 포함하는 DEVICE_RELATIONS 구조를 할당합니다. PnP 관리자는 더 이상 필요하지 않은 구조체를 해제합니다. 드라이버가 다른 드라이버가 할당한 DEVICE_RELATIONS 구조를 대체하는 경우 드라이버는 이전 구조를 해제해야 합니다.

드라이버는 이 IRP(ObReferenceObject)에서 보고하는 모든 디바이스의 PDO를 참조해야 합니다. PnP 관리자는 적절한 경우 참조를 제거합니다.

디바이스에 대한 AddDevice 루틴이 완료된 후 언제든지 디바이스에 대해 이 IRP를 처리하도록 함수 또는 필터 드라이버를 준비해야 합니다. 버스 드라이버는 디바이스가 열거된 직후 BusRelations 에 대한 쿼리를 처리할 수 있도록 준비해야 합니다.

플러그 앤 플레이 사소한 IRP 처리에 대한 일반적인 규칙은 플러그 앤 플레이 참조하세요.

다음 하위 섹션에서는 다양한 쿼리를 처리하기 위한 특정 작업을 설명합니다.

BusRelations 요청

PnP 관리자가 어댑터 또는 컨트롤러의 버스 관계(자식 디바이스)를 쿼리할 때 버스 드라이버는 버스에 물리적으로 있는 모든 디바이스의 PDO에 대한 포인터 목록을 반환해야 합니다. 버스 드라이버는 시작 여부에 관계없이 모든 디바이스를 보고합니다. 버스 드라이버는 어떤 어린이가 있는지 확인하기 위해 버스 장치의 전원을 켜야 할 수도 있습니다.

경고 PnP 관리자가 해당 개체에 대한 디바이스 노드(devnode)를 만들 때까지 PDO를 인수로 사용하는 루틴에 디바이스 개체를 전달할 수 없습니다. (드라이버가 디바이스 개체를 전달하는 경우 시스템은 버그 검사 0xCA: PNP_DETECTED_FATAL_ERROR 검사 버그를 만듭니다.) PnP 관리자는 IRP_MN_QUERY_DEVICE_RELATIONS 요청에 대한 응답으로 devnode를 만듭니다. 드라이버는 PDO의 devnode가 IRP_MN_QUERY_RESOURCE_REQUIREMENTS 요청을 수신할 때 만들어졌다고 안전하게 가정할 수 있습니다.

이 IRP에 응답하는 버스 드라이버는 어댑터 또는 컨트롤러가 연결된 버스의 부모 버스 드라이버가 아니라 버스 어댑터 또는 컨트롤러의 함수 드라이버입니다. 버스가 아닌 디바이스의 함수 드라이버는 이 쿼리를 처리하지 않습니다. 이러한 드라이버는 다음 하부 드라이버에 IRP를 전달합니다. (다음 그림을 참조하세요.) 필터 드라이버는 일반적으로 이 쿼리를 처리하지 않습니다.

Windows Vista 이상 운영 체제에서는 드라이버가 항상 IRP_MN_QUERY_DEVICE_RELATIONS IRP를 보류하고 나중에 처리를 완료하는 것이 좋습니다. 이 순서를 사용하면 시스템에서 버스 관계 쿼리를 비동기적으로 처리할 수 있습니다. (Windows Vista 이전의 운영 체제에서 드라이버는 디스패치 루틴에서 STATUS_PENDING 안전하게 반환할 수 있지만 PnP 관리자는 버스 관계 쿼리를 다른 작업과 겹치지 않습니다.

다음 다이어그램은 드라이버가 버스 관계에 대한 쿼리를 처리하는 방법을 보여줍니다.

버스 관계에 대한 쿼리를 처리하는 드라이버를 보여 주는 다이어그램

그림에 표시된 예제에서 PnP 관리자는 Usb 허브 디바이스의 드라이버에 BusRelations에 대한 IRP_MN_QUERY_DEVICE_RELATIONS 보냅니다. PnP 관리자가 허브 디바이스의 자식 목록을 요청하고 있습니다.

  1. 모든 PnP IRP와 마찬가지로 PnP 관리자는 디바이스에 대한 디바이스 스택의 최상위 드라이버에 IRP를 보냅니다.

  2. 선택적 필터 드라이버는 스택의 최상위 드라이버일 수 있습니다. 필터 드라이버는 일반적으로 이 IRP를 처리하지 않습니다. IRP를 스택 아래로 전달합니다. 예를 들어 드라이버가 버스에 열거할 수 없는 디바이스를 노출하는 경우 필터 드라이버가 이 IRP를 처리할 수 있습니다.

  3. USB 허브 버스 드라이버는 IRP를 처리합니다.

    USB 허브 버스 드라이버:

    • 아직 없는 자식 디바이스에 대한 PDO를 만듭니다.

    • 버스에 더 이상 존재하지 않는 모든 디바이스에 대해 PDO를 비활성 상태로 표시합니다. 버스 드라이버는 이러한 PDO를 삭제하지 않습니다. PDO를 삭제하는 시기에 대한 자세한 내용은 디바이스 제거를 참조하세요.

    • 버스에 있는 모든 자식 디바이스를 보고합니다.

      각 자식 디바이스에 대해 버스 드라이버는 PDO를 참조하고 PDO에 대한 포인터를 DEVICE_RELATIONS 구조에 배치합니다.

      이 예제에는 조이스틱 디바이스용과 키보드 디바이스용 PDO의 두 가지 PDO가 있습니다.

      버스 드라이버는 다른 드라이버가 이미 이 IRP에 대한 DEVICE_RELATIONS 구조를 만들었는지 여부를 검사 합니다. 그렇다면 버스 드라이버는 기존 정보에 를 추가해야 합니다.

      버스에 자식 디바이스가 없는 경우 드라이버는 DEVICE_RELATIONS 구조에서 개수를 0으로 설정하고 성공을 반환합니다.

    • I/O 상태 블록에서 적절한 값을 설정하고 IRP를 다음 하위 드라이버에 전달합니다. 어댑터 또는 컨트롤러의 버스 드라이버가 IRP를 완료하지 않습니다.

  4. 선택적 하위 필터(있는 경우)는 일반적으로 이 IRP를 처리하지 않습니다. 이러한 필터 드라이버는 IRP를 스택 아래로 전달합니다. 하위 필터 드라이버가 이 IRP를 처리하는 경우 자식 디바이스 목록에 PDO를 추가할 수 있지만 다른 드라이버에서 만든 PDO는 삭제해서는 안 됩니다.

  5. 부모 버스 드라이버는 디바이스 스택의 유일한 드라이버(디바이스가 원시 모드)가 아닌 한 이 IRP를 처리하지 않습니다. 모든 PnP IRP와 마찬가지로 부모 버스 드라이버는 IoCompleteRequest를 사용하여 IRP를 완료합니다.

    디바이스 스택에 버스 필터 드라이버가 하나 이상 있는 경우 이러한 드라이버는 버스 드라이버로 내려가는 동안 IRP를 처리하거나 IRP가 디바이스 스택을 백업하는 방법( IoCompletion 루틴이 있는 경우)을 처리할 수 있습니다. PnP IRP 규칙에 따라 이러한 드라이버는 스택 아래로 가는 길에 IRP에 PDO를 추가하거나 IRP가 스택을 백업하는 방법( IoCompletion 루틴)에서 관계 목록을 수정할 수 있습니다.

EjectionRelations 요청

드라이버는 지정된 디바이스가 배출될 때 시스템에서 물리적으로 제거될 수 있는 모든 디바이스의 PDO에 대한 포인터를 반환합니다. 디바이스 자식의 PDO를 보고하지 마세요. PnP 관리자는 항상 부모 디바이스 전에 자식 디바이스를 제거할 것을 요청합니다.

PnP 관리자는 IRP_MN_EJECT IRP를 꺼내는 디바이스로 보냅니다. 이러한 디바이스의 드라이버도 제거 IRP를 받습니다. 디바이스의 배출 관계는 IRP_MN_EJECT IRP가 아닌 IRP_MN_REMOVE_DEVICE IRP를 받습니다.

부모 버스 드라이버만 자식 디바이스 중 하나에 대한 EjectionRelations 쿼리에 응답할 수 있습니다. 함수 및 필터 드라이버는 디바이스 스택의 다음 하위 드라이버에 전달해야 합니다. 버스 드라이버가 이 IRP를 어댑터 또는 컨트롤러의 함수 드라이버로 수신하는 경우 버스 드라이버는 함수 드라이버의 작업을 수행하고 IRP를 다음 하위 드라이버에 전달해야 합니다.

PowerRelations 요청

Windows 7부터 PowerRelations 쿼리를 사용하면 드라이버가 PnP 열거형을 지원하는 부모 버스와 버스의 열거형 자식 디바이스 간의 기존 관계 이외의 전원 관리 관계를 지정할 수 있습니다. 예를 들어 버스 드라이버가 버스에서 자식 디바이스를 열거할 수 없거나 디바이스가 둘 이상의 버스의 자식인 경우 PowerRelations 쿼리는 버스 또는 버스와 자식 디바이스의 전원 관계를 설명할 수 있습니다.

PnP 관리자는 디바이스에 대한 드라이버가 IoInvalidateDeviceRelations 루틴을 호출하고 PowerRelationsType 매개 변수 값을 지정할 때 디바이스에 대한 PowerRelations 쿼리를 발급합니다.

이 쿼리에 대한 응답으로 대상 디바이스의 드라이버(즉, 쿼리의 대상인 디바이스)는 대상 디바이스를 켜기 전에 전원 관리자가 켜야 하는 다른 디바이스의 PDO에 대한 포인터를 포함하는 DEVICE_RELATIONS 구조를 제공합니다 . 반대로 이러한 다른 디바이스는 대상 디바이스가 꺼진 후에만 꺼야 합니다. 전원 관리자는 쿼리의 정보를 사용하여 이러한 디바이스가 올바른 순서로 켜지고 꺼지도록 보장합니다.

이 순서 지정 보장은 S1, S2, S3(절전 모드), S4(최대 절전 모드) 및 S5(종료) 시스템 전원 상태로의 전환을 포함하는 전역 시스템 전 상태 전환에만 적용됩니다. DFx(Directed Runtime Power Management) 전환의 경우를 제외하고 시스템이 S0(실행 중인) 시스템 상태로 유지되는 동안 PowerRelations 순서 지정 보장은 Dx 디바이스 전원 상태 전환에 적용되지 않습니다.

대상 디바이스가 특수 파일(예: 페이징 파일, 최대 절전 모드 파일 또는 크래시 덤프 파일)의 디바이스 경로에 있는 경우 대상 디바이스의 드라이버는 InPathTRUEIRP_MN_DEVICE_USAGE_NOTIFICATION IRP를 처리할 때 추가 단계를 수행해야 합니다. 이 드라이버는 PowerRelations 쿼리에 PDO가 제공된 디바이스도 특수 파일의 디바이스 경로에 있는 것을 지원할 수 있도록 해야 합니다. 이 지원을 확인하려면 대상 디바이스의 드라이버가 먼저 이러한 각 디바이스에 IRP_MN_DEVICE_USAGE_NOTIFICATION IRP를 보내야 하며, 이 IRP는 대상 디바이스와 동일한 UsageNotification.Type 을 지정해야 합니다. 이 IRP를 수신하는 모든 디바이스가 성공 상태 코드로 IRP를 완료하는 경우에만 대상 디바이스의 드라이버가 IRP_MN_DEVICE_USAGE_NOTIFICATION IRP를 성공적으로 완료할 수 있습니다. 그렇지 않으면 이 드라이버는 오류 상태 코드로 이 IRP를 완료해야 합니다.

이 동일한 드라이버가 InPathFALSEIRP_MN_DEVICE_USAGE_NOTIFICATION IRP를 처리하는 경우 드라이버는 InPathTRUE인 경우와 동일한 종속 디바이스 집합에 IRP_MN_DEVICE_USAGE_NOTIFICATION IRP를 보내야 합니다. 그러나 InPathFALSE인 경우 드라이버는 오류 상태 코드로 이 IRP를 완료해서는 안 됩니다.

PowerRelations 쿼리에 응답하는 드라이버는 PowerRelations 쿼리에 대해 PDO가 제공되는 모든 디바이스에서 대상 디바이스 변경 알림을 등록해야 합니다. 이러한 알림을 등록하기 위해 드라이버는 IoRegisterPlugPlayNotification 루틴을 호출하고 EventCategoryTargetDeviceChangeEventCategory 매개 변수 값을 지정할 수 있습니다.

RemovalRelations 요청

드라이버는 지정된 디바이스의 드라이버가 제거될 때 드라이버를 제거해야 하는 모든 디바이스의 PDO에 대한 포인터를 반환합니다. 디바이스의 자식 PDO를 보고하지 마세요. PnP 관리자는 디바이스를 제거하기 전에 자식 디바이스 제거를 이미 요청합니다.

제거 관계가 제거되는 순서는 정의되지 않습니다.

디바이스 스택의 모든 드라이버는 이러한 유형의 관계 쿼리를 처리할 수 있습니다. 함수 또는 필터 드라이버는 IRP를 다음 하위 드라이버에 전달하기 전에 처리합니다. 버스 드라이버가 IRP를 처리한 다음 완료합니다.

TargetDeviceRelation 요청

TargetDeviceRelation 쿼리를 사용하면 PnP 관리자가 하드웨어를 제어하는 PnP 디바이스 스택의 PDO에 대해 PnP가 아닌 디바이스 스택을 쿼리할 수 있습니다.

일반적으로 드라이버는 IRP 가 특정 디바이스 스택의 맨 아래에 도달할 때까지 IRP_MN_QUERY_DEVICE_RELATIONS IRP를 스택 아래로 전달합니다. PnP가 아닌 스택의 맨 아래에 있는 드라이버는 IRP를 관련 PnP 스택으로 전달하거나 다시 발급합니다. 예를 들어 PnP 관리자는 PnP가 아닌 스택인 파일 시스템 스택의 맨 위에 있는 디바이스 개체에 TargetDeviceRelation 쿼리를 보낼 수 있습니다. 파일 시스템 스택의 각 디바이스 개체는 쿼리가 스택의 맨 아래에 있는 디바이스 개체에 도달할 때까지 쿼리를 아래의 디바이스 개체에 전달합니다. 스택에서 가장 낮은 디바이스 개체는 TargetDeviceRelation 쿼리를 PnP 스토리지 볼륨 스택의 맨 위에 있는 디바이스 개체로 전달하거나 다시 실행한 다음, 쿼리가 스토리지 볼륨 스택의 맨 아래에 있는 PDO로 전달됩니다.

다음 목록에서는 PnP 디바이스 스택의 맨 아래에 있는 PDO에 대한 포인터를 안전하게 획득할 수 있는 상황을 요약합니다.

  • PnP의 디바이스 개체

    PnP 디바이스 스택에 있는 디바이스 개체는 디바이스에 대한 AddDevice 루틴이 호출되면 스택의 PDO에 대해 알아봅니다. 포인터 사용이 잠금 제거 루틴을 사용하여 들어오는 IRP_MN_REMOVE_DEVICE 메시지와 제대로 동기화된 경우 드라이버는 PDO에 대한 포인터를 안전하게 캐시할 수 있습니다.

  • 스택 아래쪽이 아닌 PnP가 아닌 스택의 디바이스 개체

    PnP가 아닌 스택의 맨 아래에 없는 디바이스 개체의 경우 드라이버는 TargetDeviceRelation 쿼리를 보내 해당 PnP 디바이스 스택의 맨 아래에 있는 PDO에 대한 포인터를 가져올 수 있습니다.

  • 디바이스에 대한 파일 개체

    디바이스에 대한 파일 개체가 지정된 경우 드라이버는 IoGetRelatedDeviceObject 를 호출하여 디바이스 개체를 가져와서 이전 목록 항목의 지침을 따를 수 있습니다.

  • 디바이스 개체에 대한 핸들

    디바이스 개체에 대한 핸들이 제공되면 드라이버는 ObReferenceObjectByHandle 을 호출하여 디바이스에 대한 파일 개체를 가져와서 이전 목록 항목의 지침을 따를 수 있습니다.

부모 버스 드라이버는 자식 디바이스에 대한 TargetDeviceRelation 관계 쿼리를 처리해야 합니다. 버스 드라이버는 ObReferenceObject 를 사용하여 자식 디바이스의 PDO를 참조하고 DEVICE_RELATIONS 구조의 PDO에 대한 포인터를 반환합니다. 이 관계 유형에 대한 구조체에는 하나의 PDO 포인터만 있습니다. PnP 관리자는 드라이버 또는 애플리케이션이 디바이스에서 알림을 등록 취소할 때 PDO에 대한 참조를 제거합니다.

부모 버스 드라이버만 TargetDeviceRelation 쿼리에 응답합니다. 함수 및 필터 드라이버는 디바이스 스택의 다음 하위 드라이버에 전달해야 합니다. 버스 드라이버가 이 IRP를 어댑터 또는 컨트롤러의 함수 드라이버로 수신하는 경우 버스 드라이버는 함수 드라이버의 작업을 수행하고 IRP를 다음 하위 드라이버에 전달해야 합니다.

드라이버가 PDO 기반 스택에 없는 경우 드라이버는 드라이버가 I/O를 수행하는 파일 핸들과 연결된 디바이스 개체에 새 대상 디바이스 관계 쿼리 IRP를 보냅니다.

이 IRP 보내기

드라이버는 BusRelations를 요청하기 위해 IRP_MN_QUERY_DEVICE_RELATIONS 보내면 안 됩니다. 드라이버는 RemoveRelations 또는 EjectionRelations에 대해 이 IRP를 보내는 것이 제한되지 않지만 드라이버가 그렇게 할 가능성은 없습니다.

드라이버는 TargetDeviceRelation에 대한 디바이스 스택을 쿼리할 수 있습니다. IRP 전송에 대한 자세한 내용은 IRP 처리를 참조하세요. 다음 단계는 이 IRP에 특히 적용됩니다.

  • IRP의 다음 I/O 스택 위치에 있는 값을 설정합니다. MajorFunctionIRP_MJ_PNP 설정하고, MinorFunctionIRP_MN_QUERY_DEVICE_RELATIONS 설정하고, Parameters.QueryDeviceRelations.TypeTargetDeviceRelation으로 설정하고, Irp-FileObject>를 유효한 파일 개체로 설정합니다.

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

드라이버가 받은 TargetDeviceRelation에 대한 IRP_MN_QUERY_DEVICE_RELATIONS 대한 응답으로 PDO를 보고하도록 이 IRP를 보낸 경우 드라이버는 PDO를 보고하고 IRP가 완료되면 반환된 관계 구조를 해제합니다. 드라이버가 다른 이유로 이 IRP를 시작한 경우 드라이버는 IRP가 완료될 때 관계 구조를 해제하고 더 이상 필요하지 않을 때 PDO를 역참조합니다.

요구 사항

헤더

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

추가 정보

AddDevice

IoCompleteRequest

IoGetRelatedDeviceObject

IoInvalidateDeviceRelations

IoRegisterPlugPlayNotification

IRP_MJ_PNP

IRP_MN_DEVICE_USAGE_NOTIFICATION

IRP_MN_EJECT

IRP_MN_QUERY_RESOURCE_REQUIREMENTS

IRP_MN_REMOVE_DEVICE

IO_STACK_LOCATION

ObReferenceObject

ObReferenceObjectByHandle