注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

从C开始

 
 
 

日志

 
 

NT式驱动的基本结构  

2010-12-09 17:06:53|  分类: 驱动编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

驱动对象(DRIVER_OBJECT
typedef struct _DRIVER_OBJECT {

    //结构的类型和大小
    CSHORT Type;
    CSHORT Size;
    PDEVICE_OBJECT DeviceObject;  //
指向驱动的第一个设备对象
    ULONG Flags;

    //这个驱动设备在内核空间中的开始地址和大小
    PVOID DriverStart;                                 
    ULONG DriverSize;                            
    PVOID DriverSection;  
    PDRIVER_EXTENSION DriverExtension;                           //
驱动扩展
    UNICODE_STRING DriverName;//
驱动程序名字,例如:\\Driver\\【驱动程序名称】

    //指向注册表中的硬件配置信息,一般为    \Registry\Machine\Hardware\DESCRIPTION\SYSTEM
    PUNICODE_STRING HardwareDatabase;

    PFAST_IO_DISPATCH FastIoDispatch;     //
文件驱动中用到的派遣函数                            
    PDRIVER_INITIALIZE DriverInit;  //
驱动程序的DriverEntery例程入口点
    PDRIVER_STARTIO DriverStartIo;                                //
驱动程序的DriverStartIo
    PDRIVER_UNLOAD DriverUnload;                                 //
驱动程序的DriverUnload
    PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];  //
驱动程序的派遣例程入口点              

} DRIVER_OBJECT;
typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT;


NT式驱动的基本结构 - Fly - 从C开始
 

 

设备对象(DEVICE_OBJECT

typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _DEVICE_OBJECT {
    //结构的类型和大小
    CSHORT Type;
    USHORT Size;
    //引用计数
    LONG ReferenceCount;
    struct _DRIVER_OBJECT *DriverObject;                        //
这个设备所属的驱动对象
    struct _DEVICE_OBJECT *NextDevice;                          //
指向该驱动程序的下一个设备对象
    struct _DEVICE_OBJECT *AttachedDevice; //
如果有更高一层驱动附加到这个驱动,这个指向更高一层驱动的设备对象
    struct _IRP *CurrentIrp;                                   //
指向当前IRP
    PIO_TIMER Timer;
    ULONG Flags;                                // See above:  DO_...
设备的缓冲方式
    ULONG Characteristics;   // See ntioapi:  FILE_...
IoCreateDevice函数设置
    PVPB Vpb;
    PVOID DeviceExtension;                                       //
指向设备扩展
    DEVICE_TYPE DeviceType;
    CCHAR StackSize;                                             //IRP
中栈单元的最少个数
    union {
        LIST_ENTRY ListEntry;
        WAIT_CONTEXT_BLOCK Wcb;
    } Queue;
    ULONG AlignmentRequirement;
    KDEVICE_QUEUE DeviceQueue;
    KDPC Dpc;

    //
    //  The following field is for exclusive use by the filesystem to keep
    //  track of the number of Fsp threads currently using the device
    //


    ULONG ActiveThreadCount;
    PSECURITY_DESCRIPTOR SecurityDescriptor;
    KEVENT DeviceLock;
    USHORT SectorSize;
    USHORT Spare1;
    struct _DEVOBJ_EXTENSION  *DeviceObjectExtension;
    PVOID  Reserved;
} DEVICE_OBJECT;
typedef struct _DEVICE_OBJECT *PDEVICE_OBJECT; // ntndis
NT式驱动的基本结构 - Fly - 从C开始
 

设备扩展

   设备对象记录“通用设备信息,而另外一些“特殊”的信息记录在设备扩展里。各个设备扩展由程序员自己定义,每个设备的扩展也不尽相同。设备扩展是由程序员指定内容和大小,由I/O管理器创建的,并保存在非分页内存中

在设备扩展中会记录下列这些内容:

1.  设备对象的反向指针

2.  设备状态或驱动环境信息

3.  中断对象指针

4.  控制器对象指针

由于设备扩展是驱动程序专用的,它的结构必须在驱动程序的头文件中定义。

 

NT式驱动的基本结构

1.  驱动入口函数(DriverEntry)

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDrover_Object,

IN PUNICODE_STRING pRegistryPath);

DriverEntry主要是对驱动程序进行初始化工作,它由系统进程即System进程在驱动加载的时候,启动新的线程,调用执行体组件中的对象管理器,创建一个驱动对象。

pDrover_Object:指向这个驱动对象。

pRegistryPath:指向设备服务键的键名字符串的指针。该字符串的内容一般为\REGISTRY\MACHINE\SYSTEM\ControlSet\Services\[服务名]

 

在驱动程序中,字符串用UNICODE字符集来表示,每个字符用16位即两个字节表示。其中,UNICODEUNICODE_STRING结构体表示。

typedef struct _UNICODE_STRING {
  USHORT  Length; //
字符串的长度,如果字符串有N个字符,那么Length将会是N2倍。
  USHORT  MaximumLength; //
指定这个结构最大能记录的字节数
  PWSTR  Buffer; //
记录字符串的指针,每个字符占两个字节
} UNICODE_STRING *PUNICODE_STRING;

 

在驱动程序中,可以用KdPrint打印UNICODE信息。其语法是:

KdPrint((“%S”, pRegistryPath->Buffer)); //s大写

   

KdPrint((“%ws”, pRegistryPath->Buffer)); //ws小写

 

    注意:

1.DriverEntry函数中,一般设置设置卸载例程和IRP派遣函数,另外还有一部分代码用来创建驱动的设备对象。

2.DriverEntry返回值是NTSTATUS的数据。其中宏NT_SUCCESS,被用来检测状态的正确性。

3.DriverEntry中的参数修饰符“IN”,OUT”,INOUT”DDK中被定义为空串,他们的功能类似于程序的注释。

 

2.创建设备对象

NTSTATUS 
  IoCreateDevice(
    IN PDRIVER_OBJECT  DriverObject,
    IN ULONG  DeviceExtensionSize, //
指定设备扩展的大小
    IN PUNICODE_STRING  DeviceName  OPTIONAL,//
设备对象的名字
    IN DEVICE_TYPE  DeviceType,
    IN ULONG  DeviceCharacteristics,//
设置设备对象的特征
    IN BOOLEAN  Exclusive,//
设置设备对象是否在内核模式下使用,一般为TRUE
    OUT PDEVICE_OBJECT  *DeviceObject //
指向新创建的设备对象。
    );

参数DeviceName UNICODE字符串来指定设备对象的名字,该字符串必须为”\Device\[设备名]”的形式。

当然,也可以不指定设备名字,这样I/O管理器会自动分配一个数字作为设备的设备名,例如:\Device\00000001;

 

如果指定了设备名,但是也只能被内核模式下的其他驱动所识别,用户模式下的应用程序是无法识别的。我们可以通过符号链接来让用户模式下的程序识别这个设备。

创建符号链接的函数是IoCreateSymbolicLink,声明如下:

NTSTATUS 
   IoCreateSymbolicLink(
    IN PUNICODE_STRING  SymbolicLinkName,
    IN PUNICODE_STRING  DeviceName
    );

在内核模式下,符号链接就是以”\??\”开头的(或者“\DosDevice\”开头的)。如C盘就是“\??\C:”。而在用户模式下则是以“\\.\开头的,如C盘就是“\\.\C:

 

 

3.DriverUnload例程

此例程在驱动被卸载时调用,在NT式驱动中,DriverUnload一般负责删除在DriverEntry中创建的设备对象,并且将设备对象所关联的符号链接删除。另外,DriverUnload还负责对一些资源进行回收。

 

删除设备对象:

VOID 
   IoDeleteDevice(
    IN PDEVICE_OBJECT  DeviceObject
    );

 

删除符号链接

NTSTATUS 
IoDeleteSymbolicLink(
   IN PUNICODE_STRING  SymbolicLinkName
);

  评论这张
 
阅读(646)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018