编译第一个驱动程序笔记

(以下代码大部分摘抄自王艳平老师的《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驱动程序文件。至此驱动编译成功!

posted on 2008-04-18 10:47  ZYM  阅读(1408)  评论(2编辑  收藏  举报