strmbase: Move BasePin implementation to strmbase.
diff --git a/dlls/qcap/pin.c b/dlls/qcap/pin.c
index d4ba451..52fb311 100644
--- a/dlls/qcap/pin.c
+++ b/dlls/qcap/pin.c
@@ -30,13 +30,13 @@
 #include "dshow.h"
 
 #include "qcap_main.h"
-#include "pin.h"
 
 #include "wine/debug.h"
 #include "wine/unicode.h"
 #include "uuids.h"
 #include "vfwmsgs.h"
 #include <assert.h>
+#include "pin.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
 
@@ -54,103 +54,6 @@
     pDest->pFilter = pSrc->pFilter;
 }
 
-HRESULT WINAPI IPinImpl_ConnectedTo(IPin * iface, IPin ** ppPin)
-{
-    HRESULT hr;
-    IPinImpl *This = (IPinImpl *)iface;
-
-/*  TRACE("(%p)\n", ppPin);*/
-
-    EnterCriticalSection(This->pCritSec);
-    {
-        if (This->pConnectedTo)
-        {
-            *ppPin = This->pConnectedTo;
-            IPin_AddRef(*ppPin);
-            hr = S_OK;
-        }
-        else
-            hr = VFW_E_NOT_CONNECTED;
-    }
-    LeaveCriticalSection(This->pCritSec);
-
-    return hr;
-}
-
-HRESULT WINAPI IPinImpl_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt)
-{
-    HRESULT hr;
-    IPinImpl *This = (IPinImpl *)iface;
-
-    TRACE("(%p/%p)->(%p)\n", This, iface, pmt);
-
-    EnterCriticalSection(This->pCritSec);
-    {
-        if (This->pConnectedTo)
-        {
-            CopyMediaType(pmt, &This->mtCurrent);
-            hr = S_OK;
-        }
-        else
-        {
-            ZeroMemory(pmt, sizeof(*pmt));
-            hr = VFW_E_NOT_CONNECTED;
-        }
-    }
-    LeaveCriticalSection(This->pCritSec);
-
-    return hr;
-}
-
-HRESULT WINAPI IPinImpl_QueryPinInfo(IPin * iface, PIN_INFO * pInfo)
-{
-    IPinImpl *This = (IPinImpl *)iface;
-
-    TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
-
-    Copy_PinInfo(pInfo, &This->pinInfo);
-    IBaseFilter_AddRef(pInfo->pFilter);
-
-    return S_OK;
-}
-
-HRESULT WINAPI IPinImpl_QueryDirection(IPin * iface, PIN_DIRECTION * pPinDir)
-{
-    IPinImpl *This = (IPinImpl *)iface;
-
-    TRACE("(%p/%p)->(%p)\n", This, iface, pPinDir);
-
-    *pPinDir = This->pinInfo.dir;
-
-    return S_OK;
-}
-
-HRESULT WINAPI IPinImpl_QueryId(IPin * iface, LPWSTR * Id)
-{
-    IPinImpl *This = (IPinImpl *)iface;
-
-    TRACE("(%p/%p)->(%p)\n", This, iface, Id);
-
-    *Id = CoTaskMemAlloc((strlenW(This->pinInfo.achName) + 1) * sizeof(WCHAR));
-    if (!*Id)
-        return E_OUTOFMEMORY;
-
-    strcpyW(*Id, This->pinInfo.achName);
-
-    return S_OK;
-}
-
-HRESULT WINAPI IPinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt)
-{
-    IPinImpl *This = (IPinImpl *)iface;
-
-    TRACE("(%p/%p)->(%p)\n", This, iface, pmt);
-
-    if (!This->fnQueryAccept) return S_OK;
-
-    return (This->fnQueryAccept(This->pUserData, pmt) == S_OK ? S_OK : S_FALSE);
-}
-
 /* Function called as a helper to IPin_Connect */
 /* specific AM_MEDIA_TYPE - it cannot be NULL */
 /* NOTE: not part of standard interface */
@@ -215,7 +118,6 @@
 }
 
 HRESULT OutputPin_Init(const PIN_INFO * pPinInfo, const ALLOCATOR_PROPERTIES * props,
-                       LPVOID pUserData, QUERYACCEPTPROC pQueryAccept,
                        LPCRITICAL_SECTION pCritSec, OutputPin * pPinImpl)
 {
     TRACE("\n");
@@ -223,8 +125,6 @@
     /* Common attributes */
     pPinImpl->pin.refCount = 1;
     pPinImpl->pin.pConnectedTo = NULL;
-    pPinImpl->pin.fnQueryAccept = pQueryAccept;
-    pPinImpl->pin.pUserData = pUserData;
     pPinImpl->pin.pCritSec = pCritSec;
     Copy_PinInfo(&pPinImpl->pin.pinInfo, pPinInfo);
 
diff --git a/dlls/qcap/pin.h b/dlls/qcap/pin.h
index e738b58..ef129cc 100644
--- a/dlls/qcap/pin.h
+++ b/dlls/qcap/pin.h
@@ -35,22 +35,10 @@
  */
 typedef HRESULT (* PRECONNECTPROC)(IPin * iface, IPin * pConnectPin);
 
-typedef struct IPinImpl
-{
-	const struct IPinVtbl * lpVtbl;
-	LONG refCount;
-	LPCRITICAL_SECTION pCritSec;
-	PIN_INFO pinInfo;
-	IPin * pConnectedTo;
-	AM_MEDIA_TYPE mtCurrent;
-	QUERYACCEPTPROC fnQueryAccept;
-	LPVOID pUserData;
-} IPinImpl;
-
 typedef struct OutputPin
 {
 	/* inheritance C style! */
-	IPinImpl pin;
+	BasePin pin;
 
 	IMemInputPin * pMemInputPin;
 	HRESULT (* pConnectSpecific)(IPin * iface, IPin * pReceiver, const AM_MEDIA_TYPE * pmt);
@@ -59,18 +47,8 @@
 
 /*** Initializers ***/
 HRESULT OutputPin_Init(const PIN_INFO * pPinInfo, const ALLOCATOR_PROPERTIES *props,
-                       LPVOID pUserData, QUERYACCEPTPROC pQueryAccept,
                        LPCRITICAL_SECTION pCritSec, OutputPin * pPinImpl);
 
-/* Common */
-HRESULT WINAPI IPinImpl_ConnectedTo(IPin * iface, IPin ** ppPin);
-HRESULT WINAPI IPinImpl_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt);
-HRESULT WINAPI IPinImpl_QueryPinInfo(IPin * iface, PIN_INFO * pInfo);
-HRESULT WINAPI IPinImpl_QueryDirection(IPin * iface, PIN_DIRECTION * pPinDir);
-HRESULT WINAPI IPinImpl_QueryId(IPin * iface, LPWSTR * Id);
-HRESULT WINAPI IPinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt);
-HRESULT WINAPI IPinImpl_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum);
-
 /* Output Pin */
 HRESULT WINAPI OutputPin_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt);
 HRESULT WINAPI OutputPin_Disconnect(IPin * iface);
diff --git a/dlls/qcap/vfwcapture.c b/dlls/qcap/vfwcapture.c
index d72bed2..cf8f8c4 100644
--- a/dlls/qcap/vfwcapture.c
+++ b/dlls/qcap/vfwcapture.c
@@ -193,7 +193,7 @@
 
     if (!refCount)
     {
-        IPinImpl *pin;
+        BasePin *pin;
 
         TRACE("destroying everything\n");
         if (This->init)
@@ -202,7 +202,7 @@
                 qcap_driver_stop(This->driver_info, &This->state);
             qcap_driver_destroy(This->driver_info);
         }
-        pin = (IPinImpl*) This->pOutputPin;
+        pin = (BasePin*) This->pOutputPin;
         if (pin->pConnectedTo != NULL)
         {
             IPin_Disconnect(pin->pConnectedTo);
@@ -414,7 +414,7 @@
 {
     HRESULT hr;
     ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
-    IPinImpl *pin;
+    BasePin *pin;
 
     TRACE("(%p): %p->%p\n", iface, pmt, pmt ? pmt->pbFormat : NULL);
 
@@ -432,7 +432,7 @@
 
     dump_AM_MEDIA_TYPE(pmt);
 
-    pin = (IPinImpl *)This->pOutputPin;
+    pin = (BasePin *)This->pOutputPin;
     if (pin->pConnectedTo != NULL)
     {
         hr = IPin_QueryAccept(pin->pConnectedTo, pmt);
@@ -806,7 +806,7 @@
     lstrcpyW(piOutput.achName, wszOutputPinName);
     ObjectRefCount(TRUE);
 
-    hr = OutputPin_Init(&piOutput, &ap, pBaseFilter, NULL, pCritSec, &pPinImpl->pin);
+    hr = OutputPin_Init(&piOutput, &ap, pCritSec, &pPinImpl->pin);
     if (SUCCEEDED(hr))
     {
         pPinImpl->KSP_VT = &KSP_VTable;
@@ -927,12 +927,12 @@
     OutputPin_Connect,
     OutputPin_ReceiveConnection,
     OutputPin_Disconnect,
-    IPinImpl_ConnectedTo,
-    IPinImpl_ConnectionMediaType,
-    IPinImpl_QueryPinInfo,
-    IPinImpl_QueryDirection,
-    IPinImpl_QueryId,
-    IPinImpl_QueryAccept,
+    BasePinImpl_ConnectedTo,
+    BasePinImpl_ConnectionMediaType,
+    BasePinImpl_QueryPinInfo,
+    BasePinImpl_QueryDirection,
+    BasePinImpl_QueryId,
+    BasePinImpl_QueryAccept,
     VfwPin_EnumMediaTypes,
     VfwPin_QueryInternalConnections,
     VfwPin_EndOfStream,
diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c
index f29f55a..63846ce 100644
--- a/dlls/quartz/dsoundrender.c
+++ b/dlls/quartz/dsoundrender.c
@@ -825,7 +825,7 @@
         if (This->pin.pConnectedTo)
             hr = VFW_E_ALREADY_CONNECTED;
 
-        if (SUCCEEDED(hr) && This->pin.fnQueryAccept(This->pin.pUserData, pmt) != S_OK)
+        if (SUCCEEDED(hr) && This->fnQueryAccept(This->pUserData, pmt) != S_OK)
             hr = VFW_E_TYPE_NOT_ACCEPTED;
 
         if (SUCCEEDED(hr))
@@ -899,7 +899,7 @@
 
 static HRESULT WINAPI DSoundRender_InputPin_Disconnect(IPin * iface)
 {
-    IPinImpl *This = (IPinImpl*)iface;
+    BasePin *This = (BasePin*)iface;
     DSoundRenderImpl *DSImpl;
 
     TRACE("(%p)->()\n", iface);
@@ -909,7 +909,7 @@
         IDirectSoundBuffer_Release(DSImpl->dsbuffer);
     DSImpl->dsbuffer = NULL;
 
-    return IPinImpl_Disconnect(iface);
+    return BasePinImpl_Disconnect(iface);
 }
 
 static HRESULT WINAPI DSoundRender_InputPin_EndOfStream(IPin * iface)
@@ -1012,19 +1012,19 @@
 static const IPinVtbl DSoundRender_InputPin_Vtbl =
 {
     InputPin_QueryInterface,
-    IPinImpl_AddRef,
+    BasePinImpl_AddRef,
     InputPin_Release,
     InputPin_Connect,
     DSoundRender_InputPin_ReceiveConnection,
     DSoundRender_InputPin_Disconnect,
-    IPinImpl_ConnectedTo,
-    IPinImpl_ConnectionMediaType,
-    IPinImpl_QueryPinInfo,
-    IPinImpl_QueryDirection,
-    IPinImpl_QueryId,
-    IPinImpl_QueryAccept,
-    IPinImpl_EnumMediaTypes,
-    IPinImpl_QueryInternalConnections,
+    BasePinImpl_ConnectedTo,
+    BasePinImpl_ConnectionMediaType,
+    BasePinImpl_QueryPinInfo,
+    BasePinImpl_QueryDirection,
+    BasePinImpl_QueryId,
+    InputPin_QueryAccept,
+    BasePinImpl_EnumMediaTypes,
+    BasePinImpl_QueryInternalConnections,
     DSoundRender_InputPin_EndOfStream,
     DSoundRender_InputPin_BeginFlush,
     DSoundRender_InputPin_EndFlush,
diff --git a/dlls/quartz/filesource.c b/dlls/quartz/filesource.c
index fb3f523..1cbc0cc 100644
--- a/dlls/quartz/filesource.c
+++ b/dlls/quartz/filesource.c
@@ -794,17 +794,18 @@
     return (FileAsyncReader *)((char*)iface - FIELD_OFFSET(FileAsyncReader, lpVtblAR));
 }
 
-static HRESULT AcceptProcAFR(LPVOID iface, const AM_MEDIA_TYPE *pmt)
+static HRESULT WINAPI FileAsyncReaderPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *pmt)
 {
-    AsyncReader *This = iface;
+    FileAsyncReader *This = (FileAsyncReader *)iface;
+    AM_MEDIA_TYPE *pmt_filter = ((AsyncReader *)This->pin.pin.pinInfo.pFilter)->pmt;
 
     FIXME("(%p, %p)\n", iface, pmt);
 
-    if (IsEqualGUID(&pmt->majortype, &This->pmt->majortype) &&
-        IsEqualGUID(&pmt->subtype, &This->pmt->subtype) &&
+    if (IsEqualGUID(&pmt->majortype, &pmt_filter->majortype) &&
+        IsEqualGUID(&pmt->subtype, &pmt_filter->subtype) &&
         IsEqualGUID(&pmt->formattype, &FORMAT_None))
         return S_OK;
-    
+
     return S_FALSE;
 }
 
@@ -883,19 +884,19 @@
 static const IPinVtbl FileAsyncReaderPin_Vtbl = 
 {
     FileAsyncReaderPin_QueryInterface,
-    IPinImpl_AddRef,
+    BasePinImpl_AddRef,
     FileAsyncReaderPin_Release,
     OutputPin_Connect,
     OutputPin_ReceiveConnection,
-    IPinImpl_Disconnect,
-    IPinImpl_ConnectedTo,
-    IPinImpl_ConnectionMediaType,
-    IPinImpl_QueryPinInfo,
-    IPinImpl_QueryDirection,
-    IPinImpl_QueryId,
-    IPinImpl_QueryAccept,
+    BasePinImpl_Disconnect,
+    BasePinImpl_ConnectedTo,
+    BasePinImpl_ConnectionMediaType,
+    BasePinImpl_QueryPinInfo,
+    BasePinImpl_QueryDirection,
+    BasePinImpl_QueryId,
+    FileAsyncReaderPin_QueryAccept,
     FileAsyncReaderPin_EnumMediaTypes,
-    IPinImpl_QueryInternalConnections,
+    BasePinImpl_QueryInternalConnections,
     OutputPin_EndOfStream,
     OutputPin_BeginFlush,
     OutputPin_EndFlush,
@@ -942,7 +943,7 @@
     piOutput.dir = PINDIR_OUTPUT;
     piOutput.pFilter = pBaseFilter;
     strcpyW(piOutput.achName, wszOutputPinName);
-    hr = OutputPin_Construct(&FileAsyncReaderPin_Vtbl, sizeof(FileAsyncReader), &piOutput, NULL, pBaseFilter, AcceptProcAFR, pCritSec, ppPin);
+    hr = OutputPin_Construct(&FileAsyncReaderPin_Vtbl, sizeof(FileAsyncReader), &piOutput, NULL, pCritSec, ppPin);
 
     if (SUCCEEDED(hr))
     {
diff --git a/dlls/quartz/nullrenderer.c b/dlls/quartz/nullrenderer.c
index 2b4be24..954f93e 100644
--- a/dlls/quartz/nullrenderer.c
+++ b/dlls/quartz/nullrenderer.c
@@ -553,19 +553,19 @@
 static const IPinVtbl NullRenderer_InputPin_Vtbl =
 {
     InputPin_QueryInterface,
-    IPinImpl_AddRef,
+    BasePinImpl_AddRef,
     InputPin_Release,
     InputPin_Connect,
     InputPin_ReceiveConnection,
-    IPinImpl_Disconnect,
-    IPinImpl_ConnectedTo,
-    IPinImpl_ConnectionMediaType,
-    IPinImpl_QueryPinInfo,
-    IPinImpl_QueryDirection,
-    IPinImpl_QueryId,
-    IPinImpl_QueryAccept,
-    IPinImpl_EnumMediaTypes,
-    IPinImpl_QueryInternalConnections,
+    BasePinImpl_Disconnect,
+    BasePinImpl_ConnectedTo,
+    BasePinImpl_ConnectionMediaType,
+    BasePinImpl_QueryPinInfo,
+    BasePinImpl_QueryDirection,
+    BasePinImpl_QueryId,
+    InputPin_QueryAccept,
+    BasePinImpl_EnumMediaTypes,
+    BasePinImpl_QueryInternalConnections,
     NullRenderer_InputPin_EndOfStream,
     InputPin_BeginFlush,
     NullRenderer_InputPin_EndFlush,
diff --git a/dlls/quartz/parser.c b/dlls/quartz/parser.c
index deb993f..0c93cca 100644
--- a/dlls/quartz/parser.c
+++ b/dlls/quartz/parser.c
@@ -41,7 +41,6 @@
 static const IPinVtbl Parser_OutputPin_Vtbl;
 static const IPinVtbl Parser_InputPin_Vtbl;
 
-static HRESULT Parser_OutputPin_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt);
 static HRESULT Parser_ChangeCurrent(IBaseFilter *iface);
 static HRESULT Parser_ChangeStop(IBaseFilter *iface);
 static HRESULT Parser_ChangeRate(IBaseFilter *iface);
@@ -492,7 +491,7 @@
     This->ppPins = CoTaskMemAlloc((This->cStreams + 2) * sizeof(IPin *));
     memcpy(This->ppPins, ppOldPins, (This->cStreams + 1) * sizeof(IPin *));
 
-    hr = OutputPin_Construct(&Parser_OutputPin_Vtbl, sizeof(Parser_OutputPin), piOutput, props, NULL, Parser_OutputPin_QueryAccept, &This->csFilter, This->ppPins + (This->cStreams + 1));
+    hr = OutputPin_Construct(&Parser_OutputPin_Vtbl, sizeof(Parser_OutputPin), piOutput, props, &This->csFilter, This->ppPins + (This->cStreams + 1));
 
     if (SUCCEEDED(hr))
     {
@@ -502,7 +501,6 @@
         CopyMediaType(pin->pmt, amt);
         pin->dwSamplesProcessed = 0;
 
-        pin->pin.pin.pUserData = This->ppPins[This->cStreams + 1];
         pin->pin.pin.pinInfo.pFilter = (LPVOID)This;
         pin->pin.custom_allocator = 1;
         This->cStreams++;
@@ -689,9 +687,9 @@
     return OutputPin_Connect(iface, pReceivePin, pmt);
 }
 
-static HRESULT Parser_OutputPin_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
+static HRESULT WINAPI Parser_OutputPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE * pmt)
 {
-    Parser_OutputPin *This = iface;
+    Parser_OutputPin *This = (Parser_OutputPin *)iface;
 
     TRACE("()\n");
     dump_AM_MEDIA_TYPE(pmt);
@@ -702,19 +700,19 @@
 static const IPinVtbl Parser_OutputPin_Vtbl = 
 {
     Parser_OutputPin_QueryInterface,
-    IPinImpl_AddRef,
+    BasePinImpl_AddRef,
     Parser_OutputPin_Release,
     Parser_OutputPin_Connect,
     OutputPin_ReceiveConnection,
     OutputPin_Disconnect,
-    IPinImpl_ConnectedTo,
-    IPinImpl_ConnectionMediaType,
-    IPinImpl_QueryPinInfo,
-    IPinImpl_QueryDirection,
-    IPinImpl_QueryId,
-    IPinImpl_QueryAccept,
+    BasePinImpl_ConnectedTo,
+    BasePinImpl_ConnectionMediaType,
+    BasePinImpl_QueryPinInfo,
+    BasePinImpl_QueryDirection,
+    BasePinImpl_QueryId,
+    Parser_OutputPin_QueryAccept,
     Parser_OutputPin_EnumMediaTypes,
-    IPinImpl_QueryInternalConnections,
+    BasePinImpl_QueryInternalConnections,
     OutputPin_EndOfStream,
     OutputPin_BeginFlush,
     OutputPin_EndFlush,
@@ -768,7 +766,7 @@
     hr = PullPin_ReceiveConnection(iface, pReceivePin, pmt);
     if (FAILED(hr))
     {
-        IPinImpl *This = (IPinImpl *)iface;
+        BasePin *This = (BasePin *)iface;
 
         EnterCriticalSection(This->pCritSec);
         Parser_RemoveOutputPins((ParserImpl *)This->pinInfo.pFilter);
@@ -781,19 +779,19 @@
 static const IPinVtbl Parser_InputPin_Vtbl =
 {
     PullPin_QueryInterface,
-    IPinImpl_AddRef,
+    BasePinImpl_AddRef,
     PullPin_Release,
     InputPin_Connect,
     Parser_PullPin_ReceiveConnection,
     Parser_PullPin_Disconnect,
-    IPinImpl_ConnectedTo,
-    IPinImpl_ConnectionMediaType,
-    IPinImpl_QueryPinInfo,
-    IPinImpl_QueryDirection,
-    IPinImpl_QueryId,
-    IPinImpl_QueryAccept,
-    IPinImpl_EnumMediaTypes,
-    IPinImpl_QueryInternalConnections,
+    BasePinImpl_ConnectedTo,
+    BasePinImpl_ConnectionMediaType,
+    BasePinImpl_QueryPinInfo,
+    BasePinImpl_QueryDirection,
+    BasePinImpl_QueryId,
+    PullPin_QueryAccept,
+    BasePinImpl_EnumMediaTypes,
+    BasePinImpl_QueryInternalConnections,
     PullPin_EndOfStream,
     PullPin_BeginFlush,
     PullPin_EndFlush,
diff --git a/dlls/quartz/pin.c b/dlls/quartz/pin.c
index 25dff17..1862292 100644
--- a/dlls/quartz/pin.c
+++ b/dlls/quartz/pin.c
@@ -154,174 +154,6 @@
     pDest->pFilter = pSrc->pFilter;
 }
 
-/*** Common Base Pin function */
-HRESULT WINAPI BasePinImpl_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt)
-{
-    if (iPosition < 0)
-        return E_INVALIDARG;
-    return VFW_S_NO_MORE_ITEMS;
-}
-
-LONG WINAPI BasePinImpl_GetMediaTypeVersion(IPin *iface)
-{
-    return 1;
-}
-
-/*** Common pin functions ***/
-
-ULONG WINAPI IPinImpl_AddRef(IPin * iface)
-{
-    IPinImpl *This = (IPinImpl *)iface;
-    ULONG refCount = InterlockedIncrement(&This->refCount);
-    
-    TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1);
-    
-    return refCount;
-}
-
-HRESULT WINAPI IPinImpl_Disconnect(IPin * iface)
-{
-    HRESULT hr;
-    IPinImpl *This = (IPinImpl *)iface;
-
-    TRACE("()\n");
-
-    EnterCriticalSection(This->pCritSec);
-    {
-        if (This->pConnectedTo)
-        {
-            IPin_Release(This->pConnectedTo);
-            This->pConnectedTo = NULL;
-            FreeMediaType(&This->mtCurrent);
-            ZeroMemory(&This->mtCurrent, sizeof(This->mtCurrent));
-            hr = S_OK;
-        }
-        else
-            hr = S_FALSE;
-    }
-    LeaveCriticalSection(This->pCritSec);
-    
-    return hr;
-}
-
-HRESULT WINAPI IPinImpl_ConnectedTo(IPin * iface, IPin ** ppPin)
-{
-    HRESULT hr;
-    IPinImpl *This = (IPinImpl *)iface;
-
-    TRACE("(%p)\n", ppPin);
-
-    EnterCriticalSection(This->pCritSec);
-    {
-        if (This->pConnectedTo)
-        {
-            *ppPin = This->pConnectedTo;
-            IPin_AddRef(*ppPin);
-            hr = S_OK;
-        }
-        else
-        {
-            hr = VFW_E_NOT_CONNECTED;
-            *ppPin = NULL;
-        }
-    }
-    LeaveCriticalSection(This->pCritSec);
-
-    return hr;
-}
-
-HRESULT WINAPI IPinImpl_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt)
-{
-    HRESULT hr;
-    IPinImpl *This = (IPinImpl *)iface;
-
-    TRACE("(%p/%p)->(%p)\n", This, iface, pmt);
-
-    EnterCriticalSection(This->pCritSec);
-    {
-        if (This->pConnectedTo)
-        {
-            CopyMediaType(pmt, &This->mtCurrent);
-            hr = S_OK;
-        }
-        else
-        {
-            ZeroMemory(pmt, sizeof(*pmt));
-            hr = VFW_E_NOT_CONNECTED;
-        }
-    }
-    LeaveCriticalSection(This->pCritSec);
-
-    return hr;
-}
-
-HRESULT WINAPI IPinImpl_QueryPinInfo(IPin * iface, PIN_INFO * pInfo)
-{
-    IPinImpl *This = (IPinImpl *)iface;
-
-    TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
-
-    Copy_PinInfo(pInfo, &This->pinInfo);
-    IBaseFilter_AddRef(pInfo->pFilter);
-
-    return S_OK;
-}
-
-HRESULT WINAPI IPinImpl_QueryDirection(IPin * iface, PIN_DIRECTION * pPinDir)
-{
-    IPinImpl *This = (IPinImpl *)iface;
-
-    TRACE("(%p/%p)->(%p)\n", This, iface, pPinDir);
-
-    *pPinDir = This->pinInfo.dir;
-
-    return S_OK;
-}
-
-HRESULT WINAPI IPinImpl_QueryId(IPin * iface, LPWSTR * Id)
-{
-    IPinImpl *This = (IPinImpl *)iface;
-
-    TRACE("(%p/%p)->(%p)\n", This, iface, Id);
-
-    *Id = CoTaskMemAlloc((strlenW(This->pinInfo.achName) + 1) * sizeof(WCHAR));
-    if (!*Id)
-        return E_OUTOFMEMORY;
-
-    strcpyW(*Id, This->pinInfo.achName);
-
-    return S_OK;
-}
-
-HRESULT WINAPI IPinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt)
-{
-    IPinImpl *This = (IPinImpl *)iface;
-
-    TRACE("(%p/%p)->(%p)\n", This, iface, pmt);
-
-    return (This->fnQueryAccept(This->pUserData, pmt) == S_OK ? S_OK : S_FALSE);
-}
-
-HRESULT WINAPI IPinImpl_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
-{
-    IPinImpl *This = (IPinImpl *)iface;
-
-    TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
-
-    /* override this method to allow enumeration of your types */
-
-    return EnumMediaTypes_Construct(iface, BasePinImpl_GetMediaType, BasePinImpl_GetMediaTypeVersion , ppEnum);
-}
-
-HRESULT WINAPI IPinImpl_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin)
-{
-    IPinImpl *This = (IPinImpl *)iface;
-
-    TRACE("(%p/%p)->(%p, %p)\n", This, iface, apPin, cPin);
-
-    return E_NOTIMPL; /* to tell caller that all input pins connected to all output pins */
-}
-
 /*** IPin implementation for an input pin ***/
 
 HRESULT WINAPI InputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
@@ -397,7 +229,7 @@
         if (This->pin.pConnectedTo)
             hr = VFW_E_ALREADY_CONNECTED;
 
-        if (SUCCEEDED(hr) && This->pin.fnQueryAccept(This->pin.pUserData, pmt) != S_OK)
+        if (SUCCEEDED(hr) && This->fnQueryAccept(This->pUserData, pmt) != S_OK)
             hr = VFW_E_TYPE_NOT_ACCEPTED; /* FIXME: shouldn't we just map common errors onto
                                            * VFW_E_TYPE_NOT_ACCEPTED and pass the value on otherwise? */
 
@@ -429,6 +261,15 @@
     return IPin_EndOfStream( pin );
 }
 
+HRESULT WINAPI InputPin_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt)
+{
+    InputPin *This = (InputPin *)iface;
+
+    TRACE("(%p/%p)->(%p)\n", This, iface, pmt);
+
+    return (This->fnQueryAccept(This->pUserData, pmt) == S_OK ? S_OK : S_FALSE);
+}
+
 HRESULT WINAPI InputPin_EndOfStream(IPin * iface)
 {
     HRESULT hr = S_OK;
@@ -463,7 +304,7 @@
     This->flushing = 1;
 
     if (This->fnCleanProc)
-        This->fnCleanProc(This->pin.pUserData);
+        This->fnCleanProc(This->pUserData);
 
     hr = SendFurther( iface, deliver_beginflush, NULL, NULL );
     LeaveCriticalSection(This->pin.pCritSec);
@@ -520,19 +361,19 @@
 static const IPinVtbl InputPin_Vtbl = 
 {
     InputPin_QueryInterface,
-    IPinImpl_AddRef,
+    BasePinImpl_AddRef,
     InputPin_Release,
     InputPin_Connect,
     InputPin_ReceiveConnection,
-    IPinImpl_Disconnect,
-    IPinImpl_ConnectedTo,
-    IPinImpl_ConnectionMediaType,
-    IPinImpl_QueryPinInfo,
-    IPinImpl_QueryDirection,
-    IPinImpl_QueryId,
-    IPinImpl_QueryAccept,
-    IPinImpl_EnumMediaTypes,
-    IPinImpl_QueryInternalConnections,
+    BasePinImpl_Disconnect,
+    BasePinImpl_ConnectedTo,
+    BasePinImpl_ConnectionMediaType,
+    BasePinImpl_QueryPinInfo,
+    BasePinImpl_QueryDirection,
+    BasePinImpl_QueryId,
+    InputPin_QueryAccept,
+    BasePinImpl_EnumMediaTypes,
+    BasePinImpl_QueryInternalConnections,
     InputPin_EndOfStream,
     InputPin_BeginFlush,
     InputPin_EndFlush,
@@ -626,7 +467,7 @@
 
     /* this trace commented out for performance reasons */
     /*TRACE("(%p/%p)->(%p)\n", This, iface, pSample);*/
-    hr = This->fnSampleProc(This->pin.pUserData, pSample);
+    hr = This->fnSampleProc(This->pUserData, pSample);
     return hr;
 }
 
@@ -871,19 +712,19 @@
 static const IPinVtbl OutputPin_Vtbl = 
 {
     OutputPin_QueryInterface,
-    IPinImpl_AddRef,
+    BasePinImpl_AddRef,
     OutputPin_Release,
     OutputPin_Connect,
     OutputPin_ReceiveConnection,
     OutputPin_Disconnect,
-    IPinImpl_ConnectedTo,
-    IPinImpl_ConnectionMediaType,
-    IPinImpl_QueryPinInfo,
-    IPinImpl_QueryDirection,
-    IPinImpl_QueryId,
-    IPinImpl_QueryAccept,
-    IPinImpl_EnumMediaTypes,
-    IPinImpl_QueryInternalConnections,
+    BasePinImpl_ConnectedTo,
+    BasePinImpl_ConnectionMediaType,
+    BasePinImpl_QueryPinInfo,
+    BasePinImpl_QueryDirection,
+    BasePinImpl_QueryId,
+    BasePinImpl_QueryAccept,
+    BasePinImpl_EnumMediaTypes,
+    BasePinImpl_QueryInternalConnections,
     OutputPin_EndOfStream,
     OutputPin_BeginFlush,
     OutputPin_EndFlush,
@@ -1063,13 +904,13 @@
     pPinImpl->pin.lpVtbl = PullPin_Vtbl;
     pPinImpl->pin.refCount = 1;
     pPinImpl->pin.pConnectedTo = NULL;
-    pPinImpl->pin.fnQueryAccept = pQueryAccept;
-    pPinImpl->pin.pUserData = pUserData;
     pPinImpl->pin.pCritSec = pCritSec;
     Copy_PinInfo(&pPinImpl->pin.pinInfo, pPinInfo);
     ZeroMemory(&pPinImpl->pin.mtCurrent, sizeof(AM_MEDIA_TYPE));
 
     /* Input pin attributes */
+    pPinImpl->pUserData = pUserData;
+    pPinImpl->fnQueryAccept = pQueryAccept;
     pPinImpl->fnSampleProc = pSampleProc;
     pPinImpl->fnCleanProc = pCleanUp;
     pPinImpl->fnDone = pDone;
@@ -1142,7 +983,7 @@
         props.cbAlign = 1;
         props.cbPrefix = 0;
 
-        if (SUCCEEDED(hr) && (This->pin.fnQueryAccept(This->pin.pUserData, pmt) != S_OK))
+        if (SUCCEEDED(hr) && (This->fnQueryAccept(This->pUserData, pmt) != S_OK))
             hr = VFW_E_TYPE_NOT_ACCEPTED; /* FIXME: shouldn't we just map common errors onto 
                                            * VFW_E_TYPE_NOT_ACCEPTED and pass the value on otherwise? */
 
@@ -1305,7 +1146,7 @@
     }
 
     /* There is no sample in our buffer */
-    hr = This->fnCustomRequest(This->pin.pUserData);
+    hr = This->fnCustomRequest(This->pUserData);
 
     if (FAILED(hr))
         ERR("Request error: %x\n", hr);
@@ -1327,7 +1168,7 @@
         /* Return an empty sample on error to the implementation in case it does custom parsing, so it knows it's gone */
         if (SUCCEEDED(hr))
         {
-            hr = This->fnSampleProc(This->pin.pUserData, pSample, dwUser);
+            hr = This->fnSampleProc(This->pUserData, pSample, dwUser);
         }
         else
         {
@@ -1358,7 +1199,7 @@
      * Flush remaining samples
      */
     if (This->fnDone)
-        This->fnDone(This->pin.pUserData);
+        This->fnDone(This->pUserData);
 
     TRACE("End: %08x, %d\n", hr, This->stop_playback);
 }
@@ -1537,6 +1378,15 @@
     return S_OK;
 }
 
+HRESULT WINAPI PullPin_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt)
+{
+    PullPin *This = (PullPin *)iface;
+
+    TRACE("(%p/%p)->(%p)\n", This, iface, pmt);
+
+    return (This->fnQueryAccept(This->pUserData, pmt) == S_OK ? S_OK : S_FALSE);
+}
+
 HRESULT WINAPI PullPin_EndOfStream(IPin * iface)
 {
     FIXME("(%p)->() stub\n", iface);
@@ -1571,7 +1421,7 @@
 
     EnterCriticalSection(This->pin.pCritSec);
     {
-        This->fnCleanProc(This->pin.pUserData);
+        This->fnCleanProc(This->pUserData);
     }
     LeaveCriticalSection(This->pin.pCritSec);
 
@@ -1653,19 +1503,19 @@
 static const IPinVtbl PullPin_Vtbl = 
 {
     PullPin_QueryInterface,
-    IPinImpl_AddRef,
+    BasePinImpl_AddRef,
     PullPin_Release,
     InputPin_Connect,
     PullPin_ReceiveConnection,
     PullPin_Disconnect,
-    IPinImpl_ConnectedTo,
-    IPinImpl_ConnectionMediaType,
-    IPinImpl_QueryPinInfo,
-    IPinImpl_QueryDirection,
-    IPinImpl_QueryId,
-    IPinImpl_QueryAccept,
-    IPinImpl_EnumMediaTypes,
-    IPinImpl_QueryInternalConnections,
+    BasePinImpl_ConnectedTo,
+    BasePinImpl_ConnectionMediaType,
+    BasePinImpl_QueryPinInfo,
+    BasePinImpl_QueryDirection,
+    BasePinImpl_QueryId,
+    PullPin_QueryAccept,
+    BasePinImpl_EnumMediaTypes,
+    BasePinImpl_QueryInternalConnections,
     PullPin_EndOfStream,
     PullPin_BeginFlush,
     PullPin_EndFlush,
@@ -1759,13 +1609,13 @@
     /* Common attributes */
     pPinImpl->pin.refCount = 1;
     pPinImpl->pin.pConnectedTo = NULL;
-    pPinImpl->pin.fnQueryAccept = pQueryAccept;
-    pPinImpl->pin.pUserData = pUserData;
     pPinImpl->pin.pCritSec = pCritSec;
     Copy_PinInfo(&pPinImpl->pin.pinInfo, pPinInfo);
     ZeroMemory(&pPinImpl->pin.mtCurrent, sizeof(AM_MEDIA_TYPE));
 
     /* Input pin attributes */
+    pPinImpl->pUserData = pUserData;
+    pPinImpl->fnQueryAccept = pQueryAccept;
     pPinImpl->fnSampleProc = pSampleProc;
     pPinImpl->fnCleanProc = pCleanUp;
     pPinImpl->pAllocator = pPinImpl->preferred_allocator = allocator;
@@ -1781,8 +1631,8 @@
     return S_OK;
 }
 
-static HRESULT OutputPin_Init(const IPinVtbl *OutputPin_Vtbl, const PIN_INFO * pPinInfo, const ALLOCATOR_PROPERTIES * props, LPVOID pUserData,
-                              QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, OutputPin * pPinImpl)
+static HRESULT OutputPin_Init(const IPinVtbl *OutputPin_Vtbl, const PIN_INFO * pPinInfo, const ALLOCATOR_PROPERTIES * props,
+                              LPCRITICAL_SECTION pCritSec, OutputPin * pPinImpl)
 {
     TRACE("\n");
 
@@ -1790,8 +1640,6 @@
     pPinImpl->pin.lpVtbl = OutputPin_Vtbl;
     pPinImpl->pin.refCount = 1;
     pPinImpl->pin.pConnectedTo = NULL;
-    pPinImpl->pin.fnQueryAccept = pQueryAccept;
-    pPinImpl->pin.pUserData = pUserData;
     pPinImpl->pin.pCritSec = pCritSec;
     Copy_PinInfo(&pPinImpl->pin.pinInfo, pPinInfo);
     ZeroMemory(&pPinImpl->pin.mtCurrent, sizeof(AM_MEDIA_TYPE));
@@ -1844,7 +1692,7 @@
     return E_FAIL;
 }
 
-HRESULT OutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, LONG outputpin_size, const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES *props, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
+HRESULT OutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, LONG outputpin_size, const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES *props, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
 {
     OutputPin * pPinImpl;
 
@@ -1863,7 +1711,7 @@
     if (!pPinImpl)
         return E_OUTOFMEMORY;
 
-    if (SUCCEEDED(OutputPin_Init(OutputPin_Vtbl, pPinInfo, props, pUserData, pQueryAccept, pCritSec, pPinImpl)))
+    if (SUCCEEDED(OutputPin_Init(OutputPin_Vtbl, pPinInfo, props, pCritSec, pPinImpl)))
     {
         *ppPin = (IPin *)(&pPinImpl->pin.lpVtbl);
         return S_OK;
diff --git a/dlls/quartz/pin.h b/dlls/quartz/pin.h
index 38af040..3e61a9f 100644
--- a/dlls/quartz/pin.h
+++ b/dlls/quartz/pin.h
@@ -66,25 +66,15 @@
 #define ALIGNDOWN(value,boundary) ((value)/(boundary)*(boundary))
 #define ALIGNUP(value,boundary) (ALIGNDOWN((value)+(boundary)-1, (boundary)))
 
-typedef struct IPinImpl
-{
-	const struct IPinVtbl * lpVtbl;
-	LONG refCount;
-	LPCRITICAL_SECTION pCritSec;
-	PIN_INFO pinInfo;
-	IPin * pConnectedTo;
-	AM_MEDIA_TYPE mtCurrent;
-	QUERYACCEPTPROC fnQueryAccept;
-	LPVOID pUserData;
-} IPinImpl;
-
 typedef struct InputPin
 {
 	/* inheritance C style! */
-	IPinImpl pin;
+	BasePin pin;
+	LPVOID pUserData;
 
 	const IMemInputPinVtbl * lpVtblMemInput;
 	IMemAllocator * pAllocator;
+	QUERYACCEPTPROC fnQueryAccept;
 	SAMPLEPROC_PUSH fnSampleProc;
 	CLEANUPPROC fnCleanProc;
 	REFERENCE_TIME tStart;
@@ -97,7 +87,7 @@
 typedef struct OutputPin
 {
 	/* inheritance C style! */
-	IPinImpl pin;
+	BasePin  pin;
 
 	IMemInputPin * pMemInputPin;
 	HRESULT (* pConnectSpecific)(IPin * iface, IPin * pReceiver, const AM_MEDIA_TYPE * pmt);
@@ -110,11 +100,13 @@
 typedef struct PullPin
 {
 	/* inheritance C style! */
-	IPinImpl pin;
+	BasePin pin;
+	LPVOID pUserData;
 
 	REFERENCE_TIME rtStart, rtCurrent, rtNext, rtStop;
 	IAsyncReader * pReader;
 	IMemAllocator * pAlloc;
+	QUERYACCEPTPROC fnQueryAccept;
 	SAMPLEPROC_PULL fnSampleProc;
 	PRECONNECTPROC fnPreConnect;
 	REQUESTPROC fnCustomRequest;
@@ -142,29 +134,18 @@
 
 /*** Constructors ***/
 HRESULT InputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IMemAllocator *, IPin ** ppPin);
-HRESULT OutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, LONG outputpin_size, const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES *props, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin);
+HRESULT OutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, LONG outputpin_size, const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES *props, LPCRITICAL_SECTION pCritSec, IPin ** ppPin);
 HRESULT PullPin_Construct(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PULL pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, STOPPROCESSPROC, REQUESTPROC pCustomRequest, LPCRITICAL_SECTION pCritSec, IPin ** ppPin);
 
 /**************************/
 /*** Pin Implementation ***/
 
-/* Common */
-ULONG   WINAPI IPinImpl_AddRef(IPin * iface);
-HRESULT WINAPI IPinImpl_Disconnect(IPin * iface);
-HRESULT WINAPI IPinImpl_ConnectedTo(IPin * iface, IPin ** ppPin);
-HRESULT WINAPI IPinImpl_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt);
-HRESULT WINAPI IPinImpl_QueryPinInfo(IPin * iface, PIN_INFO * pInfo);
-HRESULT WINAPI IPinImpl_QueryDirection(IPin * iface, PIN_DIRECTION * pPinDir);
-HRESULT WINAPI IPinImpl_QueryId(IPin * iface, LPWSTR * Id);
-HRESULT WINAPI IPinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt);
-HRESULT WINAPI IPinImpl_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum);
-HRESULT WINAPI IPinImpl_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin);
-
 /* Input Pin */
 HRESULT WINAPI InputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv);
 ULONG   WINAPI InputPin_Release(IPin * iface);
 HRESULT WINAPI InputPin_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt);
 HRESULT WINAPI InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt);
+HRESULT WINAPI InputPin_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt);
 HRESULT WINAPI InputPin_EndOfStream(IPin * iface);
 HRESULT WINAPI InputPin_BeginFlush(IPin * iface);
 HRESULT WINAPI InputPin_EndFlush(IPin * iface);
@@ -193,6 +174,7 @@
 HRESULT WINAPI PullPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv);
 ULONG   WINAPI PullPin_Release(IPin * iface);
 HRESULT WINAPI PullPin_EndOfStream(IPin * iface);
+HRESULT WINAPI PullPin_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt);
 HRESULT WINAPI PullPin_BeginFlush(IPin * iface);
 HRESULT WINAPI PullPin_EndFlush(IPin * iface);
 HRESULT WINAPI PullPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
diff --git a/dlls/quartz/quartz_private.h b/dlls/quartz/quartz_private.h
index 7a8ccb3..3094b1b 100644
--- a/dlls/quartz/quartz_private.h
+++ b/dlls/quartz/quartz_private.h
@@ -84,8 +84,4 @@
     LONGLONG tMediaEnd;
 } StdMediaSample2;
 
-
-HRESULT WINAPI BasePinImpl_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt);
-LONG WINAPI BasePinImpl_GetMediaTypeVersion(IPin *iface);
-
 #endif /* __QUARTZ_PRIVATE_INCLUDED__ */
diff --git a/dlls/quartz/transform.c b/dlls/quartz/transform.c
index a24865a..fd97f52 100644
--- a/dlls/quartz/transform.c
+++ b/dlls/quartz/transform.c
@@ -49,7 +49,7 @@
 
 static HRESULT TransformFilter_Input_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
 {
-    TransformFilterImpl* This = (TransformFilterImpl *)((IPinImpl *)iface)->pinInfo.pFilter;
+    TransformFilterImpl* This = (TransformFilterImpl *)((BasePin *)iface)->pinInfo.pFilter;
     TRACE("%p\n", iface);
     dump_AM_MEDIA_TYPE(pmt);
 
@@ -61,9 +61,10 @@
 }
 
 
-static HRESULT TransformFilter_Output_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
+static HRESULT WINAPI TransformFilter_Output_QueryAccept(IPin *iface, const AM_MEDIA_TYPE * pmt)
 {
-    TransformFilterImpl* pTransformFilter = iface;
+    BasePin *This = (BasePin *)iface;
+    TransformFilterImpl *pTransformFilter = (TransformFilterImpl *)This->pinInfo.pFilter;
     AM_MEDIA_TYPE* outpmt = &pTransformFilter->pmt;
     TRACE("%p\n", iface);
 
@@ -114,9 +115,9 @@
         props.cbBuffer = 0; /* Will be updated at connection time */
         props.cBuffers = 1;
 
-       ((InputPin *)pTransformFilter->ppPins[0])->pin.pUserData = pTransformFilter->ppPins[0];
+       ((InputPin *)pTransformFilter->ppPins[0])->pUserData = pTransformFilter->ppPins[0];
 
-        hr = OutputPin_Construct(&TransformFilter_OutputPin_Vtbl, sizeof(OutputPin), &piOutput, &props, pTransformFilter, TransformFilter_Output_QueryAccept, &pTransformFilter->csFilter, &pTransformFilter->ppPins[1]);
+        hr = OutputPin_Construct(&TransformFilter_OutputPin_Vtbl, sizeof(OutputPin), &piOutput, &props, &pTransformFilter->csFilter, &pTransformFilter->ppPins[1]);
 
         if (FAILED(hr))
             ERR("Cannot create output pin (%x)\n", hr);
@@ -521,7 +522,7 @@
     pTransform = (TransformFilterImpl*)This->pin.pinInfo.pFilter;
     pTransform->pFuncsTable->pfnCleanup(This);
 
-    return IPinImpl_Disconnect(iface);
+    return BasePinImpl_Disconnect(iface);
 }
 
 static HRESULT WINAPI TransformFilter_InputPin_BeginFlush(IPin * iface)
@@ -581,19 +582,19 @@
 static const IPinVtbl TransformFilter_InputPin_Vtbl = 
 {
     InputPin_QueryInterface,
-    IPinImpl_AddRef,
+    BasePinImpl_AddRef,
     InputPin_Release,
     InputPin_Connect,
     TransformFilter_InputPin_ReceiveConnection,
     TransformFilter_InputPin_Disconnect,
-    IPinImpl_ConnectedTo,
-    IPinImpl_ConnectionMediaType,
-    IPinImpl_QueryPinInfo,
-    IPinImpl_QueryDirection,
-    IPinImpl_QueryId,
-    IPinImpl_QueryAccept,
-    IPinImpl_EnumMediaTypes,
-    IPinImpl_QueryInternalConnections,
+    BasePinImpl_ConnectedTo,
+    BasePinImpl_ConnectionMediaType,
+    BasePinImpl_QueryPinInfo,
+    BasePinImpl_QueryDirection,
+    BasePinImpl_QueryId,
+    InputPin_QueryAccept,
+    BasePinImpl_EnumMediaTypes,
+    BasePinImpl_QueryInternalConnections,
     TransformFilter_InputPin_EndOfStream,
     TransformFilter_InputPin_BeginFlush,
     TransformFilter_InputPin_EndFlush,
@@ -602,7 +603,7 @@
 
 static HRESULT WINAPI TransformFilter_Output_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt)
 {
-    IPinImpl *This = (IPinImpl *)iface;
+    BasePin *This = (BasePin *)iface;
     TransformFilterImpl *pTransform = (TransformFilterImpl *)This->pinInfo.pFilter;
 
     if (iPosition < 0)
@@ -615,7 +616,7 @@
 
 static HRESULT WINAPI TransformFilter_Output_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
 {
-    IPinImpl *This = (IPinImpl *)iface;
+    BasePin *This = (BasePin *)iface;
     TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
 
     return EnumMediaTypes_Construct(iface, TransformFilter_Output_GetMediaType, BasePinImpl_GetMediaTypeVersion, ppEnum);
@@ -624,19 +625,19 @@
 static const IPinVtbl TransformFilter_OutputPin_Vtbl =
 {
     OutputPin_QueryInterface,
-    IPinImpl_AddRef,
+    BasePinImpl_AddRef,
     OutputPin_Release,
     OutputPin_Connect,
     OutputPin_ReceiveConnection,
     OutputPin_Disconnect,
-    IPinImpl_ConnectedTo,
-    IPinImpl_ConnectionMediaType,
-    IPinImpl_QueryPinInfo,
-    IPinImpl_QueryDirection,
-    IPinImpl_QueryId,
-    IPinImpl_QueryAccept,
+    BasePinImpl_ConnectedTo,
+    BasePinImpl_ConnectionMediaType,
+    BasePinImpl_QueryPinInfo,
+    BasePinImpl_QueryDirection,
+    BasePinImpl_QueryId,
+    TransformFilter_Output_QueryAccept,
     TransformFilter_Output_EnumMediaTypes,
-    IPinImpl_QueryInternalConnections,
+    BasePinImpl_QueryInternalConnections,
     OutputPin_EndOfStream,
     OutputPin_BeginFlush,
     OutputPin_EndFlush,
diff --git a/dlls/quartz/videorenderer.c b/dlls/quartz/videorenderer.c
index 6d8b120..0cfef54 100644
--- a/dlls/quartz/videorenderer.c
+++ b/dlls/quartz/videorenderer.c
@@ -1069,19 +1069,19 @@
 static const IPinVtbl VideoRenderer_InputPin_Vtbl = 
 {
     InputPin_QueryInterface,
-    IPinImpl_AddRef,
+    BasePinImpl_AddRef,
     InputPin_Release,
     InputPin_Connect,
     InputPin_ReceiveConnection,
-    IPinImpl_Disconnect,
-    IPinImpl_ConnectedTo,
-    IPinImpl_ConnectionMediaType,
-    IPinImpl_QueryPinInfo,
-    IPinImpl_QueryDirection,
-    IPinImpl_QueryId,
-    IPinImpl_QueryAccept,
-    IPinImpl_EnumMediaTypes,
-    IPinImpl_QueryInternalConnections,
+    BasePinImpl_Disconnect,
+    BasePinImpl_ConnectedTo,
+    BasePinImpl_ConnectionMediaType,
+    BasePinImpl_QueryPinInfo,
+    BasePinImpl_QueryDirection,
+    BasePinImpl_QueryId,
+    InputPin_QueryAccept,
+    BasePinImpl_EnumMediaTypes,
+    BasePinImpl_QueryInternalConnections,
     VideoRenderer_InputPin_EndOfStream,
     VideoRenderer_InputPin_BeginFlush,
     VideoRenderer_InputPin_EndFlush,
diff --git a/dlls/strmbase/Makefile.in b/dlls/strmbase/Makefile.in
index 1e5bf57..ac6a61f 100644
--- a/dlls/strmbase/Makefile.in
+++ b/dlls/strmbase/Makefile.in
@@ -2,6 +2,7 @@
 
 C_SRCS = \
 	enumpins.c \
-	mediatype.c
+	mediatype.c \
+	pin.c
 
 @MAKE_IMPLIB_RULES@
diff --git a/dlls/strmbase/pin.c b/dlls/strmbase/pin.c
new file mode 100644
index 0000000..ef5aba5
--- /dev/null
+++ b/dlls/strmbase/pin.c
@@ -0,0 +1,207 @@
+/*
+ * Generic Implementation of IPin Interface
+ *
+ * Copyright 2003 Robert Shearman
+ * Copyright 2010 Aric Stewart, CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include "dshow.h"
+#include "wine/debug.h"
+#include "wine/unicode.h"
+#include "wine/strmbase.h"
+#include "uuids.h"
+#include "vfwmsgs.h"
+#include <assert.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(strmbase);
+
+static void Copy_PinInfo(PIN_INFO * pDest, const PIN_INFO * pSrc)
+{
+    /* Tempting to just do a memcpy, but the name field is
+       128 characters long! We will probably never exceed 10
+       most of the time, so we are better off copying
+       each field manually */
+    strcpyW(pDest->achName, pSrc->achName);
+    pDest->dir = pSrc->dir;
+    pDest->pFilter = pSrc->pFilter;
+}
+
+/*** Common Base Pin function */
+HRESULT WINAPI BasePinImpl_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt)
+{
+    if (iPosition < 0)
+        return E_INVALIDARG;
+    return VFW_S_NO_MORE_ITEMS;
+}
+
+LONG WINAPI BasePinImpl_GetMediaTypeVersion(IPin *iface)
+{
+    return 1;
+}
+
+ULONG WINAPI BasePinImpl_AddRef(IPin * iface)
+{
+    BasePin *This = (BasePin *)iface;
+    ULONG refCount = InterlockedIncrement(&This->refCount);
+
+    TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1);
+
+    return refCount;
+}
+
+HRESULT WINAPI BasePinImpl_Disconnect(IPin * iface)
+{
+    HRESULT hr;
+    BasePin *This = (BasePin *)iface;
+
+    TRACE("()\n");
+
+    EnterCriticalSection(This->pCritSec);
+    {
+        if (This->pConnectedTo)
+        {
+            IPin_Release(This->pConnectedTo);
+            This->pConnectedTo = NULL;
+            FreeMediaType(&This->mtCurrent);
+            ZeroMemory(&This->mtCurrent, sizeof(This->mtCurrent));
+            hr = S_OK;
+        }
+        else
+            hr = S_FALSE;
+    }
+    LeaveCriticalSection(This->pCritSec);
+
+    return hr;
+}
+
+HRESULT WINAPI BasePinImpl_ConnectedTo(IPin * iface, IPin ** ppPin)
+{
+    HRESULT hr;
+    BasePin *This = (BasePin *)iface;
+
+    TRACE("(%p)\n", ppPin);
+
+    EnterCriticalSection(This->pCritSec);
+    {
+        if (This->pConnectedTo)
+        {
+            *ppPin = This->pConnectedTo;
+            IPin_AddRef(*ppPin);
+            hr = S_OK;
+        }
+        else
+        {
+            hr = VFW_E_NOT_CONNECTED;
+            *ppPin = NULL;
+        }
+    }
+    LeaveCriticalSection(This->pCritSec);
+
+    return hr;
+}
+
+HRESULT WINAPI BasePinImpl_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt)
+{
+    HRESULT hr;
+    BasePin *This = (BasePin *)iface;
+
+    TRACE("(%p/%p)->(%p)\n", This, iface, pmt);
+
+    EnterCriticalSection(This->pCritSec);
+    {
+        if (This->pConnectedTo)
+        {
+            CopyMediaType(pmt, &This->mtCurrent);
+            hr = S_OK;
+        }
+        else
+        {
+            ZeroMemory(pmt, sizeof(*pmt));
+            hr = VFW_E_NOT_CONNECTED;
+        }
+    }
+    LeaveCriticalSection(This->pCritSec);
+
+    return hr;
+}
+
+HRESULT WINAPI BasePinImpl_QueryPinInfo(IPin * iface, PIN_INFO * pInfo)
+{
+    BasePin *This = (BasePin *)iface;
+
+    TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
+
+    Copy_PinInfo(pInfo, &This->pinInfo);
+    IBaseFilter_AddRef(pInfo->pFilter);
+
+    return S_OK;
+}
+
+HRESULT WINAPI BasePinImpl_QueryDirection(IPin * iface, PIN_DIRECTION * pPinDir)
+{
+    BasePin *This = (BasePin *)iface;
+
+    TRACE("(%p/%p)->(%p)\n", This, iface, pPinDir);
+
+    *pPinDir = This->pinInfo.dir;
+
+    return S_OK;
+}
+
+HRESULT WINAPI BasePinImpl_QueryId(IPin * iface, LPWSTR * Id)
+{
+    BasePin *This = (BasePin *)iface;
+
+    TRACE("(%p/%p)->(%p)\n", This, iface, Id);
+
+    *Id = CoTaskMemAlloc((strlenW(This->pinInfo.achName) + 1) * sizeof(WCHAR));
+    if (!*Id)
+        return E_OUTOFMEMORY;
+
+    strcpyW(*Id, This->pinInfo.achName);
+
+    return S_OK;
+}
+
+HRESULT WINAPI BasePinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt)
+{
+    TRACE("(%p)->(%p)\n", iface, pmt);
+
+    return S_OK;
+}
+
+HRESULT WINAPI BasePinImpl_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
+{
+    BasePin *This = (BasePin *)iface;
+
+    TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
+
+    /* override this method to allow enumeration of your types */
+
+    return EnumMediaTypes_Construct(iface, BasePinImpl_GetMediaType, BasePinImpl_GetMediaTypeVersion , ppEnum);
+}
+
+HRESULT WINAPI BasePinImpl_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin)
+{
+    BasePin *This = (BasePin *)iface;
+
+    TRACE("(%p/%p)->(%p, %p)\n", This, iface, apPin, cPin);
+
+    return E_NOTIMPL; /* to tell caller that all input pins connected to all output pins */
+}
diff --git a/include/wine/strmbase.h b/include/wine/strmbase.h
index 8502ca5..a9aa167 100644
--- a/include/wine/strmbase.h
+++ b/include/wine/strmbase.h
@@ -34,3 +34,29 @@
 HRESULT WINAPI EnumMediaTypes_Construct(IPin *iface, BasePin_GetMediaType enumFunc, BasePin_GetMediaTypeVersion versionFunc, IEnumMediaTypes ** ppEnum);
 
 HRESULT WINAPI EnumPins_Construct(IBaseFilter *base,  BaseFilter_GetPin receive_pin, BaseFilter_GetPinCount receive_pincount, BaseFilter_GetPinVersion receive_version, IEnumPins ** ppEnum);
+
+/* Pin functions */
+
+typedef struct BasePin
+{
+	const struct IPinVtbl * lpVtbl;
+	LONG refCount;
+	LPCRITICAL_SECTION pCritSec;
+	PIN_INFO pinInfo;
+	IPin * pConnectedTo;
+	AM_MEDIA_TYPE mtCurrent;
+} BasePin;
+
+/* Base Pin */
+HRESULT WINAPI BasePinImpl_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt);
+LONG WINAPI BasePinImpl_GetMediaTypeVersion(IPin *iface);
+ULONG WINAPI BasePinImpl_AddRef(IPin * iface);
+HRESULT WINAPI BasePinImpl_Disconnect(IPin * iface);
+HRESULT WINAPI BasePinImpl_ConnectedTo(IPin * iface, IPin ** ppPin);
+HRESULT WINAPI BasePinImpl_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt);
+HRESULT WINAPI BasePinImpl_QueryPinInfo(IPin * iface, PIN_INFO * pInfo);
+HRESULT WINAPI BasePinImpl_QueryDirection(IPin * iface, PIN_DIRECTION * pPinDir);
+HRESULT WINAPI BasePinImpl_QueryId(IPin * iface, LPWSTR * Id);
+HRESULT WINAPI BasePinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt);
+HRESULT WINAPI BasePinImpl_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum);
+HRESULT WINAPI BasePinImpl_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin);