KS源码分析
+ -

CKsRequestor类

2025-03-10 2 0

CKsRequestor用于实现内核的请求对象,其主要包括以下方法:

  • RetireFrame[Header]
  • CloneFrameHeader
  • GetAvailableFrameHeader
  • PutAvailableFrameHeader
  • GetAvailableIrp
  • PutAvailableIrp
  • AllocateIrp
  • FreeIrp
  • AllocateFrameBuffer
  • FreeFrameBuffer

从其类职业函数可以看到主要涉及FrameHeader,Irp和FrameBuffer.

FrameHeader

FrameHeader终究归于链表

  • m_FrameHeadersAvailable.ListEntry
  • m_FrameHeadersAvailable.SpinLock

  • m_FrameHeadersToRetire.ListEntry

  • m_FrameHeadersToRetire.SpinLock

所以

  • PutAvailableFrameHeader:就是挂入m_FrameHeadersAvailable链表
  • GetAvailableFrameHeader:从链表m_FrameHeadersAvailable中取出一个,看长度是否满足,如果不满足,就Free掉,再重新ExAllocatePool一个。
  • RetireFrame:就是挂入m_FrameHeadersToRetire
  • CloneFrameHeader:调用GetAvailableFrameHeader获取一个,将入参的FrameHeader dump给从GetAvailableFrameHeader拿到的,并返回。

所以从函数来看m_FrameHeadersAvailable和m_FrameHeadersToRetire中应都是空闲的,但两者有区别。

IRP

IPR涉及的链表如下:

  • m_IrpsAvailable.ListEntry
  • m_IrpsAvailable.SpinLock

函数介绍:

  • AllocateIrp:单纯的就是IoAllocateIrp,并将其初始化为IRP_MJ_DEVICE_CONTROL,控制码为IOCTL_KS_READ_STREAM
  • PutAvailableIrp:挂入m_IrpsAvailable链表。
  • GetAvailableIrp:从链表m_IrpsAvailable中获取一个,如果没有了,就调用AllocateIrp。
  • FreeIrp: IoFreeIrp(Irp)

FrameBuffer

根据是否有分配器调用不同。
分配器为: KSSTREAMALLOCATOR_FUNCTIONTABLE m_AllocatorFunctionTable

typedef struct {
    PFNALLOCATOR_ALLOCATEFRAME  AllocateFrame;
    PFNALLOCATOR_FREEFRAME      FreeFrame;
} KSSTREAMALLOCATOR_FUNCTIONTABLE, *PKSSTREAMALLOCATOR_FUNCTIONTABLE;

实际这就是内存的分配与释放。如果没有分配器,就退化为根据成员变量m_FrameSize的值ExAllocatePoolWithTag或ExFreePool。

CKsRequestor的创建与初始化

NTSTATUS
KspCreateRequestor(
    OUT PIKSREQUESTOR* Requestor,
    IN PIKSPIPESECTION PipeSection,
    IN PIKSPIN Pin,
    IN PFILE_OBJECT AllocatorFileObject OPTIONAL,
    IN PIKSRETIREFRAME RetireFrame OPTIONAL,
    IN PIKSIRPCOMPLETION IrpCompletion OPTIONAL
    )
{
    NTSTATUS status;
    CKsRequestor *requestor = new(NonPagedPool,POOLTAG_REQUESTOR) CKsRequestor(NULL);
    if (requestor) 
    {
        requestor->AddRef();

        status = 
            requestor->Init(
                PipeSection,
                Pin,
                AllocatorFileObject,
                RetireFrame,
                IrpCompletion);

        if (NT_SUCCESS(status)) {
            *Requestor = PIKSREQUESTOR(requestor);
        } else {
            requestor->Release();
        }
    } else {
        status = STATUS_INSUFFICIENT_RESOURCES;
    }

    return status;
}

初始化FrmeaSize和m_FrameCount

  PKSPIN pin = Pin->GetStruct();
  if (pin->Descriptor->AllocatorFraming) 
  {
      m_FrameSize =  pin->Descriptor->AllocatorFraming->FramingItem[0].FramingRange.Range.MaxFrameSize;
      m_FrameCount = pin->Descriptor->AllocatorFraming->FramingItem[0].Frames;
  }

这一块对应于avshws中相关代码来验证

  • 通过IntersectHandler来校验所有的格式分辨率参数
  • DispatchSetFormat 设置用户选择的参数和分辨率
  • 故在创建读取数据流Pin时,其DumpCaptureVideoInfoHeader来DUMP该管脚的参数,并配置PIN描述符中相关的参数
    PKSALLOCATOR_FRAMING_EX Framing = const_cast <PKSALLOCATOR_FRAMING_EX>(Pin->Descriptor->AllocatorFraming);
    Framing->FramingItem[0].Frames = 2;
    Framing->FramingItem[0].PhysicalRange.MinFrameSize =
      Framing->FramingItem[0].PhysicalRange.MaxFrameSize =
      Framing->FramingItem[0].FramingRange.Range.MinFrameSize =
      Framing->FramingItem[0].FramingRange.Range.MaxFrameSize = CapPin->m_VideoInfoHeader->bmiHeader.biSizeImage;
    Framing->FramingItem[0].PhysicalRange.Stepping = Framing->FramingItem[0].FramingRange.Range.Stepping = 0;
    

总结

CKsRequestor类代表了IRP_MJ_DEVICE_CONTROL,控制码为IOCTL_KS_READ_STREAM请求数据流到下层驱动程序。

0 篇笔记 写笔记

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

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

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