设备管理通过设备接口打开设备详细步骤XXXX.docx

上传人:b****5 文档编号:5142047 上传时间:2022-12-13 格式:DOCX 页数:17 大小:293.64KB
下载 相关 举报
设备管理通过设备接口打开设备详细步骤XXXX.docx_第1页
第1页 / 共17页
设备管理通过设备接口打开设备详细步骤XXXX.docx_第2页
第2页 / 共17页
设备管理通过设备接口打开设备详细步骤XXXX.docx_第3页
第3页 / 共17页
设备管理通过设备接口打开设备详细步骤XXXX.docx_第4页
第4页 / 共17页
设备管理通过设备接口打开设备详细步骤XXXX.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

设备管理通过设备接口打开设备详细步骤XXXX.docx

《设备管理通过设备接口打开设备详细步骤XXXX.docx》由会员分享,可在线阅读,更多相关《设备管理通过设备接口打开设备详细步骤XXXX.docx(17页珍藏版)》请在冰豆网上搜索。

设备管理通过设备接口打开设备详细步骤XXXX.docx

设备管理通过设备接口打开设备详细步骤XXXX

通过设备接口打开设备详细步骤

一、驱动程序

1.驱动程序框架的创建

(1)用VC建立一个新工程。

在VCIDE环境中选择File|New,弹出New对话框。

在对话框中,选择Project选项卡。

在Project选项卡中,选择Win32Application。

设置工程名为OpenGuid.如图1所示,单击OK,进入下一个对话框,在对话框中选择一个空的工程。

如图2。

 

图1

 

图2

(2).新建两个文件GuidOpen.h和GuidOpen.cpp.这两个文件的具体写法,详见程序编写。

也可以直接添加现成的已经写好的文件,张帆这本书中,一般都是用的HelloWDM.h和HelloWDM.cpp.

(3).增加新的编译版本,去掉Debug和Release版本。

在Build|Configuration如图3和图4。

 

图3

 

 

图4

(4).修改工程属性。

选择Project|Setting,在弹出的对话框中,选择General选项卡,将Intermediatefiles和Outputfiles改为MyDriver_Check,这个名字英语C/C++中,所设置的Fo和Fd后面的文件名相一致。

如图5。

 

图5

将C/C++选项卡中,原有的ProjectOptions内容全部删掉,换成一下内容。

/nologo/Gz/MLd/W3/WX/Z7/Od/DWIN32=100/D_X86_=1/DWINVER=0x500/DDBG=1/Fo"MyDriver_Check/"/Fd"MyDriver_Check/"/FD/c

其中:

/nologo:

表示不显示编译的版本信息

/Gz:

默认函数调用采用标准调用(_stdcall)

/MLd

/W3:

采用第三级警告模式

/WX:

将警告信息转换为错误信息,最大程度保证代码可靠

/Z7:

用Z7模式产生调试信息?

/Od:

关闭调试模式,VC的调试命令不能调试内核下的程序

/DWIN32=100/D_X86_=1/DWINVER=0x500/DDBG=1:

定义4个宏(不知道为什么)

/Fo"MyDriver_Check/:

MyDriver_Check/为OutputDirectories中“创建”的文件夹,存放中间生成的目标代码路径

/Fd"MyDriver_Check/":

MyDriver_Check/为存放.PDB文件的文件夹

/FD:

生成文件依奈

/c:

只进行编译,不连接

 

图6

选择Link选项卡,将原有的ProjectOptions内容全部删除,替换成如下内容:

wdm.lib/nologo/base:

"0x10000"/stack:

0x400000,0x1000/entry:

"DriverEntry"/subsystem:

console/incremental:

no/pdb:

"MyDriver_Check/GuidOpen.pdb"/debug/machine:

I386/nodefaultlib/out:

"MyDriver_Check/GuiOpen.sys"/pdbtype:

sept/subsystem:

native/driver/SECTION:

INIT,D/IGNORE:

4078

其中:

wdm.lib:

链接WDM库

/nologo:

链接时不显示版本信息

/base:

"0x10000":

加载驱动时,设定加载到虚拟内存的地址

/stack:

0x400000,0x1000:

设定函数使用堆栈的地址与大小

/entry:

"DriverEntry":

入口函数的地址(为符合标准函数调用的)

/subsystem:

console:

设置子系统

/incremental:

no:

非递曾式链接

/pdb:

"MyDriver_Check/GuidOpen.pdb":

设置pdb文件的文件名为GuidOpen,保存于MyDriver_Check文件夹下面C/C++属性页中的设置一样。

/debug:

以Debug方式链接

/machine:

I386:

产生代码为386兼容的平台下的

/nodefaultlib:

不使用默认的库

/out:

"MyDriver_Check/GuidOpen.sys":

输出2进制的代码的文件名,保存于MyDriver_Check文件夹下与C/C++属性页中的设置一样。

/pdbtype:

sept:

设置pdb文件的类型

/subsystem:

native:

子系统为内核系统

/driver:

编译驱动

/SECTION:

INIT,D:

将INIT的段设置为可抛弃的

/IGNORE:

4078:

忽略4078号警告错误

 

图7

(5).修改VC的lib目录和include目录。

Tools->Options->Directories属性页下的

Showdirectoriesfor

切换到Includefie

添加DDK的头文件(安装的ddk的目录文件夹)\Inc\w2k

(ddk的目录文件夹)\Inc\ddk\wdm\w2k

置于最上面

添加库文件(安装的ddk的目录文件夹)\lib\w2k\i386

置于最上面

2.驱动程序说明

(1)重要驱动程序中重要的数据结构

驱动对象(DRIVER_OBJECT)在驱动加载时被内核中的对象管理程序所创建,由内核中的I/O管理器负责加载。

typedefstruct_DRIVER_OBJECT{

CSHORTType;

CSHORTSize;

PDEVICE_OBJECTDeviceObject;

ULONGFlags;

PVOIDDriverStart;

ULONGDriverSize;

PVOIDDriverSection;

PDRIVER_EXTENSIONDriverExtension;

UNICODE_STRINGDriverName;

PUNICODE_STRINGHardwareDatabase;

PFAST_IO_DISPATCHFastIoDispatch;

PDRIVER_INITIALIZEDriverInit;

PDRIVER_STARTIODriverStartIo;

PDRIVER_UNLOADDriverUnload;

PDRIVER_DISPATCHMajorFunction[IRP_MJ_MAXIMUM_FUNCTION+1];

}DRIVER_OBJECT;

typedefstruct_DRIVER_OBJECT*PDRIVER_OBJECT;

DeviceObject:

每个驱动程序会有一个或多个设备对象。

设备对象是由程序员自己创建的,而非操作系统完成,在驱动被卸载时,遍历每个设备对象,并将其删除。

设备对象(DEVICE_OBJECT)

typedefstruct_DEVICE_OBJECT{

struct_DRIVER_OBJECT*DriverObject;

struct_DEVICE_OBJECT*NextDevice;

struct_DEVICE_OBJECT*AttachedDevice;

struct_IRP*CurrentIrp;

ULONGFlags;

struct_DEVOBJ_EXTENSION*DeviceObjectExtension;

......................

}DEVICE_OBJECT;

typedefstruct_DEVICE_OBJECT*PDEVICE_OBJECT;//ntndis

设备扩展是由程序员制定内容和大小,由I/O管理器创建的,并且保存在非分页内存中。

(2)WDM驱动程序基本结构,在WDM驱动程序中,完成一个设备操作,至少需要两个设备对象共同完成,一个是物理设备对象(PhysicalDeviceObject)PDO和功能设备对象(FunctionDeviceObject)FDO。

当PC插入一个设备时,PDO会自动创建。

确切的说是由总线驱动创建的,PDO不能单独操作设备,需要配合FDO一起使用。

系统会检测到新设备,要求安装驱动程序,需要安装的驱动程序指的就是WDM程序,此驱动程序负责创建FDO,并且附加到PDO上。

(3)驱动程序分析

头文件中,除了生命函数之外,还要定义一个设备扩展。

typedefstruct_DEVICE_EXTENSION

{

PDEVICE_OBJECTfdo;

PDEVICE_OBJECTNextStackDevice;

UNICODE_STRINGinterfaceName;//设备接口

}DEVICE_EXTENSION,*PDEVICE_EXTENSION;

当驱动程序被加载时,首先进入DriverEntry函数。

DriverEntry主要是对驱动程序进行初始化,它是由系统进程所调用的,在Windows中有个特殊的进程叫做系统进程,打开进程管理器,里面有一个名为System的进程就是系统进程。

系统进程在系统启动的时候就被创建了。

驱动加载时,系统进程启动新的线程,调用执行体组建中的对象管理器,创建一个驱动对象。

这个驱动对象是一个DRIVER_OBJECT的结构体。

另外,系统进程调用执行体组建中的配置管理器程序,查询词驱动程序对应的注册表项。

DriverEntry函数由两个参数PDRIVER_OBJECTpDeriverObject是刚才被创建的驱动对象的指针,和PUNICODE_STRINGpRegistryPath,设备服务键的的键名字符串的指针。

在这个函数中,主要是对系统进程创建的驱动对象进行初始化。

DriverEntry函数中,它对驱动对象的初始化一般是对例程的设置,卸载例程,AddDevice和IRP派遣函数。

具体代码如下:

pDriverObject->DriverExtension->AddDevice=GuidOpenAddDevice;

pDriverObject->MajorFunction[IRP_MJ_PNP]=GuidOpenPnp;

pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=

pDriverObject->MajorFunction[IRP_MJ_CREATE]=

pDriverObject->MajorFunction[IRP_MJ_CLOSE]=

pDriverObject->MajorFunction[IRP_MJ_READ]=

pDriverObject->MajorFunction[IRP_MJ_WRITE]=GuidOpenDispatchRoutine;

pDriverObject->DriverUnload=GuidOpenUnload;

另外,设备服务键的键名有时候需要保存下来,因为这个字符串不是长期存在的,如果以后想使用这个UNICODE字符串,就必须先把它复制到安全的地方,这个字符串的内容一般是\REGISTRY\MACHINE\SYSTEM\ControlSet\Service\[服务名].DriverEntry的返回值是NTSTATUS,是被定义的为32位的无符号长整形。

0~0X7FFFFFFF被认为是正确的。

而0X80000000~0XFFFFFFFF被认为是错误的。

接着驱动程序进入GuidOpenAddDevice例程。

它的主要任务是创建设备对象(功能设备对象)并将其附加到PDO之上。

它有两个参数PDRIVER_OBJECTDriverObject,驱动对象和PDEVICE_OBJECTPhysicalDeviceObject设备对象,就是底层总线驱动创建的PDO对象。

创建设备对象,用IoCreatDevice(

INPDRIVER_OBJECTDriverObject,//系统创建的驱动对象

INULONGDeviceExtensionSize,//程序员自己定义的(在头文件中)设备扩展的大小

INPUNICODE_STRINGDeviceNameOPTIONAL,//设备名,可以为空,此时,I/O管理器会自动以一个数字作为该设备对象的名称

INDEVICE_TYPEDeviceType,//设备类型

INULONGDeviceCharacteristics,//对设备的进一步描述

INBOOLEANExclusize,//是否一次只能进行一次IRP处理

OUTPDEVICE_OBJECT*DeviceObject)//新创建的设备对象

具体代码如下

PDEVICE_OBJECTfdo;

status=IoCreateDevice(

DriverObject,

sizeof(DEVICE_EXTENSION),

NULL,//没有指定设备名

FILE_DEVICE_UNKNOWN,

0,

FALSE,

&fdo);

此时,功能设备对象,创建完毕,接着是将,功能设备对象FDO附加到物理设备对象上PDO。

利用函数PDEVICE_OBJECTIoAttachDeviceToDeviceStack(

INPDEVICE_OBJECTSourceDevice,//新创建的功能设备对象FDO

INPDEVICE_OBJECTTargetDevice//物理设备对象PDO

);

该函数调用成功的话返回一个设备对象,附加设备对象的设备对象,例如在这里,返回的是PDO,如果,ThereturneddeviceobjectpointercandifferfromTargetDeviceifTargetDevicehadadditionaldriverslayeredontopofit.如果该函数运行失败,则返回NULL。

具体程序,我们将该函数返回的设备对象,保存在,设备扩展中,这样一来,我们就需要先得到新创建的功能设备对象的设备扩展。

//得到设备扩展

PDEVICE_EXTENSIONpdx=(PDEVICE_EXTENSION)fdo->DeviceExtension;

pdx->fdo=fdo;

//将FDO附加到PDO上

pdx->NextStackDevice=IoAttachDeviceToDeviceStack(fdo,PhysicalDeviceObject);

WDM驱动程序,设备名无法被用户模式下的应用程序查询到,应用程序可以通过符号链接,设备名或者是设备接口来访问设备。

本文只介绍设备接口方式。

设备接口就是一组全局标志,他是一个128位组成的数字,并能保证在全世界范围内不会冲突。

VC中有一个创建GUID的工具,叫guidgen.exe,它在D:

\ProgramFiles\MicrosoftVisualStudio\Common\Tools中,运行它,它为用户提供了四种方式产生guid,其实它们都是128位的,只是输出的形式不同而已,一般选择第二种,单击NewGUID会产生新的的guid,单击Copy将这个guid复制到新建的guid.h头文件中。

DEFINE_GUID(<>,

0x5dada759,0xde9a,0x45e2,0x8f,0xb4,0x1a,0xa8,0x8b,0x1d,0xe7,0x8);

需要将《name》换成自己为这个接口而起的名字,例如MY_WDM_DEVICE.另外需要注意,在创建guid时,程序中应该包含头文件#include,其中initguid.h只能在一个.cpp中包含,DEFINE_GUID()宏定义了,如果包含了一个initguid.h,那么定义一个guid,如果没有包含一个initguid.h,则定义一个externguid指向定义的那个guid,所以项目中必须有一个文件.cpp包含initguid.h,否则会出错。

但如果包含了多个的initguid.h,也会出错否则会出现错误。

unresolvedexternalsymbol_MY_WDM_DEVICE

创建设备接口用函数NTSTATUS

IoRegisterDeviceInterface(

INPDEVICE_OBJECTPhysicalDeviceObject,

INCONSTGUID*InterfaceClassGuid,

INPUNICODE_STRINGReferenceStringOPTIONAL,

OUTPUNICODE_STRINGSymbolicLinkName//将GUID输出一串UNICODE字符串

);

具体代码创建设备接口

status=IoRegisterDeviceInterface(PhysicalDeviceObject,&MY_WDM_DEVICE,NULL,&pdx->interfaceName);其中pdx->interfaceName就是暴露给应用程序的符号链接。

包括四部分如图8

图8

(1)何种总线设备,例如ROOT

(2)类设备的名称,LIUYOUJINDEVICE

(3)这种设备的第几个设备#0000

(4)制定的设备接口GUID。

设置接口

IoSetDeviceInterfaceState(&pdx->interfaceName,TRUE);

//设置操作模式

fdo->Flags|=DO_BUFFERED_IO|DO_POWER_PAGABLE;

fdo->Flags&=~DO_DEVICE_INITIALIZING;

实现即插即用

即插即用IRP即IRP_MJ_PNP,它一般是由即插即用管理器发送给WDM驱动程序的。

不同情况下,即插即用管理器会发送不同子类型的IRP_MJ_PNPIRP。

在IRP_MJ_PNP派遣函数中要处理不同子功能代码的IRP,本程序采用函数指针的方法。

首先初始化一个函数指针组成的数组,然后在派遣函数中判断是那种子功能代码。

根据这个子功能代码区寻找行的函数指针,再通过指针找到针对具体子功能代码所作的操作函数。

加载驱动时,所用到的各个IRP_MJ_PNP子功能代码。

1.953DefaultEnterDefaultPnpHandler

11.953DefaultLeaveDefaultPnpHandler

11.953DefaultEnterGuidOpenPnp

11.953DefaultPNPRequest(IRP_MN_FILTER_RESOURCE_REQUIREMENTS)修改I/O资源需求列表

11.953DefaultEnterDefaultPnpHandler

11.953DefaultLeaveDefaultPnpHandler

11.953DefaultLeaveGuidOpenPnp

11.953DefaultEnterGuidOpenPnp

11.953DefaultPNPRequest(IRP_MN_START_DEVICE)配置并初始化设备

11.953DefaultEnterHandleStartDevice

11.953DefaultEnterDefaultPnpHandler

11.953DefaultLeaveDefaultPnpHandler

11.953DefaultLeaveHandleStartDevice

11.953DefaultLeaveGuidOpenPnp

11.953DefaultEnterGuidOpenPnp

11.953DefaultPNPRequest(IRP_MN_QUERY_CAPABILITIES)取设备能力

11.953DefaultEnterDefaultPnpHandler

11.953DefaultLeaveDefaultPnpHandler

11.953DefaultLeaveGuidOpenPnp

11.953DefaultEnterGuidOpenPnp

11.953DefaultPNPRequest(IRP_MN_QUERY_PNP_DEVICE_STATE)取设备状态

11.953DefaultEnterDefaultPnpHandler

11.953DefaultLeaveDefaultPnpHandler

11.953DefaultLeaveGuidOpenPnp

11.953DefaultEnterGuidOpenPnp

11.953DefaultPNPRequest(IRP_MN_QUERY_DEVICE_RELATIONS)给出与制定特征相关的设备列表

11.953DefaultEnterDefaultPnpHandler

11.953DefaultLeaveDefaultPnpHandler

11.953DefaultLeaveGuidOpenPnp

对IRP_MN_DEVICE的处理

3.应用程序说明

创建一个对话框类型的驱动程序框架。

(1)首先需要将驱动程序中的guid.h文件copy到应用程序中,并且添加到应用程序的工程里。

(2)应用程序的Porject|Setting|Link的Object/librarymodules里要添加setupapi.lib库,否则会有类似这样的错误:

GuidOpen_AppDlg.obj:

unresolvedexternalsymbol__imp__SetupDiGetDeviceInterfaceDetailA@24

GuidOpen_AppDlg.obj:

errorLNK2001:

unresolvedexternalsymbol__imp__SetupDiDestroyDeviceInfoList@4

GuidOpen_AppDlg.obj:

errorLNK2001:

unresolvedexternalsymbol__imp__SetupDiEnumDeviceInterfaces@20

GuidOpen_AppDlg.obj:

errorLNK2001:

unresolvedexternalsymbol__imp__SetupDiGetClassDevsA@16

程序中应该包含setupapi.h头文件,否则,会出现这样的错误:

errorC2065:

'HDEVINFO':

undeclaredidentifier

errorC2146:

syntaxerror:

missing';'beforeidentifier'info'

error

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 艺术

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1