KS源码分析
+ -

KsAddDevice

2025-03-05 12 0

对于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.

对象关系图如下:
152422624300

KsGetDeviceForDeviceObject

KsGetDeviceForDeviceObject其实是不调用的,因为Device为空。不过看其代码也只是获取的是m_Ext.Public,也是 deviceHeader->Object

0 篇笔记 写笔记

作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!