您的位置:首页 > 其它

一个简单的NT驱动之创建设备对象函数(CreateDevice)

2012-04-13 17:16 411 查看
/****************************************************************

* 函数名称:CreateDrivce

* 功能描述:初始化设备对象

* 参数列表:

pDriverObject:从I/O管理器中传进来的驱动对象

* 返回值:返回初始化状态

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

#pragma INITCODE

NTSTATUS CreateDeivce( IN PDRIVER_OBJECT pDriverObject )

{

NTSTATUS status;

PDEVICE_OBJECT pDevObj;

PDEVICE_EXTENSION pDevExt;

//创建设备名称

UNICODE_STRING devName;

RtlInitUnicodeString( &devName, L"\\device\\MyDDKDevice" );

//创建设备

status = IoCreateDevice( pDriverObject,

sizeof( DEVICE_EXTENSION ),

&( UNICODE_STRING ) devName,

FILE_DEVICE_UNKNOWN,

0, TRUE, &pDevObj );

if ( !NT_SUCCESS( status ) )

return status;

pDevObj->Flags |= DO_BUFFERED_IO;

pDevExt = ( PDEVICE_EXTENSION ) pDevObj->DeviceExtension;

pDevExt->pDevice = pDevObj;

pDevExt->ustrDeviceName = devName;

//创建符号链接

UNICODE_STRING symLinkName;

RtlInitUnicodeString( &symLinkName, L"\\??\\HelloDDK" );

pDevExt->ustrSymLinkName = symLinkName;

status = IoCreateSymbolicLink( &symLinkName, &devName );

if ( !NT_SUCCESS( status ) )

{

IoDeleteDevice( pDevObj );

return status;

}

return STATUS_SUCCESS;

}

这个函数是在DriverEntry入口函数中执行的,该函数使用了5个数据类型,分别是PDRIVER_OBJECT、NTSTATUS、PDEVICE_OBJECT、PDEVICE_EXTENSION和UNICODE_STRING。其中PDRIVER_OBJECt是驱动对象,NTSTATUS是函数返回状态,PDEVICE_OBJECt是设备对象,PDEVICE_EXTENSION是头文件中自定义的一个结构体。该函数使用了四个内核函数,分别是RtlInitUnicodeString、IoCreateDevice、IoCreateSymbolicLink和IoDeleteDevice。

其中几个数据类型在第一篇笔记中差不多都已经谈到了,除了PDEVICE_EXTENSION这个结构体,该结构体定义的是设备对象扩展,其定义如下:

typedef struct _DEVICE_EXTENSION

{

PDEVICE_OBJECT pDevice;

UNICODE_STRING ustrDeviceName; //设备名称

UNICODE_STRING ustrSymLinkName; //符号链接名

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

该结构体只有三个成员,pDevice是设备对象,该成员的值由IoCreateDevice函数获得;ustrDeviceName是创建的设备名称;ustrSymLinkName是符号链接名。

接下来就是在驱动程序中第一次接触的几个内核函数,RtlInitUnicodeString函数是用来给UNICODE_STRING字符串赋值的;IoCreateDevice是用来创建设备对象的,在此有必要熟悉熟悉IoCreateDevice函数:

NTKERNELAPI

NTSTATUS

IoCreateDevice(

__in PDRIVER_OBJECT DriverObject,

__in ULONG DeviceExtensionSize,

__in_opt PUNICODE_STRING DeviceName,

__in DEVICE_TYPE DeviceType,

__in ULONG DeviceCharacteristics,

__in BOOLEAN Exclusive,

__out

__drv_out_deref(

__drv_allocatesMem(Mem)

__drv_when((((inFunctionClass$("DRIVER_INITIALIZE"))

||(inFunctionClass$("DRIVER_DISPATCH")))),

__drv_aliasesMem)

__on_failure(__null))

PDEVICE_OBJECT *DeviceObject

);

IoCreateDevice函数共有7个参数,包含6个输入函数和1个输出函数。其中DriverObject是驱动对象实例句柄;DeviceExtensionSize是自定义设备对象扩展的大小;DeviceName是设备对象名称,这个名称可以不设置,系统会自动为其命名;

DeviceType是一个比较重要的参数,该参数可以指定添加的驱动是即插即用设备还是非即插即用设备,对于非即插即用设备,应设置为FILE_DEVICE_UNKNOWN;DeviceCharacteristics为设置设备对象特征;Exclusive设置设备对象在内核模式下是否可用,一般为TRUE;最后一个参数是DeviceObject,该参数返回设备对象的地址。

现在要初始化设备对象扩展,在该扩展中指定当前设备对象的指针和设备对象名称,代码如下:

pDevObj->Flags |= DO_BUFFERED_IO;

pDevExt = ( PDEVICE_EXTENSION ) pDevObj->DeviceExtension;

pDevExt->pDevice = pDevObj;

pDevExt->ustrDeviceName = devName;

pDevObj为设备对象指针,“pDevObj->Flags |= DO_BUFFERED_IO;”是将设备设置为缓冲区设备,接着获取设备扩展指针赋值到pDevExt中,并设置设备对象扩展的设备对象及设备对象名称。

最后是创建符号链接,这如同给对象设备一个别名,以便记忆和识别。

//创建符号链接

UNICODE_STRING symLinkName;

RtlInitUnicodeString( &symLinkName, L"\\??\\HelloDDK" );

pDevExt->ustrSymLinkName = symLinkName;

status = IoCreateSymbolicLink( &symLinkName, &devName );

if ( !NT_SUCCESS( status ) )

{

IoDeleteDevice( pDevObj );

return status;

}

IoCreateSymbolicLink函数的第一个参数是符号链接名称,第二个参数是设备对象名称。

至此,DriverEntry入口函数中的功能均已实现,其大致顺序如下:

第一步:初始化驱动对象,设置IRP派遣函数和驱动卸载函数

第二步:创建设备对象。这一步可细分为创建设备对象、设置设备对象扩展、创建设备对象符号链接。

由于驱动程序对线程、硬件等的操作与文件操作类似,都包括打开、关闭、取消和退出等操作,所以也使用IO方式来进行控制,而在IRP派遣函数中就包含了这些特性。

在这第一个驱动程序中,只有一个IRP派遣函数,即HelloDDKDispatchRuntine,对于派遣函数的作用及设置将在另外一篇笔记中详细整理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: