Windows內(nèi)核中把驅(qū)動,設備,文件等都稱為"對象",在系統(tǒng)啟動后,這些對象都在內(nèi)存中.
一個驅(qū)動對象(DRIVER_OBJECT)代表了一個驅(qū)動程序,或者是內(nèi)核模塊.
設備對象(DEVICE_OBJECT)是在內(nèi)核中唯一接收請求的實體.大部分消息都是以請求(IRP)方式傳遞的,而任何一個請求都是發(fā)送被某個設備對象的.設備對象是驅(qū)動對象結(jié)構(gòu)的第三個參數(shù)對象.
內(nèi)核程序是以一個驅(qū)動對象表示的,所以一個設備對象總是屬于一個驅(qū)動對象.
驅(qū)動對象結(jié)構(gòu):
typedef struct _DRIVER_OBJECT{
CSHORT Type;
CSHORT Size;
//設備對象,是一個設備對象鏈表的開始.
PDEVICE_OBJECT DeviceObject;
ULONG Flags;
//驅(qū)動在內(nèi)核空間的開始地址和大小
PVOID DriverStart;
ULONG DriverSize;
PVOID DriverSection;
PDRIVER_EXTENSION DriverExtension;
//驅(qū)動的名字,確定一個I/O請求被綁定的驅(qū)動程序的名稱
UNICODE_STRING DriverName;
//指向注冊表中的硬件信息的路徑
PUNICODE_STRING HardwareDatabase;
//快速IO分發(fā)函數(shù)的入口,數(shù)組的可選指針,通過參數(shù)單獨調(diào)用驅(qū)動程序執(zhí)行,而不是使用IRP(操作系統(tǒng)內(nèi)核的一個數(shù)據(jù)結(jié)構(gòu),應用程序與驅(qū)動程序進行通信需要通過IRP包)調(diào)用機制,這些功能只能被用戶同步IO或者文件緩存
PFAST_IO_DISPATCH FastIoDispatch;
//驅(qū)動程序初始化
PDRIVER_INITIALIZE DriverInit;
//特定入口,
PDRIVER_STARTIO DriverStartIo;
//驅(qū)動卸載函數(shù)
PDRIVER_UNLOAD DriverUnload;
//普通分發(fā)函數(shù)(IRP)
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
} DRIVER_OBJECT;
設備對象結(jié)構(gòu):
typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _DEVICE_OBJECT {
CSHORT Type;
USHORT Size;
//引用計數(shù)
LONG ReferenceCount;
//設備所屬驅(qū)動對象
struct _DRIVER_OBJECT *DriverObject;
//下一個設備對象,一個驅(qū)動對象中可能有許多個設備,這些設備用指針連接,作為單向鏈表
struct _DEVICE_OBJECT *NextDevice;
struct _DEVICE_OBJECT *AttachedDevice;
struct _IRP *CurrentIrp;
PIO_TIMER Timer;
ULONG Flags;
ULONG Characteristics;
__volatile PVPB Vpb;
PVOID DeviceExtension;
//設備類型
DEVICE_TYPE DeviceType;
//IRP棧的大小
CCHAR StackSize;
union {
LIST_ENTRY ListEntry;
WAIT_CONTEXT_BLOCK Wcb;
} Queue;
ULONG AlignmentRequirement;
KDEVICE_QUEUE DeviceQueue;
KDPC Dpc;
ULONG ActiveThreadCount;
PSECURITY_DESCRIPTOR SecurityDescriptor;
KEVENT DeviceLock;
USHORT SectorSize;
USHORT Spare1;
struct _DEVOBJ_EXTENSION ?*DeviceObjectExtension;
PVOID ?Reserved;
} DEVICE_OBJECT;
IRP向設備對象發(fā)送請求時會被驅(qū)動對象的分發(fā)函數(shù)捕獲,被其中一個調(diào)用
分發(fā)函數(shù)原型
NTSTATUS MyDispatch(PDEVICE_OBJECT device, PIRP irp);
參數(shù)1是請求的目標設備,參數(shù)2是IRP請求的指針
IRP的結(jié)構(gòu)
IRP是一個內(nèi)核數(shù)據(jù)結(jié)構(gòu),結(jié)構(gòu)非常復雜,因為要表示無數(shù)中實際請求.
typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _IRP 共300多行代碼,位于 wdm.h 24795行
其中
PMDL MdlAddress; 內(nèi)存描述符表鏈表指針,是一個緩沖區(qū),內(nèi)核請求都需要一個緩沖區(qū),用來保存數(shù)據(jù)
union {
struct _IRP *MasterIrp;
__volatile LONG IrpCount;
PVOID SystemBuffer;
} AssociatedIrp; 該共用體也是一個系統(tǒng)緩沖,比 MdlAddress 稍簡單表示緩沖的方式,IRP會根據(jù)IO的請求方式選擇其中的某一個.
IO_STATUS_BLOCK IoStatus; IO狀態(tài),請求完成之后的返回情況放在這里.
CHAR StackCount; IRP椓馐簦空間大小
CHAR CurrentLocation; IRP當前椧淮空間
__volatile PDRIVER_CANCEL CancelRoutine; 用來取消一個未決(沒有執(zhí)行完成?)請求的函數(shù)
PVOID UserBuffer; 與上面兩個一樣可以表示緩沖區(qū),但特性稍有不同
union {
struct {
union {
KDEVICE_QUEUE_ENTRY DeviceQueueEntry;
struct {
PVOID DriverContext[4];
} ;
} ;
//發(fā)出這個請求的線程
PETHREAD Thread;
PCHAR AuxiliaryBuffer;
struct {
LIST_ENTRY ListEntry;
union {
//IRP棿滩剩空間元素
struct _IO_STACK_LOCATION *CurrentStackLocation;
ULONG PacketType;
};
};
PFILE_OBJECT OriginalFileObject;
} Overlay;
KAPC Apc;
PVOID CompletionKey;
} Tail;
因為IRP請求會傳遞許多個設備才能完成,所以每次中轉(zhuǎn)都會留一個椀迷耍空間,用于保存中間參數(shù).