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