(以下代码大部分摘抄自王艳平老师的《Windows程序设计》一书中的源代码,这里只是为了展示驱动的编译过程)
1:安装VC6
2:安装DDK(大概230M,最好完全安装)
3:写以下源代码(随便用一个编辑器来写):
CharConvert.h:
#define
CHAR_CONVERT \
CTL_CODE(FILE_DEVICE_UNKNOWN,
0x830
, METHOD_BUFFERED, FILE_ANY_ACCESS)
CharConvert.cpp
extern
"
C
"
{
#include
<
ntddk.h
>
}
#include
<
devioctl.h
>
#include
"
CharConvert.h
"
//
自定义函数的声明
NTSTATUS DispatchCreateClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
void
DriverUnload(PDRIVER_OBJECT pDriverObj);
NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
//
驱动内部名称和符号连接名称
#define
DEVICE_NAME L"\\Device\\devCharConvert"
#define
LINK_NAME L"\\DosDevices\\slCharConvert"
//
驱动程序加载时调用DriverEntry例程
extern
"
C
"
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
{
NTSTATUS status
=
STATUS_SUCCESS;
//
初始化各个派遣例程
pDriverObj
->
MajorFunction[IRP_MJ_CREATE]
=
DispatchCreateClose;
pDriverObj
->
MajorFunction[IRP_MJ_CLOSE]
=
DispatchCreateClose;
pDriverObj
->
MajorFunction[IRP_MJ_DEVICE_CONTROL]
=
DispatchIoctl;
pDriverObj
->
DriverUnload
=
DriverUnload;
//
创建、初始化设备对象
//
设备名称
UNICODE_STRING ustrDevName;
RtlInitUnicodeString(
&
ustrDevName, DEVICE_NAME);
//
创建设备对象
PDEVICE_OBJECT pDevObj;
status
=
IoCreateDevice(pDriverObj,
0
,
&
ustrDevName,
FILE_DEVICE_UNKNOWN,
0
,
FALSE,
&
pDevObj);
if
(
!
NT_SUCCESS(status))
{
return
status;
}
//
创建符号连接名称
//
符号连接名称
UNICODE_STRING ustrLinkName;
RtlInitUnicodeString(
&
ustrLinkName, LINK_NAME);
//
创建关联
status
=
IoCreateSymbolicLink(
&
ustrLinkName,
&
ustrDevName);
if
(
!
NT_SUCCESS(status))
{
IoDeleteDevice(pDevObj);
return
status;
}
return
STATUS_SUCCESS;
}
void
DriverUnload(PDRIVER_OBJECT pDriverObj)
{
//
删除符号连接名称
UNICODE_STRING strLink;
RtlInitUnicodeString(
&
strLink, LINK_NAME);
IoDeleteSymbolicLink(
&
strLink);
//
删除设备对象
IoDeleteDevice(pDriverObj
->
DeviceObject);
}
//
处理IRP_MJ_CREATE、IRP_MJ_CLOSE功能代码
NTSTATUS DispatchCreateClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
pIrp
->
IoStatus.Status
=
STATUS_SUCCESS;
//
完成此请求
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return
STATUS_SUCCESS;
}
//
I/O控制派遣例程
NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
//
假设失败
NTSTATUS status
=
STATUS_INVALID_DEVICE_REQUEST;
//
取得此IRP(pIrp)的I/O堆栈指针
PIO_STACK_LOCATION pIrpStack
=
IoGetCurrentIrpStackLocation(pIrp);
//
取得I/O控制代码
ULONG uIoControlCode
=
pIrpStack
->
Parameters.DeviceIoControl.IoControlCode;
//
取得I/O缓冲区指针和它的长度
PVOID pIoBuffer
=
pIrp
->
AssociatedIrp.SystemBuffer;
ULONG uInSize
=
pIrpStack
->
Parameters.DeviceIoControl.InputBufferLength;
ULONG uOutSize
=
pIrpStack
->
Parameters.DeviceIoControl.OutputBufferLength;
switch
(uIoControlCode)
{
case
CHAR_CONVERT:
{
char
str[]
=
"
零一二三四五六七八九
"
;
if
(uInSize
>=
1
&&
uOutSize
>=
2
)
{
char
c
=
((
char
*
)pIoBuffer)[
0
];
if
(c
>=
'
0
'
&&
c
<=
'
9
'
)
{
//
进行转换
c
-=
'
0
'
;
RtlCopyMemory(pIoBuffer,
&
str[c
*
2
],
2
);
status
=
STATUS_SUCCESS;
}
}
}
break
;
}
if
(status
==
STATUS_SUCCESS)
pIrp
->
IoStatus.Information
=
uOutSize;
else
pIrp
->
IoStatus.Information
=
0
;
//
完成请求
pIrp
->
IoStatus.Status
=
status;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return
status;
}
注意:当你的驱动源代码文件为.cpp时,驱动的入口点函数名
DriverEntry前需要添加
extern "C"修饰符。
makefile:
#
# DO NOT EDIT THIS FILE
!!!
Edit .\sources.
if
you want to add a
new
source
# file to
this
component. This file merely indirects to the real make file
# that
is
shared by all the driver components of the Windows NT DDK
#
!
IF DEFINED(_NT_TARGET_VERSION)
!
IF $(_NT_TARGET_VERSION)
>=
0x501
!
IFNDEF AMD64
!
INCLUDE $(NTMAKEENV)\makefile.def
!
ELSE
!
message BUILDMSG: Warning : Perm2 sample
is
not supported on AMD64.
!
ENDIF
!
ELSE
!
message BUILDMSG: Warning : The sample
"
$(MAKEDIR)
"
is
not valid
for
the current OS target.
!
ENDIF
!
ELSE
!
INCLUDE $(NTMAKEENV)\makefile.def
!
ENDIF
注意:每个驱动的makefile文件都是一样的,可以直接COPY。
sources:
TARGETNAME
=
CharConvert
TARGETPATH
=
obj
TARGETTYPE
=
DRIVER
SOURCES
=
CharConvert.cpp
注意:TARGETNAME是驱动编译后的驱动文件名,TARGETTYPE是驱动类型,SOURCES是源代码文件名。
4:开始-程序-Development Kits-Windows DDK 3790.1830-Windows XP-Windows XP Checked Build Environment
从而打开了一个命令行窗口。
cd E: //进入源代码目录(我的是E:\CharConvert文件夹)
cd CharConvert (回车)
build //运行build命令
BUILD:Adding /Y to COPYCMD so xcopy ops won't hang.
BUILD:Object root set to: ==> objchk_wxp_x86
BUILD:Compile and Link for i386
BUILD:Loading D:\WINDDK\3790~1.183\build.dat...
BUILD:Computing Include file dependencies:
BUILD:Examining e:\CharConvert directory for files to compile.
e:\CharConvert - 1 source files <138 lines>
BUILD:Compiling <NoSync> e:\CharConvert directory
Compiling - CharConvert.cpp for i386
BUILD:Linking e:\CharConvert directory
Linking Executable - objchk_wxp_x86\i386\CharConvert.sys for i386
BUILD:Done
2 files compiled
1 executable built
在E:\CharConvert\objchk_wxp_x86\i386目录下就生成了CharConvert.sys驱动程序文件。至此驱动编译成功!