KS源码分析
+ -

CKsQueue

2025-03-06 2 0

CKsQueue是KSSTREAM_POINTER的数据队列管理?
其成员函数如下:

  • CreateStreamPointer
  • SetStreamPointer
  • GetAvailableFrameHeader
  • PutAvailableFrameHeader
  • AddFrame[Header]
  • CancelStreamPointers
  • CancelAllIrps
  • RemoveIrpFrameHeaders
  • CreateMappingsTable
  • DeleteMappingsTable
  • FreeMappings
  • PassiveFlush
  • Flush
  • CancelRoutine
  • ReleaseIrp
  • ForwardIrp
  • ForwardWaitingIrps
  • ZeroIrp
  • DispatchTimer
  • GetTime
  • SetTimerUnsafe
  • SetTimer
  • CancelTimeoutUnsafe
  • FreeStreamPointer
  • FlushWorker
  • ReleaseCopyReference
  • CompleteWaitingFrames
  • FrameToFrameCopy

前面的函数涉及到KSPSTREAM_POINTER和PKSPFRAME_HEADER,还有一个KSSTREAM_POINTER用于MINI驱动开发使用的暴露接口。他们三者的关系很简单:

struct _KSPSTREAM_POINTER {
    LIST_ENTRY ListEntry;
    LIST_ENTRY TimeoutListEntry;
    LONGLONG TimeoutTime;
    PFNKSSTREAMPOINTER CancelCallback;
    PFNKSSTREAMPOINTER TimeoutCallback;
    KSPSTREAM_POINTER_STATE State;
    KSPSTREAM_POINTER_TYPE Type;
    ULONG Stride;
    PIKSQUEUE Queue;
    PKSPFRAME_HEADER FrameHeader;
    PKSPFRAME_HEADER FrameHeaderStarted;
    KSSTREAM_POINTER Public;
};

struct _KSPFRAME_HEADER
{
    LIST_ENTRY ListEntry;
    PKSPFRAME_HEADER NextFrameHeaderInIrp;
    PVOID Queue;
    PIRP OriginalIrp;
    PMDL Mdl;
    PIRP Irp;
    PKSPIRP_FRAMING IrpFraming;
    PKSSTREAM_HEADER StreamHeader;
    PVOID FrameBuffer;
    PKSPMAPPINGS_TABLE MappingsTable;
    ULONG StreamHeaderSize;
    ULONG FrameBufferSize;
    PVOID Context;
    LONG RefCount;
    PVOID OriginalData;
    NTSTATUS Status;
    BOOLEAN DismissalCall;
    KSPFRAME_HEADER_TYPE Type;
    PKSPSTREAM_POINTER FrameHolder;
    //PKSPFRAME_HEADER ParentFrameHeader;
    //PKSSPLITPIN SplitPins;
    //ULONG ChildrenOut;
};

struct _KSSTREAM_POINTER
{
    PVOID Context;
    PKSPIN Pin;
    PKSSTREAM_HEADER StreamHeader;
    PKSSTREAM_POINTER_OFFSET Offset;
    KSSTREAM_POINTER_OFFSET OffsetIn;
    KSSTREAM_POINTER_OFFSET OffsetOut;
};

KS内部用的结构体以KSP开头,外的是KS。
KSPFRAME_HEADER是数据的整体,故通过CreateStreamPointer申请内存空间并返回。

    PKSPSTREAM_POINTER m_Leading;
    PKSPSTREAM_POINTER m_Trailing;

CKsQueue::Init创建也是:

    if (NT_SUCCESS(status)) {
        status = CreateStreamPointer(&m_Leading);
        if (NT_SUCCESS(status) && (Flags & KSPIN_FLAG_DISTINCT_TRAILING_EDGE)) {
            status = CreateStreamPointer(&m_Trailing);
        }
    }

当有IRP数据流到时,调用CKsQueue::TransferKsIrp处理。创建新的FrameHeader,然后调用AddFrame函数,将新创建的Frame通过SetStreamPointer添加到m_Leading和m_Trailing(如果有的话)中。

当然,AddFrame中也需要将自己这个Frame增加链表m_FrameQueue.ListEntry中。

创建

由函数KspCreateQueue创建。实际过程如下:

NTSTATUS
KspCreateQueue(
    OUT PIKSQUEUE* Queue,
    IN ULONG Flags,
    IN PIKSPIPESECTION PipeSection,
    IN PIKSPROCESSINGOBJECT ProcessingObject,
    IN PKSPIN MasterPin,
    IN PKSGATE FrameGate OPTIONAL,
    IN BOOLEAN FrameGateIsOr,
    IN PKSGATE StateGate OPTIONAL,
    IN PIKSDEVICE Device,
    IN PDEVICE_OBJECT FunctionalDeviceObject,
    IN PADAPTER_OBJECT AdapterObject OPTIONAL,
    IN ULONG MaxMappingByteCount OPTIONAL,
    IN ULONG MappingTableStride OPTIONAL,
    IN BOOLEAN InputData,
    IN BOOLEAN OutputData
    )
{
    NTSTATUS status;
    CKsQueue *queue =  new(NonPagedPool,POOLTAG_QUEUE) CKsQueue(NULL);
    if (queue){
        queue->AddRef();
        status = queue->Init(
                Queue,
                Flags,
                PipeSection,
                ProcessingObject,
                MasterPin,
                FrameGate,
                FrameGateIsOr,
                StateGate,
                Device, 
                FunctionalDeviceObject,
                AdapterObject,
                MaxMappingByteCount,
                MappingTableStride,
                InputData,
                OutputData);

        queue->Release();
    } else {
        status = STATUS_INSUFFICIENT_RESOURCES;
    }

    return status;
}

类定义如下:

class CKsQueue:
    public IKsQueue,
    public CBaseUnknown
{
...
    PKSPSTREAM_POINTER m_Leading;
    PKSPSTREAM_POINTER m_Trailing;
}

故IKsQueue是CKsQueue的父类,可进行指针转换。返回的其实Queue指针类型也即是queue指针。

另外,在CKsQueue::Init函数中,关于m_Leading和m_Trailing的创建如下

status = CreateStreamPointer(&m_Leading);
if (NT_SUCCESS(status) && (Flags & KSPIN_FLAG_DISTINCT_TRAILING_EDGE)) {
    status = CreateStreamPointer(&m_Trailing);
}

m_Trailing是根据是否有KSPIN_FLAG_DISTINCT_TRAILING_EDGE标识,是可选的。
CreateStreamPointer实现如下:

NTSTATUS
CKsQueue::
CreateStreamPointer(
    OUT PKSPSTREAM_POINTER* StreamPointer
    )
{
    NTSTATUS status;
    PKSPSTREAM_POINTER streamPointer = (PKSPSTREAM_POINTER) ExAllocatePoolWithTag(NonPagedPool,sizeof(KSPSTREAM_POINTER),POOLTAG_STREAMPOINTER);
    if (streamPointer) 
    {
        //InterlockedIncrement(&m_StreamPointersPlusOne);
        RtlZeroMemory(streamPointer,sizeof(KSPSTREAM_POINTER));
        streamPointer->State = KSPSTREAM_POINTER_STATE_UNLOCKED;
        streamPointer->Type = KSPSTREAM_POINTER_TYPE_NORMAL;
        streamPointer->Stride = m_MappingTableStride;
        streamPointer->Queue = this;
        streamPointer->Public.Pin = m_MasterPin;
        //是输入还是输出
        if (m_InputData) {
            streamPointer->Public.Offset = &streamPointer->Public.OffsetIn;
        } else {
            streamPointer->Public.Offset = &streamPointer->Public.OffsetOut;
        }

        *StreamPointer = streamPointer;
        status = STATUS_SUCCESS;
    } else {
        status = STATUS_INSUFFICIENT_RESOURCES;
    }

    return status;
}

KSPSTREAM_POINTER结构体的定义见:https://www.pnpon.com/article/detail-826.html

0 篇笔记 写笔记

CKsQueue
CKsQueue是KSSTREAM_POINTER的数据队列管理?其成员函数如下:CreateStreamPointerSetStreamPointerGetAvailableFrameHeaderPutAvailableFrameHeaderAddFrame[Header]CancelStre......
作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

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

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