• 编译第一个驱动程序笔记


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

  • 相关阅读:
    go案例:客户管理系统流程 mvc模式 分层设计
    珠峰2016,第9期 vue.js 笔记部份
    前后端分离电商,业务逻辑部份
    'Specifying a namespace in include() without providing an app_name '报错解决
    vue2.0 前端框架
    vue项目实战
    电商网前后端分离数据表设计部份
    djang2.1教育平台02
    django框架开发流程
    测试的艺术:测试用例的设计
  • 原文地址:https://www.cnblogs.com/ZYM/p/1159484.html
Copyright © 2020-2023  润新知