天天看點

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;
}

//參考資料:
//郁金香老師講課資料整理

*/