NT式驱动的基本结构

转载自:http://mzf2008.blog.163.com/blog/static/3559978620101195653754/

驱动对象(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位即两个字节表示。其中,UNICODE用UNICODE_STRING结构体表示。

typedef struct _UNICODE_STRING {
  USHORT  Length; //字符串的长度,如果字符串有N个字符,那么Length将会是N的2倍。
  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
);


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值