设备对象,顾名思义,就是把一个设备抽象成一个对象来管理。它代表一个被驱动管理的设备,但这个设备,不一定是实际存在的。在WDM驱动中,一般我们在AddDevice函数中来创建它。指向AddDevice的函数指针是驱动对象的一个域。下面我们给出它书本中的数据结构说明。
当然,我们也可以使用windbg的dt命令查看设备对象的数据结构。结构中的数据成员,基本看名字就知道含义,这里只介绍其中的几个。
Flags域
Characteristics域
我们可以看到创建设备对象的函数AddDevice和系统传进来的参数如下:
NTSTATUS AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT pdo)
而我们调用如下的函数来创建设备对象:
NTSTATUS
IoCreateDevice(
IN PDRIVER_OBJECT DriverObject,
IN ULONG DeviceExtensionSize,
IN PUNICODE_STRING DeviceName OPTIONAL,
IN DEVICE_TYPE DeviceType,
IN ULONG DeviceCharacteristics,
IN BOOLEAN Exclusive,
OUT PDEVICE_OBJECT *DeviceObject
);
重点介绍两个参数,DeviceCharacteristics就是上面设备对象的域Characteristics.Exclusive,说明是否为独占设备。
而在WDF驱动中,创建设备对象的函数,变成了WDF_DRIVER_CONFIG的一个成员,这就是WDF中的F的功劳了。下面给出MSDN中的说明。
typedef struct _WDF_DRIVER_CONFIG {
ULONG Size;
PFN_WDF_DRIVER_DEVICE_ADD EvtDriverDeviceAdd;
PFN_WDF_DRIVER_UNLOAD EvtDriverUnload;
ULONG DriverInitFlags;
ULONG DriverPoolTag;
} WDF_DRIVER_CONFIG, *PWDF_DRIVER_CONFIG;
当然初始化它也不需要借助宏来帮忙。这里用到WDF_DRIVER_CONFIG_INIT宏。
再看 EvtAddDevice(WDFDRIVER Driver,PWDFDEVICE_INIT DeviceInit),函数名可以自己指定,但传入参数变了PWDFDEVICE_INIT DeviceInit,这里我们可以猜测到此时的设备对象被赋予了更多的功能,用windbg我们可以看到,设备对象的数据结构里,有队列对象!所以在WDF中,之前需要在驱动对象中,填充的IRP的指针函数不需要了,因为WDF封装了电源管理的IRP,做成了事件的回调。其他的IRP也变成了队列的形式来指定处理的例程。所以设备对象的功能增多了。我们这里只讲设备对象相关,其他的以后再说。
然后再来看,设备对象创建函数,变成了如下函数。
NTSTATUS WdfDeviceCreate(
IN OUT PWDFDEVICE_INIT* DeviceInit,
IN OPTIONAL PWDF_OBJECT_ATTRIBUTES DeviceAttributes,
OUT WDFDEVICE* Device
);
第一个参数,MSDN没有给出说明,不过我们猜也可以猜下,应该是初始化设备对象的属性的,也就是其成员。第二个参数MSDN有说明:
typedef struct _WDF_OBJECT_ATTRIBUTES {
ULONG Size;
PFN_WDF_OBJECT_CONTEXT_CLEANUP EvtCleanupCallback;
PFN_WDF_OBJECT_CONTEXT_DESTROY EvtDestroyCallback;
WDF_EXECUTION_LEVEL ExecutionLevel;
WDF_SYNCHRONIZATION_SCOPE SynchronizationScope;
WDFOBJECT ParentObject;
size_t ContextSizeOverride;
PCWDF_OBJECT_CONTEXT_TYPE_INFO ContextTypeInfo;
} WDF_OBJECT_ATTRIBUTES, *PWDF_OBJECT_ATTRIBUTES;
但相反,这个参数一般不怎么使用,为什么了,因为是WDF,有WDF01000这个驱动帮我们做这些事情,如果要使用也是指定设备扩展,其他的域可使用,也可不指定,因为框架都会帮你做一切!