(三)NT驱动基础——创建驱动设备 并 实现驱动与应用程序的通信

来源:互联网 发布:微信小店 源码 编辑:程序博客网 时间:2024/04/30 11:28

NT驱动需要至少在入口函数创建一个设备对象,这个对象可以与物理设备建立映射,来操控物理设备;也可以独立存在,作为软件驱动设备 一、设备对象的功能

1.

作为物理设备的虚拟映射,即作为物理设备与应用程序的中间层

2.接收处理应用程序请求的实体

二、设备对象的结构

typedef struct _DEVICE_OBJECT

{

  CSHORT Type;

  CSHORT Size;

  ULONG ReferenceCount;//引用计数器

  struct _DRIVER_OBJECT *DriverObject;//所属的驱动对象

  struct _DEVIEC_OBJECT *NextDevice;//设备链的下一个设备对象

  DEVICE_TYPE DeviceType;//设备对象类型

  void DeviceExtension;//设备拓展结构

  HAR StackSzie;//IRP栈的大小

  ......

}

三、创建设备对象

1.

函数:IoCreateDevice()

声明:NTSTATUS IoCreateDevice(

                          IN PDRIVER_OBJECT pDriver,

                          IN ULONG DeviceExtensionSize,

                          IN PUNICODE_STRING DeviceName,

                          IN DEVICE_TYPE DeviceType,

                          IN ULONG DeviceCharacteristics,

                          IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *pDeviceObject

                        )

第一个参数pDriver:是设备对象所属的驱动对象

第二个参数DeviceExtensionSize:指定返回的设备对象拓展结构的大小,即为Device->DeviceExtension预留内存大小

第三个参数DeviceName:指定设备对象的名称,必须是"/Device/[设备名]"的形式,C语言下实际写为//Device//[设备名]

第四个参数DeviceType:指定设备对象的类型,现在一般写为FILE_DEVICE_UNKNOWN

第五个参数DeviceCharacteristics:设备对象的特征,现在写为0即可

第六个参数Exclusive:设置设备是否为内核模式下使用,一般为TRUE

第七个参数pDeviceObject:返回所创建的设备对象

 

2.

由于上面函数生成必须拥有管理员权限才能打开,所以必须还有一个创建所有用户都可以打开设备的函数

它是:IoCreateDeviceSecure()

声明:NTSTATUS IoCreateDeviceSecure(

                                                              IN PDRIVER_OBJECT pDriver,

                                                              IN ULONG DeviceExtensionSize,

                                                              IN PUNICODE_STRING DeviceName,

                                                              IN DEVICE_TYPE DeviceType,

                                                              IN ULONG DeviceCharacteristics,

                                                              IN BOOLEAN Exclusive,

                                                              IN PCUNICODE_STRING DefaultDDLString,

                                                              IN LPCGUID DeviceClassGuid,

                                                              OUT PDEVICE_OBJECT *pDeviceObject

                                                            )

这个函数多了两个参数:

DefaultDDLString:指定谁能打开该设备,将该UNICODE_STRING字符串写为"D:P(A;;GA;;;WD)"即满足“人人皆可打开”的要求 

DeviceClassGuid:只要不和其他驱动重复即可,形式如{E927C266-5364-449E-AE52-D6A782AFDA9C}

 

四、设备与物理设备的绑定

      如果该设备对象时操控物理设备的,那么就需要将设备对象与物理设备绑定

步骤:

1.将设备对象的标志位(pDevice->flags),设置为与被绑定对象相一致,且设置pDevice->flags&~DO_DEVICE_INITIALIZEING

 

2.用函数IoAttachDevice()将设备对象与物理设备绑定

声明:NTSTATUS IoAttach(

                                        IN PDEVICE_OBJECT SourceDevice,

                                        IN PUNICODE_STRING TargetDevice,

                                        OUT PDEVICE_OBJCET AttachDevice  

                                       )

另外,还有其他函数如IoAttachDeviceToDeviceStack()、IoAttachDeviceToDeviceStackSafe()、

 

五、驱动与应用程序的通信

      我们知道应用程序不能直接操作像驱动程序这样的内核组件,因此驱动程序需要建立一个符号链接,以供应用程序调用驱动程序,这样调用驱动就像对待空白文件一样,这时符号链接就是文件名。

函数:IoCreateSymbolicLink()

声明:NTSTATUS IoCreateSymbolicLink(

                                                            IN PUNICODE_STRING Symbol_link,

                                                            IN device_name

                                                           )

第一个参数Symbol_link:所创建的符号链接名,形式必须是"/??/[符合链接名]",在C语言实际写为“//??//[符号链接名]”,而应用程序时

                                   用名称“////.//[设备名]”。

第二个参数device_name:指出建立符号链接名的设备。

 

原创粉丝点击