• [转]驱动程序开发—Hello Word(3)


    看了好多天的书!特别到书店买了《Windows 200/xp wdm 设备驱动开发》这本书,在这里我不想怎么评论它!对于高手来说,我觉得她一定不能满足,但是对于像我这样想入门的人来说,仿佛看了半天,还是不知道从何下手。什么原理、模型、分层等等讲不讲,讲!绝对应该讲!但是你得快点告诉我怎么先弄一个像“Hello Word!”的什么简单来不能再简单的完整的例子给我呀!到网上找阿找啊!那些高手啊!也不为我们新手写点图文并茂的上手资料。没办法!结合自己的需要再参考一些别人的东东,算是自己的一点不成熟的想法吧!

    我觉得下面这个介绍非常不错!我能看懂,所以贴了出来。

    我道为什么找不到“Hello Word!”呢?原来在驱动开发的例子里是没有所谓的“Hello World”程序的。这主要还是因为网络上的WDM资料太少造成的。但是程序的入口点呢?c语言有Main(),用Vc的常看见的是WinMain(),Delphi开发的是Program里的Begin,但是驱动开发呢?那也是应该有程序的入口点啊。后来我才明白了,那就是DriverEntry()函数。还有一个问题让我怀疑了老半天,那就是驱动开发的源程序中需不需要include头文件呀?为什么会怀疑呢?那是因为我看了半天的书都没有看到一个完整的驱动程序结构。真的是郁闷。下面是我看到的一个完整的结构,我先放上来,让大家看看驱动开发的结构吧。

    /***************************************************************
    程序名称:Hello World for WDM
    文件名称:HelloWDM.cpp
    日期:2002-8-16
    ***************************************************************/

    //一定要的头文件,声明了函数模块和变量:

    #include "HelloWDM.h"

    /***************************************************************
    函数名称:DriverEntry()
    功能描述:WDM程序入口(原来的WinMain被换成了DriverEntry,也是驱动程序的大门)
    ***************************************************************/

    //extern "C"是必须的,表示“用C链接”。如果你的文件名是HelloWDM.c的话,这句可以省略。
    extern "C"
    NTSTATUS DriverEntry(    IN PDRIVER_OBJECT DriverObject, //IN 是一个关键字表示这是一个输 入参数,PDRIVER_OBJECT是一个数据结构的指针,就像PCHAR一样,这个数据结构是什么样子的,后面我会列出来。她描述了一个驱动设备对象。
                            IN PUNICODE_STRING RegistryPath)//参数RegistryPath指定了驱动程序注册表健的路径,因为驱动程序安装后总会在系统注册表里留下一点东西的。
    {
        //指定“添加设备”消息由函数“HelloWDMAddDevice()”来处理:
        DriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;
        //指定“即插即用”消息由函数“HelloWDMPnp()”来处理:
        DriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;

        //返回一个NTSTATUS值STATUS_SUCCESS。几乎所有的驱动程序例程都必须返回一个NTSTATUS值,这些值在NTSTATUS.H DDK头文件中有详细的定义。
        return STATUS_SUCCESS;
    }

    //NTSTATUS也是一个数据类型,上面我所说的消息有点不准确的,准确地说是“I/O请求包”,不过如果像我们以前理解消息那样来理解也无不可,我觉得两者太想了。无非就是上层的应用程序通过它来告诉驱动程序,你要给我什么服务吧!IRP_MJ_PNP就是即插即用处理的请求。你发没发觉上面其实是在制造进入各个房间的“小门”


    /***************************************************************
    函数名称:HelloWDMAddDevice()
    功能描述:处理“添加设备”消息
    ***************************************************************/

    NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,
                               IN PDEVICE_OBJECT PhysicalDeviceObject)
    {
        //定义一个NTSTATUS类型的返回值:
        NTSTATUS status;
        //定义一个功能设备对象(Functional Device Object):
        PDEVICE_OBJECT fdo;

        //创建我们的功能设备对象,并储存到fdo中:
        status = IoCreateDevice(
            DriverObject,                //驱动程序对象
            sizeof(DEVICE_EXTENSION),    //要求的设备扩展的大小
            NULL,                        //设备名称,这里为NULL
            FILE_DEVICE_UNKNOWN,        //设备的类型,在标准头文件WDM.H或NTDDK.H中列出的FILE_DEVICE_xxx值之一
            0,                            //各种常量用OR组合在一起,指示可删除介质、只读等。
            FALSE,                        //如果一次只有一个线程可以访问该设备,为TRUE,否则为FALSE
            &fdo);                        //返回的设备对象

        //NT_SUCCESS宏用于测试IoCreateDevice内核是否成功完成。不要忘记检查对内核的所有调用是否成功。NT_ERROR宏不等同于!NT_SUCCESS,最好使用!NT_SUCCESS,因为除了错误外,它还截获警告信息。
        if( !NT_SUCCESS(status))
            return status;

        //创建一个设备扩展对象dx,用于存储指向fdo的指针:
        PDEVICE_EXTENSION dx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
        dx->fdo = fdo;

        //用IoAttachDeviceToDeviceStack函数把HelloWDM设备挂接到设备栈:
        dx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);

        //设置fdo的flags。有两个“位”是必须改变的,一个是必须清除DO_DEVICE_INITIALIZING标志,如果在DriverEntry例程中调用IoCreateDevice(),就不需要清除这个标志位。还有一个是必须设置DO_BUFFER_IO标志位:
        fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
        fdo->Flags &= ~DO_DEVICE_INITIALIZING;

        //返回值:
        return STATUS_SUCCESS;
    }


    /***************************************************************
    函数名称:HelloWDMPnp()
    功能描述:处理“即插即用”消息
    ***************************************************************/

    NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,
                            IN PIRP Irp)
    {
        //创建一个设备扩展对象dx,用于存储指向fdo的指针:
        PDEVICE_EXTENSION dx=(PDEVICE_EXTENSION)fdo->DeviceExtension;

        //首先要通过函数IoGetCurrentIrpStackLocation()得到当前的IRP,并由此得到Minor Function:
        PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
        ULONG MinorFunction = IrpStack->MinorFunction;

        //然后把这个Minor Function传递给下一个设备栈:
        IoSkipCurrentIrpStackLocation(Irp);
        NTSTATUS status = IoCallDriver( dx->NextStackDevice, Irp);

        //处理“即插即用”次功能代码:
        //当Minor Function等于IRP_MN_REMOVE_DEVICE时,说明有设备被拔出或卸下,这时要取消资源分配并删除设备:
        if( MinorFunction==IRP_MN_REMOVE_DEVICE)
        {
            //取消设备接口:
            IoSetDeviceInterfaceState(&dx->ifSymLinkName, FALSE);
            RtlFreeUnicodeString(&dx->ifSymLinkName);
            
            //调用IoDetachDevice()把fdo从设备栈中脱开:
            if (dx->NextStackDevice)
                IoDetachDevice(dx->NextStackDevice);
            //删除fdo:
            IoDeleteDevice(fdo);
        }

        //返回值:
        return status;
    }



    /***************************************************************
    程序名称:Hello World for WDM
    文件名称:HelloWDM.h
    作者:罗聪
    日期:2002-8-16
    ***************************************************************/


    //头文件,只是声明一些函数和变量,比较简单就不多说了,请读者自行研究:

    #ifdef __cplusplus

    extern "C"
    {
    #endif

    #include "ntddk.h"

    #ifdef __cplusplus
    }
    #endif

    typedef struct _DEVICE_EXTENSION
    {
        PDEVICE_OBJECT    fdo;
        PDEVICE_OBJECT    NextStackDevice;
        UNICODE_STRING    ifSymLinkName;

    } DEVICE_EXTENSION, *PDEVICE_EXTENSION;

    NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,
                               IN PDEVICE_OBJECT PhysicalDeviceObject);

    NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,
                            IN PIRP Irp);



    好了,第一个WDM版的“Hello World”就介绍到这里,虽然实际上它什么都没有做,但是由于它包含了完整的框架,所以对于向我这样的新手来说还是很有参考价值的。至于怎么编译及安装只有下次再说了

  • 相关阅读:
    Hibernate4学习day0--hibernate封装--注解--单元测试
    Hibernate4学习day01--简介--基本配置
    java基础day13---引用数据类型
    java基础day14---static关键字-----继承
    java基础day12---this 关键字-----参数传递
    day05 Struts2文件上传和下载---防重复提交
    java基础day11---空指针异常----引用类型--自定义类型赋值--封装
    java基础的第二轮快速学习!day10
    Struts2,大爷你好!第四天
    java基础的第二轮快速学习!day09
  • 原文地址:https://www.cnblogs.com/4kapple/p/959418.html
Copyright © 2020-2023  润新知