함수 드라이버에서 디바이스 제거
디바이스를 제거할 때 함수 드라이버는 디바이스를 추가하고 시작하기 위해 수행한 작업을 실행 취소해야 합니다. 이 설명에는 주변 장치용 함수 드라이버와 버스 디바이스의 함수 드라이버가 포함됩니다.
함수 드라이버는 DispatchPnP 루틴에서 다음과 같은 절차를 사용하여 디바이스를 제거합니다.
버스 디바이스의 함수 드라이버인가요?
그렇다면 버스 내 장치의 남아 있는 자식 PDO를 삭제할 수 있습니다.
버스 드라이버가 자식 디바이스에 대한 이전 IRP_MN_SURPRISE_REMOVAL 요청을 처리했지만 드라이버가 후속 IRP_MN_REMOVE_DEVICE 요청을 아직 받지 못한 경우 버스 드라이버는 자식 PDO를 그대로 둡니다. 나중에 자식 디바이스에 대한 모든 핸들을 닫으면 PnP 관리자는 자식 디바이스에 대한 제거 IRP를 보내고 버스 드라이버는 해당 시간에 자식 PDO를 삭제합니다.
버스 드라이버가 디바이스에 대한 이전 IRP_MN_REMOVE_DEVICE 요청을 처리하고 후속 IRP_MN_SURPRISE_REMOVAL 요청이 없는 경우 버스 드라이버는 자식 PDO를 삭제합니다. 이 경우 PnP 관리자는 IRP 제거를 부모 버스 디바이스로 보내기 전에 자식 디바이스(FDO 및 필터 DO가 삭제됨)에서 함수 및 필터 드라이버가 제거되었는지 확인합니다. 자식 PDO는 여전히 존재할 수 있으므로 버스 드라이버는 버스 디바이스를 제거하기 전에 자식 PDO를 삭제해야 합니다.
드라이버가 이 FDO에 대한 이전 IRP_MN_SURPRISE_REMOVAL 요청을 이미 처리했나요?
그렇다면 나머지 정리를 수행하고 IoCallDriver를 사용하여 8단계로 건너뛰세요.
드라이버는 일반적으로 디바이스 확장에서 드라이버가 디바이스에 대한 IRP_MN_SURPRISE_REMOVAL 요청을 처리했는지 여부를 나타내는 플래그를 유지 관리합니다.
드라이버가 이전에 절전 모드 해제를 위해 디바이스를 사용하도록 설정한 경우 IRP_MN_WAIT_WAKE 요청을 취소합니다.
디바이스가 비활성 상태인지 확인합니다.
이전 IRP_MN_QUERY_REMOVE_DEVICE대한 응답으로 디바이스가 아직 비활성 상태가 아닌 경우 드라이버는 디바이스를 새 요청을 수락하지 않는 것으로 표시해야 하며 이 드라이버에 대기 중인 모든 요청을 완료해야 합니다. 드라이버는 디바이스에 액세스해야 하는 미해결 요청을 실패해야 합니다.
드라이버는 IoXxxRemoveLockXxx 루틴을 사용하여 미해결 I/O를 계산하고 제거 처리를 계속할 수 있음을 나타내는 이벤트를 설정할 수 있습니다.
전원 차단 작업을 수행합니다.
디바이스의 각 드라이버는 IRP_MN_REMOVE_DEVICE 요청을 수신할 때 전원 다운 작업을 수행합니다(있는 경우). 디바이스의 전원 정책 소유자(일반적으로 함수 드라이버)는 디바이스 전원 상태를 D3으로 설정하는 별도의 IRP_MN_SET_POWER 요청을 보내지 않습니다. 부모 버스 드라이버는 일반적으로 슬롯의 전원을 끄고, 버스 드라이버가 제거 IRP를 받을 때 PoSetPowerState를 사용하여 전원 관리자에게 알립니다. 자세한 내용은 전원 관리 참조하세요.
IoSetDeviceInterfaceState호출하여 디바이스 인터페이스를 사용하지 않도록 설정합니다.
드라이버에서 사용 중인 디바이스에 대한 하드웨어 리소스를 해제합니다.
정확한 작업은 디바이스와 드라이버에 따라 달라지지만 IoDisconnectInterrupt인터럽트 연결 끊기, MmUnmapIoSpace물리적 주소 범위 해제 및 I/O 포트 해제를 포함할 수 있습니다.
IRP_MN_REMOVE_DEVICE 요청을 다음 드라이버로 전달합니다.
IoSkipCurrentIrpStackLocation 사용하여 다음 하위 드라이버에 대한 IRP 스택 위치를 설정하고 IoCallDriver사용하여 IRP를 다음 드라이버에 전달합니다.
드라이버는 제거 작업을 계속하기 전에 기본 드라이버가 제거 작업을 완료할 때까지 기다릴 필요가 없습니다.
IoDetachDevice사용하여 디바이스 스택에서 디바이스 개체를 제거합니다.
다음 하위 디바이스 개체에 대한 포인터를 TargetDevice 매개 변수로 지정합니다. 드라이버는 드라이버의 AddDevice 루틴에서 IoAttachDeviceToDeviceStack 호출로부터 이러한 포인터를 받습니다.
디바이스별 할당, 메모리, 이벤트 등을 정리합니다.
IoDeleteDevice사용하여 FDO를 해제합니다.
DispatchPnP 루틴에서 반환하여 IoCallDriver반환 상태를 전파합니다.
함수 드라이버는 IRP 제거에 대한 IoCompletion 루틴을 지정하지 않으며 IRP를 완료하지도 않습니다. 제거 IRP는 부모 버스 드라이버에 의해 완료됩니다.