- Start Implementing IKsPin interface
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Wed, 29 Jul 2009 09:48:36 +0000 (09:48 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Wed, 29 Jul 2009 09:48:36 +0000 (09:48 +0000)
- Increment PinInstanceCount when a pin has succcessfully been created
- Implement KsPinAcquireProcessingMutex, KsPinGetConnectedPinDeviceObject, KsPinGetConnectedFileObject, KsPinGetConnectedPinInterface, KsPinGetNextSiblingPin, KsPinGetParentFilter, KsPinRegisterFrameReturnCallback, KsPinRegisterHandshakeCallback, KsPinRegisterIrpCompletionCallback, KsPinRegisterPowerCallbacks, KsPinReleaseProcessingMutex
- Initialize pin dispatch table
- Add create items for allocator, clock, node create requests
- AVStream clients should now be able to instantiated pins, streaming not yet supported

svn path=/trunk/; revision=42283

reactos/drivers/ksfilter/ks/filter.c
reactos/drivers/ksfilter/ks/ksfunc.h
reactos/drivers/ksfilter/ks/ksiface.h
reactos/drivers/ksfilter/ks/pin.c

index 3467fc5..2167bae 100644 (file)
@@ -924,8 +924,22 @@ IKsFilter_DispatchCreatePin(
 
     if (NT_SUCCESS(Status))
     {
-        /* create the pin */
-        Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->lpVtbl, Connect);
+        if (This->PinInstanceCount[Connect->PinId] < This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible)
+        {
+            /* create the pin */
+            Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->lpVtbl, Connect, (KSPIN_DESCRIPTOR_EX*)&This->Filter.Descriptor->PinDescriptors[Connect->PinId]);
+
+            if (NT_SUCCESS(Status))
+            {
+                /* successfully created pin, increment pin instance count */
+                This->PinInstanceCount[Connect->PinId]++;
+            }
+        }
+        else
+        {
+            /* maximum instance count reached, bye-bye */
+            Status = STATUS_UNSUCCESSFUL;
+        }
     }
 
     /* release control mutex */
@@ -1040,11 +1054,13 @@ KspCreateFilter(
     This->Factory = Factory;
     This->FilterFactory = iface;
     This->FileObject = IoStack->FileObject;
+    KeInitializeMutex(&This->ProcessingMutex, 0);
+    /* initialize basic header */
     This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
     This->Header.Parent.KsFilterFactory = iface->lpVtbl->GetStruct(iface);
     This->Header.Type = KsObjectTypeFilter;
     KeInitializeMutex(&This->Header.ControlMutex, 0);
-    KeInitializeMutex(&This->ProcessingMutex, 0);
+
 
 
     /* allocate the stream descriptors */
@@ -1095,9 +1111,7 @@ KspCreateFilter(
         return Status;
     }
 
-    /* initialize object header */
-    This->Header.Type = KsObjectTypeFilter;
-    This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
+    /* initialize object header extra fields */
     This->ObjectHeader->Type = KsObjectTypeFilter;
     This->ObjectHeader->Unknown = (PUNKNOWN)&This->lpVtbl;
     This->ObjectHeader->ObjectType = (PVOID)&This->Filter;
index 5a3ea48..68508e5 100644 (file)
@@ -121,7 +121,8 @@ KspCreatePin(
     IN PKSDEVICE KsDevice,
     IN IKsFilterFactory * FilterFactory, 
     IN IKsFilter* Filter,
-    IN PKSPIN_CONNECT Connect);
+    IN PKSPIN_CONNECT Connect,
+    IN KSPIN_DESCRIPTOR_EX* Descriptor);
 
 
 #endif
index 3078f56..a69848e 100644 (file)
@@ -62,6 +62,20 @@ DECLARE_INTERFACE_(IKsClock, IUnknown)
     DEFINE_ABSTRACT_UNKNOWN()
 };
 
+/*****************************************************************************
+ * IKsTransport
+ *****************************************************************************
+ */
+
+#undef INTERFACE
+#define INTERFACE IKsTransport
+
+DECLARE_INTERFACE_(IKsTransport, IUnknown)
+{
+    DEFINE_ABSTRACT_UNKNOWN()
+};
+
+
 /*****************************************************************************
  * IKsPin
  *****************************************************************************
@@ -70,9 +84,60 @@ DECLARE_INTERFACE_(IKsClock, IUnknown)
 #undef INTERFACE
 #define INTERFACE IKsPin
 
+struct KSPTRANSPORTCONFIG;
+
 DECLARE_INTERFACE_(IKsPin, IUnknown)
 {
     DEFINE_ABSTRACT_UNKNOWN()
+
+    STDMETHOD_(NTSTATUS, TransferKsIrp)(THIS_
+        IN PIRP Irp,
+        IN IKsTransport **OutTransport) PURE;
+
+    STDMETHOD_(VOID, DiscardKsIrp)(THIS_
+        IN PIRP Irp,
+        IN IKsTransport * *OutTransport) PURE;
+
+    STDMETHOD_(NTSTATUS, Connect)(THIS_
+        IN IKsTransport * TransportIn,
+        OUT IKsTransport ** OutTransportIn,
+        OUT IKsTransport * *OutTransportOut,
+        IN KSPIN_DATAFLOW DataFlow) PURE;
+
+    STDMETHOD_(NTSTATUS, SetDeviceState)(THIS_
+        IN KSSTATE OldState,
+        IN KSSTATE NewState,
+        IN IKsTransport * *OutTransport) PURE;
+
+    STDMETHOD_(VOID, SetResetState)(THIS_ 
+        IN KSRESET ResetState,
+        OUT IKsTransport * * OutTransportOut) PURE;
+
+    STDMETHOD_(NTSTATUS, GetTransportConfig)(THIS_
+        IN struct KSPTRANSPORTCONFIG * TransportConfig,
+        OUT IKsTransport ** OutTransportIn,
+        OUT IKsTransport ** OutTransportOut) PURE;
+
+    STDMETHOD_(NTSTATUS, SetTransportConfig)(THIS_
+        IN struct KSPTRANSPORTCONFIG const * TransportConfig,
+        OUT IKsTransport ** OutTransportIn,
+        OUT IKsTransport ** OutTransportOut) PURE;
+
+    STDMETHOD_(NTSTATUS, ResetTransportConfig)(THIS_
+        OUT IKsTransport ** OutTransportIn,
+        OUT IKsTransport ** OutTransportOut) PURE;
+
+    STDMETHOD_(PKSPIN, GetStruct)(THIS) PURE;
+    STDMETHOD_(PKSPROCESSPIN, GetProcessPin)(THIS) PURE;
+    STDMETHOD_(NTSTATUS, AttemptBypass)(THIS) PURE;
+    STDMETHOD_(NTSTATUS, AttemptUnbypass)(THIS) PURE;
+
+    STDMETHOD_(VOID, GenerateConnectionEvents)(THIS_
+        IN ULONG EventMask) PURE;
+
+    STDMETHOD_(NTSTATUS, ClientSetDeviceState)(THIS_
+        IN KSSTATE StateIn,
+        IN KSSTATE StateOut) PURE;
 };
 
 /*****************************************************************************
index 5f14cdd..247480e 100644 (file)
 
 #include "priv.h"
 
+typedef struct
+{
+    KSBASIC_HEADER BasicHeader;
+    KSPIN Pin;
+    PKSIOBJECT_HEADER ObjectHeader;
+    LIST_ENTRY Entry;
+
+    IKsPinVtbl *lpVtbl;
+
+    LONG ref;
+    KMUTEX ProcessingMutex;
+    PFILE_OBJECT FileObject;
+
+    PFNKSPINPOWER  Sleep;
+    PFNKSPINPOWER  Wake;
+    PFNKSPINHANDSHAKE  Handshake;
+    PFNKSPINFRAMERETURN  FrameReturn;
+    PFNKSPINIRPCOMPLETION  IrpCompletion;
+
+}IKsPinImpl;
+
+NTSTATUS
+NTAPI
+IKsPin_fnQueryInterface(
+    IKsPin * iface,
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtbl);
+
+    if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
+    {
+        *Output = &This->lpVtbl;
+        _InterlockedIncrement(&This->ref);
+        return STATUS_SUCCESS;
+    }
+    return STATUS_UNSUCCESSFUL;
+}
+
+ULONG
+NTAPI
+IKsPin_fnAddRef(
+    IKsPin * iface)
+{
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtbl);
+
+    return InterlockedIncrement(&This->ref);
+}
+
+ULONG
+NTAPI
+IKsPin_fnRelease(
+    IKsPin * iface)
+{
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtbl);
+
+    InterlockedDecrement(&This->ref);
+
+    if (This->ref == 0)
+    {
+        FreeItem(This);
+        return 0;
+    }
+    /* Return new reference count */
+    return This->ref;
+}
+
+NTSTATUS
+NTAPI
+IKsPin_fnTransferKsIrp(
+    IN IKsPin *iface,
+    IN PIRP Irp,
+    IN IKsTransport **OutTransport)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+VOID
+NTAPI
+IKsPin_fnDiscardKsIrp(
+    IN IKsPin *iface,
+    IN PIRP Irp,
+    IN IKsTransport * *OutTransport)
+{
+    UNIMPLEMENTED
+}
+
+
+NTSTATUS
+NTAPI
+IKsPin_fnConnect(
+    IN IKsPin *iface,
+    IN IKsTransport * TransportIn,
+    OUT IKsTransport ** OutTransportIn,
+    OUT IKsTransport * *OutTransportOut,
+    IN KSPIN_DATAFLOW DataFlow)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+IKsPin_fnSetDeviceState(
+    IN IKsPin *iface,
+    IN KSSTATE OldState,
+    IN KSSTATE NewState,
+    IN IKsTransport * *OutTransport)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+VOID
+NTAPI
+IKsPin_fnSetResetState(
+    IN IKsPin *iface,
+    IN KSRESET ResetState,
+    OUT IKsTransport * * OutTransportOut)
+{
+    UNIMPLEMENTED
+}
+
+NTSTATUS
+NTAPI
+IKsPin_fnGetTransportConfig(
+    IN IKsPin *iface,
+    IN struct KSPTRANSPORTCONFIG * TransportConfig,
+    OUT IKsTransport ** OutTransportIn,
+    OUT IKsTransport ** OutTransportOut)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+IKsPin_fnSetTransportConfig(
+    IN IKsPin *iface,
+    IN struct KSPTRANSPORTCONFIG const * TransportConfig,
+    OUT IKsTransport ** OutTransportIn,
+    OUT IKsTransport ** OutTransportOut)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+IKsPin_fnResetTransportConfig(
+    IN IKsPin *iface,
+    OUT IKsTransport ** OutTransportIn,
+    OUT IKsTransport ** OutTransportOut)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+PKSPIN
+NTAPI
+IKsPin_fnGetStruct(
+    IN IKsPin *iface)
+{
+    UNIMPLEMENTED
+    return NULL;
+}
+
+PKSPROCESSPIN
+NTAPI
+IKsPin_fnGetProcessPin(
+    IN IKsPin *iface)
+{
+    UNIMPLEMENTED
+    return NULL;
+}
+
+NTSTATUS
+NTAPI
+IKsPin_fnAttemptBypass(
+    IN IKsPin *iface)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+IKsPin_fnAttemptUnbypass(
+    IN IKsPin *iface)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+VOID
+NTAPI
+IKsPin_fnGenerateConnectionEvents(
+    IN IKsPin *iface,
+    IN ULONG EventMask)
+{
+    UNIMPLEMENTED
+}
+
+NTSTATUS
+NTAPI
+IKsPin_fnClientSetDeviceState(
+    IN IKsPin *iface,
+    IN KSSTATE StateIn,
+    IN KSSTATE StateOut)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static IKsPinVtbl vt_IKsPin =
+{
+    IKsPin_fnQueryInterface,
+    IKsPin_fnAddRef,
+    IKsPin_fnRelease,
+    IKsPin_fnTransferKsIrp,
+    IKsPin_fnDiscardKsIrp,
+    IKsPin_fnConnect,
+    IKsPin_fnSetDeviceState,
+    IKsPin_fnSetResetState,
+    IKsPin_fnGetTransportConfig,
+    IKsPin_fnSetTransportConfig,
+    IKsPin_fnResetTransportConfig,
+    IKsPin_fnGetStruct,
+    IKsPin_fnGetProcessPin,
+    IKsPin_fnAttemptBypass,
+    IKsPin_fnAttemptUnbypass,
+    IKsPin_fnGenerateConnectionEvents,
+    IKsPin_fnClientSetDeviceState
+};
+
+
+//==============================================================
+
 /*
-    @unimplemented
+    @implemented
 */
 VOID
 NTAPI
 KsPinAcquireProcessingMutex(
     IN PKSPIN  Pin)
 {
-    UNIMPLEMENTED
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+    KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
 }
 
 /*
@@ -96,31 +337,34 @@ KsPinGetAndGate(
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 PDEVICE_OBJECT
 NTAPI
 KsPinGetConnectedPinDeviceObject(
     IN PKSPIN Pin)
 {
-    UNIMPLEMENTED
-    return NULL;
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+    /* return related file object */
+    return IoGetRelatedDeviceObject(This->FileObject);
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 PFILE_OBJECT
 NTAPI
 KsPinGetConnectedPinFileObject(
     IN PKSPIN Pin)
 {
-    UNIMPLEMENTED
-    return NULL;
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+    return This->FileObject;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 NTSTATUS
 NTAPI
@@ -129,8 +373,14 @@ KsPinGetConnectedPinInterface(
     IN const GUID*  InterfaceId,
     OUT PVOID*  Interface)
 {
-    UNIMPLEMENTED
-    return STATUS_UNSUCCESSFUL;
+    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);
 }
 
 /*
@@ -147,27 +397,28 @@ KsPinGetCopyRelationships(
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 PKSPIN
 NTAPI
 KsPinGetNextSiblingPin(
     IN PKSPIN  Pin)
 {
-    UNIMPLEMENTED
-    return NULL;
+    return KsGetNextSibling((PVOID)Pin);
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 PKSFILTER
 NTAPI
 KsPinGetParentFilter(
     IN PKSPIN  Pin)
 {
-    UNIMPLEMENTED
-    return NULL;
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+    /* return parent filter */
+    return This->BasicHeader.Parent.KsFilter;
 }
 
 /*
@@ -184,7 +435,7 @@ NTAPI
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 VOID
 NTAPI
@@ -192,11 +443,14 @@ KsPinRegisterFrameReturnCallback(
     IN PKSPIN  Pin,
     IN PFNKSPINFRAMERETURN  FrameReturn)
 {
-    UNIMPLEMENTED
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+    /* register frame return callback */
+    This->FrameReturn = FrameReturn;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 VOID
 NTAPI
@@ -204,11 +458,14 @@ KsPinRegisterHandshakeCallback(
     IN PKSPIN  Pin,
     IN PFNKSPINHANDSHAKE  Handshake)
 {
-    UNIMPLEMENTED
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+    /* register private protocol handshake callback */
+    This->Handshake = Handshake;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 VOID
 NTAPI
@@ -216,11 +473,14 @@ KsPinRegisterIrpCompletionCallback(
     IN PKSPIN  Pin,
     IN PFNKSPINIRPCOMPLETION  IrpCompletion)
 {
-    UNIMPLEMENTED
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+    /* register irp completion callback */
+    This->IrpCompletion = IrpCompletion;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 VOID
 NTAPI
@@ -229,18 +489,25 @@ KsPinRegisterPowerCallbacks(
     IN PFNKSPINPOWER  Sleep OPTIONAL,
     IN PFNKSPINPOWER  Wake OPTIONAL)
 {
-    UNIMPLEMENTED
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+    /* register power callbacks */
+    This->Sleep = Sleep;
+    This->Wake = Wake;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 VOID
 NTAPI
 KsPinReleaseProcessingMutex(
     IN PKSPIN  Pin)
 {
-    UNIMPLEMENTED
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+    /* release processing mutex */
+    KeReleaseMutex(&This->ProcessingMutex, FALSE);
 }
 
 /*
@@ -521,15 +788,225 @@ KsStreamPointerGetNextClone(
 }
 
 NTSTATUS
-KspCreatePin(
+NTAPI
+IKsPin_DispatchDeviceIoControl(
     IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP Irp, 
-    IN PKSDEVICE KsDevice, 
-    IN IKsFilterFactory * FilterFactory, 
-    IN IKsFilter* Filter,
-    IN PKSPIN_CONNECT Connect)
+    IN PIRP Irp)
+{
+    UNIMPLEMENTED;
+
+    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+IKsPin_Close(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    UNIMPLEMENTED;
+
+    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+IKsPin_DispatchCreateAllocator(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
 {
+    UNIMPLEMENTED;
 
+    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
     return STATUS_NOT_IMPLEMENTED;
 }
 
+NTSTATUS
+NTAPI
+IKsPin_DispatchCreateClock(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    UNIMPLEMENTED;
+
+    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+IKsPin_DispatchCreateNode(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    UNIMPLEMENTED;
+
+    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static KSDISPATCH_TABLE PinDispatchTable = 
+{
+    IKsPin_DispatchDeviceIoControl,
+    KsDispatchInvalidDeviceRequest,
+    KsDispatchInvalidDeviceRequest,
+    KsDispatchInvalidDeviceRequest,
+    IKsPin_Close,
+    KsDispatchQuerySecurity,
+    KsDispatchSetSecurity,
+    KsDispatchFastIoDeviceControlFailure,
+    KsDispatchFastReadFailure,
+    KsDispatchFastReadFailure
+};
+
+
+NTSTATUS
+KspCreatePin(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp, 
+    IN PKSDEVICE KsDevice,
+    IN IKsFilterFactory * FilterFactory,
+    IN IKsFilter* Filter,
+    IN PKSPIN_CONNECT Connect,
+    IN KSPIN_DESCRIPTOR_EX* Descriptor)
+{
+    IKsPinImpl * This;
+    PIO_STACK_LOCATION IoStack;
+    IKsDevice * Device;
+    PDEVICE_EXTENSION DeviceExtension;
+    PKSOBJECT_CREATE_ITEM CreateItem;
+    NTSTATUS Status;
+
+    /* sanity checks */
+    ASSERT(Descriptor->Dispatch);
+    ASSERT(Descriptor->Dispatch->Create);
+
+    /* get current irp stack */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    /* get device extension */
+    DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    /* get ks device interface */
+    Device = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice;
+
+    /* first allocate pin ctx */
+    This = AllocateItem(NonPagedPool, sizeof(IKsPinImpl));
+    if (!This)
+    {
+        /* not enough memory */
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* allocate create item */
+    CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 3);
+    if (!CreateItem)
+    {
+        /* not enough memory */
+        FreeItem(This);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* initialize basic header */
+    This->BasicHeader.KsDevice = KsDevice;
+    This->BasicHeader.Type = KsObjectTypePin;
+    This->BasicHeader.Parent.KsFilter = Filter->lpVtbl->GetStruct(Filter);
+    KeInitializeMutex(&This->BasicHeader.ControlMutex, 0);
+
+    /* initialize pin */
+    This->lpVtbl = &vt_IKsPin;
+    This->ref = 1;
+    This->FileObject = IoStack->FileObject;
+    KeInitializeMutex(&This->ProcessingMutex, 0);
+
+    /* initialize ks pin descriptor */
+    This->Pin.Descriptor = Descriptor;
+    This->Pin.Id = Connect->PinId;
+
+    /* allocate object bag */
+    This->Pin.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
+    if (!This->Pin.Bag)
+    {
+        /* not enough memory */
+        FreeItem(This);
+        FreeItem(CreateItem);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* initialize object bag */
+    Device->lpVtbl->InitializeObjectBag(Device, This->Pin.Bag, &This->BasicHeader.ControlMutex); /* is using control mutex right? */
+
+    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.AttributeList = NULL; //FIXME
+    This->Pin.StreamHeaderSize = sizeof(KSSTREAM_HEADER);
+    This->Pin.DataFlow = Descriptor->PinDescriptor.DataFlow;
+    This->Pin.DeviceState = KSSTATE_STOP;
+    This->Pin.ResetState = KSRESET_END;
+    This->Pin.ClientState = KSSTATE_STOP;
+
+    /* intialize allocator create item */
+    CreateItem[0].Context = (PVOID)This;
+    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].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].Create = IKsPin_DispatchCreateNode;
+    CreateItem[2].Flags = KSCREATE_ITEM_FREEONSTOP;
+    RtlInitUnicodeString(&CreateItem[2].ObjectClass, KSSTRING_TopologyNode);
+
+    /* now allocate object header */
+    Status = KsAllocateObjectHeader((KSOBJECT_HEADER*)&This->ObjectHeader, 3, CreateItem, Irp, &PinDispatchTable);
+    if (!NT_SUCCESS(Status))
+    {
+        /* failed to create object header */
+        KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
+        FreeItem(This);
+        FreeItem(CreateItem);
+
+        /* return failure code */
+        return Status;
+    }
+
+     /* add extra info to object header */
+    This->ObjectHeader->Type = KsObjectTypePin;
+    This->ObjectHeader->Unknown = (PUNKNOWN)&This->lpVtbl;
+    This->ObjectHeader->ObjectType = (PVOID)&This->Pin;
+
+    /*  now inform the driver to create a new pin */
+    Status = Descriptor->Dispatch->Create(&This->Pin, Irp);
+
+    if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
+    {
+        /* failed to create pin, release resources */
+        KsFreeObjectHeader((KSOBJECT_HEADER)This->ObjectHeader);
+        KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
+        FreeItem(This);
+
+        /* return failure code */
+        return Status;
+    }
+
+    /* FIXME add pin instance to filter instance */
+
+    return Status;
+}