《Windows驱动开发技术详解》读书笔记(二)

本文介绍了一种基于WDM的驱动程序开发实例,包括关键函数的实现与编译过程,并提供了两种编译方法及驱动安装步骤。

再来看基于WDM的驱动程序,

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#ifdef__cplusplus
extern"C"
{
#endif
#include
<wdm.h>
#ifdef__cplusplus
}
#endif

typedef
struct_DEVICE_EXTENSION
{
PDEVICE_OBJECTfdo;
PDEVICE_OBJECTNextStackDevice;
UNICODE_STRINGustrDeviceName;
//设备名
UNICODE_STRINGustrSymLinkName;//符号链接名
}DEVICE_EXTENSION,*PDEVICE_EXTENSION;

#definePAGEDCODEcode_seg("PAGE")
#defineLOCKEDCODEcode_seg()
#defineINITCODEcode_seg("INIT")

#definePAGEDDATAdata_seg("PAGE")
#defineLOCKEDDATAdata_seg()
#defineINITDATAdata_seg("INIT")

#definearraysize(p)(sizeof(p)/sizeof((p)[0]))

NTSTATUSHelloWDMAddDevice(INPDRIVER_OBJECTDriverObject,
INPDEVICE_OBJECTPhysicalDeviceObject);
NTSTATUSHelloWDMPnp(INPDEVICE_OBJECTfdo,
INPIRPIrp);
NTSTATUSHelloWDMDispatchRoutine(INPDEVICE_OBJECTfdo,
INPIRPIrp);
voidHelloWDMUnload(INPDRIVER_OBJECTDriverObject);

extern"C"
NTSTATUSDriverEntry(INPDRIVER_OBJECTDriverObject,
INPUNICODE_STRINGRegistryPath);

ContractedBlock.gifExpandedBlockStart.gifHelloWDM.cpp
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include"HelloWDM.h"

/************************************************************************
*函数名称:DriverEntry
*功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象
*参数列表:
pDriverObject:从I/O管理器中传进来的驱动对象
pRegistryPath:驱动程序在注册表的中的路径
*返回值:返回初始化驱动状态
************************************************************************
*/
#pragmaINITCODE
extern"C"NTSTATUSDriverEntry(INPDRIVER_OBJECTpDriverObject,
INPUNICODE_STRINGpRegistryPath)
{
KdPrint((
"EnterDriverEntry/n"));

pDriverObject
->DriverExtension->AddDevice=HelloWDMAddDevice;
pDriverObject
->MajorFunction[IRP_MJ_PNP]=HelloWDMPnp;
pDriverObject
->MajorFunction[IRP_MJ_DEVICE_CONTROL]=
pDriverObject
->MajorFunction[IRP_MJ_CREATE]=
pDriverObject
->MajorFunction[IRP_MJ_READ]=
pDriverObject
->MajorFunction[IRP_MJ_WRITE]=HelloWDMDispatchRoutine;
pDriverObject
->DriverUnload=HelloWDMUnload;

KdPrint((
"LeaveDriverEntry/n"));
returnSTATUS_SUCCESS;
}

/************************************************************************
*函数名称:HelloWDMAddDevice
*功能描述:添加新设备
*参数列表:
DriverObject:从I/O管理器中传进来的驱动对象
PhysicalDeviceObject:从I/O管理器中传进来的物理设备对象
*返回值:返回添加新设备状态
************************************************************************
*/
#pragmaPAGEDCODE
NTSTATUSHelloWDMAddDevice(INPDRIVER_OBJECTDriverObject,
INPDEVICE_OBJECTPhysicalDeviceObject)
{
PAGED_CODE();
KdPrint((
"EnterHelloWDMAddDevice/n"));

NTSTATUSstatus;
PDEVICE_OBJECTfdo;
UNICODE_STRINGdevName;
RtlInitUnicodeString(
&devName,L"//Device//MyWDMDevice");
status
=IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
&(UNICODE_STRING)devName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&fdo);
if(!NT_SUCCESS(status))
returnstatus;
PDEVICE_EXTENSIONpdx
=(PDEVICE_EXTENSION)fdo->DeviceExtension;
pdx
->fdo=fdo;
pdx
->NextStackDevice=IoAttachDeviceToDeviceStack(fdo,PhysicalDeviceObject);
UNICODE_STRINGsymLinkName;
RtlInitUnicodeString(
&symLinkName,L"//DosDevices//HelloWDM");

pdx
->ustrDeviceName=devName;
pdx
->ustrSymLinkName=symLinkName;
status
=IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName,&(UNICODE_STRING)devName);

if(!NT_SUCCESS(status))
{
IoDeleteSymbolicLink(
&pdx->ustrSymLinkName);
status
=IoCreateSymbolicLink(&symLinkName,&devName);
if(!NT_SUCCESS(status))
{
returnstatus;
}
}

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

KdPrint((
"LeaveHelloWDMAddDevice/n"));
returnSTATUS_SUCCESS;
}

/************************************************************************
*函数名称:DefaultPnpHandler
*功能描述:对PNPIRP进行缺省处理
*参数列表:
pdx:设备对象的扩展
Irp:从IO请求包
*返回值:返回状态
************************************************************************
*/
#pragmaPAGEDCODE
NTSTATUSDefaultPnpHandler(PDEVICE_EXTENSIONpdx,PIRPIrp)
{
PAGED_CODE();
KdPrint((
"EnterDefaultPnpHandler/n"));
IoSkipCurrentIrpStackLocation(Irp);
KdPrint((
"LeaveDefaultPnpHandler/n"));
returnIoCallDriver(pdx->NextStackDevice,Irp);
}

/************************************************************************
*函数名称:HandleRemoveDevice
*功能描述:对IRP_MN_REMOVE_DEVICEIRP进行处理
*参数列表:
fdo:功能设备对象
Irp:从IO请求包
*返回值:返回状态
************************************************************************
*/
#pragmaPAGEDCODE
NTSTATUSHandleRemoveDevice(PDEVICE_EXTENSIONpdx,PIRPIrp)
{
PAGED_CODE();
KdPrint((
"EnterHandleRemoveDevice/n"));

Irp
->IoStatus.Status=STATUS_SUCCESS;
NTSTATUSstatus
=DefaultPnpHandler(pdx,Irp);
IoDeleteSymbolicLink(
&(UNICODE_STRING)pdx->ustrSymLinkName);

//调用IoDetachDevice()把fdo从设备栈中脱开:
if(pdx->NextStackDevice)
IoDetachDevice(pdx
->NextStackDevice);

//删除fdo:
IoDeleteDevice(pdx->fdo);
KdPrint((
"LeaveHandleRemoveDevice/n"));
returnstatus;
}

/************************************************************************
*函数名称:HelloWDMPnp
*功能描述:对即插即用IRP进行处理
*参数列表:
fdo:功能设备对象
Irp:从IO请求包
*返回值:返回状态
************************************************************************
*/
#pragmaPAGEDCODE
NTSTATUSHelloWDMPnp(INPDEVICE_OBJECTfdo,
INPIRPIrp)
{
PAGED_CODE();

KdPrint((
"EnterHelloWDMPnp/n"));
NTSTATUSstatus
=STATUS_SUCCESS;
PDEVICE_EXTENSIONpdx
=(PDEVICE_EXTENSION)fdo->DeviceExtension;
PIO_STACK_LOCATIONstack
=IoGetCurrentIrpStackLocation(Irp);
staticNTSTATUS(*fcntab[])(PDEVICE_EXTENSIONpdx,PIRPIrp)=
{
DefaultPnpHandler,
//IRP_MN_START_DEVICE
DefaultPnpHandler,//IRP_MN_QUERY_REMOVE_DEVICE
HandleRemoveDevice,//IRP_MN_REMOVE_DEVICE
DefaultPnpHandler,//IRP_MN_CANCEL_REMOVE_DEVICE
DefaultPnpHandler,//IRP_MN_STOP_DEVICE
DefaultPnpHandler,//IRP_MN_QUERY_STOP_DEVICE
DefaultPnpHandler,//IRP_MN_CANCEL_STOP_DEVICE
DefaultPnpHandler,//IRP_MN_QUERY_DEVICE_RELATIONS
DefaultPnpHandler,//IRP_MN_QUERY_INTERFACE
DefaultPnpHandler,//IRP_MN_QUERY_CAPABILITIES
DefaultPnpHandler,//IRP_MN_QUERY_RESOURCES
DefaultPnpHandler,//IRP_MN_QUERY_RESOURCE_REQUIREMENTS
DefaultPnpHandler,//IRP_MN_QUERY_DEVICE_TEXT
DefaultPnpHandler,//IRP_MN_FILTER_RESOURCE_REQUIREMENTS
DefaultPnpHandler,//
DefaultPnpHandler,//IRP_MN_READ_CONFIG
DefaultPnpHandler,//IRP_MN_WRITE_CONFIG
DefaultPnpHandler,//IRP_MN_EJECT
DefaultPnpHandler,//IRP_MN_SET_LOCK
DefaultPnpHandler,//IRP_MN_QUERY_ID
DefaultPnpHandler,//IRP_MN_QUERY_PNP_DEVICE_STATE
DefaultPnpHandler,//IRP_MN_QUERY_BUS_INFORMATION
DefaultPnpHandler,//IRP_MN_DEVICE_USAGE_NOTIFICATION
DefaultPnpHandler,//IRP_MN_SURPRISE_REMOVAL
};

ULONGfcn
=stack->MinorFunction;
if(fcn>=arraysize(fcntab))
{
//未知的子功能代码
status=DefaultPnpHandler(pdx,Irp);//somefunctionwedon'tknowabout
returnstatus;
}

#ifDBG
staticchar*fcnname[]=
{
"IRP_MN_START_DEVICE",
"IRP_MN_QUERY_REMOVE_DEVICE",
"IRP_MN_REMOVE_DEVICE",
"IRP_MN_CANCEL_REMOVE_DEVICE",
"IRP_MN_STOP_DEVICE",
"IRP_MN_QUERY_STOP_DEVICE",
"IRP_MN_CANCEL_STOP_DEVICE",
"IRP_MN_QUERY_DEVICE_RELATIONS",
"IRP_MN_QUERY_INTERFACE",
"IRP_MN_QUERY_CAPABILITIES",
"IRP_MN_QUERY_RESOURCES",
"IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
"IRP_MN_QUERY_DEVICE_TEXT",
"IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
"",
"IRP_MN_READ_CONFIG",
"IRP_MN_WRITE_CONFIG",
"IRP_MN_EJECT",
"IRP_MN_SET_LOCK",
"IRP_MN_QUERY_ID",
"IRP_MN_QUERY_PNP_DEVICE_STATE",
"IRP_MN_QUERY_BUS_INFORMATION",
"IRP_MN_DEVICE_USAGE_NOTIFICATION",
"IRP_MN_SURPRISE_REMOVAL",
};

KdPrint((
"PNPRequest(%s)/n",fcnname[fcn]));
#endif//DBG

status
=(*fcntab[fcn])(pdx,Irp);
KdPrint((
"LeaveHelloWDMPnp/n"));
returnstatus;
}

/************************************************************************
*函数名称:HelloWDMDispatchRoutine
*功能描述:对缺省IRP进行处理
*参数列表:
fdo:功能设备对象
Irp:从IO请求包
*返回值:返回状态
************************************************************************
*/
#pragmaPAGEDCODE
NTSTATUSHelloWDMDispatchRoutine(INPDEVICE_OBJECTfdo,
INPIRPIrp)
{
PAGED_CODE();
KdPrint((
"EnterHelloWDMDispatchRoutine/n"));
Irp
->IoStatus.Status=STATUS_SUCCESS;
Irp
->IoStatus.Information=0;//nobytesxfered
IoCompleteRequest(Irp,IO_NO_INCREMENT);
KdPrint((
"LeaveHelloWDMDispatchRoutine/n"));
returnSTATUS_SUCCESS;
}

/************************************************************************
*函数名称:HelloWDMUnload
*功能描述:负责驱动程序的卸载操作
*参数列表:
DriverObject:驱动对象
*返回值:返回状态
************************************************************************
*/
#pragmaPAGEDCODE
voidHelloWDMUnload(INPDRIVER_OBJECTDriverObject)
{
PAGED_CODE();
KdPrint((
"EnterHelloWDMUnload/n"));
KdPrint((
"LeaveHelloWDMUnload/n"));
}

同前面一样,编译也是两种方式,第一种用DDK编译,准备两个脚本文件,makefile和Sources,其中Sources有所不同,如下所示:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->TARGETNAME=HelloWDM
TARGETTYPE
=DRIVER
DRIVERTYPE
=WDM
TARGETPATH
=OBJ

INCLUDES
=$(BASEDIR)/inc;/
$(BASEDIR)/inc/ddk;/

SOURCES
=HelloWDM.cpp/

另一种是用VC进行编译,有三点需要注意:

1, 选择c/c++选项卡,将原来的Project Options全删掉,换成下面的:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->/nologo/Gz/MLd/W3/WX/Z7/Od/DWIN32=100/D_X86_=1/DWINVER=0x500/DDBG=1/Fo"MyDriver_Check/"/Fd"MyDriver_Check/"/FD/c

2, 选择Link选项卡,将原来的Project Options全删掉,换成下面的:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->wdm.lib/nologo/base:"0x10000"/stack:0x400000,0x1000/entry:"DriverEntry"/subsystem:console/incremental:no/pdb:"MyDriver_Check/HelloWDM.pdb"/debug/machine:I386/nodefaultlib/out:"MyDriver_Check/HelloWDM.sys"/pdbtype:sept/subsystem:native/driver/SECTION:INIT,D/RELEASE/IGNORE:4078

3, 修改include目录时,加入

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->D:/WINDDK/3790.1830/INC/DDK/WDM/W2K

否则会报错如下:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->fatalerrorC1083:Cannotopenincludefile:'wdm.h':Nosuchfileordirectory

最后是驱动的安装,WDM驱动的安装需要写一个inf文件,如下所示:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->;---------VersionSection---------------------------------------------------

[Version]
Signature
="$CHICAGO$";
Provider
=Phinecos_Device
DriverVer
=20/2/2000,3.0.0.3

;Ifdevicefitsoneofthestandardclasses,usethenameandGUIDhere,
;otherwisecreateyourowndeviceclassandGUIDasthisexampleshows.

Class
=PhinecosDevice
ClassGUID
={EF2962F0-0D55-4bff-B8AA-2221EE8A79B0}


;---------SourceDiskNamesandSourceDiskFilesSection-----------------------

;Thesesectionsidentifysourcedisksandfilesforinstallation.Theyare
;shownhereasanexample,butcommentedout.

[SourceDisksNames]
1="HelloWDM",Disk1,,

[SourceDisksFiles]
HelloWDM
.sys=1,MyDriver_Check,

;---------ClassInstall/ClassInstall32Section-------------------------------

;Notnecessaryifusingastandardclass

;9XStyle
[ClassInstall]
Addreg
=Class_AddReg

;NTStyle
[ClassInstall32]
Addreg
=Class_AddReg

[Class_AddReg]
HKR
,,,,%DeviceClassName%
HKR
,,Icon,,"-5"

;---------DestinationDirsSection-------------------------------------------

[DestinationDirs]
YouMark_Files_Driver
=10,System32/Drivers

;---------ManufacturerandModelsSections----------------------------------

[Manufacturer]
%MfgName%
=Mfg0

[Mfg0]

;PCIhardwareIdsusetheform
;PCI/VEN_aaaa&DEV_bbbb&SUBSYS_cccccccc&REV_dd
;改成你自己的ID
%DeviceDesc%
=YouMark_DDI,PCI/VEN_9999&DEV_9999

;----------DDInstallSections-----------------------------------------------
;---------Windows9X-----------------

;ExperimentationhasshownthatDDInstallrootnamesgreaterthan19characters
;causeproblemsinWindows98

[YouMark_DDI]
CopyFiles
=YouMark_Files_Driver
AddReg
=YouMark_9X_AddReg

[YouMark_9X_AddReg]
HKR
,,DevLoader,,*ntkern
HKR
,,NTMPDriver,,HelloWDM.sys
HKR
,"Parameters","BreakOnEntry",0x00010001,0

;---------WindowsNT-----------------

[YouMark_DDI
.NT]
CopyFiles
=YouMark_Files_Driver
AddReg
=YouMark_NT_AddReg

[YouMark_DDI
.NT.Services]
Addservice
=HelloWDM,0x00000002,YouMark_AddService

[YouMark_AddService]
DisplayName
=%SvcDesc%
ServiceType
=1;SERVICE_KERNEL_DRIVER
StartType
=3;SERVICE_DEMAND_START
ErrorControl
=1;SERVICE_ERROR_NORMAL
ServiceBinary
=%10%/System32/Drivers/HelloWDM.sys

[YouMark_NT_AddReg]
HKLM
,"System/CurrentControlSet/Services/HelloWDM/Parameters",/
"BreakOnEntry",0x00010001,0


;---------Files(common)-------------

[YouMark_Files_Driver]
HelloWDM
.sys

;---------StringsSection---------------------------------------------------

[Strings]
ProviderName
="Phinecos."
MfgName
="VistaSoft"
DeviceDesc
="HelloWorldWDM!"
DeviceClassName
="Phinecos_Device"
SvcDesc
="Phinecos"

这里有两种安装方式,一种是进入“控制面板”,选择添加硬件,加载进inf文件完成安装,如图所示:

另一种可选的安装测试方式是使用Driver Studio中的EzDriverInstaller工具来进行安装,如图所示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值