iT邦幫忙

2023 iThome 鐵人賽

DAY 6
0
Software Development

Windows Driver + Electron 學習筆記系列 第 6

Day06 非隨插即用(Non-PnP)驅動程式-2

  • 分享至 

  • xImage
  •  

今天繼續以Non-PnP Driver Sample來介紹驅動程式的架構,昨天有提到由WDF所撰寫的驅動程式會有一個DriverEntry和一些對應特定事件發生時所呼叫的函式,而FileEvtIoDeviceControl就是針對發生I/O控制要求時所呼叫的函式,部分函式實作如下:

VOID
FileEvtIoDeviceControl(
    IN WDFQUEUE         Queue,
    IN WDFREQUEST       Request,
    IN size_t            OutputBufferLength,
    IN size_t            InputBufferLength,
    IN ULONG            IoControlCode
    )
/*++
Routine Description:

    This event is called when the framework receives IRP_MJ_DEVICE_CONTROL
    requests from the system.

Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.
    Request - Handle to a framework request object.

    OutputBufferLength - length of the request's output buffer,
                        if an output buffer is available.
    InputBufferLength - length of the request's input buffer,
                        if an input buffer is available.

    IoControlCode - the driver-defined or system-defined I/O control code
                    (IOCTL) that is associated with the request.

Return Value:

   VOID

--*/
{
    NTSTATUS            status = STATUS_SUCCESS;// Assume success
    PCHAR               inBuf = NULL, outBuf = NULL; // pointer to Input and output buffer
    PCHAR               data = "this String is from Device Driver !!!";
    ULONG               datalen = (ULONG) strlen(data)+1;//Length of data including null
    PCHAR               buffer = NULL;
    PREQUEST_CONTEXT    reqContext = NULL;
    size_t               bufSize;

    UNREFERENCED_PARAMETER( Queue );

    PAGED_CODE();

    if(!OutputBufferLength || !InputBufferLength)
    {
        WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
        return;
    }

    //
    // Determine which I/O control code was specified.
    //

    switch (IoControlCode)
    {
    case IOCTL_NONPNP_METHOD_BUFFERED:


        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_BUFFERED\n");

        //
        // For bufffered ioctls WdfRequestRetrieveInputBuffer &
        // WdfRequestRetrieveOutputBuffer return the same buffer
        // pointer (Irp->AssociatedIrp.SystemBuffer), so read the
        // content of the buffer before writing to it.
        //
        status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize);
        if(!NT_SUCCESS(status)) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        ASSERT(bufSize == InputBufferLength);

        //
        // Read the input buffer content.
        // We are using the following function to print characters instead
        // TraceEvents with %s format because the string we get may or
        // may not be null terminated. The buffer may contain non-printable
        // characters also.
        //
        Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data from User : %!HEXDUMP!\n",
                        log_xstr(inBuf, (USHORT)InputBufferLength)));
        PrintChars(inBuf, InputBufferLength  );


        status = WdfRequestRetrieveOutputBuffer(Request, 0, &outBuf, &bufSize);
        if(!NT_SUCCESS(status)) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        ASSERT(bufSize == OutputBufferLength);

        //
        // Writing to the buffer over-writes the input buffer content
        //

        RtlCopyMemory(outBuf, data, OutputBufferLength);

        Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data to User : %!HEXDUMP!\n",
                        log_xstr(outBuf, (USHORT)datalen)));
        PrintChars(outBuf, datalen  );

        //
        // Assign the length of the data copied to IoStatus.Information
        // of the request and complete the request.
        //
        WdfRequestSetInformation(Request,
                OutputBufferLength < datalen? OutputBufferLength:datalen);

        //
        // When the request is completed the content of the SystemBuffer
        // is copied to the User output buffer and the SystemBuffer is
        // is freed.
        //

       break;

...

    default:

        //
        // The specified I/O control code is unrecognized by this driver.
        //
        status = STATUS_INVALID_DEVICE_REQUEST;
        TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "ERROR: unrecognized IOCTL %x\n", IoControlCode);
        break;
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Completing Request %p with status %X",
                   Request, status );

    WdfRequestComplete( Request, status);

}

FileEvtIoDeviceControl可以依據傳入的I/O control code執行對應的動作,I/O control code可以為系統宣告或驅動程式自行宣告,若要自行宣告則會使用巨集CTRL_CODE來處理,格式如下:

#define IOCTL_Device_Function CTL_CODE(DeviceType, FunctionCode, TransferType, RequiredAccess)
  • DeviceType
    • 符合驅動程式DEVICE_OBJECT結構之DeviceType成員中所設定的值,小於0x800的值為微軟所保留。
  • FunctionCode
    • 識別驅動程式所要執行的函式,小於0x800的值為微軟所保留。
  • TransferType
    • 指出系統如何在DeviceIoControl和處理 IRP 的驅動程式之間傳遞資料,使用下列其中一個系統定義的常數:
      • METHOD_BUFFERED
      • METHOD_IN_DIRECTMETHOD_OUT_DIRECT
      • METHOD_NEITHER
  • RequiredAccess
    • 指出呼叫端在開啟代表裝置的檔案物件時必須要求的存取類型,使用下列其中一個系統定義的常數:
      • FILE_ANY_ACCESS
      • FILE_READ_DATA
      • FILE_WRITE_DATA

在Non-PnP driver中,有自行宣告I/O control code,位於public.h,宣告如下,分別對應四種不同的TransferType。

//
// The IOCTL function codes from 0x800 to 0xFFF are for customer use.
//
#define IOCTL_NONPNP_METHOD_IN_DIRECT \
    CTL_CODE( FILEIO_TYPE, 0x900, METHOD_IN_DIRECT, FILE_ANY_ACCESS  )

#define IOCTL_NONPNP_METHOD_OUT_DIRECT \
    CTL_CODE( FILEIO_TYPE, 0x901, METHOD_OUT_DIRECT , FILE_ANY_ACCESS  )

#define IOCTL_NONPNP_METHOD_BUFFERED \
    CTL_CODE( FILEIO_TYPE, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS  )

#define IOCTL_NONPNP_METHOD_NEITHER \
    CTL_CODE( FILEIO_TYPE, 0x903, METHOD_NEITHER , FILE_ANY_ACCESS  )

以本次主題要用到驅動程式透過I/O埠與環控晶片溝通,就可以自行定義I/O control code,當驅動程式收到對應的I/O control code,就可以對指定的I/O埠讀取或寫入資料。

參考內容

Non-PnP Driver Sample
定義 I/O 控制程式碼 - Windows drivers | Microsoft Learn
指定裝置類型 - Windows drivers | Microsoft Learn


上一篇
Day05 非隨插即用(Non-PnP)驅動程式-1
下一篇
Day07 非隨插即用(Non-PnP)驅動程式-3
系列文
Windows Driver + Electron 學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言