WDM驱动程序入门(1)-Hello WDM
生活随笔
收集整理的這篇文章主要介紹了
WDM驱动程序入门(1)-Hello WDM
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
WDM驅動程序入門(1)-Hello WDM
??? WDM驅動程序是一種很新的東西,相信很多人都跟我一樣,對它很感興趣,但是又找不到學習的切入點。究其原因,還是因為WDM是一種非常“死板板”的程序,它一運行就是工作在系統的底層RING 0處,提供各種接口給應用程序調用。也正因為如此,它不像普通的應用程序一樣,可以很快地上手——更多的時候,你是在閱讀它的技術資料和各種接口信息,你還要非常地熟悉系統底層的工作原理,否則一個不小心,就“藍屏”了,呵呵——話說回來,寫驅動程序的時候,死機是家常便飯。
??? 因此很多人都對WDM望而生畏了。回想一下,我剛開始學WDM的情形還歷歷在目——看書看了整整3天,但是看完之后好像跟沒看也差不了多少,還是不知道怎么入門,甚至連怎么寫一個“Hello World”都不知道——后來才知道其實WDM是沒有所謂的“Hello World”程序的,唉,真是痛苦啊,這主要還是因為網絡上的WDM資料太少造成的。為了不讓大家重蹈我的覆轍并對WDM有個感性的認識,在此我給出一個最簡單的完整的WDM框架,并附有注釋,姑且可以算是一個入門的“Hello World”吧。
??? 廢話少說,讓我們馬上開始研究,要求讀者已安裝DDK 2000。(在Win98中我還沒有測試過,不清楚是否能正常運行)
/***************************************************************
程序名稱:Hello World for WDM
文件名稱:HelloWDM.cpp
作者:羅聰
日期:2002-8-16
***************************************************************/
//一定要的頭文件,聲明了函數模塊和變量:
#include "HelloWDM.h"
/***************************************************************
函數名稱:DriverEntry()
功能描述:WDM程序入口
***************************************************************/
//extern "C"是必須的,表示“用C鏈接”。如果你的文件名是HelloWDM.c的話,這句可以省略。
extern "C"
NTSTATUS DriverEntry(????IN PDRIVER_OBJECT DriverObject,
????????????????????????IN PUNICODE_STRING RegistryPath)
{
????//指定“添加設備”消息由函數“HelloWDMAddDevice()”來處理:
????DriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;
????//指定“即插即用”消息由函數“HelloWDMPnp()”來處理:
????DriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;
????//返回一個NTSTATUS值STATUS_SUCCESS。幾乎所有的驅動程序例程都必須返回一個NTSTATUS值,這些值在NTSTATUS.H DDK頭文件中有詳細的定義。
????return STATUS_SUCCESS;
}
/***************************************************************
函數名稱: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”就介紹到這里,雖然實際上它什么都沒有做,但是由于它包含了完整的框架,所以對于初學者來說還是很有參考價值的。至于怎么編譯及安裝,留待下次再講,敬請留意。(不是我想賣關子啊,這些步驟實在是很麻煩的,要另外寫一篇文章才說得清楚哦!)
??? WDM驅動程序是一種很新的東西,相信很多人都跟我一樣,對它很感興趣,但是又找不到學習的切入點。究其原因,還是因為WDM是一種非常“死板板”的程序,它一運行就是工作在系統的底層RING 0處,提供各種接口給應用程序調用。也正因為如此,它不像普通的應用程序一樣,可以很快地上手——更多的時候,你是在閱讀它的技術資料和各種接口信息,你還要非常地熟悉系統底層的工作原理,否則一個不小心,就“藍屏”了,呵呵——話說回來,寫驅動程序的時候,死機是家常便飯。
??? 因此很多人都對WDM望而生畏了。回想一下,我剛開始學WDM的情形還歷歷在目——看書看了整整3天,但是看完之后好像跟沒看也差不了多少,還是不知道怎么入門,甚至連怎么寫一個“Hello World”都不知道——后來才知道其實WDM是沒有所謂的“Hello World”程序的,唉,真是痛苦啊,這主要還是因為網絡上的WDM資料太少造成的。為了不讓大家重蹈我的覆轍并對WDM有個感性的認識,在此我給出一個最簡單的完整的WDM框架,并附有注釋,姑且可以算是一個入門的“Hello World”吧。
??? 廢話少說,讓我們馬上開始研究,要求讀者已安裝DDK 2000。(在Win98中我還沒有測試過,不清楚是否能正常運行)
/***************************************************************
程序名稱:Hello World for WDM
文件名稱:HelloWDM.cpp
作者:羅聰
日期:2002-8-16
***************************************************************/
//一定要的頭文件,聲明了函數模塊和變量:
#include "HelloWDM.h"
/***************************************************************
函數名稱:DriverEntry()
功能描述:WDM程序入口
***************************************************************/
//extern "C"是必須的,表示“用C鏈接”。如果你的文件名是HelloWDM.c的話,這句可以省略。
extern "C"
NTSTATUS DriverEntry(????IN PDRIVER_OBJECT DriverObject,
????????????????????????IN PUNICODE_STRING RegistryPath)
{
????//指定“添加設備”消息由函數“HelloWDMAddDevice()”來處理:
????DriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;
????//指定“即插即用”消息由函數“HelloWDMPnp()”來處理:
????DriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;
????//返回一個NTSTATUS值STATUS_SUCCESS。幾乎所有的驅動程序例程都必須返回一個NTSTATUS值,這些值在NTSTATUS.H DDK頭文件中有詳細的定義。
????return STATUS_SUCCESS;
}
/***************************************************************
函數名稱: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”就介紹到這里,雖然實際上它什么都沒有做,但是由于它包含了完整的框架,所以對于初學者來說還是很有參考價值的。至于怎么編譯及安裝,留待下次再講,敬請留意。(不是我想賣關子啊,這些步驟實在是很麻煩的,要另外寫一篇文章才說得清楚哦!)
總結
以上是生活随笔為你收集整理的WDM驱动程序入门(1)-Hello WDM的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hangfire 过期记录_韩剧丨顶楼、
- 下一篇: infor wms 中英文对照_【融合·