KsStreamPointerClone
2025-02-27
14
0
typedef struct _KSISTREAM_POINTER
{
PFNKSSTREAMPOINTER Callback;
PIRP Irp;
KTIMER Timer;
KDPC TimerDpc;
struct _KSISTREAM_POINTER *Next;
PKSPIN Pin;
PVOID Data;
ULONG Offset;
ULONG Length;
KSSTREAM_POINTER StreamPointer;//实际外面暴露的
KSPIN_LOCK Lock;
}KSISTREAM_POINTER, *PKSISTREAM_POINTER;
typedef struct {
PVOID Context;
PKSPIN Pin;
PKSSTREAM_HEADER StreamHeader;
PKSSTREAM_POINTER_OFFSET Offset; //指针 Offset = &OffsetIn or &OffsetOut
KSSTREAM_POINTER_OFFSET OffsetIn;//in
KSSTREAM_POINTER_OFFSET OffsetOut;//out
} KSSTREAM_POINTER, *PKSSTREAM_POINTER;
当该请求为输出管脚时(测试例程为相机时),则Offset = &OffsetOut
未处理数据时:
reactos函数实现,重新实现的是KSISTREAM_POINTER
KSDDKAPI NTSTATUS NTAPI KsStreamPointerClone ( IN PKSSTREAM_POINTER StreamPointer,
IN PFNKSSTREAMPOINTER CancelCallback OPTIONAL,
IN ULONG ContextSize,
OUT PKSSTREAM_POINTER * CloneStreamPointer
)
{
IKsPinImpl * This;
PKSISTREAM_POINTER CurFrame;
PKSISTREAM_POINTER NewFrame;
ULONG_PTR RefCount;
NTSTATUS Status;
ULONG Size;
/* get stream pointer */
CurFrame = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
/* calculate context size */
Size = sizeof(KSISTREAM_POINTER) + ContextSize;
/* allocate new stream pointer */
NewFrame = (PKSISTREAM_POINTER)AllocateItem(NonPagedPool, Size);
if (!NewFrame)
return STATUS_INSUFFICIENT_RESOURCES;
/* get current irp stack location */
RefCount = (ULONG_PTR)CurFrame->Irp->Tail.Overlay.DriverContext[0];
/* increment reference count */
//引用计数
RefCount++;
CurFrame->Irp->Tail.Overlay.DriverContext[0] = (PVOID)RefCount;
/* copy stream pointer */
//故数组的指针相同,raw和clone两个结构体引用同一个指针StreamPointer.data
RtlMoveMemory(NewFrame, CurFrame, sizeof(KSISTREAM_POINTER));
/* locate pin */
This = (IKsPinImpl*)CONTAINING_RECORD(CurFrame->Pin, IKsPinImpl, Pin);
/* prepare stream header in case required */
if (CurFrame->StreamPointer.Offset->Remaining == 0)
{
Status = IKsPin_PrepareStreamHeader(This, NewFrame);
if (!NT_SUCCESS(Status))
{
FreeItem(NewFrame);
return STATUS_DEVICE_NOT_READY;
}
}
//clone的用户上下文
if (ContextSize)
NewFrame->StreamPointer.Context = (NewFrame + 1);
//这个好
if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN)
NewFrame->StreamPointer.Offset = &NewFrame->StreamPointer.OffsetIn;
else
NewFrame->StreamPointer.Offset = &NewFrame->StreamPointer.OffsetOut;
NewFrame->StreamPointer.Pin = &This->Pin;
ASSERT(NewFrame->StreamPointer.Pin);
ASSERT(NewFrame->StreamPointer.Context);
ASSERT(NewFrame->StreamPointer.Offset);
ASSERT(NewFrame->StreamPointer.StreamHeader);
/* store result */
*CloneStreamPointer = &NewFrame->StreamPointer;
DPRINT("KsStreamPointerClone CloneStreamPointer %p\n", *CloneStreamPointer);
return STATUS_SUCCESS;
}