/*
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;
}
//參考資料:
//郁金香老師講課資料整理
*/