第一个驱动 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目录。

第八行指定源文件。

 

源码:

posted @ 2019-12-18 21:30  bashcode  阅读(163)  评论(0)    收藏  举报