首先需要安装DDK,这里我选择Microsoft Windows Server 2003 SP1 DDK
Windows驱动分成两类,一类是不支持即插即用的NT式驱动,一类是支持即插即用的WDM驱动.
首先来看一个最简单的NT式驱动。
- #pragma once
-
- #ifdef __cplusplus
- extern "C"
- {
- #endif
- #include <NTDDK.h>
- #ifdef __cplusplus
- }
- #endif
-
- #define PAGEDCODE code_seg("PAGE")
- #define LOCKEDCODE code_seg()
- #define INITCODE code_seg("INIT")
-
- #define PAGEDDATA data_seg("PAGE")
- #define LOCKEDDATA data_seg()
- #define INITDATA data_seg("INIT")
-
- #define arraysize(p) (sizeof(p)/sizeof((p)[0]))
-
- typedef struct _DEVICE_EXTENSION {
- PDEVICE_OBJECT pDevice;
- UNICODE_STRING ustrDeviceName;
- UNICODE_STRING ustrSymLinkName;
- } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
-
-
- NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject);
- VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject);
- NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
- IN PIRP pIrp);
Driver.h头文件中包含了开发NT式驱动所需要的NTDDK.h,此外还定义了几个标志来指明函数和变量分配在分页内存还是非分页内存中。Windows驱动程序的入口函数是DriverEntry函数,
- #include "Driver.h"
-
-
-
-
-
-
-
-
-
- #pragma INITCODE
- extern "C" NTSTATUS DriverEntry (
- IN PDRIVER_OBJECT pDriverObject,
- IN PUNICODE_STRING pRegistryPath )
- {
- NTSTATUS status;
- KdPrint(("Enter DriverEntry\n"));
-
-
- pDriverObject->DriverUnload = HelloDDKUnload;
- pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutine;
- pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutine;
- pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutine;
- pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKDispatchRoutine;
-
-
- status = CreateDevice(pDriverObject);
-
- KdPrint(("DriverEntry end\n"));
- return status;
- }
-
-
-
-
-
-
-
-
- #pragma INITCODE //指明此函数加载到INIT内存区域(即只在加载的时候需要载入内存,加载成功后可以从内存中卸载掉)
- NTSTATUS CreateDevice (
- IN PDRIVER_OBJECT pDriverObject)
- {
- NTSTATUS status;
- PDEVICE_OBJECT pDevObj;
- PDEVICE_EXTENSION pDevExt;
-
-
- UNICODE_STRING devName;
- RtlInitUnicodeString(&devName,L"\\Device\\MyDDKDevice");
-
-
- status = IoCreateDevice( pDriverObject,
- sizeof(DEVICE_EXTENSION),
- &(UNICODE_STRING)devName,
- FILE_DEVICE_UNKNOWN,
- 0, TRUE,
- &pDevObj );
- if (!NT_SUCCESS(status))
- return status;
-
- pDevObj->Flags |= DO_BUFFERED_IO;
- pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
- pDevExt->pDevice = pDevObj;
- pDevExt->ustrDeviceName = devName;
-
- UNICODE_STRING symLinkName;
- RtlInitUnicodeString(&symLinkName,L"\\??\\HelloDDK");
- pDevExt->ustrSymLinkName = symLinkName;
- status = IoCreateSymbolicLink( &symLinkName,&devName );
- if (!NT_SUCCESS(status))
- {
- IoDeleteDevice( pDevObj );
- return status;
- }
- return STATUS_SUCCESS;
- }
-
-
-
-
-
-
-
-
- #pragma PAGEDCODE
- VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject)
- {
- PDEVICE_OBJECT pNextObj;
- KdPrint(("Enter DriverUnload\n"));
- pNextObj = pDriverObject->DeviceObject;
- while (pNextObj != NULL)
- {
- PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
- pNextObj->DeviceExtension;
-
-
- UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
- IoDeleteSymbolicLink(&pLinkName);
- pNextObj = pNextObj->NextDevice;
- IoDeleteDevice( pDevExt->pDevice );
- }
- }
-
-
-
-
-
-
-
-
-
- #pragma PAGEDCODE
- NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
- IN PIRP pIrp)
- {
- KdPrint(("Enter HelloDDKDispatchRoutine\n"));
- NTSTATUS status = STATUS_SUCCESS;
-
- pIrp->IoStatus.Status = status;
- pIrp->IoStatus.Information = 0;
- IoCompleteRequest( pIrp, IO_NO_INCREMENT );
- KdPrint(("Leave HelloDDKDispatchRoutine\n"));
- return status;
- }
有两种编译驱动的办法,一种是用DDK环境来编译,需要在源代码所在目录下创建两个文件makefile和Sources,
makefile内容如下,功能是引入DDK的bin目录下的makefile.def文件:
- !INCLUDE $(NTMAKEENV)\makefile.def
Sources内容如下:
- TARGETNAME=HelloDDK
- TARGETTYPE=DRIVER
- TARGETPATH=OBJ
- INCLUDES=$(BASEDIR)\inc;\
- $(BASEDIR)\inc\ddk;\
- SOURCES=Driver.cpp\
然后在开始菜单中选择“Windows XP Checked Build Environment”编译环境,进入需要编译的目录,输入”build“命令就可以,
编译后的驱动位于objchk_wxp_x86"i386目录下,名为HelloDDK.sys
第二种编译方式是使用VC++进行编译
1,用vc新建工程。在"project"选项卡中,选择win32 Application,选择一个空的工程。
2,将两个源文件Driver.h和Driver.cpp拷贝到工程目录中,并添加到工程中。
3,增加新的编译版本,去掉Debug 和Release 版本,增加一个Win32 Driver Check Edition
4,修改工程属性。选择"Project|Setting",或者直接按下Alt+F7键,弹出"Project Settings"。在对话框中,选择“General”选项卡。将Intermediate files和Output files都改为MyDriver_Check.
5,选择C/C++选项卡,将原有的Project Options 内容全部删除替换成如下内容:
- /nologo /Gz /MLd /W3 /WX /Z7 /Od /D WIN32=100 /D _X86_=1 /D WINVER=0x500 /D DBG=1 /Fo"MyDriver_Check/" /Fd"MyDriver_Check/" /FD /c
6,选择Link选项卡,将原有的Project Options 内容全部删除,替换成如下内容:
- ntoskrnl.lib /nologo /base:"0x10000" /stack:0x400000,0x1000 /entry:"DriverEntry" /subsystem:console /incremental:no /pdb:"MyDriver_Check/HelloDDK.pdb" /map:"MyDriver_Check/HelloDDK.map" /debug /machine:I386 /nodefaultlib /out:"MyDriver_Check/HelloDDK.sys" /pdbtype:sept /subsystem:native /driver /SECTION:INIT,D /RELEASE /IGNORE:4078
7。修改VC的lib目录和include目录。
在vc中选择"Tools"|"Options",在弹出的对话框中选择“Directories”选项卡。在“Show directories for”下拉菜单中选择“Include files”菜单,添加
- D:\WINDDK\3790.1830\INC\W2K
和
- D:\WINDDK\3790.1830\INC\DDK\W2K
并将这两个目录置于最上。
在"Show directories for "下拉菜单中选择“Library files”菜单,添加目录
- D:\WINDDK\3790.1830\LIB\W2K\I386
并置于最上端。
8,按照书上所述的步骤做完后编译,会报错如下:
- fatal error C1083: Cannot open include file: 'specstrings.h': No such file or directory
原因是include目录设置没完整,加入如下目录既可以正确编译
- D:\WINDDK\3790.1830\INC\CRT
最后来安装此驱动,这里使用Driver Studio3.2.1中的Driver Monitor来完成
本文出自 “洞庭散人” 博客,请务必保留此出处http://phinecos.blog.51cto.com/1941821/368163