WdfIoTargetFormatRequestForIoctl 함수(wdfiotarget.h)

[KMDF 및 UMDF에 적용]

WdfIoTargetFormatRequestForIoctl 메서드는 I/O 대상에 대한 디바이스 제어 요청을 빌드하지만 요청을 보내지 않습니다.

구문

NTSTATUS WdfIoTargetFormatRequestForIoctl(
  [in]           WDFIOTARGET       IoTarget,
  [in]           WDFREQUEST        Request,
  [in]           ULONG             IoctlCode,
  [in, optional] WDFMEMORY         InputBuffer,
  [in, optional] PWDFMEMORY_OFFSET InputBufferOffset,
  [in, optional] WDFMEMORY         OutputBuffer,
  [in, optional] PWDFMEMORY_OFFSET OutputBufferOffset
);

매개 변수

[in] IoTarget

WdfDeviceGetIoTarget 또는 WdfIoTargetCreate에 대한 이전 호출 또는 특수 I/O 대상에서 제공하는 메서드에서 가져온 로컬 또는 원격 I/O 대상 개체에 대한 핸들입니다.

[in] Request

프레임워크 요청 개체에 대한 핸들입니다. 자세한 내용은 아래 설명 부분을 참조하십시오.

[in] IoctlCode

I/O 대상이 지원하는 IOCTL(I/O 제어 코드)입니다.

[in, optional] InputBuffer

프레임워크 메모리 개체에 대한 핸들입니다. 이 개체는 I/O 대상으로 전송될 데이터가 포함된 버퍼를 나타냅니다. 자세한 내용은 아래 설명 부분을 참조하십시오.

[in, optional] InputBufferOffset

선택적 바이트 오프셋 및 길이 값을 제공하는 호출자가 할당한 WDFMEMORY_OFFSET 구조체에 대한 포인터입니다. 프레임워크는 이러한 값을 사용하여 입력 버퍼 내에서 데이터 전송의 시작 주소와 길이를 결정합니다. 이 포인터가 NULL이면 입력 버퍼의 시작 부분에서 데이터 전송이 시작되고 전송 크기는 버퍼 크기입니다.

[in, optional] OutputBuffer

프레임워크 메모리 개체에 대한 핸들입니다. 이 개체는 I/O 대상에서 데이터를 수신하는 버퍼를 나타냅니다. 자세한 내용은 아래 설명 부분을 참조하십시오.

[in, optional] OutputBufferOffset

선택적 바이트 오프셋 및 길이 값을 제공하는 호출자가 할당한 WDFMEMORY_OFFSET 구조체에 대한 포인터입니다. 프레임워크는 이러한 값을 사용하여 데이터 전송에 대한 출력 버퍼 내의 시작 주소와 길이를 결정합니다. 이 포인터가 NULL이면 출력 버퍼의 시작 부분에서 데이터 전송이 시작되고 전송 크기는 버퍼 크기입니다.

반환 값

WdfIoTargetFormatRequestForIoctl 은 작업이 성공하면 STATUS_SUCCESS 반환합니다. 그렇지 않으면 이 메서드는 다음 값 중 하나를 반환할 수 있습니다.

반환 코드 설명
STATUS_INVALID_PARAMETER
잘못된 매개 변수가 감지되었습니다.
STATUS_INVALID_DEVICE_REQUEST
전송 길이가 버퍼 길이보다 크거나 I/O 요청이 이미 I/O 대상에 큐에 대기되었습니다.
STATUS_INSUFFICIENT_RESOURCES
프레임워크에서 시스템 리소스(일반적으로 메모리)를 할당할 수 없습니다.
STATUS_REQUEST_NOT_ACCEPTED
Request 매개 변수가 나타내는 IRP(I/O 요청 패킷)는 드라이버가 요청을 전달할 수 있도록 충분한 IO_STACK_LOCATION 구조를 제공하지 않습니다.
 

이 메서드는 다른 NTSTATUS 값을 반환할 수도 있습니다.

드라이버가 잘못된 개체 핸들을 제공하는 경우 버그 검사 발생합니다.

설명

WdfIoTargetFormatRequestForIoctl 메서드와 WdfRequestSend 메서드를 사용하여 디바이스 제어 요청을 동기적으로 또는 비동기적으로 보냅니다. 또는 WdfIoTargetSendIoctlSynchronously 메서드를 사용하여 디바이스 제어 요청을 동기적으로 보냅니다.

디바이스 제어 요청에 대한 자세한 내용은 I/O 제어 코드 사용을 참조하세요.

드라이버가 I/O 큐에서 받은 디바이스 제어 요청을 전달하거나 새 요청을 만들고 보낼 수 있습니다. 두 경우 모두 프레임워크에는 요청 개체와 일부 버퍼 공간이 필요합니다.

드라이버가 I/O 큐에서 받은 디바이스 제어 요청을 전달하려면 다음을 수행합니다.

  1. WdfIoTargetFormatRequestForIoctl 메서드의 Request 매개 변수에 대해 받은 요청의 핸들을 지정합니다.
  2. WdfIoTargetFormatRequestForIoctl 메서드의 InputBuffer 매개 변수에 대해 수신된 요청의 입력 버퍼를 사용합니다.

    드라이버는 WdfRequestRetrieveInputMemory 를 호출하여 요청의 입력 버퍼를 나타내는 프레임워크 메모리 개체에 대한 핸들을 가져와야 하며 해당 핸들을 InputBuffer의 값으로 사용해야 합니다.

  3. WdfIoTargetFormatRequestForIoctl 메서드의 OutputBuffer 매개 변수에 대해 수신된 요청의 출력 버퍼를 사용합니다.

    드라이버는 WdfRequestRetrieveOutputMemory 를 호출하여 요청의 출력 버퍼에 대한 핸들을 가져와야 하며 해당 핸들을 OutputBuffer의 값으로 사용해야 합니다.

I/O 요청을 전달하는 방법에 대한 자세한 내용은 I/O 요청 전달을 참조하세요.

드라이버는 수신된 I/O 요청을 I/O 대상으로 보내는 더 작은 요청으로 나누는 경우가 많으므로 드라이버가 새 요청을 만들 수 있습니다.

새 I/O 요청을 만들려면 다음을 수행합니다.

  1. 새 요청 개체를 만들고 WdfIoTargetFormatRequestForIoctl 메서드의 Request 매개 변수에 대한 핸들을 입력합니다.

    WdfRequestCreate를 호출하여 하나 이상의 요청 개체를 미리 할당합니다. WdfRequestReuse를 호출하여 이러한 요청 개체를 다시 사용할 수 있습니다. 드라이버의 EvtDriverDeviceAdd 콜백 함수는 디바이스에 대한 요청 개체를 미리 할당할 수 있습니다.

  2. 버퍼 공간을 제공하고 WdfIoTargetFormatRequestForIoctl 메서드의 InputBuffer 및 OutputBuffer 매개 변수에 대한 버 퍼 핸들을 제공합니다.

    드라이버는 WDFMEMORY가 프레임워크 관리 메모리에 대해 처리할 때 이 버퍼 공간을 지정해야 합니다. 드라이버는 다음 중 하나를 수행할 수 있습니다.

    드라이버가 WdfRequestRetrieveInputMemory 또는 WdfRequestRetrieveOutputMemory 를 호출하고 메모리 핸들을 WdfIoTargetFormatRequestForIoctl에 전달하는 경우 드라이버가 드라이버에서 만든 새 요청 개체를 삭제, 재사용 또는 다시 포맷할 때까지 수신된 I/O 요청을 완료하지 않아야 합니다. (WdfIoTargetFormatRequestForIoctl은 메모리 개체의 참조 수를 증분합니다. 요청 개체를 삭제, 재사용 또는 다시 포맷하면 메모리 개체의 참조 수가 감소합니다.)
드라이버가 WdfIoTargetFormatRequestForIoctl 을 호출하여 디바이스 제어 요청의 형식을 지정한 후 드라이버는 WdfRequestSend 를 호출하여 요청을 I/O 대상에 동기적으로 또는 비동기적으로 보내야 합니다.

동일한 요청을 사용하는 WdfIoTargetFormatRequestForIoctl에 대한 여러 호출은 추가 리소스 할당을 유발하지 않습니다. 따라서 WdfRequestCreate 가 STATUS_INSUFFICIENT_RESOURCES 반환할 가능성을 줄이기 위해 드라이버의 EvtDriverDeviceAdd 콜백 함수는 WdfRequestCreate 를 호출하여 디바이스에 대해 하나 이상의 요청 개체를 미리 할당할 수 있습니다. 이후 드라이버는 WdfRequestCreate에 대한 이후 호출에서 STATUS_INSUFFICIENT_RESOURCES 반환 값을 위험하지 않고 각 요청 개체를 다시 사용(WdfRequestReuse 호출), reformat(WdfIoTargetFormatRequestForIoctl 호출) 및 다시 보내기(WdfRequestSend 호출)할 수 있습니다. 다시 사용 요청 개체에 대한 WdfIoTargetFormatRequestForIoctl 에 대한 모든 후속 호출은 매개 변수 값이 변경되지 않으면 STATUS_SUCCESS 반환합니다. (드라이버가 매번 동일한 요청 형식 메서드를 호출하지 않으면 추가 리소스가 할당될 수 있습니다. 또한 I/O 제어 코드 가 METHOD_BUFFERED 전송 유형을 지정하는 경우 프레임워크는 각 요청에 대해 시스템 버퍼를 할당해야 하며 메모리 리소스가 부족하여 할당이 실패할 수 있습니다.)

I/O 요청이 완료된 후 상태 정보를 가져오는 방법에 대한 자세한 내용은 완료 정보 가져오기를 참조하세요.

WdfIoTargetFormatRequestForIoctl에 대한 자세한 내용은 일반 I/O 대상에 I/O 요청 보내기를 참조하세요.

I/O 대상에 대한 자세한 내용은 I/O 대상 사용을 참조하세요.

예제

다음 코드는 미리 할당된 요청 개체와 미리 할당된 메모리 개체를 다시 사용합니다. 이 예제에서는 입력 및 출력 버퍼를 메모리 개체에 할당하고, 요청 개체의 형식을 지정하고, CompletionRoutine 콜백 함수를 등록하고, 요청을 I/O 대상에 보냅니다.

NTSTATUS
NICSendOidRequestToTargetAsync(
    IN WDFIOTARGET  IoTarget,
    IN WDFREQUEST  Request,
    IN PFILE_OBJECT  FileObject,
    IN ULONG  IoctlControlCode,
    IN OUT PVOID  InputBuffer,
    IN ULONG  InputBufferLength,
    IN OUT PVOID  OutputBuffer,
    IN ULONG  OutputBufferLength,
    OUT PULONG  BytesReadOrWritten
    )
{
    NTSTATUS  status;
    PREQUEST_CONTEXT  reqContext;
    WDF_REQUEST_REUSE_PARAMS  params;
    WDFMEMORY  inputMem, outputMem;
 
    WDF_REQUEST_REUSE_PARAMS_INIT(
                                  &params, 
                                  WDF_REQUEST_REUSE_NO_FLAGS, 
                                  STATUS_SUCCESS
                                  );
    status = WdfRequestReuse(Request, &params);
    if (!NT_SUCCESS(status)){
        return status;
    }

    reqContext = GetRequestContext(Request);

    inputMem = outputMem = NULL;
 
    if (InputBuffer != NULL) {
        status = WdfMemoryAssignBuffer(
                                       reqContext->InputMemory,
                                       InputBuffer, 
                                       InputBufferLength
                                       );
        if (!NT_SUCCESS(status)) {
             return status;
        }
        inputMem = reqContext->InputMemory;
    }

    if (OutputBuffer != NULL) {
        status = WdfMemoryAssignBuffer(
                                       reqContext->OutputMemory,
                                       OutputBuffer, 
                                       OutputBufferLength
                                       );
        if (!NT_SUCCESS(status)) {
            return status;
        }
        outputMem = reqContext->OutputMemory;
    }

    status = WdfIoTargetFormatRequestForIoctl(
                                              IoTarget,
                                              Request,
                                              IoctlControlCode,
                                              inputMem,
                                              NULL,
                                              outputMem,
                                              NULL
                                              );
    if (!NT_SUCCESS(status)) {
        return status;
    }

    WdfRequestSetCompletionRoutine(
                                   Request,
                                   NICSendOidRequestToTargetAsyncCompletionRoutine,
                                   BytesReadOrWritten
                                   );

    if (WdfRequestSend(
                       Request,
                       IoTarget,
                       WDF_NO_SEND_OPTIONS
                       ) == FALSE) {
        status = WdfRequestGetStatus(Request);
    }
    return status;
}

요구 사항

요구 사항
대상 플랫폼 유니버설
최소 KMDF 버전 1.0
최소 UMDF 버전 2.0
머리글 wdfiotarget.h(Wdf.h 포함)
라이브러리 Wdf01000.sys(KMDF); WUDFx02000.dll(UMDF)
IRQL <=DISPATCH_LEVEL
DDI 규정 준수 규칙 DriverCreate(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), RequestFormattedValid(kmdf), RequestSendAndForgetNoFormatting(kmdf), RequestSendAndForgetNoFormatting2(kmdf)

추가 정보

EvtDriverDeviceAdd

WDFMEMORY_OFFSET

WdfDeviceGetIoTarget

WdfIoTarget만들기

WdfIoTargetFormatRequestForInternalIoctl

WdfIoTargetSendIoctlSynchronously

WdfMemoryCreate

WdfMemoryCreatePreallocated

WdfRequestCreate

WdfRequestRetrieveInputMemory

WdfRequestRetrieveOutputMemory

WdfRequestReuse

WdfRequestSend