WDM驱动程序入门(很详细)
WDM驅(qū)動(dòng)程序是一種很新的東西,相信很多人都跟我一樣,對(duì)它很感興趣,但是又找不到學(xué)習(xí)的切入點(diǎn)。究其原因,還是因?yàn)閃DM是一種非?!八腊灏濉钡某绦?#xff0c;它一運(yùn)行就是工作在系統(tǒng)的底層RING 0處,提供各種接口給應(yīng)用程序調(diào)用。也正因?yàn)槿绱?#xff0c;它不像普通的應(yīng)用程序一樣,可以很快地上手——更多的時(shí)候,你是在閱讀它的技術(shù)資料和各種接口信息,你還要非常地熟悉系統(tǒng)底層的工作原理,否則一個(gè)不小心,就“藍(lán)屏”了,呵呵——話說回來,寫驅(qū)動(dòng)程序的時(shí)候,死機(jī)是家常便飯。
因此很多人都對(duì)WDM望而生畏了?;叵胍幌?#xff0c;我剛開始學(xué)WDM的情形還歷歷在目——看書看了整整3天,但是看完之后好像跟沒看也差不了多少,還是不知道怎么入門,甚至連怎么寫一個(gè)“Hello World”都不知道——后來才知道其實(shí)WDM是沒有所謂的“Hello World”程序的,唉,真是痛苦啊,這主要還是因?yàn)榫W(wǎng)絡(luò)上的WDM資料太少造成的。為了不讓大家重蹈我的覆轍并對(duì)WDM有個(gè)感性的認(rèn)識(shí),在此我給出一個(gè)最簡(jiǎn)單的完整的WDM框架,并附有注釋,姑且可以算是一個(gè)入門的“Hello World”吧。
廢話少說,讓我們馬上開始研究,要求讀者已安裝DDK 2000。(在Win98中我還沒有測(cè)試過,不清楚是否能正常運(yùn)行)
/***************************************************************
程序名稱:Hello World for WDM
文件名稱:HelloWDM.cpp
作者:羅聰
日期:2002-8-16
***************************************************************/
//一定要的頭文件,聲明了函數(shù)模塊和變量:
#include "HelloWDM.h"
/***************************************************************
函數(shù)名稱:DriverEntry()
功能描述:WDM程序入口
***************************************************************/
//extern "C"是必須的,表示“用C鏈接”。如果你的文件名是HelloWDM.c的話,這句可以省略。
extern "C"
NTSTATUS DriverEntry(??? IN PDRIVER_OBJECT DriverObject,
??????????????????????? IN PUNICODE_STRING RegistryPath)
{
??? //指定“添加設(shè)備”消息由函數(shù)“HelloWDMAddDevice()”來處理:
??? DriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;
??? //指定“即插即用”消息由函數(shù)“HelloWDMPnp()”來處理:
??? DriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;
??? //返回一個(gè)NTSTATUS值STATUS_SUCCESS。幾乎所有的驅(qū)動(dòng)程序例程都必須返回一個(gè)NTSTATUS值,這些值在NTSTATUS.H DDK頭文件中有詳細(xì)的定義。
??? return STATUS_SUCCESS;
}
/***************************************************************
函數(shù)名稱:HelloWDMAddDevice()
功能描述:處理“添加設(shè)備”消息
***************************************************************/
NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,
?????????????????????????? IN PDEVICE_OBJECT PhysicalDeviceObject)
{
??? //定義一個(gè)NTSTATUS類型的返回值:
??? NTSTATUS status;
??? //定義一個(gè)功能設(shè)備對(duì)象(Functional Device Object):
??? PDEVICE_OBJECT fdo;
??? //創(chuàng)建我們的功能設(shè)備對(duì)象,并儲(chǔ)存到fdo中:
??? status = IoCreateDevice(
??????? DriverObject,??????????????? //驅(qū)動(dòng)程序?qū)ο?br />??????? sizeof(DEVICE_EXTENSION),??? //要求的設(shè)備擴(kuò)展的大小
??????? NULL,??????????????????????? //設(shè)備名稱,這里為NULL
??????? FILE_DEVICE_UNKNOWN,??????? //設(shè)備的類型,在標(biāo)準(zhǔn)頭文件WDM.H或NTDDK.H中列出的FILE_DEVICE_xxx值之一
??????? 0,??????????????????????????? //各種常量用OR組合在一起,指示可刪除介質(zhì)、只讀等。
??????? FALSE,??????????????????????? //如果一次只有一個(gè)線程可以訪問該設(shè)備,為TRUE,否則為FALSE
??????? &fdo);??????????????????????? //返回的設(shè)備對(duì)象
??? //NT_SUCCESS宏用于測(cè)試IoCreateDevice內(nèi)核是否成功完成。不要忘記檢查對(duì)內(nèi)核的所有調(diào)用是否成功。NT_ERROR宏不等同于!NT_SUCCESS,最好使用!NT_SUCCESS,因?yàn)槌隋e(cuò)誤外,它還截獲警告信息。
??? if( !NT_SUCCESS(status))
??????? return status;
??? //創(chuàng)建一個(gè)設(shè)備擴(kuò)展對(duì)象dx,用于存儲(chǔ)指向fdo的指針:
??? PDEVICE_EXTENSION dx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
??? dx->fdo = fdo;
??? //用IoAttachDeviceToDeviceStack函數(shù)把HelloWDM設(shè)備掛接到設(shè)備棧:
??? dx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);
??? // 設(shè)置fdo的flags。有兩個(gè)“位”是必須改變的,一個(gè)是必須清除DO_DEVICE_INITIALIZING標(biāo)志,如果在DriverEntry例程中調(diào)用IoCreateDevice(),就不需要清除這個(gè)標(biāo)志位。還有一個(gè)是必須設(shè)置DO_BUFFER_IO標(biāo)志位:
??? fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
??? fdo->Flags &= ~DO_DEVICE_INITIALIZING;
??? //返回值:
??? return STATUS_SUCCESS;
}
/***************************************************************
函數(shù)名稱:HelloWDMPnp()
功能描述:處理“即插即用”消息
***************************************************************/
NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,
??????????????????????? IN PIRP Irp)
{
??? //創(chuàng)建一個(gè)設(shè)備擴(kuò)展對(duì)象dx,用于存儲(chǔ)指向fdo的指針:
??? PDEVICE_EXTENSION dx=(PDEVICE_EXTENSION)fdo->DeviceExtension;
??? //首先要通過函數(shù)IoGetCurrentIrpStackLocation()得到當(dāng)前的IRP,并由此得到Minor Function:
??? PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
??? ULONG MinorFunction = IrpStack->MinorFunction;
??? //然后把這個(gè)Minor Function傳遞給下一個(gè)設(shè)備棧:
??? IoSkipCurrentIrpStackLocation(Irp);
??? NTSTATUS status = IoCallDriver( dx->NextStackDevice, Irp);
??? //處理“即插即用”次功能代碼:
??? //當(dāng)Minor Function等于IRP_MN_REMOVE_DEVICE時(shí),說明有設(shè)備被拔出或卸下,這時(shí)要取消資源分配并刪除設(shè)備:
??? if( MinorFunction==IRP_MN_REMOVE_DEVICE)
??? {
??????? //取消設(shè)備接口:
??????? IoSetDeviceInterfaceState(&dx->ifSymLinkName, FALSE);
??????? RtlFreeUnicodeString(&dx->ifSymLinkName);
???????
??????? //調(diào)用IoDetachDevice()把fdo從設(shè)備棧中脫開:
??????? if (dx->NextStackDevice)
??????????? IoDetachDevice(dx->NextStackDevice);
??????? //刪除fdo:
??????? IoDeleteDevice(fdo);
??? }
??? //返回值:
??? return status;
}
/***************************************************************
程序名稱:Hello World for WDM
文件名稱:HelloWDM.h
作者:羅聰
日期:2002-8-16
***************************************************************/
//頭文件,只是聲明一些函數(shù)和變量,比較簡(jiǎn)單就不多說了,請(qǐng)讀者自行研究:
#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);
好了,第一個(gè)WDM版的“Hello World”就介紹到這里,雖然實(shí)際上它什么都沒有做,但是由于它包含了完整的框架,所以對(duì)于初學(xué)者來說還是很有參考價(jià)值的。至于怎么編譯及安裝,留待下次再講,敬請(qǐng)留意。(不是我想賣關(guān)子啊,這些步驟實(shí)在是很麻煩的,要另外寫一篇文章才說得清楚哦!)
總結(jié)
以上是生活随笔為你收集整理的WDM驱动程序入门(很详细)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python全排序算法题_Python的
- 下一篇: 域名与转发服务器ip指向不一致_域名映射