Lower-Level 드라이버에 대한 IRP 만들기

하위 드라이버에 의해 임의의 스레드 컨텍스트에서 처리되는 비동기 요청에 대해 IRP를 할당하기 위해 DispatchReadWrite 루틴은 다음 지원 루틴 중 하나를 호출할 수 있습니다.

  • IRP 및 초기화되지 않은 여러 I/O 스택 위치를 할당하는 IoAllocateIrp

    디스패치 루틴은 일반적으로 원래 IRP의 자체 스택 위치에서 정보를 복사(수정)하여 새로 할당된 IRP에 대해 다음으로 낮은 드라이버의 I/O 스택 위치를 설정해야 합니다. 상위 수준 드라이버가 새로 할당된 IRP에 대해 자체 I/O 스택 위치를 할당하는 경우 디스패치 루틴은 IoCompletion 루틴이 사용할 수 있도록 요청당 컨텍스트 정보를 설정할 수 있습니다.

  • 호출자 지정 매개 변수에 따라 호출자에 대해 다음으로 낮은 드라이버의 I/O 스택 위치를 설정하는 IoBuildAsynchronousFsdRequest

    상위 수준 드라이버는 이 루틴을 호출하여 IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERSIRP_MJ_SHUTDOWN 요청에 대한 IRP를 할당할 수 있습니다.

    이러한 IRP에 대해 IoCompletion 루틴이 호출되면 I/O 상태 블록을 검사 필요한 경우 IRP에서 다음 하위 드라이버의 I/O 스택 위치를 다시 설정하고 요청을 다시 시도하거나 다시 사용할 수 있습니다. 그러나 IoCompletion 루틴에는 IRP 자체에 대한 로컬 컨텍스트 스토리지가 없으므로 드라이버는 상주 메모리의 다른 위치에서 원래 요청에 대한 컨텍스트를 유지해야 합니다.

  • IRP 및 초기화되지 않은 여러 I/O 스택 위치를 할당하고 IRP를 master IRP와 연결하는 IoMakeAssociatedIrp입니다.

    중간 드라이버는 IoMakeAssociatedIrp 을 호출하여 낮은 드라이버에 대한 IRP를 만들 수 없습니다.

    낮은 드라이버에 대한 IRP를 만들기 위해 IoMakeAssociatedIrp를 호출하는 최상위 수준의 드라이버는 연결된 IRP를 에 보내고 원래 master IRP에 대해 IoMarkIrpPending을 호출한 후 I/O 관리자에게 제어권을 반환할 수 있습니다. 최상위 드라이버는 I/O 관리자를 사용하여 연결된 모든 IRP가 하위 드라이버에 의해 완료된 경우 master IRP를 완료할 수 있습니다.

    드라이버는 연결된 IRP에 대한 IoCompletion 루틴을 거의 설정하지 않습니다. 최상위 드라이버가 만든 연결된 IRP에 대해 IoSetCompletionRoutine을 호출하는 경우 드라이버가 IoCompletion 루틴에서 STATUS_MORE_PROCESSING_REQUIRED 반환하는 경우 I/O 관리자는 master IRP를 완료하지 않습니다. 이러한 경우 드라이버의 IoCompletion 루틴은 IoCompleteRequest를 사용하여 master IRP를 명시적으로 완료해야 합니다.

드라이버가 새 IRP에서 자체 I/O 스택 위치를 할당하는 경우 IoGetCurrentIrpStackLocation을 호출하기 전에 디스패치 루틴은 IoSetNextIrpStackLocation을 호출하여 IoCompletion 루틴에 대한 자체 I/O 스택 위치에 컨텍스트를 설정해야 합니다. 자세한 내용은 Intermediate-Level 드라이버에서 IRP 처리를 참조하세요.

디스패치 루틴은 원래 IRP를 사용하여 IoMarkIrpPending을 호출해야 하지만 IoCompletion 루틴이 해제되므로 드라이버 할당 IRP에서는 호출하지 않아야 합니다.

디스패치 루틴이 부분 전송을 위해 IRP를 할당하고 기본 디바이스 드라이버가 이동식 미디어 디바이스를 제어할 수 있는 경우 디스패치 루틴은 원래 IRP의 Tail.Overlay.Thread 값에서 새로 할당된 IRP의 스레드 컨텍스트를 설정해야 합니다.

이동식 미디어 디바이스의 기본 드라이버는 드라이버 할당 IRP에 대해 Irp-Tail.Overlay.Thread>의 포인터를 참조하는 IoSetHardErrorOrVerifyDevice를 호출할 수 있습니다. 드라이버가 이 지원 루틴을 호출하는 경우 파일 시스템 드라이버는 사용자에게 드라이버가 충족할 수 없는 작업을 취소, 다시 시도 또는 실패하라는 메시지를 표시하는 대화 상자를 적절한 사용자 스레드로 보낼 수 있습니다. 자세한 내용은 이동식 미디어 지원을 참조하세요.

디스패치 루틴은 드라이버가 할당한 모든 IRP를 낮은 드라이버로 보낸 후 STATUS_PENDING 반환해야 합니다.

드라이버의 IoCompletion 루틴은 원래 IRP에 대해 IoCompleteRequest를 호출하기 전에 IoFreeIrp로 드라이버 할당 IRP를 모두 해제해야 합니다. 원래 IRP를 완료하면 IoCompletion 루틴은 컨트롤을 반환하기 전에 드라이버 할당 IRP를 모두 해제해야 합니다.

각 상위 수준 드라이버는 지정된 요청이 중간 드라이버에서 온 것인지 아니면 파일 시스템 또는 사용자 모드 애플리케이션과 같은 다른 원본에서 발생하든 기본 디바이스 드라이버에 비물질적인 방식으로 낮은 드라이버에 대해 드라이버 할당(및 재사용) IRP를 설정합니다.

최고 수준의 드라이버는 IoMakeAssociatedIrp 를 호출하여 IRP를 할당하고 낮은 드라이버 체인에 대해 설정할 수 있습니다. I/O 관리자는 드라이버가 원래 IRP 또는 할당하는 연결된 IRP를 사용하여 IoSetCompletionRoutine을 호출하지 않는 한 연결된 모든 IRP가 완료되면 원래 IRP를 자동으로 완료합니다. 그러나 최상위 드라이버는 버퍼링된 I/O 작업을 요청하는 모든 IRP에 대해 연결된 IRP를 할당해서는 안 됩니다.

중간 수준 드라이버는 IoMakeAssociatedIrp를 호출하여 하위 수준 드라이버에 대해 IRP를 할당할 수 없습니다. 중간 드라이버가 수신하는 모든 IRP는 이미 연결된 IRP일 수 있으며 드라이버는 다른 IRP를 이러한 IRP와 연결할 수 없습니다.

대신 중간 드라이버가 낮은 드라이버에 대한 IRP를 만드는 경우 IoAllocateIrp, IoBuildDeviceIoControlRequest, IoBuildSynchronousFsdRequest 또는 IoBuildAsynchronousFsdRequest를 호출해야 합니다. 그러나 IoBuildSynchronousFsdRequest 는 다음과 같은 경우에만 호출할 수 있습니다.

  • IoBuildSynchronousFsdRequest에 전달된 드라이버 초기화된 이벤트와 같이 디스패처 개체의 비중단 스레드 컨텍스트(자체)에서 이러한 스레드가 대기할 수 있으므로 읽기 또는 쓰기 요청에 대한 IRP를 빌드하기 위한 드라이버 생성 스레드

  • 초기화 중 또는 언로드하는 동안 시스템 스레드 컨텍스트에서

  • 만들기, 플러시, 종료, 닫기 및 디바이스 제어 요청과 같은 본질적으로 동기 작업에 대한 IRP를 빌드하려면

그러나 드라이버는 IoBuildSynchronousFsdRequest보다 디바이스 제어 IRP를 할당하기 위해 IoBuildDeviceIoControlRequest를 호출할 가능성이 더 높습니다.