第一个驱动 HelloDDK
windows驱动程序分为两种,一类是不支持即插即用功能的NT式驱动,另一类式支持即插即用的WDM驱动。本节介绍的是一个最简单的NT式驱动
Driver.h头文件
1 #pragma once 2 3 #ifdef __cplusplus 4 extern "C" 5 { 6 #endif 7 #include <NTDDK.h> 8 #ifdef __cplusplus 9 } 10 #endif // __cplusplus 11 12 #define PAGEDCODE code_seg("PAGE") 13 #define LOCKEDCODE code_seg() 14 #define INITCODE code_seg("INIT") 15 16 #define PAGEDDATA data_seg("PAGE") 17 #define LOCKEDDATA data_seg() 18 #define INITDATA data_seg("INIT") 19 20 #define arraysize(p) (sizeof(p) / sizeof((p)[0])) 21 22 typedef struct _DEVICE_EXTENSION { 23 PDEVICE_OBJECT pDevice; 24 UNICODE_STRING ustrDeviceName; //设备名称 25 UNICODE_STRING ustrSymLinkName; //符号链接名 26 } DEVICE_EXTENSION, *PDEVICE_EXTENSION; 27 28 //函数声明 29 NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject); 30 VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject); 31 NTSTATUS HelloDDKDispatchRoutine (IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp);
Driver.cpp文件
1 #include "Driver.h" 2 3 #pragma INITCODE 4 extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath) 5 { 6 NTSTATUS status; 7 KdPrint(("Enter DriverEntry\n")); 8 //注册其他驱动调用函数入口 9 pDriverObject->DriverUnload = DriverUnload; 10 pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutine; 11 pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutine; 12 pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutine; 13 pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKDispatchRoutine; 14 //创建驱动设备对象 15 status = CreateDevice(pDriverObject); 16 17 KdPrint(("DriverEntry end\n")); 18 return status; 19 } 20 21 #pragma INITCODE 22 NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject) 23 { 24 NTSTATUS status; 25 PDEVICE_OBJECT pDevObj; 26 PDEVICE_EXTENSION pDevExt; 27 28 //创建设备名称 29 UNICODE_STRING devName; 30 RtlInitUnicodeString(&devName, L"\\Device\\MyDDKDevice"); 31 32 //创建设备 33 status = IoCreateDevice(pDriverObject, 34 sizeof(DEVICE_EXTENSION), 35 &(UNICODE_STRING)devName, 36 FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj); 37 if (!NT_SUCCESS(status)) 38 return status; 39 40 pDevObj->Flags |= DO_BUFFERED_IO; 41 pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension; 42 pDevExt->pDevice = pDevObj; 43 pDevExt->ustrDeviceName = devName; 44 45 //创建符号链接 46 UNICODE_STRING symLinkName; 47 RtlInitUnicodeString(&symLinkName, L"\\??\\HelloDDK"); 48 pDevExt->ustrSymLinkName = symLinkName; 49 status = IoCreateSymbolicLink(&symLinkName, &devName); 50 if (!NT_SUCCESS(status)) 51 { 52 IoDeleteDevice(pDevObj); 53 return status; 54 } 55 return STATUS_SUCCESS; 56 57 } 58 59 #pragma PAGEDCODE 60 VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject) 61 { 62 PDEVICE_OBJECT pNextObj; 63 KdPrint(("Enter DriverUnload\n")); 64 pNextObj = pDriverObject->DeviceObject; 65 while (pNextObj != NULL) 66 { 67 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pNextObj->DeviceExtension; 68 69 //删除符号链接 70 UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName; 71 IoDeleteSymbolicLink(&pLinkName); 72 pNextObj = pNextObj->NextDevice; 73 IoDeleteDevice(pDevExt->pDevice); 74 } 75 } 76 77 #pragma PAGEDCODE 78 NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) 79 { 80 KdPrint(("Enter HelloDDKdispatchRoutine\n")); 81 NTSTATUS status = STATUS_SUCCESS; 82 83 //完成IRP 84 pIrp->IoStatus.Status = status; 85 pIrp->IoStatus.Information = 0; 86 IoCompleteRequest(pIrp, IO_NO_INCREMENT); 87 KdPrint(("leave HelloDDKDispatchRoutine\n")); 88 return status; 89 }
用#pragma指明此函数是加载到INITN内存区域中,即成功卸载后可以退出内存。
从DriverEntry函数开始执行,此处在函数体前面用extern "C"修饰,这样在编译的时候会编译成_DriverEntry@8的符号。如果不加入此修饰符号,编译器会自动按照C++的符号名编译,导致错误链接。
IoCreateDevice函数创建一个设备对象。
第40行,表明此种设备位BUFFERED_IO设备,设备对内存的操作分为两种,BUFFERED_IO和D-_DIRECT_IO。
makefile文件
1 !INCLUDE $(NTMAKEENV)/makefile.def
Sources文件
1 TARGETNAME=HelloDDK 2 TARGETTYPE=DRIVER 3 TARGETPATH=OBJ 4 5 INCLUDES=$(BASEDIR)\inc;\ 6 $(BASEDIR)\inc\ddk;\ 7 8 SOURCES=Driver.cpp\
第一行说明驱动的名称。
第二行指明此驱动的类型为NT型驱动。
第三行设置编译输出目录
第五~六行设置include目录。
第八行指定源文件。
源码: