WDM驱动程序入门(1)——HelloWDM

原创 2002年08月23日 09:42:00

WDM驱动程序是一种很新的东西,相信很多人都跟我一样,对它很感兴趣,但是又找不到学习的切入点。究其原因,还是因为WDM是一种非常“死板板”的程序,它一运行就是工作在系统的底层RING 0处,提供各种接口给应用程序调用。也正因为如此,它不像普通的应用程序一样,可以很快地上手——更多的时候,你是在阅读它的技术资料和各种接口信息,你还要非常地熟悉系统底层的工作原理,否则一个不小心,就“蓝屏”了,呵呵——话说回来,写驱动程序的时候,死机是家常便饭。

因此很多人都对WDM望而生畏了。回想一下,我刚开始学WDM的情形还历历在目——看书看了整整3天,但是看完之后好像跟没看也差不了多少,还是不知道怎么入门,甚至连怎么写一个“Hello World”都不知道——后来才知道其实WDM是没有所谓的“Hello World”程序的,唉,真是痛苦啊,这主要还是因为网络上的WDM资料太少造成的。为了不让大家重蹈我的覆辙并对WDM有个感性的认识,在此我给出一个最简单的完整的WDM框架,并附有注释,姑且可以算是一个入门的“Hello World”吧。

废话少说,让我们马上开始研究,要求读者已安装DDK 2000。(在Win98中我还没有测试过,不清楚是否能正常运行)



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


//一定要的头文件,声明了函数模块和变量:
#include "HelloWDM.h"

/***************************************************************
函数名称:DriverEntry()
功能描述:WDM程序入口
***************************************************************/

//extern "C"是必须的,表示“用C链接”。如果你的文件名是HelloWDM.c的话,这句可以省略。
extern "C"
NTSTATUS DriverEntry(    IN PDRIVER_OBJECT DriverObject,
                        IN PUNICODE_STRING RegistryPath)
{
    //指定“添加设备”消息由函数“HelloWDMAddDevice()”来处理:
    DriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;
    //指定“即插即用”消息由函数“HelloWDMPnp()”来处理:
    DriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;

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


/***************************************************************
函数名称: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”就介绍到这里,虽然实际上它什么都没有做,但是由于它包含了完整的框架,所以对于初学者来说还是很有参考价值的。至于怎么编译及安装,留待下次再讲,敬请留意。(不是我想卖关子啊,这些步骤实在是很麻烦的,要另外写一篇文章才说得清楚哦!)

 

(来源:http://laoluoc.yeah.net)

WDM驱动程序入门(1)——HelloWDM

WDM驱动程序是一种很新的东西,相信很多人都跟我一样,对它很感兴趣,但是又找不到学习的切入点。究其原因,还是因为WDM是一种非常“死板板”的程序,它一运行就是工作在系统的底层RING 0处,提供各种接...
  • zy122
  • zy122
  • 2006年11月15日 11:01
  • 700

WDM驱动程序入门(1)——HelloWDM

WDM驱动程序是一种很新的东西,相信很多人都跟我一样,对它很感兴趣,但是又找不到学习的切入点。究其原因,还是因为WDM是一种非常“死板板”的程序,它一运行就是工作在系统的底层RING 0处,提供各种接...
  • phecg
  • phecg
  • 2007年01月13日 18:14
  • 517

Windows驱动开发WDM (1) - 基本结构

陆陆续续做过一些驱动的开发,但是一直以来都没有系统的学习过。这次重新阅读《windows驱动开发技术详解》(张帆,史彩成等编著),写博客记录一下,用以加深自己对驱动的理解。   驱动对象(DRIV...
  • zj510
  • zj510
  • 2012年11月21日 14:13
  • 9203

WDM驱动程序入门(1)-Hello WDM

WDM驱动程序入门(1)-Hello WDM    WDM驱动程序是一种很新的东西,相信很多人都跟我一样,对它很感兴趣,但是又找不到学习的切入点。究其原因,还是因为WDM是一种非常“死板板”的程序,它...
  • i_like_cpp
  • i_like_cpp
  • 2005年06月03日 13:15
  • 1324

NT式驱动和WDM式驱动程序

1.Windows驱动程序分为两类,一类是不支持即插即用功能的NT式的驱动程序;另一类是支持即插即用功能的WDM式的驱动程序。   2.NT式的驱动程序要导入的头文件时NTDDK.H,而WDM式的...
  • whatday
  • whatday
  • 2015年03月28日 15:27
  • 2893

WDM驱动程序入门-Hello WDM

***************************************************************/ //一定要的头文件,声明了函数模块和变量: #include "H...
  • zacklin
  • zacklin
  • 2012年04月19日 10:50
  • 926

WDM驱动程序入门示例

驱动程序开发实在是一件很头疼的事情,入手几天还是没什么感觉。找到一段代码,麻雀虽小五脏俱全,看了之后能对整个完整的框架有个基本的了解,很有参考价值。发这里一起分享。 //头文件 #if...
  • wwwgeyang777
  • wwwgeyang777
  • 2011年10月26日 16:48
  • 646

WDM驱动程序入门

 WDM驱动程序入门(1)-Hello WDM WDM驱动程序入门(2)――驱动程序的小秘密 WDM驱动程序入门(3)——安装步骤 ...
  • daichanglin
  • daichanglin
  • 2007年05月10日 15:05
  • 877

编写WDM驱动,如何写AddDevice例程

AddDevice例程 在前一节中,我讲述了当WDM驱动程序被第一次装入时如何初始化。通常,一个驱动程序可以被多个设备利用。WDM驱动程序有一个特殊的AddDevice函数,PnP管理器为每个设...
  • kinhum
  • kinhum
  • 2013年10月19日 02:44
  • 868

WDM驱动程序入门-Hello WDM - ZZ

/***************************************************************程序名称:Hello World for WDM            ...
  • zdy_0321
  • zdy_0321
  • 2008年10月03日 12:48
  • 289
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:WDM驱动程序入门(1)——HelloWDM
举报原因:
原因补充:

(最多只允许输入30个字)