鬱金香驅動學習>第三課:新增裝置物件
阿新 • • 發佈:2018-12-14
#include <ntddk.h> //定義個INITCODE巨集,這個巨集表示 初始化的時候載入記憶體,然後可以從記憶體中解除安裝掉 #define INITCODE code_seg("INIT") //;注意這裡是不能加分號的 #define PAGECODE code_seg("PAGE") //表示記憶體不夠用時,可以置換到虛擬記憶體(硬碟) //驅動裝置 #pragma INITCODE //表示這個函式執行後,就從記憶體中釋放掉 NTSTATUS CreateMyDevice (IN PDRIVER_OBJECT pDriverObject) { NTSTATUS status; // NTSTATUS 等價於 LONG PDEVICE_OBJECT pDevObj;/*用來返回建立裝置*/ //UNICODE_STRING 型別為UNICODE的字元結構,裡面包含3個成員,第一個Length 表示buffer位元組的長度,不包含NULL,第二個MaximumLength:buffer總的位元組大小,第三個Buffer:指向寬字元的指標 //建立裝置名稱 UNICODE_STRING devName; UNICODE_STRING symLinkName; //會動態分配一塊指向“\\Device\\yjxDDK_Device”的記憶體指標,賦值給devName.Buffer; RtlInitUnicodeString(&devName,L"\\Device\\yjxDDK_Device");/*對devName初始化字串為 "\\Device\\yjxDDK_Device"*/ //IoCreateDevice 建立裝置物件,並更新pDriverObject->DeviceObject 為新建立的裝置物件 //介紹每個引數 // pDriverObject 該引數用於在驅動程式和新裝置物件之間建立連線, // 0 第二個引數是裝置擴充套件結構的大小 // &devName 命名該裝置物件的UNICODE_STRING串的地址 // &FILE_DEVICE_UNKNOWN 裝置型別 // 0 為裝置物件提供Characteristics標誌 // TRUE 指出裝置是否是排斥的 // &pDevObj 裝置物件的名字,有了名字應用程式就可以訪問該裝置的驅動物件了 status = IoCreateDevice( pDriverObject,\ 0,\ &devName,\ FILE_DEVICE_UNKNOWN,\ 0, TRUE,\ &pDevObj); //NT_SUCCESS巨集定義:表示判斷 status>=0 if (!NT_SUCCESS(status)) //成功返回0 0>=0 嗎 true 取反 false 不執行 { if(status == STATUS_INSUFFICIENT_RESOURCES) { KdPrint(("STATUS_INSUFFICIENT_RESOURCES 資源不足")); } if(status == STATUS_OBJECT_NAME_EXISTS) { KdPrint(("STATUS_OBJECT_NAME_EXISTS 指定物件不存在")); } if(status == STATUS_OBJECT_NAME_COLLISION) { KdPrint(("STATUS_INSUFFICIENT_RESOURCES 物件名有衝突")); } KdPrint(("建立裝置錯誤,返回值是=%d ",status)); return status; } KdPrint(("建立裝置成功,返回值是=%d ",status)); //所建立裝置被設定為直接緩衝I/O,這是裝置讀寫三種方式中的一種 pDevObj->Flags |= DO_BUFFERED_IO; //建立符號連結 RtlInitUnicodeString(&symLinkName,L"\\??\\yjx888"); //建立一個裝置連結。驅動程式雖然有了裝置名稱,但是這種裝置名只能在核心狀態可見,而對於應用程式是不可見的,因此,驅動需要要暴露一個符號連結,來方便應用程式的訪問,該連結指向真正的裝置名稱 status = IoCreateSymbolicLink( &symLinkName,&devName ); if (!NT_SUCCESS(status)) { KdPrint(("建立符號連線錯誤,返回值是=%d ",status)); //刪除裝置物件 IoDeleteDevice( pDevObj ); return status; } KdPrint(("建立符號連線成功,返回值是=%d ",status)); return STATUS_SUCCESS; } //解除安裝函式的前置說明 VOID DDK_Unload(IN PDRIVER_OBJECT pDriverObject); //設定函式程式碼存放的程式碼段,這是是放在init段中 #pragma INITCODE //NTSTATUS 等價與 LONG NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING B) { KdPrint(("驅動成功被載入...")); //建立裝置物件 CreateMyDevice(pDriverObject); //Driverunload 回撥函式的一個指標,這裡的回撥函式是解除安裝驅動的函式 pDriverObject->DriverUnload = DDK_Unload; return 1; } VOID DDK_Unload(IN PDRIVER_OBJECT pDriverObject) { //KdPrint使用方法類似printf,注意KdPrint((" ", ));使用的是雙括號。 //這個比DbgPrint 呼叫要稍好。因為在free 版不被編譯。 KdPrint(("驅動成功被解除安裝...")); DbgPrint("DbgPrint功能與KdPrint相同"); }