您的位置:首页 > 其它

驱动程序开发学习(三)hello world

2014-03-09 22:19 337 查看
原帖地址:http://blog.csdn.net/masofeng/article/details/7544791

 

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

[cpp]
view plaincopyprint?

/***************************************************************

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

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

#include "HelloWDM.h" 
 
/***************************************************************

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

参数:IN PDRIVER_OBJECT  DriverObject  IN 是一个关键字表示这是一个输入参数,PDRIVER_OBJECT是一个数据结构的指针,就像PCHAR一样,这个数据结构是什么样子的,描述了一个驱动设备对象。

      IN PUNICODE_STRING RegistryPath  指定了驱动程序注册表健的路径,因为驱动程序安装后总会在系统注册表里留下一点东西的。

返回值:NTSTATUS数据类型。上层的应用程序通过I/O请求包来告诉驱动程序,你要给我什么服务吧!IRP_MJ_PNP就是即插即用处理的请求。你发没发觉上面其实是在制造进入各个房间的“小门”

***************************************************************/ 

//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.cpp
日期:2002-8-16
***************************************************************/

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

/***************************************************************
函数名称:DriverEntry()
功能描述:WDM程序入口(原来的WinMain被换成了DriverEntry,也是驱动程序的大门)
参数:IN PDRIVER_OBJECT  DriverObject  IN 是一个关键字表示这是一个输入参数,PDRIVER_OBJECT是一个数据结构的指针,就像PCHAR一样,这个数据结构是什么样子的,描述了一个驱动设备对象。
IN PUNICODE_STRING RegistryPath  指定了驱动程序注册表健的路径,因为驱动程序安装后总会在系统注册表里留下一点东西的。
返回值:NTSTATUS数据类型。上层的应用程序通过I/O请求包来告诉驱动程序,你要给我什么服务吧!IRP_MJ_PNP就是即插即用处理的请求。你发没发觉上面其实是在制造进入各个房间的“小门”
***************************************************************/
//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;
}


 

[cpp]
view plaincopyprint?

/***************************************************************

程序名称: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); 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: