看了好多天的書!特別到書店買了《Windows 200/xp wdm 設(shè)備驅(qū)動(dòng)開發(fā)》這本書,在這里我不想怎么評(píng)論它!對(duì)于高手來說,我覺得她一定不能滿足,但是對(duì)于像我這樣想入門的人來說,仿佛看了半天,還是不知道從何下手。什么原理、模型、分層等等講不講,講!絕對(duì)應(yīng)該講!但是你得快點(diǎn)告訴我怎么先弄一個(gè)像“Hello Word!”的什么簡(jiǎn)單來不能再簡(jiǎn)單的完整的例子給我呀!到網(wǎng)上找阿找??!那些高手啊!也不為我們新手寫點(diǎn)圖文并茂的上手資料。沒辦法!結(jié)合自己的需要再參考一些別人的東東,算是自己的一點(diǎn)不成熟的想法吧!
我覺得下面這個(gè)介紹非常不錯(cuò)!我能看懂,所以貼了出來。
我道為什么找不到“Hello Word!”呢?原來在驅(qū)動(dòng)開發(fā)的例子里是沒有所謂的“Hello World”程序的。這主要還是因?yàn)榫W(wǎng)絡(luò)上的WDM資料太少造成的。但是程序的入口點(diǎn)呢?c語言有Main(),用Vc的??匆姷氖荳inMain(),Delphi開發(fā)的是Program里的Begin,但是驅(qū)動(dòng)開發(fā)呢?那也是應(yīng)該有程序的入口點(diǎn)啊。后來我才明白了,那就是DriverEntry()函數(shù)。還有一個(gè)問題讓我懷疑了老半天,那就是驅(qū)動(dòng)開發(fā)的源程序中需不需要include頭文件呀?為什么會(huì)懷疑呢?那是因?yàn)槲铱戳税胩斓臅紱]有看到一個(gè)完整的驅(qū)動(dòng)程序結(jié)構(gòu)。真的是郁悶。下面是我看到的一個(gè)完整的結(jié)構(gòu),我先放上來,讓大家看看驅(qū)動(dòng)開發(fā)的結(jié)構(gòu)吧。
/***************************************************************
程序名稱:Hello World for WDM
文件名稱:HelloWDM.cpp
日期:2002-8-16
***************************************************************/
//一定要的頭文件,聲明了函數(shù)模塊和變量:
#include "HelloWDM.h"
/***************************************************************
函數(shù)名稱:DriverEntry()
功能描述:WDM程序入口(原來的WinMain被換成了DriverEntry,也是驅(qū)動(dòng)程序的大門)
***************************************************************/
//extern "C"是必須的,表示“用C鏈接”。如果你的文件名是HelloWDM.c的話,這句可以省略。
extern "C"
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, //IN 是一個(gè)關(guān)鍵字表示這是一個(gè)輸 入?yún)?shù),PDRIVER_OBJECT是一個(gè)數(shù)據(jù)結(jié)構(gòu)的指針,就像PCHAR一樣,這個(gè)數(shù)據(jù)結(jié)構(gòu)是什么樣子的,后面我會(huì)列出來。她描述了一個(gè)驅(qū)動(dòng)設(shè)備對(duì)象。
IN PUNICODE_STRING RegistryPath)//參數(shù)RegistryPath指定了驅(qū)動(dòng)程序注冊(cè)表健的路徑,因?yàn)轵?qū)動(dòng)程序安裝后總會(huì)在系統(tǒng)注冊(cè)表里留下一點(diǎn)東西的。
{
//指定“添加設(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;
}
//NTSTATUS也是一個(gè)數(shù)據(jù)類型,上面我所說的消息有點(diǎn)不準(zhǔn)確的,準(zhǔn)確地說是“I/O請(qǐng)求包”,不過如果像我們以前理解消息那樣來理解也無不可,我覺得兩者太想了。無非就是上層的應(yīng)用程序通過它來告訴驅(qū)動(dòng)程序,你要給我什么服務(wù)吧!IRP_MJ_PNP就是即插即用處理的請(qǐng)求。你發(fā)沒發(fā)覺上面其實(shí)是在制造進(jìn)入各個(gè)房間的“小門”
/***************************************************************
函數(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ū)ο?/FONT>
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ì)于向我這樣的新手來說還是很有參考價(jià)值的。至于怎么編譯及安裝只有下次再說了