UMDF 1.x 드라이버에서 Kernel-Mode 클라이언트 지원

경고

UMDF 2는 UMDF의 최신 버전이며 UMDF 1을 대체합니다. 모든 새 UMDF 드라이버는 UMDF 2를 사용하여 작성해야 합니다. UMDF 1에 새 기능이 추가되지 않으며 최신 버전의 Windows 10 UMDF 1에 대한 지원이 제한되어 있습니다. 유니버설 Windows 드라이버는 UMDF 2를 사용해야 합니다.

보관된 UMDF 1 샘플은 Windows 11 버전 22H2 - 2022년 5월 드라이버 샘플 업데이트에서 찾을 수 있습니다.

자세한 내용은 UMDF를 사용하여 시작 참조하세요.

UMDF 버전 1.9 이상에서는 UMDF 드라이버가 커널 모드 클라이언트를 지원할 수 있습니다. 커널 모드 클라이언트는 다음 중 하나일 수 있습니다.

  • 디바이스의 드라이버 스택에 있는 UMDF 드라이버 위에 있는 커널 모드 드라이버입니다.

  • 한 디바이스를 지원하는 하나의 디바이스 스택에 대한 커널 모드 드라이버가 다른 디바이스에 대한 핸들을 열고 후자의 디바이스 드라이버 스택에 UMDF 드라이버가 포함되어 있습니다.

즉, 커널 모드 클라이언트를 지원하는 UMDF 드라이버는 커널 모드 드라이버에서 I/O 요청을 받을 수 있습니다. 커널 모드 드라이버는 사용자 모드 애플리케이션에서 받은 I/O 요청을 전달하거나 새 I/O 요청을 만들어 사용자 모드 드라이버로 보낼 수 있습니다.

UMDF 드라이버가 커널 모드 클라이언트를 지원해야 하는지 확인하려면 드라이버가 추가될 드라이버 스택과 해당 스택에서 드라이버가 상주할 위치를 이해해야 합니다. 또한 다른 스택의 드라이버가 드라이버의 디바이스에 I/O 요청을 보낼 수 있는지 여부를 결정해야 합니다.

다음과 같은 경우 드라이버는 커널 모드 클라이언트를 지원해야 합니다.

  • 커널 모드 드라이버는 드라이버 스택의 UMDF 드라이버 바로 위에 위치할 수 있습니다. 예를 들어 커널 모드 필터 드라이버는 UMDF 기반 함수 드라이버 바로 위에 있을 수 있습니다.

  • 다른 스택의 커널 모드 드라이버는 드라이버의 디바이스에 I/O 요청을 보낼 수 있습니다. 예를 들어 드라이버는 다른 스택의 커널 모드 드라이버가 드라이버의 디바이스에 대한 핸들을 여는 데 사용할 수 있는 기호 링크를 만들 수 있습니다. 그런 다음 커널 모드 드라이버는 디바이스에 I/O 요청을 보낼 수 있습니다.

UMDF 드라이버에서 커널 모드 클라이언트를 지원하는 방법

UMDF 드라이버는 UMDF 드라이버가 커널 모드 클라이언트에 대한 지원을 사용하도록 설정한 경우에만 커널 모드 드라이버에서 I/O 요청을 받을 수 있습니다. 또한 디바이스 설치 시 디바이스의 드라이버 스택에서 UMDF 드라이버 위에 커널 모드 드라이버를 로드하려고 하면 프레임워크를 사용하면 UMDF 드라이버가 커널 모드 클라이언트에 대한 지원을 사용하도록 설정한 경우에만 드라이버가 로드될 수 있습니다.

커널 모드 클라이언트에 대해 UMDF 드라이버의 지원을 사용하도록 설정하려면 UMDF 드라이버의 INF 파일에 INF DDInstallUmdfKernelModeClientPolicy 지시문이 포함되어야 합니다. WDF 섹션. UMDF 드라이버의 INF 파일에 이 지시문이 포함되지 않은 경우 UMDF는 UMDF 드라이버 위에 설치된 커널 모드 드라이버를 실행할 수 없습니다.

프레임워크는 커널 모드 클라이언트를 지원하는 드라이버에 유용한 두 가지 메서드를 제공합니다. 드라이버는 IWDFIoRequest2::GetRequestorMode 메서드를 호출하여 I/O 요청이 커널 모드 또는 사용자 모드에서 제공되었는지 여부를 확인할 수 있습니다. I/O 요청이 사용자 모드에서 온 경우 드라이버는 IWDFIoRequest2::IsFromUserModeDriver 를 호출하여 요청이 애플리케이션 또는 다른 사용자 모드 드라이버에서 왔는지 확인할 수 있습니다.

커널 모드 드라이버에 대한 제한 사항

UMDF 드라이버는 커널 모드 드라이버가 다음 요구 사항을 충족하는 경우에만 커널 모드 드라이버에서 I/O 요청을 처리할 수 있습니다.

  • 커널 모드 드라이버는 I/O 요청을 보낼 때 IRQL = PASSIVE_LEVEL 실행되어야 합니다.

  • 드라이버가 UmdfFileObjectPolicy INF 지시문을 AllowNullAndUnknownFileObjects로 설정하지 않은 경우 커널 모드 드라이버가 사용자 모드 드라이버에 보내는 각 I/O 요청에는 연결된 파일 개체가 있어야 합니다. 프레임워크는 이전에 I/O 관리자가 파일 개체를 만들었다는 알림을 받았어야 합니다. (이러한 알림을 통해 프레임워크는 사용자 모드 드라이버의 IQueueCallbackCreate::OnCreateFile 콜백 함수를 호출하지만 해당 콜백 함수는 선택 사항입니다.)

  • I/O 요청에는 IRP_MJ_INTERNAL_DEVICE_CONTROL 함수 코드가 포함될 수 없습니다.

  • 사용자 모드 드라이버가 포인터를 역참조할 수 없으므로 I/O 요청의 버퍼에 추가 정보에 대한 포인터가 포함되어서는 안 됩니다.

  • I/O 요청에 "둘 다" 버퍼 액세스 메서드를 지정하는 I/O 컨트롤 코드 가 포함된 경우 커널 모드 드라이버는 I/O 요청을 만든 애플리케이션의 프로세스 컨텍스트에서 I/O 요청을 보내야 합니다. UMDF 기반 드라이버에서 "둘 다" 메서드를 지원하는 방법에 대한 자세한 내용은 UMDF 드라이버에서 버퍼링된 I/O 또는 직접 I/O 사용을 참조하세요.

  • UMDF 드라이버는 사용자 모드에서 I/O 요청의 출력 데이터를 수정할 수 있습니다. 따라서 커널 모드 드라이버는 사용자 모드 드라이버에서 수신하는 출력 데이터의 유효성을 검사해야 합니다.

  • 커널 모드 클라이언트는 일반적으로 UMDF 드라이버가 IWDFIoRequest::CompleteWithInformation에 전달하는 정보 값의 유효성을 검사해야 합니다. 클라이언트가 KMDF 드라이버인 경우 WdfRequestGetCompletionParams 를 호출하여 IO_STATUS_BLOCK 구조에서 이 정보를 가져올 수 있습니다.

    일반적으로 프레임워크는 UMDF 드라이버가 IWDFIoRequest::CompleteWithInformation에 전달하는 정보 값의 유효성을 검사하지 않습니다. (이 매개 변수는 일반적으로 전송된 바이트 수를 지정합니다.) 프레임워크는 출력 버퍼에 대해서만 정보 값의 유효성을 검사하고 버퍼링된 I/O 데이터 액세스 메서드에 대해서만 유효성을 검사합니다. 예를 들어 프레임워크는 액세스 메서드가 버퍼링된 I/O인 경우 전송된 바이트 수가 읽기 작업의 출력 버퍼 크기를 초과하지 않는지 확인합니다.

UMDF 1.x 드라이버에서 반환 상태 값 처리

사용자 모드에서 커널 모드로 반환 상태 값을 전달하려면 다음과 같이 특별한 주의가 필요합니다.

  • UMDF 버전 1 드라이버는 일반적으로 HRESULT 형식의 반환 값을 수신하지만 KMDF 및 WDM 기반 커널 모드 드라이버는 일반적으로 NTSTATUS 형식 값을 받습니다. UMDF 1인 경우 x 드라이버는 I/O 요청을 완료하고 드라이버에 커널 모드 클라이언트가 있는 경우 IWDFIoRequest::Complete 또는 IWDFIoRequest::CompleteWithInformation 에 대한 드라이버 호출은 드라이버가 NTSTATUS 값에서 생성하는 HRESULT 값을 지정해야 합니다. 일반적으로 UMDF 1. x 드라이버는 HRESULT_FROM_NT 매크로(Winerror.h에 정의됨)를 사용하여 커널 모드 클라이언트로 상태 반환해야 합니다. 다음 예제에서는 요청을 완료할 때 이 매크로를 사용하는 방법을 보여줍니다.

    hr = HRESULT_FROM_NT(STATUS_BUFFER_OVERFLOW)
    request->Complete(HRESULT_FROM_NT(STATUS_BUFFER_OVERFLOW);
    return hr;
    

    커널 모드 클라이언트에 특정 HRESULT 값을 반환하려면 다음 콜백에서 HRESULT_FROM_NT 매크로를 사용해야 합니다.

    ntstatus.h, UMDF 1에 정의된 NTSTATUS 값을 사용합니다. x 드라이버는 추가 헤더를 포함하기 전에 이러한 두 줄을 포함해야 합니다.

    #define UMDF_USING_NTSTATUS
    #include <ntstatus.h>
    

    HRESULT_FROM_NT 매크로를 사용하여 STATUS_SUCCESS NTSTATUS 값에서 HRESULT 값으로 변환하지 마세요. 다음 예제와 같이 S_OK 반환합니다.

    request->Complete(S_OK);
    
  • 프레임워크는 UMDF 드라이버를 대신하여 일부 I/O 요청을 완료합니다. 경우에 따라 프레임워크는 HRESULT 형식의 반환 값을 동등한 NTSTATUS 값으로 변환하지 않으므로 프레임워크는 HRESULT 형식의 완료 상태 커널 모드 클라이언트에 전달할 수 있습니다.

    이 때문에 커널 모드 클라이언트는 NT_ERROR 매크로가 HRESULT 오류 값에 대해 TRUE를 반환하지 않으므로 I/O 요청의 완료 상태 테스트할 때 NT_ERROR 매크로를 사용하면 안 됩니다. 커널 모드 드라이버는 I/O 요청의 완료 상태 테스트할 때 NT_SUCCESS 매크로를 사용해야 합니다.

이전 UMDF 버전의 커널 모드 클라이언트 지원

버전 1.9 이전의 UMDF 버전의 경우 드라이버의 INF 파일에는 INF AddReg 지시문이 포함되어 디바이스 하드웨어 키WUDF 하위 키 아래에 REG_DWORD 크기의 UpperDriverOk 레지스트리 값을 만들 수 있습니다.

UpperDriverOk 레지스트리 값이 0이 아닌 숫자로 설정된 경우 프레임워크는 커널 모드 드라이버가 사용자 모드 드라이버 위에 로드되도록 허용합니다. 커널 모드 드라이버는 사용자 모드 애플리케이션에서 UMDF 드라이버로 I/O 요청을 전달할 수 있지만 커널 모드 드라이버는 커널 모드로 생성된 I/O 요청을 UMDF 드라이버로 보낼 수 없습니다.

UMDF 버전 1.9 이상에서는 UpperDriverOk 레지스트리 값이 사용되지 않으며 기존 드라이버에 대해서만 지원됩니다. 새 드라이버는 UmdfKernelModeClientPolicy 지시문을 사용해야 합니다.