天天看点

windows内核编程基础知识

/*
1.基本的驱动数据结构

//驱动对象结构体
typedef struct _DRIVER_OBJECT {
    CSHORT Type; //结构类型
    CSHORT Size; //结构大小
    PDEVICE_OBJECT DeviceObject; //驱动设备对象 
    PDRIVER_EXTENSION DriverExtension; //驱动扩展指针 
    UNICODE_STRING DriverName;  //驱动程序的名字
    PDRIVER_UNLOAD DriverUnload; //驱动的卸载函数
    PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; //普通的分发函数
    ......                       //其他的成员没有列出
} DRIVER_OBJECT;

//定义驱动对象指针
typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT; 

//************************************************************************************************************

//设备对象结构体
typedef struct _DEVICE_OBJECT { 
    CSHORT Type;//结构类型
    USHORT Size;//结构大小
    LONG ReferenceCount; //引用计数
    struct _DRIVER_OBJECT *DriverObject; //这个设备所属对象
    struct _DEVICE_OBJECT *NextDevice; //指向下一个设备。
                                        //在一个驱动对象中有N个设备,这些设备通过这个指针链接起来作为一个单向链表
    ULONG Flags;                   
    struct _DEVOBJ_EXTENSION  *DeviceObjectExtension; //设备扩展结构
    ......                              //其他的成员没有列出
 } DEVICE_OBJECT;

//定义设备对象指针
typedef struct _DEVICE_OBJECT *P_DEVICE_OBJECT; 

//============================================================================================================

2.驱动编程基本函数介绍:

//Unicode字符串的初始化
 VOID  RtlInitUnicodeString(  
                          OUT PUNICODE_STRING  DestinationString,   
                          IN  PCWSTR           SourceString)

DestinationString 需要初始化的指针PUNICODE_STRING
SourceString 指向一个以空结尾的Unicode字符串常量,用这个字符串来初始化DestinationString。

例子
PUNICODE_STRING  s;
RtlInitUnicodeString(s, L"宽字符");  //s=L"宽字符";

//************************************************************************************************************

//IoCreateDevice为驱动创建一个设备对象
NTSTATUS   IoCreateDevice(  
                          IN  PDRIVER_OBJECT  DriverObject,  
                          IN  ULONG  DeviceExtensionSize,  
                          IN  PUNICODE_STRING  DeviceName  OPTIONAL,   
                          IN  DEVICE_TYPE  DeviceType,    
                          IN  ULONG  DeviceCharacteristics,   
                          IN  BOOLEAN  Exclusive,   
                          OUT PDEVICE_OBJECT  *DeviceObject) //指针的指针
参数:
DriverObject 为指向驱动对象的指针。
DeviceExtensionSize 给_DEVICE_OBJECT.DeviceExtension指定内存空间大小,具体看定义的设备扩展结构的大小
DeviceName 设备名字,如:\\Device\\GetGDT0
DeviceType 设备类型,这里我们用 FILE_DEVICE_UNKNOWN
DeviceCharacteristics 设备特征信息 一般为0
Exclusive 是否指定设备为独占 是为TRUE,否为FALSE
DeviceObject 指针变量接收一个指向新创建的DEVICE_OBJECT结构。用来回传数据

返回值解释:
调用成功会返回 STATUS_SUCCESS  
如果出错会返回下列值
STATUS_INSUFFICIENT_RESOURCES  //资源不足
STATUS_OBJECT_NAME_EXISTS      //指定对象名存在
STATUS_OBJECT_NAME_COLLISION   //对象名有冲突

//************************************************************************************************************

//IoCreateSymbolicLink创建一个设备链接符。
//驱动程序虽然有了设备名称,但是这种设备名称只能在内核态可见,而对于应用程序是不可见的,
//因此,驱动程序需要暴露一个符号链接,该链接指向真正的设备名称(不是必须的)
//只是让Ring3环应用程序连接驱动程序更容易

NTSTATUS   IoCreateSymbolicLink(  
                              IN PUNICODE_STRING  SymbolicLinkName, 
                              IN PUNICODE_STRING  DeviceName);
参数:
SymbolicLinkName  Unicode字符串指针,是一个用户态可见的名称。如:\\DosDevices\\GetGDT0 或者 \\??\\GetGDT0
DeviceName  Unicode字符串指针,是驱动程序创建的设备对象名称。如:\\Device\\GetGDT0

返回值解释:
如果符号链接创建成功 返回STATUS_SUCCESS  

//************************************************************************************************************

VOID   IoDeleteDevice(   
                    IN PDEVICE_OBJECT  DeviceObject)

参数
DeviceObject  PDEVICE_OBJECT类型的设备对象指针,指向需要删除的设备对象

//============================================================================================================

3.编写简单的驱动程序Demo

创建设备的步骤:
      1用RtlInitUnicodeString初如化设备名称指针
      2用IoCreateDevice创建设备,如果不成功则返回
      3用IoCreateSymlicLink创建符号链接,创建成功返回 STATUS_SUCCESS;创建不成功则调用 IoDeleteDevice删除设备;

简单的代码示例:

//代码片段--使用C语言

#define INITCODE code_seg("INIT")  //初始化时载入内存,然后可以从内存中卸掉

#pragma INITCODE
NTSTATUS CreateMyDevice (IN PDRIVER_OBJECT pDriverObject) 
{
    NTSTATUS status;

    //用来返回创建设备
    PDEVICE_OBJECT pDevObj; 

    //创建设备名称
    UNICODE_STRING devName;
    UNICODE_STRING symLinkName;

    //对devName初始化字串为 "\\Device\\XX_Device"
    RtlInitUnicodeString(&devName,L"\\Device\\XX_Device"); 

    //创建设备对象
    status = IoCreateDevice(pDriverObject,\
                            0,\
                            &devName,\
                            FILE_DEVICE_UNKNOWN,\
                            0, TRUE,\
                            &pDevObj);
    if (!NT_SUCCESS(status))
        return status;

    //设置缓冲区通信方式
    pDevObj->Flags |= DO_BUFFERED_IO;

    //创建符号链接
    RtlInitUnicodeString(&symLinkName,L"\\??\\XX_Device");
    status = IoCreateSymbolicLink( &symLinkName,&devName );
    if (!NT_SUCCESS(status)) 
    {
        IoDeleteDevice( pDevObj );
        return status;
    }

    return STATUS_SUCCESS;
}

//参考资料:
//郁金香老师讲课资料整理

*/