KsAddDevice
对于WDM驱动,必须提供DriverObject->DriverExtension->AddDevice回调函数创建设备对象fdo.
KsInitializeDriver函数将其AddDevice置为KsAddDevice,我们来分析FDO的创建和初始化过程。
在KsAddDevice中,首先调用IoGetDriverObjectExtension从驱动象象的扩展对象链表中获取我们的设备描述符。
NTSTATUS
NTAPI
KsAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
{
PKSDEVICE_DESCRIPTOR* descriptorInExt = (PKSDEVICE_DESCRIPTOR*)(IoGetDriverObjectExtension(
DriverObject,
PVOID(KsInitializeDriver)));
return KsCreateDevice(
DriverObject,
PhysicalDeviceObject,
descriptorInExt ? *descriptorInExt : NULL,
0,
NULL);
}
注意,其对象的标识是PVOID(KsInitializeDriver),即函数指针。
获取到设备描述符之后,调用KsCreateDevice。
NTSTATUS
KsCreateDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN const KSDEVICE_DESCRIPTOR* Descriptor OPTIONAL,
IN ULONG ExtensionSize OPTIONAL,//device extensize
OUT PKSDEVICE* Device OPTIONAL
)
由于设备扩展对象ExtensionSize的值为0,故自动将期扩充为一个指针的大小。
这里其实只是一个临时创建的,后面会再次根据这个指针指向一个
typedef PVOID KSDEVICE_HEADER, KSOBJECT_HEADER;
if (ExtensionSize == 0)
{
ExtensionSize = sizeof(KSDEVICE_HEADER);
}
创建设备对象,并IoAttachDeviceToDeviceStack之后,调用KsInitializeDevice初始化设备。
PDEVICE_OBJECT FunctionalDeviceObject;
NTSTATUS status = IoCreateDevice(DriverObject,ExtensionSize,NULL,FILE_DEVICE_KS,0,FALSE,&FunctionalDeviceObject);
if (NT_SUCCESS(status))
{
PDEVICE_OBJECT nextDeviceObject = IoAttachDeviceToDeviceStack(FunctionalDeviceObject,PhysicalDeviceObject);
if (nextDeviceObject)
{
FunctionalDeviceObject->Flags |= DO_POWER_PAGABLE;
status = KsInitializeDevice(FunctionalDeviceObject,PhysicalDeviceObject,nextDeviceObject,Descriptor);
}
else
{
status = STATUS_DEVICE_REMOVED;
}
}
if (NT_SUCCESS(status))
{
FunctionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
if (Device)
{
*Device = KsGetDeviceForDeviceObject(FunctionalDeviceObject);
}
}
else
{
if (nextDeviceObject)
{
IoDetachDevice(nextDeviceObject);
}
IoDeleteDevice(FunctionalDeviceObject);
}
return status;
KsInitializeDevice
在KsInitializeDevice函数中,实际上是创建CKsDevice对象,并初始化。
CKsDevice *device = new(NonPagedPool,POOLTAG_DEVICE) CKsDevice(NULL);
NTSTATUS status;
if (device) {
device->AddRef();
status = device->Init( FunctionalDeviceObject, PhysicalDeviceObject,NextDeviceObject, Descriptor);
device->Release();
}
else
{
status = STATUS_INSUFFICIENT_RESOURCES;
}
所以,关键点在于CKsDevice::Init,Init初始化了其一系统的成员变量之后
NTSTATUS status;
//DeviceExtension如果有,一般内容为CreatedDeviceObject + 1,否则为NULL
PKSIDEVICE_HEADER deviceHeader = *(PKSIDEVICE_HEADER *)(FunctionalDeviceObject->DeviceExtension);
//其指针内容为空时,方可创建新的,为其赋值
if (! deviceHeader)
{
//创建KSDEVICE_HEADER内存空间,并返回指针
status = KsAllocateDeviceHeader((KSDEVICE_HEADER *)&deviceHeader,0,NULL);
if (NT_SUCCESS(status))
{
*(PKSIDEVICE_HEADER *)(FunctionalDeviceObject->DeviceExtension) = deviceHeader;
}
}
else
{
status = STATUS_SUCCESS;
}
成功之后:
if (NT_SUCCESS(status)) {
deviceHeader->Object = PVOID(&m_Ext.Public);
}
m_Ext.Publica其实是KSDEVICE对象,也即AVStream中外露的设备对象。
总线接口的信息的获取。
if (NT_SUCCESS(status)) {
status = GetBusInterfaceStandard();
}
根据设备描述符数组,创建其厂对象。
//
// Create filter factories.
//
if (NT_SUCCESS(status) && Descriptor) {
//AcquireDevice();
const KSFILTER_DESCRIPTOR*const* filterDescriptor = Descriptor->FilterDescriptors;
for (ULONG ul = Descriptor->FilterDescriptorsCount;NT_SUCCESS(status) && ul--; filterDescriptor++)
{
status = KspCreateFilterFactory(
&m_Ext,
&m_Ext.ChildList,
*filterDescriptor,
NULL,
NULL,
0,
NULL,
NULL,
NULL);
}
//ReleaseDevice();
}
如果设置了AddDevice回调,调用。
if (NT_SUCCESS(status) && Descriptor && Descriptor->Dispatch && Descriptor->Dispatch->Add)
{
status = Descriptor->Dispatch->Add(&m_Ext.Public);
}
这里的m_Ext.Public就是KSDEVICE.
对象关系图如下:
KsGetDeviceForDeviceObject
KsGetDeviceForDeviceObject其实是不调用的,因为Device为空。不过看其代码也只是获取的是m_Ext.Public,也是 deviceHeader->Object