다음을 통해 공유


IRP_MN_QUERY_REMOVE_DEVICE 요청 처리

PnP 관리자는 이 IRP 보내 디바이스가 컴퓨터에서 제거될 예정임을 드라이버에 알리고 컴퓨터를 방해하지 않고 디바이스를 제거할 수 있는지 여부를 묻습니다. 또한 사용자가 디바이스에 대한 드라이버 업데이트를 요청할 때 이 IRP를 보냅니다.

시스템 스레드의 컨텍스트에서 PnP 관리자는 IRQL PASSIVE_LEVEL 수준에서 이 IRP를 보냅니다.

디바이스의 드라이버에 이 IRP를 보내기 전에 다음을 수행합니다.

  • 알림을 받도록 등록된 모든 사용자 모드 애플리케이션에 디바이스(또는 관련 디바이스)에서 통지합니다.

    여기에는 디바이스 자체, 디바이스의 자식 디바이스나 그 하위 디바이스, 또는 디바이스의 제거 관계중 하나에서 알림에 등록된 애플리케이션이 포함됩니다. 애플리케이션은 CM_Register_Notification 또는 RegisterDeviceNotification호출하여 이러한 알림을 등록합니다.

    이 알림에 대한 응답으로 애플리케이션은 디바이스 제거를 준비하거나(디바이스에 대한 핸들을 닫습니다) 쿼리에 실패할 수 있습니다. 이러한 알림을 처리하는 방법에 대한 자세한 내용은 디바이스 인터페이스 도착 및 디바이스 제거 대한 알림 등록을 참조하세요.

  • 디바이스(또는 관련 디바이스)에서 알림을 위해 등록된 모든 커널 모드 드라이버에 알립니다.

    여기에는 디바이스, 디바이스의 하위 항목 중 하나 또는 디바이스의 제거 관계중 하나에서 알림을 등록한 드라이버가 포함됩니다. 드라이버는 이벤트 범주가 EventCategoryTargetDeviceChange인 경우 IoRegisterPlugPlayNotification 를 호출하여 이 알림을 등록합니다.

    이 알림에 대한 응답으로 드라이버는 장치 제거를 준비하거나(장치에 대한 핸들을 닫거나) 쿼리에 실패할 수 있습니다.

  • 디바이스의 하위 항목에 대한 드라이버에 IRP_MN_QUERY_REMOVE_DEVICE IRP를 보냅니다. 디바이스 스택이 이 IRP를 처리하는 방법에 대한 자세한 내용은 아래를 참조하세요.

  • (Windows 2000 이상 시스템) 파일 시스템이 디바이스에 탑재된 경우 PnP 관리자는 파일 시스템과 파일 시스템 필터에 쿼리 제거 요청을 보냅니다. 디바이스에 대한 열린 핸들이 있는 경우 파일 시스템은 일반적으로 쿼리 제거 요청에 실패합니다. 그렇지 않은 경우 파일 시스템은 일반적으로 볼륨을 잠가 향후 생성이 성공하지 못하도록 합니다. 탑재된 파일 시스템에서 쿼리 제거 요청을 지원하지 않는 경우 PnP 관리자는 디바이스에 대한 쿼리 제거 요청에 실패합니다.

위의 모든 단계가 성공하면 PnP 관리자는 디바이스의 드라이버에 IRP_MN_QUERY_REMOVE_DEVICE 보냅니다.

IRP_MN_QUERY_REMOVE_DEVICE 요청은 먼저 디바이스 스택의 최상위 드라이버에 의해 처리되고, 그 후 각 하위 드라이버가 순차적으로 처리합니다. 드라이버는 DispatchPnP 루틴에서 제거 요청 패킷(IRPs)을 처리합니다.

IRP_MN_QUERY_REMOVE_DEVICE에 대한 응답으로 드라이버는 다음을 수행해야 합니다.

  1. 디바이스를 컴퓨터에서 안전하게 제거할 수 있는지 여부를 확인합니다.

    다음 중 하나라도 해당되는 경우 드라이버는 쿼리 제거 IRP를 실패로 처리해야 합니다.

    • 디바이스를 제거하면 데이터가 손실될 수 있습니다.

    • 구성 요소가 장치에 대한 열린 핸들을 가진 경우 (Windows 98/Me에서만 문제가 발생합니다. Windows 2000 이상 버전의 Windows는 열린 핸들을 추적하고, IRP_MN_QUERY_REMOVE_DEVICE 이 완료된 후에 열린 핸들이 남아 있으면 쿼리에 실패합니다.)

    • 드라이버가 IRP_MN_DEVICE_USAGE_NOTIFICATION IRP를 통해 디바이스가 페이징, 크래시 덤프 또는 최대 절전 모드 파일의 경로에 있다는 알림을 받은 경우

    • 드라이버에 디바이스에 대한 해결되지 않은 인터페이스 참조가 있는 경우 즉, 드라이버는 IRP_MN_QUERY_INTERFACE 요청에 대한 응답으로 인터페이스를 제공했으며 인터페이스가 역참조되지 않았습니다.

  2. 디바이스를 제거할 수 없는 경우 쿼리-제거 IRP를 실패 처리합니다.

    Irp->IoStatus.Status를 적절한 오류 상태(일반적으로 STATUS_UNSUCCESSFUL)로 설정하고, IO_NO_INCREMENT를 사용하여 IoCompleteRequest를 호출한 후, 드라이버의 DispatchPnP 루틴에서 반환합니다. IRP를 다음 하위 드라이버에 전달하지 마세요.

  3. 드라이버가 이전에 디바이스를 깨우기 위해 IRP_MN_WAIT_WAKE 요청을 보냈다면 대기-해제 IRP를 취소합니다.

  4. 디바이스의 이전 PnP 상태를 기록합니다.

    드라이버가 쿼리가 취소된 경우 디바이스를 해당 상태로 반환해야 하므로 드라이버가 IRP_MN_QUERY_REMOVE_DEVICE 요청을 받았을 때 디바이스가 있던 PnP 상태를 기록해야 합니다(IRP_MN_CANCEL_REMOVE_DEVICE). 이전 상태는 일반적으로 드라이버가 IRP_MN_START_DEVICE 요청을 성공적으로 완료할 때 디바이스가 입력하는 상태인 "started"입니다.

    그러나 다른 이전 상태는 가능합니다. 예를 들어 사용자가 디바이스 관리자를 통해 디바이스를 사용하지 않도록 설정했을 수 있습니다. 또는 IRP_MN_QUERY_CAPABILITIES 요청에 대한 응답으로 부모 버스 드라이버(또는 버스 드라이버의 필터 드라이버)가 디바이스의 하드웨어가 비활성화되었다고 보고했을 가능성이 있습니다. 두 경우 모두 비활성화된 디바이스의 드라이버는 IRP_MN_START_DEVICE 요청을 받기 전에 IRP_MN_QUERY_REMOVE_DEVICE 요청을 받을 수 있습니다.

  5. IRP를 완료합니다.

    함수 또는 필터 드라이버에서:

    • Irp->IoStatus.Status를 STATUS_SUCCESS로 설정합니다.

    • IoSkipCurrentIrpStackLocation 사용하여 다음 스택 위치를 설정하고 IoCallDriver사용하여 IRP를 다음 하위 드라이버에 전달합니다.

    • IoCallDriver 상태를 DispatchPnP 루틴의 반환 상태로 전달하여 전파합니다.

    • IRP를 완료하지 마세요.

    버스 드라이버에서:

    • Irp->IoStatus.Status을 STATUS_SUCCESS로 설정합니다.

    • IO_NO_INCREMENT 사용하여 IRP(IoCompleteRequest)를 완료합니다.

    • DispatchPnP 루틴에서 반환합니다.

장치 스택에서 어떤 드라이버라도 IRP_MN_QUERY_REMOVE_DEVICE요청을 실패할 경우, PnP 관리자는 장치 스택에 IRP_MN_CANCEL_REMOVE_DEVICE 을(를) 전송합니다. 이렇게 하면 드라이버가 쿼리 제거 IRP에 대한 IoCompletion 루틴을 요구할 필요가 없어지고, 하위 드라이버가 IRP를 실패했는지 여부를 감지할 수 없습니다.

드라이버가 IRP_MN_QUERY_REMOVE_DEVICE을 성공적으로 수행하고 디바이스가 제거 보류 중인 상태로 간주되면, 드라이버는 디바이스에 대한 후속 생성 요청을 거부해야 합니다. 드라이버는 IRP_MN_CANCEL_REMOVE_DEVICE 또는 IRP_MN_REMOVE_DEVICE를 받을 때까지 다른 모든 IRP를 평소와 같이 처리합니다.