#include "priv.h"
+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
{
KSBASIC_HEADER BasicHeader;
KSPIN Pin;
PKSIOBJECT_HEADER ObjectHeader;
+ KSPROCESSPIN ProcessPin;
LIST_ENTRY Entry;
- IKsPinVtbl *lpVtbl;
-
LONG ref;
+
+ IKsFilter * Filter;
KMUTEX ProcessingMutex;
PFILE_OBJECT FileObject;
+ PKSGATE AttachedGate;
+ BOOL OrGate;
+
+ LIST_ENTRY IrpList;
+ KSPIN_LOCK IrpListLock;
+ volatile LONG IrpCount;
+
+ PKSISTREAM_POINTER ClonedStreamPointer;
+ KSISTREAM_POINTER LeadingEdgeStreamPointer;
+ KSISTREAM_POINTER TrailingStreamPointer;
+
PFNKSPINPOWER Sleep;
PFNKSPINPOWER Wake;
PFNKSPINHANDSHAKE Handshake;
PFNKSPINFRAMERETURN FrameReturn;
PFNKSPINIRPCOMPLETION IrpCompletion;
+ KSCLOCK_FUNCTIONTABLE ClockTable;
+ PFILE_OBJECT ClockFileObject;
+ IKsReferenceClockVtbl * lpVtblReferenceClock;
+ PKSDEFAULTCLOCK DefaultClock;
+
+ PKSWORKER PinWorker;
+ WORK_QUEUE_ITEM PinWorkQueueItem;
+ KEVENT FrameComplete;
+ ULONG FrameSize;
+ ULONG NumFrames;
+ PDMA_ADAPTER Dma;
+ ULONG MapRegisters;
+
}IKsPinImpl;
+NTSTATUS NTAPI IKsPin_PinStatePropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
+NTSTATUS NTAPI IKsPin_PinDataFormatPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
+NTSTATUS NTAPI IKsPin_PinAllocatorFramingPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
+NTSTATUS NTAPI IKsPin_PinStreamAllocator(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
+NTSTATUS NTAPI IKsPin_PinMasterClock(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
+NTSTATUS NTAPI IKsPin_PinPipeId(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
+
+
+
+DEFINE_KSPROPERTY_CONNECTIONSET(PinConnectionSet, IKsPin_PinStatePropertyHandler, IKsPin_PinDataFormatPropertyHandler, IKsPin_PinAllocatorFramingPropertyHandler);
+DEFINE_KSPROPERTY_STREAMSET(PinStreamSet, IKsPin_PinStreamAllocator, IKsPin_PinMasterClock, IKsPin_PinPipeId);
+
+//TODO
+// KSPROPSETID_Connection
+// KSPROPERTY_CONNECTION_ACQUIREORDERING
+// KSPROPSETID_StreamInterface
+// KSPROPERTY_STREAMINTERFACE_HEADERSIZE
+
+KSPROPERTY_SET PinPropertySet[] =
+{
+ {
+ &KSPROPSETID_Connection,
+ sizeof(PinConnectionSet) / sizeof(KSPROPERTY_ITEM),
+ (const KSPROPERTY_ITEM*)&PinConnectionSet,
+ 0,
+ NULL
+ },
+ {
+ &KSPROPSETID_Stream,
+ sizeof(PinStreamSet) / sizeof(KSPROPERTY_ITEM),
+ (const KSPROPERTY_ITEM*)&PinStreamSet,
+ 0,
+ NULL
+ }
+};
+
+const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
+const GUID KSPROPSETID_Stream = {0x65aaba60L, 0x98ae, 0x11cf, {0xa1, 0x0d, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4}};
+const GUID KSPROPSETID_Clock = {0xDF12A4C0L, 0xAC17, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
+
+NTSTATUS
+NTAPI
+IKsPin_PinStreamAllocator(
+ IN PIRP Irp,
+ IN PKSIDENTIFIER Request,
+ IN OUT PVOID Data)
+{
+ UNIMPLEMENTED
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+IKsPin_PinMasterClock(
+ IN PIRP Irp,
+ IN PKSIDENTIFIER Request,
+ IN OUT PVOID Data)
+{
+ PIO_STACK_LOCATION IoStack;
+ PKSIOBJECT_HEADER ObjectHeader;
+ IKsPinImpl * This;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PHANDLE Handle;
+ PFILE_OBJECT FileObject;
+ KPROCESSOR_MODE Mode;
+ KSPROPERTY Property;
+ ULONG BytesReturned;
+
+ /* get current irp stack */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ DPRINT("IKsPin_PinMasterClock\n");
+
+ /* sanity check */
+ ASSERT(IoStack->FileObject);
+ ASSERT(IoStack->FileObject->FsContext2);
+
+ /* get the object header */
+ ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
+
+ /* sanity check */
+ ASSERT(ObjectHeader);
+
+ /* locate ks pin implemention from KSPIN offset */
+ This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
+
+ /* sanity check */
+ ASSERT(This);
+
+ Handle = (PHANDLE)Data;
+
+ if (Request->Flags & KSPROPERTY_TYPE_GET)
+ {
+ if (This->Pin.Descriptor->PinDescriptor.Communication != KSPIN_COMMUNICATION_NONE &&
+ This->Pin.Descriptor->Dispatch &&
+ (This->Pin.Descriptor->Flags & KSPIN_FLAG_IMPLEMENT_CLOCK))
+ {
+ *Handle = NULL;
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ /* no clock available */
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ }
+ else if (Request->Flags & KSPROPERTY_TYPE_SET)
+ {
+ if (This->Pin.ClientState != KSSTATE_STOP)
+ {
+ /* can only set in stopped state */
+ Status = STATUS_INVALID_DEVICE_STATE;
+ }
+ else
+ {
+ if (*Handle)
+ {
+ Mode = ExGetPreviousMode();
+
+ Status = ObReferenceObjectByHandle(*Handle, SYNCHRONIZE | DIRECTORY_QUERY, IoFileObjectType, Mode, (PVOID*)&FileObject, NULL);
+
+ DPRINT("IKsPin_PinMasterClock ObReferenceObjectByHandle %lx\n", Status);
+ if (NT_SUCCESS(Status))
+ {
+ Property.Set = KSPROPSETID_Clock;
+ Property.Id = KSPROPERTY_CLOCK_FUNCTIONTABLE;
+ Property.Flags = KSPROPERTY_TYPE_GET;
+
+ Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), &This->ClockTable, sizeof(KSCLOCK_FUNCTIONTABLE), &BytesReturned);
+
+ DPRINT("IKsPin_PinMasterClock KSPROPERTY_CLOCK_FUNCTIONTABLE %lx\n", Status);
+
+ if (NT_SUCCESS(Status))
+ {
+ This->ClockFileObject = FileObject;
+ }
+ else
+ {
+ ObDereferenceObject(FileObject);
+ }
+ }
+ }
+ else
+ {
+ /* zeroing clock handle */
+ RtlZeroMemory(&This->ClockTable, sizeof(KSCLOCK_FUNCTIONTABLE));
+ Status = STATUS_SUCCESS;
+ if (This->ClockFileObject)
+ {
+ FileObject = This->ClockFileObject;
+ This->ClockFileObject = NULL;
+
+ ObDereferenceObject(This->ClockFileObject);
+ }
+ }
+ }
+ }
+
+ DPRINT("IKsPin_PinMasterClock Status %lx\n", Status);
+ return Status;
+}
+
+
+
+NTSTATUS
+NTAPI
+IKsPin_PinPipeId(
+ IN PIRP Irp,
+ IN PKSIDENTIFIER Request,
+ IN OUT PVOID Data)
+{
+ UNIMPLEMENTED
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+
+NTSTATUS
+NTAPI
+IKsPin_PinStatePropertyHandler(
+ IN PIRP Irp,
+ IN PKSIDENTIFIER Request,
+ IN OUT PVOID Data)
+{
+ PIO_STACK_LOCATION IoStack;
+ PKSIOBJECT_HEADER ObjectHeader;
+ IKsPinImpl * This;
+ NTSTATUS Status = STATUS_SUCCESS;
+ KSSTATE OldState;
+ PKSSTATE NewState;
+
+ /* get current irp stack */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ DPRINT("IKsPin_PinStatePropertyHandler\n");
+
+ /* sanity check */
+ ASSERT(IoStack->FileObject);
+ ASSERT(IoStack->FileObject->FsContext2);
+
+ /* get the object header */
+ ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
+
+ /* locate ks pin implemention from KSPIN offset */
+ This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
+
+ /* acquire control mutex */
+ KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL);
+
+ /* grab state */
+ NewState = (PKSSTATE)Data;
+
+ if (Request->Flags & KSPROPERTY_TYPE_GET)
+ {
+ *NewState = This->Pin.DeviceState;
+ Irp->IoStatus.Information = sizeof(KSSTATE);
+ }
+ else if (Request->Flags & KSPROPERTY_TYPE_SET)
+ {
+ if (This->Pin.Descriptor->Dispatch->SetDeviceState)
+ {
+ /* backup old state */
+ OldState = This->Pin.ClientState;
+
+ /* set new state */
+ This->Pin.ClientState = *NewState;
+ This->Pin.DeviceState = KSSTATE_RUN;
+
+ /* check if it supported */
+ Status = This->Pin.Descriptor->Dispatch->SetDeviceState(&This->Pin, *NewState, OldState);
+
+ DPRINT("IKsPin_PinStatePropertyHandler NewState %lu Result %lx\n", *NewState, Status);
+
+ if (!NT_SUCCESS(Status))
+ {
+ /* revert to old state */
+ This->Pin.ClientState = OldState;
+ This->Pin.DeviceState = OldState;
+ DPRINT("IKsPin_PinStatePropertyHandler failed to set state %lx Result %lx\n", *NewState, Status);
+ DbgBreakPoint();
+ }
+ else
+ {
+ /* update device state */
+ This->Pin.DeviceState = *NewState;
+ }
+ }
+ else
+ {
+ /* just set new state */
+ This->Pin.DeviceState = *NewState;
+ This->Pin.ClientState = *NewState;
+ }
+ }
+
+ /* release processing mutex */
+ KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE);
+
+ DPRINT("IKsPin_PinStatePropertyHandler Status %lx\n", Status);
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+IKsPin_PinAllocatorFramingPropertyHandler(
+ IN PIRP Irp,
+ IN PKSIDENTIFIER Request,
+ IN OUT PVOID Data)
+{
+ PIO_STACK_LOCATION IoStack;
+ PKSIOBJECT_HEADER ObjectHeader;
+ IKsPinImpl * This;
+ ULONG Size;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ /* get current irp stack */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ /* sanity check */
+ ASSERT(IoStack->FileObject);
+ ASSERT(IoStack->FileObject->FsContext2);
+
+ /* get the object header */
+ ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
+
+ /* locate ks pin implemention from KSPIN offset */
+ This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
+
+ /* setting allocator flags is not supported */
+ ASSERT(!(Request->Flags & KSPROPERTY_TYPE_SET));
+
+ /* acquire control mutex */
+ KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL);
+
+ if (This->Pin.Descriptor->AllocatorFraming)
+ {
+ /* calculate size */
+ Size = FIELD_OFFSET(KSALLOCATOR_FRAMING_EX, FramingItem[0]) + This->Pin.Descriptor->AllocatorFraming->CountItems * sizeof(KS_FRAMING_ITEM);
+
+ if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == 0)
+ {
+ /* no buffer */
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else if (Size > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
+ {
+ /* buffer too small */
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ /* copy buffer */
+ RtlMoveMemory(Data, This->Pin.Descriptor->AllocatorFraming, Size);
+ }
+
+ /* store size */
+ Irp->IoStatus.Information = Size;
+ }
+ else
+ {
+ /* no allocator framing details */
+ Status = STATUS_NOT_FOUND;
+ }
+
+ /* release processing mutex */
+ KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE);
+
+ DPRINT("IKsPin_PinAllocatorFramingPropertyHandler Status %lx\n", Status);
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+IKsPin_PinDataFormatPropertyHandler(
+ IN PIRP Irp,
+ IN PKSPROPERTY Request,
+ IN OUT PVOID Data)
+{
+ PIO_STACK_LOCATION IoStack;
+ PKSIOBJECT_HEADER ObjectHeader;
+ IKsPinImpl * This;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ /* get current irp stack */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ DPRINT("IKsPin_PinDataFormatPropertyHandler\n");
+
+ /* sanity check */
+ ASSERT(IoStack->FileObject);
+ ASSERT(IoStack->FileObject->FsContext2);
+
+ /* get the object header */
+ ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
+
+ /* locate ks pin implemention from KSPIN offset */
+ This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
+
+ /* acquire control mutex */
+ KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL);
+
+ if (Request->Flags & KSPROPERTY_TYPE_GET)
+ {
+ if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < This->Pin.ConnectionFormat->FormatSize)
+ {
+ /* buffer too small */
+ Irp->IoStatus.Information = This->Pin.ConnectionFormat->FormatSize;
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ /* copy format */
+ RtlMoveMemory(Data, This->Pin.ConnectionFormat, This->Pin.ConnectionFormat->FormatSize);
+ }
+ }
+ else if (Request->Flags & KSPROPERTY_TYPE_SET)
+ {
+ /* set format */
+ if (This->Pin.Descriptor->Flags & KSPIN_FLAG_FIXED_FORMAT)
+ {
+ /* format cannot be changed */
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ }
+ else
+ {
+ /* FIXME check if the format is supported */
+ Status = _KsEdit(This->Pin.Bag, (PVOID*)&This->Pin.ConnectionFormat, IoStack->Parameters.DeviceIoControl.OutputBufferLength, This->Pin.ConnectionFormat->FormatSize, 0);
+
+ if (NT_SUCCESS(Status))
+ {
+ /* store new format */
+ RtlMoveMemory(This->Pin.ConnectionFormat, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength);
+ }
+ }
+ }
+
+ /* release processing mutex */
+ KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE);
+
+ DPRINT("IKsPin_PinDataFormatPropertyHandler Status %lx\n", Status);
+
+ return Status;
+}
+
NTSTATUS
NTAPI
IKsPin_fnQueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
- IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtbl);
+ NTSTATUS Status;
+ IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, BasicHeader.OuterUnknown);
if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
- *Output = &This->lpVtbl;
+ *Output = &This->BasicHeader.OuterUnknown;
_InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
- return STATUS_UNSUCCESSFUL;
+
+
+ if (This->BasicHeader.ClientAggregate)
+ {
+ /* using client aggregate */
+ Status = This->BasicHeader.ClientAggregate->lpVtbl->QueryInterface(This->BasicHeader.ClientAggregate, refiid, Output);
+
+ if (NT_SUCCESS(Status))
+ {
+ /* client aggregate supports interface */
+ return Status;
+ }
+ }
+
+ DPRINT("IKsPin_fnQueryInterface no interface\n");
+ return STATUS_NOT_SUPPORTED;
}
ULONG
IKsPin_fnAddRef(
IKsPin * iface)
{
- IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtbl);
+ IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, BasicHeader.OuterUnknown);
return InterlockedIncrement(&This->ref);
}
IKsPin_fnRelease(
IKsPin * iface)
{
- IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtbl);
+ IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, BasicHeader.OuterUnknown);
InterlockedDecrement(&This->ref);
//==============================================================
+NTSTATUS
+NTAPI
+IKsReferenceClock_fnQueryInterface(
+ IKsReferenceClock * iface,
+ IN REFIID refiid,
+ OUT PVOID* Output)
+{
+ IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+ return IKsPin_fnQueryInterface((IKsPin*)&This->BasicHeader.OuterUnknown, refiid, Output);
+}
+
+ULONG
+NTAPI
+IKsReferenceClock_fnAddRef(
+ IKsReferenceClock * iface)
+{
+ IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+ return IKsPin_fnAddRef((IKsPin*)&This->BasicHeader.OuterUnknown);
+}
+
+ULONG
+NTAPI
+IKsReferenceClock_fnRelease(
+ IKsReferenceClock * iface)
+{
+ IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+ return IKsPin_fnRelease((IKsPin*)&This->BasicHeader.OuterUnknown);
+}
+
+LONGLONG
+NTAPI
+IKsReferenceClock_fnGetTime(
+ IKsReferenceClock * iface)
+{
+ LONGLONG Result;
+
+ IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+
+ DPRINT1("IKsReferenceClock_fnGetTime\n");
+
+ if (!This->ClockFileObject || !This->ClockTable.GetTime)
+ {
+ Result = 0;
+ }
+ else
+ {
+ Result = This->ClockTable.GetTime(This->ClockFileObject);
+ }
+
+ return Result;
+}
+
+LONGLONG
+NTAPI
+IKsReferenceClock_fnGetPhysicalTime(
+ IKsReferenceClock * iface)
+{
+ LONGLONG Result;
+
+ IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+ DPRINT1("IKsReferenceClock_fnGetPhysicalTime\n");
+
+
+ if (!This->ClockFileObject || !This->ClockTable.GetPhysicalTime)
+ {
+ Result = 0;
+ }
+ else
+ {
+ Result = This->ClockTable.GetPhysicalTime(This->ClockFileObject);
+ }
+
+ return Result;
+}
+
+
+LONGLONG
+NTAPI
+IKsReferenceClock_fnGetCorrelatedTime(
+ IKsReferenceClock * iface,
+ OUT PLONGLONG SystemTime)
+{
+ LONGLONG Result;
+
+ IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+ DPRINT1("IKsReferenceClock_fnGetCorrelatedTime\n");
+
+ if (!This->ClockFileObject || !This->ClockTable.GetCorrelatedTime)
+ {
+ Result = 0;
+ }
+ else
+ {
+ Result = This->ClockTable.GetCorrelatedTime(This->ClockFileObject, SystemTime);
+ }
+
+ return Result;
+}
+
+
+LONGLONG
+NTAPI
+IKsReferenceClock_fnGetCorrelatedPhysicalTime(
+ IKsReferenceClock * iface,
+ OUT PLONGLONG SystemTime)
+{
+ LONGLONG Result;
+
+ IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+ DPRINT1("IKsReferenceClock_fnGetCorrelatedPhysicalTime\n");
+
+ if (!This->ClockFileObject || !This->ClockTable.GetCorrelatedPhysicalTime)
+ {
+ Result = 0;
+ }
+ else
+ {
+ Result = This->ClockTable.GetCorrelatedPhysicalTime(This->ClockFileObject, SystemTime);
+ }
+
+ return Result;
+}
+
+NTSTATUS
+NTAPI
+IKsReferenceClock_fnGetResolution(
+ IKsReferenceClock * iface,
+ OUT PKSRESOLUTION Resolution)
+{
+ KSPROPERTY Property;
+ ULONG BytesReturned;
+
+ IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+ DPRINT1("IKsReferenceClock_fnGetResolution\n");
+
+ if (!This->ClockFileObject)
+ {
+ Resolution->Error = 0;
+ Resolution->Granularity = 1;
+ DPRINT1("IKsReferenceClock_fnGetResolution Using HACK\n");
+ return STATUS_SUCCESS;
+ }
+
+
+ if (!This->ClockFileObject)
+ return STATUS_DEVICE_NOT_READY;
+
+
+ Property.Set = KSPROPSETID_Clock;
+ Property.Id = KSPROPERTY_CLOCK_RESOLUTION;
+ Property.Flags = KSPROPERTY_TYPE_GET;
+
+ return KsSynchronousIoControlDevice(This->ClockFileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), Resolution, sizeof(KSRESOLUTION), &BytesReturned);
+
+}
+
+NTSTATUS
+NTAPI
+IKsReferenceClock_fnGetState(
+ IKsReferenceClock * iface,
+ OUT PKSSTATE State)
+{
+ KSPROPERTY Property;
+ ULONG BytesReturned;
+
+ IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+ DPRINT1("IKsReferenceClock_fnGetState\n");
+
+ if (!This->ClockFileObject)
+ {
+ *State = This->Pin.ClientState;
+ DPRINT1("IKsReferenceClock_fnGetState Using HACK\n");
+ return STATUS_SUCCESS;
+ }
+
+
+ if (!This->ClockFileObject)
+ return STATUS_DEVICE_NOT_READY;
+
+
+ Property.Set = KSPROPSETID_Clock;
+ Property.Id = KSPROPERTY_CLOCK_RESOLUTION;
+ Property.Flags = KSPROPERTY_TYPE_GET;
+
+ return KsSynchronousIoControlDevice(This->ClockFileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), State, sizeof(KSSTATE), &BytesReturned);
+}
+
+static IKsReferenceClockVtbl vt_ReferenceClock =
+{
+ IKsReferenceClock_fnQueryInterface,
+ IKsReferenceClock_fnAddRef,
+ IKsReferenceClock_fnRelease,
+ IKsReferenceClock_fnGetTime,
+ IKsReferenceClock_fnGetPhysicalTime,
+ IKsReferenceClock_fnGetCorrelatedTime,
+ IKsReferenceClock_fnGetCorrelatedPhysicalTime,
+ IKsReferenceClock_fnGetResolution,
+ IKsReferenceClock_fnGetState
+};
+
+
+//==============================================================
+
+
/*
@implemented
*/
}
/*
- @unimplemented
+ @implemented
*/
VOID
NTAPI
IN PKSPIN Pin,
IN PKSGATE AndGate OPTIONAL)
{
- UNIMPLEMENTED
+ IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+ /* FIXME attach to filter's and gate (filter-centric processing) */
+
+ This->AttachedGate = AndGate;
+ This->OrGate = FALSE;
}
/*
- @unimplemented
+ @implemented
*/
VOID
NTAPI
IN PKSPIN Pin,
IN PKSGATE OrGate OPTIONAL)
{
- UNIMPLEMENTED
+ IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+ /* FIXME attach to filter's and gate (filter-centric processing) */
+
+ This->AttachedGate = OrGate;
+ This->OrGate = TRUE;
+}
+
+/*
+ @implemented
+*/
+PKSGATE
+NTAPI
+KsPinGetAndGate(
+ IN PKSPIN Pin)
+{
+ IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+ return This->AttachedGate;
}
+
/*
@unimplemented
*/
IN PKSPIN Pin,
IN BOOLEAN Asynchronous)
{
+ DPRINT("KsPinAttemptProcessing\n");
+ DbgBreakPoint();
UNIMPLEMENTED
}
/*
@unimplemented
*/
-PKSGATE
-NTAPI
-KsPinGetAndGate(
- IN PKSPIN Pin)
-{
- UNIMPLEMENTED
- return NULL;
-}
-
-/*
- @implemented
-*/
PDEVICE_OBJECT
NTAPI
KsPinGetConnectedPinDeviceObject(
IN PKSPIN Pin)
{
- IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
-
- /* return related file object */
- return IoGetRelatedDeviceObject(This->FileObject);
+ UNIMPLEMENTED
+ return NULL;
}
/*
- @implemented
+ @unimplemented
*/
PFILE_OBJECT
NTAPI
KsPinGetConnectedPinFileObject(
IN PKSPIN Pin)
{
- IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
-
- return This->FileObject;
+ UNIMPLEMENTED
+ return NULL;
}
/*
- @implemented
+ @unimplemented
*/
NTSTATUS
NTAPI
IN const GUID* InterfaceId,
OUT PVOID* Interface)
{
- IKsPin * KsPin;
- IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
-
- /* get pin interface */
- KsPin = (IKsPin*)&This->lpVtbl;
-
- /* query pin interface for the requested interface */
- return KsPin->lpVtbl->QueryInterface(KsPin, InterfaceId, Interface);
+ UNIMPLEMENTED
+ return STATUS_NOT_IMPLEMENTED;
}
/*
}
/*
- @unimplemented
+ @implemented
*/
NTSTATUS
NTAPI
- KsPinGetReferenceClockInterface(
+KsPinGetReferenceClockInterface(
IN PKSPIN Pin,
OUT PIKSREFERENCECLOCK* Interface)
{
- UNIMPLEMENTED
- return STATUS_UNSUCCESSFUL;
+ NTSTATUS Status = STATUS_DEVICE_NOT_READY;
+ IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+ if (This->ClockFileObject)
+ {
+ /* clock is available */
+ *Interface = (PIKSREFERENCECLOCK)&This->lpVtblReferenceClock;
+ Status = STATUS_SUCCESS;
+ }
+
+ DPRINT("KsPinGetReferenceClockInterface Pin %p Interface %p Status %x\n", Pin, Interface, Status);
+ return Status;
}
/*
KeReleaseMutex(&This->ProcessingMutex, FALSE);
}
+/*
+ @implemented
+*/
+KSDDKAPI
+PKSPIN
+NTAPI
+KsGetPinFromIrp(
+ IN PIRP Irp)
+{
+ PKSIOBJECT_HEADER ObjectHeader;
+ PKSPIN Pin;
+ PKSBASIC_HEADER Header;
+ PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ DPRINT("KsGetPinFromIrp\n");
+
+ /* get object header */
+ ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
+
+ if (!ObjectHeader)
+ return NULL;
+
+ Pin = (PKSPIN)ObjectHeader->ObjectType;
+ Header = (PKSBASIC_HEADER)((ULONG_PTR)Pin - sizeof(KSBASIC_HEADER));
+
+ /* sanity check */
+ ASSERT(Header->Type == KsObjectTypePin);
+
+ /* return object type */
+ return Pin;
+}
+
+
+
/*
@unimplemented
*/
return FALSE;
}
+NTSTATUS
+IKsPin_PrepareStreamHeader(
+ IN IKsPinImpl * This,
+ IN PKSISTREAM_POINTER StreamPointer)
+{
+ PKSSTREAM_HEADER Header;
+ ULONG Length;
+
+ /* grab new irp */
+ StreamPointer->Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList, &This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
+ if (!StreamPointer->Irp)
+ {
+ /* run out of mappings */
+ DPRINT("OutOfMappings\n");
+ return STATUS_DEVICE_NOT_READY;
+ }
+
+ InterlockedDecrement(&This->IrpCount);
+ KsDecrementCountedWorker(This->PinWorker);
+
+ /* get stream header */
+ if (StreamPointer->Irp->RequestorMode == UserMode)
+ Header = (PKSSTREAM_HEADER)StreamPointer->Irp->AssociatedIrp.SystemBuffer;
+ else
+ Header = (PKSSTREAM_HEADER)StreamPointer->Irp->UserBuffer;
+
+ /* initialize stream pointer */
+ StreamPointer->Callback = NULL;
+ StreamPointer->Length = max(Header->DataUsed, Header->FrameExtent);
+ StreamPointer->Next = NULL;
+ StreamPointer->Offset = 0;
+ StreamPointer->Pin = &This->Pin;
+ StreamPointer->Data = Header->Data;
+
+ StreamPointer->StreamPointer.Context = NULL;
+ StreamPointer->StreamPointer.Pin = &This->Pin;
+ StreamPointer->StreamPointer.StreamHeader = Header;
+
+ if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN)
+ StreamPointer->StreamPointer.Offset = &StreamPointer->StreamPointer.OffsetIn;
+ else
+ StreamPointer->StreamPointer.Offset = &StreamPointer->StreamPointer.OffsetOut;
+
+ StreamPointer->StreamPointer.Offset->Alignment = 0;
+ StreamPointer->StreamPointer.Offset->Count = 0;
+ StreamPointer->StreamPointer.Offset->Data = NULL;
+ StreamPointer->StreamPointer.Offset->Remaining = 0;
+
+ ASSERT(StreamPointer->StreamPointer.Offset->Remaining == 0);
+
+ //StreamPointer->Offset += StreamPointer->StreamPointer.Offset->Count;
+
+ ASSERT(StreamPointer->Length > StreamPointer->Offset);
+ ASSERT(StreamPointer->StreamPointer.StreamHeader);
+ ASSERT(This->FrameSize);
+
+ /* calculate length */
+ /* TODO split into frames */
+ Length = StreamPointer->Length;
+
+ /* FIXME */
+ ASSERT(Length);
+
+ StreamPointer->StreamPointer.Offset->Alignment = 0;
+ StreamPointer->StreamPointer.Context = NULL;
+ StreamPointer->StreamPointer.Pin = &This->Pin;
+ StreamPointer->StreamPointer.Offset->Count = Length;
+ StreamPointer->StreamPointer.Offset->Remaining = Length;
+ StreamPointer->StreamPointer.Offset->Data = (PVOID)((ULONG_PTR)StreamPointer->Data + StreamPointer->Offset);
+ StreamPointer->StreamPointer.StreamHeader->FrameExtent = Length;
+ if (StreamPointer->StreamPointer.StreamHeader->DataUsed)
+ StreamPointer->StreamPointer.StreamHeader->DataUsed = Length;
+
+ StreamPointer->StreamPointer.StreamHeader->Data = StreamPointer->StreamPointer.Offset->Data;
+
+ return STATUS_SUCCESS;
+}
+
+
/*
@unimplemented
*/
IN PKSPIN Pin,
IN KSSTREAM_POINTER_STATE State)
{
- UNIMPLEMENTED
- return NULL;
+ IKsPinImpl * This;
+ NTSTATUS Status;
+
+ This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+ DPRINT("KsPinGetLeadingEdgeStreamPointer Pin %p State %x Count %lu Remaining %lu\n", Pin, State,
+ This->LeadingEdgeStreamPointer.Length,
+ This->LeadingEdgeStreamPointer.Offset);
+
+ /* sanity check */
+ ASSERT(State == KSSTREAM_POINTER_STATE_LOCKED);
+
+ if (State == KSSTREAM_POINTER_STATE_LOCKED)
+ {
+ if (!This->LeadingEdgeStreamPointer.Irp || This->LeadingEdgeStreamPointer.StreamPointer.Offset->Remaining == 0)
+ {
+ Status = IKsPin_PrepareStreamHeader(This, &This->LeadingEdgeStreamPointer);
+ if (!NT_SUCCESS(Status))
+ return NULL;
+ }
+
+ DPRINT("KsPinGetLeadingEdgeStreamPointer NewOffset %lu TotalLength %lu\n", This->LeadingEdgeStreamPointer.Offset, This->LeadingEdgeStreamPointer.Length);
+ }
+
+ return &This->LeadingEdgeStreamPointer.StreamPointer;
}
/*
IN PKSSTREAM_POINTER StreamPointer,
IN BOOLEAN Eject)
{
- UNIMPLEMENTED
+ PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
+
+ DPRINT("KsStreamPointerUnlock StreamPointer %pEject %lu\n", StreamPointer, Eject);
+
+ Pointer->Irp = NULL;
}
/*
IN ULONG OutUsed,
IN BOOLEAN Eject)
{
+ DPRINT("KsStreamPointerAdvanceOffsets InUsed %lu OutUsed %lu Eject %lu\n", InUsed, OutUsed, Eject);
+ DbgBreakPoint();
UNIMPLEMENTED
}
/*
- @unimplemented
+ @implemented
*/
KSDDKAPI
VOID
KsStreamPointerDelete(
IN PKSSTREAM_POINTER StreamPointer)
{
- UNIMPLEMENTED
+ IKsPinImpl * This;
+ PKSISTREAM_POINTER Cur, Last;
+ PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
+
+ DPRINT("KsStreamPointerDelete %p\n", Pointer);
+DbgBreakPoint();
+ This = (IKsPinImpl*)CONTAINING_RECORD(Pointer->StreamPointer.Pin, IKsPinImpl, Pin);
+
+ /* point to first stream pointer */
+ Last = NULL;
+ Cur = This->ClonedStreamPointer;
+
+ while(Cur != Pointer && Cur)
+ {
+ Last = Cur;
+ /* iterate to next cloned pointer */
+ Cur = Cur->Next;
+ }
+
+ if (!Cur)
+ {
+ /* you naughty driver */
+ return;
+ }
+
+ if (!Last)
+ {
+ /* remove first cloned pointer */
+ This->ClonedStreamPointer = Pointer->Next;
+ }
+ else
+ {
+ Last->Next = Pointer->Next;
+ }
+
+ /* FIXME make sure no timeouts are pending */
+ FreeItem(Pointer);
}
/*
- @unimplemented
+ @implemented
*/
KSDDKAPI
NTSTATUS
IN ULONG ContextSize,
OUT PKSSTREAM_POINTER* CloneStreamPointer)
{
- UNIMPLEMENTED
- return STATUS_NOT_IMPLEMENTED;
+ IKsPinImpl * This;
+ PKSISTREAM_POINTER CurFrame;
+ PKSISTREAM_POINTER NewFrame;
+ ULONG RefCount;
+ NTSTATUS Status;
+ ULONG Size;
+
+ DPRINT("KsStreamPointerClone StreamPointer %p CancelCallback %p ContextSize %p CloneStreamPointer %p\n", StreamPointer, CancelCallback, ContextSize, CloneStreamPointer);
+
+ /* 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)ExAllocatePool(NonPagedPool, Size);
+
+ if (!NewFrame)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* get current irp stack location */
+ RefCount = (ULONG)CurFrame->Irp->Tail.Overlay.DriverContext[0];
+
+ /* increment reference count */
+ RefCount++;
+ CurFrame->Irp->Tail.Overlay.DriverContext[0] = (PVOID)RefCount;
+
+ /* copy stream pointer */
+ 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;
+ }
+ }
+
+ 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;
}
/*
- @unimplemented
+ @implemented
*/
KSDDKAPI
NTSTATUS
IN ULONG OutUsed,
IN BOOLEAN Eject)
{
- UNIMPLEMENTED
- return STATUS_NOT_IMPLEMENTED;
+ PKSISTREAM_POINTER CurFrame;
+ IKsPinImpl * This;
+ NTSTATUS Status;
+
+ DPRINT("KsStreamPointerAdvanceOffsets StreamPointer %p InUsed %lu OutUsed %lu Eject %lu\n", StreamPointer, InUsed, OutUsed, Eject);
+
+ /* get stream pointer */
+ CurFrame = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
+
+ /* locate pin */
+ This = (IKsPinImpl*)CONTAINING_RECORD(CurFrame->Pin, IKsPinImpl, Pin);
+
+ /* TODO */
+ ASSERT(InUsed == 0);
+ ASSERT(Eject == 0);
+ ASSERT(OutUsed);
+
+ DPRINT("KsStreamPointerAdvanceOffsets Offset %lu Length %lu NewOffset %lu Remaining %lu LeadingEdge %p DataUsed %lu\n", CurFrame->Offset, CurFrame->Length, CurFrame->Offset + OutUsed,
+CurFrame->StreamPointer.OffsetOut.Remaining, &This->LeadingEdgeStreamPointer.StreamPointer, CurFrame->StreamPointer.StreamHeader->DataUsed);
+DbgBreakPoint();
+
+ if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN)
+ {
+ ASSERT(CurFrame->StreamPointer.OffsetIn.Remaining >= InUsed);
+ CurFrame->StreamPointer.OffsetIn.Remaining -= InUsed;
+ CurFrame->StreamPointer.OffsetIn.Data = (PVOID)((ULONG_PTR)CurFrame->StreamPointer.OffsetIn.Data + InUsed);
+ }
+ else
+ {
+ if (!CurFrame->StreamPointer.OffsetOut.Remaining)
+ {
+ Status = IKsPin_PrepareStreamHeader(This, CurFrame);
+ if (!NT_SUCCESS(Status))
+ {
+ return STATUS_DEVICE_NOT_READY;
+ }
+ }
+ else
+ {
+ ASSERT(CurFrame->StreamPointer.OffsetOut.Remaining >= OutUsed);
+ CurFrame->StreamPointer.OffsetOut.Remaining -= OutUsed;
+ CurFrame->StreamPointer.OffsetOut.Data = (PVOID)((ULONG_PTR)CurFrame->StreamPointer.OffsetOut.Data + OutUsed);
+ }
+ }
+
+ return STATUS_SUCCESS;
}
/*
IN PKSSTREAM_POINTER StreamPointer)
{
UNIMPLEMENTED
+ DbgBreakPoint();
return STATUS_NOT_IMPLEMENTED;
}
}
/*
- @unimplemented
+ @implemented
*/
KSDDKAPI
VOID
IN PFNKSSTREAMPOINTER Callback,
IN ULONGLONG Interval)
{
- UNIMPLEMENTED
+ LARGE_INTEGER DueTime;
+ PKSISTREAM_POINTER Pointer;
+
+ /* get stream pointer */
+ Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
+
+ /* setup timer callback */
+ Pointer->Callback = Callback;
+
+ /* setup expiration */
+ DueTime.QuadPart = (LONGLONG)Interval;
+
+ /* setup the timer */
+ KeSetTimer(&Pointer->Timer, DueTime, &Pointer->TimerDpc);
+
}
/*
- @unimplemented
+ @implemented
*/
KSDDKAPI
VOID
KsStreamPointerCancelTimeout(
IN PKSSTREAM_POINTER StreamPointer)
{
- UNIMPLEMENTED
+ PKSISTREAM_POINTER Pointer;
+
+ /* get stream pointer */
+ Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
+
+ KeCancelTimer(&Pointer->Timer);
+
}
/*
- @unimplemented
+ @implemented
*/
KSDDKAPI
PKSSTREAM_POINTER
KsPinGetFirstCloneStreamPointer(
IN PKSPIN Pin)
{
- UNIMPLEMENTED
- return NULL;
+ IKsPinImpl * This;
+
+ DPRINT("KsPinGetFirstCloneStreamPointer %p\n", Pin);
+
+ This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+ if (!This->ClonedStreamPointer)
+ return NULL;
+
+ /* return first cloned stream pointer */
+ return &This->ClonedStreamPointer->StreamPointer;
}
/*
- @unimplemented
+ @implemented
*/
KSDDKAPI
PKSSTREAM_POINTER
KsStreamPointerGetNextClone(
IN PKSSTREAM_POINTER StreamPointer)
{
- UNIMPLEMENTED
- return NULL;
+ PKSISTREAM_POINTER Pointer;
+
+ DPRINT("KsStreamPointerGetNextClone\n");
+DbgBreakPoint();
+ /* get stream pointer */
+ Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
+
+ /* is there a another cloned stream pointer */
+ if (!Pointer->Next)
+ return NULL;
+
+ /* return next stream pointer */
+ return &Pointer->Next->StreamPointer;
+}
+
+VOID
+NTAPI
+IKsPin_PinCentricWorker(
+ IN PVOID Parameter)
+{
+ NTSTATUS Status;
+ IKsPinImpl * This = (IKsPinImpl*)Parameter;
+
+ DPRINT("IKsPin_PinCentricWorker\n");
+
+ /* sanity checks */
+ ASSERT(This);
+ ASSERT(This->Pin.Descriptor);
+ ASSERT(This->Pin.Descriptor->Dispatch);
+ ASSERT(This->Pin.Descriptor->Dispatch->Process);
+ ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
+ ASSERT(!(This->Pin.Descriptor->Flags & KSPIN_FLAG_DISPATCH_LEVEL_PROCESSING));
+ ASSERT(!(This->Pin.Descriptor->Flags & KSPIN_FLAG_GENERATE_MAPPINGS));
+
+ do
+ {
+ DPRINT("IKsPin_PinCentricWorker calling Pin Process Routine\n");
+
+ Status = This->Pin.Descriptor->Dispatch->Process(&This->Pin);
+ DPRINT("IKsPin_PinCentricWorker Status %lx, Offset %lu Length %lu\n", Status,
+ This->LeadingEdgeStreamPointer.Offset,
+ This->LeadingEdgeStreamPointer.Length);
+ break;
+
+ }while(This->IrpCount);
+}
+
+
+NTSTATUS
+NTAPI
+IKsPin_DispatchKsStream(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ IKsPinImpl * This)
+{
+ PKSPROCESSPIN_INDEXENTRY ProcessPinIndex;
+ PKSSTREAM_HEADER Header;
+ ULONG NumHeaders;
+ PKSFILTER Filter;
+ PIO_STACK_LOCATION IoStack;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ DPRINT("IKsPin_DispatchKsStream\n");
+
+ /* FIXME handle reset states */
+ ASSERT(This->Pin.ResetState == KSRESET_END);
+
+ /* get current stack location */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ /* probe stream pointer */
+ if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM)
+ Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, This->Pin.StreamHeaderSize);
+ else
+ Status = KsProbeStreamIrp(Irp, KSSTREAM_READ | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, This->Pin.StreamHeaderSize);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("KsProbeStreamIrp failed with %x\n", Status);
+
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+
+ if (Irp->RequestorMode == UserMode)
+ Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
+ else
+ Header = (PKSSTREAM_HEADER)Irp->UserBuffer;
+
+ if (!Header)
+ {
+ DPRINT("NoHeader Canceling Irp %p\n", Irp);
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+
+ /* calculate num headers */
+ NumHeaders = IoStack->Parameters.DeviceIoControl.OutputBufferLength / Header->Size;
+
+ /* assume headers of same length */
+ ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength % Header->Size == 0);
+
+ /* FIXME support multiple stream headers */
+ ASSERT(NumHeaders == 1);
+
+ if (Irp->RequestorMode == UserMode)
+ {
+ /* prepare header */
+ ASSERT(Irp->MdlAddress);
+ Header->Data = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+
+ if (!Header->Data)
+ {
+ DPRINT("NoHeader->Data Canceling Irp %p\n", Irp);
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+
+ }
+
+
+
+ if (This->Pin.Descriptor->Dispatch->Process)
+ {
+ /* it is a pin centric avstream */
+
+ /* mark irp as pending */
+ IoMarkIrpPending(Irp);
+
+ /* add irp to cancelable queue */
+ KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */);
+
+ /* sanity checks */
+ ASSERT(!(This->Pin.Descriptor->Flags & KSPIN_FLAG_DISPATCH_LEVEL_PROCESSING));
+ ASSERT(This->PinWorker);
+
+ InterlockedIncrement(&This->IrpCount);
+
+ DPRINT("IKsPin_DispatchKsStream IrpCount %lu\n", This->IrpCount);
+
+ /* start the processing loop */
+ KsIncrementCountedWorker(This->PinWorker);
+
+ Status = STATUS_PENDING;
+ }
+ else
+ {
+ /* filter-centric avstream */
+ ASSERT(This->Filter);
+
+ ProcessPinIndex = This->Filter->lpVtbl->GetProcessDispatch(This->Filter);
+ Filter = This->Filter->lpVtbl->GetStruct(This->Filter);
+
+ ASSERT(ProcessPinIndex);
+ ASSERT(Filter);
+ ASSERT(Filter->Descriptor);
+ ASSERT(Filter->Descriptor->Dispatch);
+
+ if (!Filter->Descriptor->Dispatch->Process)
+ {
+ /* invalid device request */
+ DPRINT("Filter Centric Processing No Process Routine\n");
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* mark irp as pending */
+ IoMarkIrpPending(Irp);
+
+ /* add irp to cancelable queue */
+ KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */);
+
+ Status = Filter->Descriptor->Dispatch->Process(Filter, ProcessPinIndex);
+
+ DPRINT("IKsPin_DispatchKsStream FilterCentric: Status %lx \n", Status);
+
+ }
+
+ return Status;
}
NTSTATUS
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- UNIMPLEMENTED;
+ PIO_STACK_LOCATION IoStack;
+ PKSIOBJECT_HEADER ObjectHeader;
+ IKsPinImpl * This;
+ NTSTATUS Status;
+ UNICODE_STRING GuidString;
+ PKSPROPERTY Property;
+ ULONG SetCount = 0;
- Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_NOT_IMPLEMENTED;
+ /* get current irp stack */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ /* sanity check */
+ ASSERT(IoStack->FileObject);
+ ASSERT(IoStack->FileObject->FsContext2);
+
+ /* get the object header */
+ ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
+
+ /* locate ks pin implemention from KSPIN offset */
+ This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
+
+ /* current irp stack */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM ||
+ IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM)
+ {
+ /* handle ks stream packets */
+ return IKsPin_DispatchKsStream(DeviceObject, Irp, This);
+ }
+
+ /* get property from input buffer */
+ Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+
+ /* sanity check */
+ ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSIDENTIFIER));
+ ASSERT(This->Pin.Descriptor->AutomationTable);
+
+ RtlStringFromGUID(&Property->Set, &GuidString);
+ DPRINT("IKsPin_DispatchDeviceIoControl property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
+ RtlFreeUnicodeString(&GuidString);
+
+
+ if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_METHOD)
+ {
+ const KSMETHOD_SET *MethodSet = NULL;
+ ULONG MethodItemSize = 0;
+
+ /* check if the driver supports method sets */
+ if (This->Pin.Descriptor->AutomationTable->MethodSetsCount)
+ {
+ SetCount = This->Pin.Descriptor->AutomationTable->MethodSetsCount;
+ MethodSet = This->Pin.Descriptor->AutomationTable->MethodSets;
+ MethodItemSize = This->Pin.Descriptor->AutomationTable->MethodItemSize;
+ }
+
+ /* call method set handler */
+ Status = KspMethodHandlerWithAllocator(Irp, SetCount, MethodSet, NULL, MethodItemSize);
+ }
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
+ {
+ const KSPROPERTY_SET *PropertySet = NULL;
+ ULONG PropertyItemSize = 0;
+
+ /* check if the driver supports method sets */
+ if (This->Pin.Descriptor->AutomationTable->PropertySetsCount)
+ {
+ SetCount = This->Pin.Descriptor->AutomationTable->PropertySetsCount;
+ PropertySet = This->Pin.Descriptor->AutomationTable->PropertySets;
+ PropertyItemSize = This->Pin.Descriptor->AutomationTable->PropertyItemSize;
+ }
+
+ /* needed for our property handlers */
+ KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (KSPROPERTY_ITEM*)This;
+
+ /* call property handler */
+ Status = KspPropertyHandler(Irp, SetCount, PropertySet, NULL, PropertyItemSize);
+ }
+ else
+ {
+ /* sanity check */
+ ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT ||
+ IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT);
+
+ if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
+ {
+ /* call enable event handlers */
+ Status = KspEnableEvent(Irp,
+ This->Pin.Descriptor->AutomationTable->EventSetsCount,
+ (PKSEVENT_SET)This->Pin.Descriptor->AutomationTable->EventSets,
+ &This->BasicHeader.EventList,
+ KSEVENTS_SPINLOCK,
+ (PVOID)&This->BasicHeader.EventListLock,
+ NULL,
+ This->Pin.Descriptor->AutomationTable->EventItemSize);
+ }
+ else
+ {
+ /* disable event handler */
+ Status = KsDisableEvent(Irp, &This->BasicHeader.EventList, KSEVENTS_SPINLOCK, &This->BasicHeader.EventListLock);
+ }
+ }
+
+ RtlStringFromGUID(&Property->Set, &GuidString);
+ DPRINT("IKsPin_DispatchDeviceIoControl property Set |%S| Id %u Flags %x Status %lx ResultLength %lu\n", GuidString.Buffer, Property->Id, Property->Flags, Status, Irp->IoStatus.Information);
+ RtlFreeUnicodeString(&GuidString);
+
+ if (Status != STATUS_PENDING)
+ {
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+
+ /* done */
+ return Status;
}
NTSTATUS
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- UNIMPLEMENTED;
+ PIO_STACK_LOCATION IoStack;
+ PKSIOBJECT_HEADER ObjectHeader;
+ IKsPinImpl * This;
+ NTSTATUS Status = STATUS_SUCCESS;
- Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_NOT_IMPLEMENTED;
+ /* get current irp stack */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ /* sanity check */
+ ASSERT(IoStack->FileObject);
+ ASSERT(IoStack->FileObject->FsContext2);
+
+ /* get the object header */
+ ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
+
+ /* locate ks pin implemention fro KSPIN offset */
+ This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
+
+ if (This->Pin.Descriptor->Dispatch->Close)
+ {
+ /* call pin close routine */
+ Status = This->Pin.Descriptor->Dispatch->Close(&This->Pin, Irp);
+
+ if (!NT_SUCCESS(Status))
+ {
+ /* abort closing */
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+
+ /* remove pin from filter pin list and decrement reference count */
+ IKsFilter_RemovePin(This->Filter->lpVtbl->GetStruct(This->Filter), &This->Pin);
+
+ if (Status != STATUS_PENDING)
+ {
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+ }
+
+ return Status;
}
NTSTATUS
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- UNIMPLEMENTED;
+ PKSPIN Pin;
+ NTSTATUS Status = STATUS_SUCCESS;
+ IKsPinImpl * This;
+ KSRESOLUTION Resolution;
+ PKSRESOLUTION pResolution = NULL;
+ PKSOBJECT_CREATE_ITEM CreateItem;
- Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+ DPRINT("IKsPin_DispatchCreateClock\n");
+
+ /* get the create item */
+ CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
+
+ /* sanity check */
+ ASSERT(CreateItem);
+
+ /* get the pin object */
+ Pin = (PKSPIN)CreateItem->Context;
+
+ /* sanity check */
+ ASSERT(Pin);
+
+ /* locate ks pin implemention fro KSPIN offset */
+ This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+ /* sanity check */
+ ASSERT(This->BasicHeader.Type == KsObjectTypePin);
+ ASSERT(This->BasicHeader.ControlMutex);
+
+ /* acquire control mutex */
+ KsAcquireControl(Pin);
+
+ if ((This->Pin.Descriptor->PinDescriptor.Communication != KSPIN_COMMUNICATION_NONE &&
+ This->Pin.Descriptor->Dispatch) ||
+ (This->Pin.Descriptor->Flags & KSPIN_FLAG_IMPLEMENT_CLOCK))
+ {
+ if (!This->DefaultClock)
+ {
+ if (This->Pin.Descriptor->Dispatch && This->Pin.Descriptor->Dispatch->Clock)
+ {
+ if (This->Pin.Descriptor->Dispatch->Clock->Resolution)
+ {
+ This->Pin.Descriptor->Dispatch->Clock->Resolution(&This->Pin, &Resolution);
+ pResolution = &Resolution;
+ }
+
+ Status = KsAllocateDefaultClockEx(&This->DefaultClock,
+ (PVOID)&This->Pin,
+ (PFNKSSETTIMER)This->Pin.Descriptor->Dispatch->Clock->SetTimer,
+ (PFNKSCANCELTIMER)This->Pin.Descriptor->Dispatch->Clock->CancelTimer,
+ (PFNKSCORRELATEDTIME)This->Pin.Descriptor->Dispatch->Clock->CorrelatedTime,
+ pResolution,
+ 0);
+ }
+ else
+ {
+ Status = KsAllocateDefaultClockEx(&This->DefaultClock, (PVOID)&This->Pin, NULL, NULL, NULL, NULL, 0);
+ }
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ Status = KsCreateDefaultClock(Irp, This->DefaultClock);
+ }
+ }
+
+ DPRINT("IKsPin_DispatchCreateClock %lx\n", Status);
+
+ /* release control mutex */
+ KsReleaseControl(Pin);
+
+ /* done */
+ Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_NOT_IMPLEMENTED;
+ return Status;
}
NTSTATUS
KsDispatchFastReadFailure
};
-
NTSTATUS
KspCreatePin(
IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp,
+ IN PIRP Irp,
IN PKSDEVICE KsDevice,
IN IKsFilterFactory * FilterFactory,
IN IKsFilter* Filter,
PDEVICE_EXTENSION DeviceExtension;
PKSOBJECT_CREATE_ITEM CreateItem;
NTSTATUS Status;
+ PKSDATAFORMAT DataFormat;
+ PKSBASIC_HEADER BasicHeader;
+ ULONG Index;
+ ULONG FrameSize = 0;
+ ULONG NumFrames = 0;
+ KSAUTOMATION_TABLE AutomationTable;
/* sanity checks */
ASSERT(Descriptor->Dispatch);
- ASSERT(Descriptor->Dispatch->Create);
+
+ DPRINT("KspCreatePin PinId %lu Flags %x\n", Connect->PinId, Descriptor->Flags);
+
+//Output Pin: KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY
+//Input Pin: KSPIN_FLAG_FIXED_FORMAT|KSPIN_FLAG_DO_NOT_USE_STANDARD_TRANSPORT|KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING
+
+ DPRINT("KspCreatePin Dataflow %lu\n", Descriptor->PinDescriptor.DataFlow);
+ DPRINT("KspCreatePin Communication %lu\n", Descriptor->PinDescriptor.Communication);
+ if (Descriptor->AllocatorFraming)
+ {
+ DPRINT("KspCreatePin CountItems %lu\n", Descriptor->AllocatorFraming->CountItems);
+ DPRINT("KspCreatePin PinFlags %lx\n", Descriptor->AllocatorFraming->PinFlags);
+ DPRINT("KspCreatePin OutputCompression RatioNumerator %lu RatioDenominator %lu RatioConstantMargin %lu\n", Descriptor->AllocatorFraming->OutputCompression.RatioNumerator,
+ Descriptor->AllocatorFraming->OutputCompression.RatioDenominator, Descriptor->AllocatorFraming->OutputCompression.RatioConstantMargin);
+ DPRINT("KspCreatePin PinWeight %lx\n", Descriptor->AllocatorFraming->PinWeight);
+
+ for(Index = 0; Index < Descriptor->AllocatorFraming->CountItems; Index++)
+ {
+ DPRINT("KspCreatePin Index %lu MemoryFlags %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].MemoryFlags);
+ DPRINT("KspCreatePin Index %lu BusFlags %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].BusFlags);
+ DPRINT("KspCreatePin Index %lu Flags %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].Flags);
+ DPRINT("KspCreatePin Index %lu Frames %lu\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].Frames);
+ DPRINT("KspCreatePin Index %lu FileAlignment %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].FileAlignment);
+ DPRINT("KspCreatePin Index %lu MemoryTypeWeight %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].MemoryTypeWeight);
+ DPRINT("KspCreatePin Index %lu PhysicalRange MinFrameSize %lu MaxFrameSize %lu Stepping %lu\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.MinFrameSize,
+ Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.MaxFrameSize,
+ Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.Stepping);
+
+ DPRINT("KspCreatePin Index %lu FramingRange MinFrameSize %lu MaxFrameSize %lu Stepping %lu InPlaceWeight %lu NotInPlaceWeight %lu\n",
+ Index,
+ Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.MinFrameSize,
+ Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.MaxFrameSize,
+ Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.Stepping,
+ Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.InPlaceWeight,
+ Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.NotInPlaceWeight);
+
+ FrameSize = Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.MaxFrameSize;
+ NumFrames = Descriptor->AllocatorFraming->FramingItem[Index].Frames;
+ }
+ }
+
+ for (Index = 0; Index < Descriptor->PinDescriptor.DataRangesCount; Index++)
+ {
+ UNICODE_STRING GuidString;
+ /* convert the guid to string */
+ RtlStringFromGUID(&Descriptor->PinDescriptor.DataRanges[Index]->MajorFormat, &GuidString);
+ DPRINT("Index %lu MajorFormat %S\n", Index, GuidString.Buffer);
+ RtlStringFromGUID(&Descriptor->PinDescriptor.DataRanges[Index]->SubFormat, &GuidString);
+ DPRINT("Index %lu SubFormat %S\n", Index, GuidString.Buffer);
+ RtlStringFromGUID(&Descriptor->PinDescriptor.DataRanges[Index]->Specifier, &GuidString);
+ DPRINT("Index %lu Specifier %S\n", Index, GuidString.Buffer);
+ RtlStringFromGUID(&Descriptor->PinDescriptor.DataRanges[Index]->Specifier, &GuidString);
+ DPRINT("Index %lu FormatSize %lu Flags %lu SampleSize %lu Reserved %lu KSDATAFORMAT %lu\n", Index,
+ Descriptor->PinDescriptor.DataRanges[Index]->FormatSize, Descriptor->PinDescriptor.DataRanges[Index]->Flags, Descriptor->PinDescriptor.DataRanges[Index]->SampleSize, Descriptor->PinDescriptor.DataRanges[Index]->Reserved, sizeof(KSDATAFORMAT));
+
+ if (IsEqualGUIDAligned(&Descriptor->PinDescriptor.DataRanges[Index]->SubFormat, &KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT))
+ {
+ PKS_DATARANGE_BDA_TRANSPORT Transport = (PKS_DATARANGE_BDA_TRANSPORT)&Descriptor->PinDescriptor.DataRanges[Index];
+ DPRINT("KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT AvgTimePerFrame %I64u ulcbPhyiscalFrame %lu ulcbPhyiscalFrameAlignment %lu ulcbPhyiscalPacket %lu\n", Transport->BdaTransportInfo.AvgTimePerFrame, Transport->BdaTransportInfo.ulcbPhyiscalFrame,
+ Transport->BdaTransportInfo.ulcbPhyiscalFrameAlignment, Transport->BdaTransportInfo.ulcbPhyiscalPacket);
+ }
+ }
+ if (!FrameSize)
+ {
+ /* default to 50 * 188 (MPEG2 TS packet size) */
+ FrameSize = 9400;
+ }
+
+ if (!NumFrames)
+ {
+ NumFrames = 8;
+ }
/* get current irp stack */
IoStack = IoGetCurrentIrpStackLocation(Irp);
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* get ks device interface */
- Device = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice;
+ Device = (IKsDevice*)&DeviceExtension->DeviceHeader->BasicHeader.OuterUnknown;
/* first allocate pin ctx */
This = AllocateItem(NonPagedPool, sizeof(IKsPinImpl));
{
/* not enough memory */
FreeItem(This);
+ DPRINT("KspCreatePin OutOfMemory\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
This->BasicHeader.KsDevice = KsDevice;
This->BasicHeader.Type = KsObjectTypePin;
This->BasicHeader.Parent.KsFilter = Filter->lpVtbl->GetStruct(Filter);
- KeInitializeMutex(&This->BasicHeader.ControlMutex, 0);
+ This->BasicHeader.OuterUnknown = (PUNKNOWN)&vt_IKsPin;
+ InitializeListHead(&This->BasicHeader.EventList);
+ KeInitializeSpinLock(&This->BasicHeader.EventListLock);
+
+ ASSERT(This->BasicHeader.Parent.KsFilter);
+
+ BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)This->BasicHeader.Parent.KsFilter - sizeof(KSBASIC_HEADER));
+
+ This->BasicHeader.ControlMutex = BasicHeader->ControlMutex;
+ ASSERT(This->BasicHeader.ControlMutex);
+
+ InitializeListHead(&This->BasicHeader.EventList);
+ KeInitializeSpinLock(&This->BasicHeader.EventListLock);
/* initialize pin */
- This->lpVtbl = &vt_IKsPin;
+ This->FrameSize = FrameSize;
+ This->NumFrames = NumFrames;
+ This->lpVtblReferenceClock = &vt_ReferenceClock;
This->ref = 1;
This->FileObject = IoStack->FileObject;
+ This->Filter = Filter;
KeInitializeMutex(&This->ProcessingMutex, 0);
-
- /* initialize ks pin descriptor */
- This->Pin.Descriptor = Descriptor;
- This->Pin.Id = Connect->PinId;
+ InitializeListHead(&This->IrpList);
+ KeInitializeSpinLock(&This->IrpListLock);
/* allocate object bag */
This->Pin.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
}
/* initialize object bag */
- Device->lpVtbl->InitializeObjectBag(Device, This->Pin.Bag, &This->BasicHeader.ControlMutex); /* is using control mutex right? */
+ Device->lpVtbl->InitializeObjectBag(Device, This->Pin.Bag, NULL);
+
+ /* allocate pin descriptor */
+ This->Pin.Descriptor = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR_EX));
+ if (!This->Pin.Descriptor)
+ {
+ /* not enough memory */
+ KsFreeObjectBag(This->Pin.Bag);
+ FreeItem(This);
+ FreeItem(CreateItem);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ /* copy pin descriptor */
+ RtlMoveMemory((PVOID)This->Pin.Descriptor, Descriptor, sizeof(KSPIN_DESCRIPTOR_EX));
+
+ /* initialize automation table */
+ RtlZeroMemory(&AutomationTable, sizeof(KSAUTOMATION_TABLE));
+
+ AutomationTable.PropertyItemSize = sizeof(KSPROPERTY_ITEM);
+ AutomationTable.PropertySets = PinPropertySet;
+ AutomationTable.PropertySetsCount = sizeof(PinPropertySet) / sizeof(KSPROPERTY_SET);
+
+ /* merge in pin property sets */
+ Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&This->Pin.Descriptor->AutomationTable, (PKSAUTOMATION_TABLE)Descriptor->AutomationTable, &AutomationTable, This->Pin.Bag);
+
+ if (!NT_SUCCESS(Status))
+ {
+ /* not enough memory */
+ KsFreeObjectBag(This->Pin.Bag);
+ FreeItem(This);
+ FreeItem(CreateItem);
+ return Status;
+ }
+
+ /* get format */
+ DataFormat = (PKSDATAFORMAT)(Connect + 1);
+
+ /* initialize pin descriptor */
+ This->Pin.Context = NULL;
+ This->Pin.Id = Connect->PinId;
This->Pin.Communication = Descriptor->PinDescriptor.Communication;
- This->Pin.ConnectionIsExternal = FALSE; /* FIXME */
- //FIXME This->Pin.ConnectionInterface = Descriptor->PinDescriptor.Interfaces;
- //FIXME This->Pin.ConnectionMedium = Descriptor->PinDescriptor.Mediums;
- //FIXME This->Pin.ConnectionPriority = KSPRIORITY_NORMAL;
- This->Pin.ConnectionFormat = (PKSDATAFORMAT) (Connect + 1);
+ This->Pin.ConnectionIsExternal = FALSE; //FIXME
+ RtlMoveMemory(&This->Pin.ConnectionInterface, &Connect->Interface, sizeof(KSPIN_INTERFACE));
+ RtlMoveMemory(&This->Pin.ConnectionMedium, &Connect->Medium, sizeof(KSPIN_MEDIUM));
+ RtlMoveMemory(&This->Pin.ConnectionPriority, &Connect->Priority, sizeof(KSPRIORITY));
+
+ /* allocate format */
+ Status = _KsEdit(This->Pin.Bag, (PVOID*)&This->Pin.ConnectionFormat, DataFormat->FormatSize, DataFormat->FormatSize, 0);
+ if (!NT_SUCCESS(Status))
+ {
+ /* failed to allocate format */
+ KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
+ FreeItem(This);
+ FreeItem(CreateItem);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* copy format */
+ RtlMoveMemory((PVOID)This->Pin.ConnectionFormat, DataFormat, DataFormat->FormatSize);
+
This->Pin.AttributeList = NULL; //FIXME
This->Pin.StreamHeaderSize = sizeof(KSSTREAM_HEADER);
This->Pin.DataFlow = Descriptor->PinDescriptor.DataFlow;
This->Pin.ClientState = KSSTATE_STOP;
/* intialize allocator create item */
- CreateItem[0].Context = (PVOID)This;
+ CreateItem[0].Context = (PVOID)&This->Pin;
CreateItem[0].Create = IKsPin_DispatchCreateAllocator;
CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Allocator);
/* intialize clock create item */
- CreateItem[1].Context = (PVOID)This;
+ CreateItem[1].Context = (PVOID)&This->Pin;
CreateItem[1].Create = IKsPin_DispatchCreateClock;
CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_Clock);
/* intialize topology node create item */
- CreateItem[2].Context = (PVOID)This;
+ CreateItem[2].Context = (PVOID)&This->Pin;
CreateItem[2].Create = IKsPin_DispatchCreateNode;
CreateItem[2].Flags = KSCREATE_ITEM_FREEONSTOP;
RtlInitUnicodeString(&CreateItem[2].ObjectClass, KSSTRING_TopologyNode);
if (!NT_SUCCESS(Status))
{
/* failed to create object header */
+ DPRINT("KspCreatePin KsAllocateObjectHeader failed %lx\n", Status);
KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
FreeItem(This);
FreeItem(CreateItem);
/* add extra info to object header */
This->ObjectHeader->Type = KsObjectTypePin;
- This->ObjectHeader->Unknown = (PUNKNOWN)&This->lpVtbl;
+ This->ObjectHeader->Unknown = (PUNKNOWN)&This->BasicHeader.OuterUnknown;
This->ObjectHeader->ObjectType = (PVOID)&This->Pin;
- /* now inform the driver to create a new pin */
- Status = Descriptor->Dispatch->Create(&This->Pin, Irp);
+ if (!Descriptor->Dispatch || !Descriptor->Dispatch->Process)
+ {
+ /* the pin is part of filter-centric processing filter
+ * add process pin to filter
+ */
+ This->ProcessPin.BytesAvailable = 0;
+ This->ProcessPin.BytesUsed = 0;
+ This->ProcessPin.CopySource = NULL;
+ This->ProcessPin.Data = NULL;
+ This->ProcessPin.DelegateBranch = NULL;
+ This->ProcessPin.Flags = 0;
+ This->ProcessPin.InPlaceCounterpart = NULL;
+ This->ProcessPin.Pin = &This->Pin;
+ This->ProcessPin.StreamPointer = (PKSSTREAM_POINTER)&This->LeadingEdgeStreamPointer.StreamPointer;
+ This->ProcessPin.Terminate = FALSE;
+
+ Status = Filter->lpVtbl->AddProcessPin(Filter, &This->ProcessPin);
+ DPRINT("KspCreatePin AddProcessPin %lx\n", Status);
+
+ if (!NT_SUCCESS(Status))
+ {
+ /* failed to add process pin */
+ KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
+ KsFreeObjectHeader(&This->ObjectHeader);
+ FreeItem(This);
+ FreeItem(CreateItem);
+ /* return failure code */
+ return Status;
+ }
+ }
+ else if (Descriptor->Dispatch && Descriptor->Dispatch->Process)
+ {
+ /* pin centric processing filter */
+
+ /* initialize work item */
+ ExInitializeWorkItem(&This->PinWorkQueueItem, IKsPin_PinCentricWorker, (PVOID)This);
+
+ /* allocate counted work item */
+ Status = KsRegisterCountedWorker(HyperCriticalWorkQueue, &This->PinWorkQueueItem, &This->PinWorker);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Failed to register Worker %lx\n", Status);
+ KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
+ KsFreeObjectHeader(&This->ObjectHeader);
+ FreeItem(This);
+ FreeItem(CreateItem);
+ return Status;
+ }
+
+ if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN)
+ This->LeadingEdgeStreamPointer.StreamPointer.Offset = &This->LeadingEdgeStreamPointer.StreamPointer.OffsetIn;
+ else
+ This->LeadingEdgeStreamPointer.StreamPointer.Offset = &This->LeadingEdgeStreamPointer.StreamPointer.OffsetOut;
+
+
+ KeInitializeEvent(&This->FrameComplete, NotificationEvent, FALSE);
+
+ }
+
+ /* FIXME add pin instance to filter instance */
+ IKsFilter_AddPin(Filter->lpVtbl->GetStruct(Filter), &This->Pin);
+
+ if (Descriptor->Dispatch && Descriptor->Dispatch->SetDataFormat)
+ {
+ Status = Descriptor->Dispatch->SetDataFormat(&This->Pin, NULL, NULL, This->Pin.ConnectionFormat, NULL);
+ DPRINT("KspCreatePin SetDataFormat %lx\n", Status);
+ }
+
+
+ /* does the driver have a pin dispatch */
+ if (Descriptor->Dispatch && Descriptor->Dispatch->Create)
+ {
+ /* now inform the driver to create a new pin */
+ Status = Descriptor->Dispatch->Create(&This->Pin, Irp);
+ DPRINT("KspCreatePin DispatchCreate %lx\n", Status);
+ }
+
+
+ DPRINT("KspCreatePin Status %lx KsDevice %p\n", Status, KsDevice);
if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
{
/* failed to create pin, release resources */
+ IKsFilter_RemovePin(Filter->lpVtbl->GetStruct(Filter), &This->Pin);
KsFreeObjectHeader((KSOBJECT_HEADER)This->ObjectHeader);
KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
FreeItem(This);
return Status;
}
- /* FIXME add pin instance to filter instance */
-
return Status;
}