第一個驅動程序---Hello world

驅動開發程序的入口點那就是DriverEntry()函數。還有一個問題讓我懷疑了老半天,那就是驅動開發的源程序中需不需要include頭文件呀?爲什麼會懷疑呢?那是因爲我看了半天的書都沒有看到一個完整的驅動程序結構。真的是鬱悶。下面是我看到的一個完整的結構,我先放上來,讓大家看看驅動開發的結構吧。

/***************************************************************
程序名稱:Hello World for WDM
文件名稱:HelloWDM.cpp
日期:2002-8-16
***************************************************************/

//一定要的頭文件,聲明瞭函數模塊和變量:
#include "HelloWDM.h"

/***************************************************************
函數名稱:DriverEntry()
功能描述:WDM程序入口(原來的WinMain被換成了DriverEntry,也是驅動程序的大門)
***************************************************************/
//extern "C"是必須的,表示“用C鏈接”。如果你的文件名是HelloWDM.c的話,這句可以省略。
extern "C"
NTSTATUS DriverEntry(    IN PDRIVER_OBJECT DriverObject, //IN 是一個關鍵字表示這是一個輸 入參數,

PDRIVER_OBJECT是一個數據結構的指針,就像PCHAR一樣,這個數據結構是什麼樣子的,後面我會列出來。她描述

了一個驅動設備對象。
                        IN PUNICODE_STRING RegistryPath)//參數RegistryPath指定了驅動程序註冊表健的路

徑,因爲驅動程序安裝後總會在系統註冊表裏留下一點東西的。
{
    //指定“添加設備”消息由函數“HelloWDMAddDevice()”來處理:
    DriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;
    //指定“即插即用”消息由函數“HelloWDMPnp()”來處理:
    DriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;

    //返回一個NTSTATUS值STATUS_SUCCESS。幾乎所有的驅動程序例程都必須返回一個NTSTATUS值,這些值在

NTSTATUS.H DDK頭文件中有詳細的定義。
    return STATUS_SUCCESS;
}

//NTSTATUS也是一個數據類型,上面我所說的消息有點不準確的,準確地說是“I/O請求包”,不過如果像我們以

前理解消息那樣來理解也無不可,我覺得兩者太想了。無非就是上層的應用程序通過它來告訴驅動程序,你要給我

什麼服務吧!IRP_MJ_PNP就是即插即用處理的請求。你發沒發覺上面其實是在製造進入各個房間的“小門”


/***************************************************************
函數名稱:HelloWDMAddDevice()
功能描述:處理“添加設備”消息
***************************************************************/
NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,
                           IN PDEVICE_OBJECT PhysicalDeviceObject)
{
    //定義一個NTSTATUS類型的返回值:
    NTSTATUS status;
    //定義一個功能設備對象(Functional Device Object):
    PDEVICE_OBJECT fdo;

    //創建我們的功能設備對象,並儲存到fdo中:
    status = IoCreateDevice(
        DriverObject,                //驅動程序對象
        sizeof(DEVICE_EXTENSION),    //要求的設備擴展的大小
        NULL,                        //設備名稱,這裏爲NULL
        FILE_DEVICE_UNKNOWN,        //設備的類型,在標準頭文件WDM.H或NTDDK.H中列出的FILE_DEVICE_xxx

值之一
        0,                            //各種常量用OR組合在一起,指示可刪除介質、只讀等。
        FALSE,                        //如果一次只有一個線程可以訪問該設備,爲TRUE,否則爲FALSE
        &fdo);                        //返回的設備對象

    //NT_SUCCESS宏用於測試IoCreateDevice內核是否成功完成。不要忘記檢查對內核的所有調用是否成功。

NT_ERROR宏不等同於!NT_SUCCESS,最好使用!NT_SUCCESS,因爲除了錯誤外,它還截獲警告信息。
    if( !NT_SUCCESS(status))
        return status;

    //創建一個設備擴展對象dx,用於存儲指向fdo的指針:
    PDEVICE_EXTENSION dx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
    dx->fdo = fdo;

    //用IoAttachDeviceToDeviceStack函數把HelloWDM設備掛接到設備棧:
    dx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);

    //設置fdo的flags。有兩個“位”是必須改變的,一個是必須清除DO_DEVICE_INITIALIZING標誌,如果在

DriverEntry例程中調用IoCreateDevice(),就不需要清除這個標誌位。還有一個是必須設置DO_BUFFER_IO標誌位


    fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
    fdo->Flags &= ~DO_DEVICE_INITIALIZING;

    //返回值:
    return STATUS_SUCCESS;
}


/***************************************************************
函數名稱:HelloWDMPnp()
功能描述:處理“即插即用”消息
***************************************************************/
NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,
                        IN PIRP Irp)
{
    //創建一個設備擴展對象dx,用於存儲指向fdo的指針:
    PDEVICE_EXTENSION dx=(PDEVICE_EXTENSION)fdo->DeviceExtension;

    //首先要通過函數IoGetCurrentIrpStackLocation()得到當前的IRP,並由此得到Minor Function:
    PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
    ULONG MinorFunction = IrpStack->MinorFunction;

    //然後把這個Minor Function傳遞給下一個設備棧:
    IoSkipCurrentIrpStackLocation(Irp);
    NTSTATUS status = IoCallDriver( dx->NextStackDevice, Irp);

    //處理“即插即用”次功能代碼:
    //當Minor Function等於IRP_MN_REMOVE_DEVICE時,說明有設備被拔出或卸下,這時要取消資源分配並刪除設

備:
    if( MinorFunction==IRP_MN_REMOVE_DEVICE)
    {
        //取消設備接口:
        IoSetDeviceInterfaceState(&dx->ifSymLinkName, FALSE);
        RtlFreeUnicodeString(&dx->ifSymLinkName);
       
        //調用IoDetachDevice()把fdo從設備棧中脫開:
        if (dx->NextStackDevice)
            IoDetachDevice(dx->NextStackDevice);
        //刪除fdo:
        IoDeleteDevice(fdo);
    }

    //返回值:
    return status;
}

/***************************************************************
程序名稱:Hello World for WDM
文件名稱:HelloWDM.h
作者:羅聰
日期:2002-8-16
***************************************************************/

//頭文件,只是聲明一些函數和變量,比較簡單就不多說了,請讀者自行研究:

#ifdef __cplusplus

extern "C"
{
#endif

#include "ntddk.h"

#ifdef __cplusplus
}
#endif

typedef struct _DEVICE_EXTENSION
{
    PDEVICE_OBJECT    fdo;
    PDEVICE_OBJECT    NextStackDevice;
    UNICODE_STRING    ifSymLinkName;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,
                           IN PDEVICE_OBJECT PhysicalDeviceObject);

NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,
                        IN PIRP Irp);

好了,第一個WDM版的“Hello World”就介紹到這裏,雖然實際上它什麼都沒有做,但是由於它包含了完整的框架,所以對於向我這樣的新手來說還是很有參考價值的。至於怎麼編譯及安裝只有下次再說了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章