[KSPROXY]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Thu, 11 Mar 2010 21:38:13 +0000 (21:38 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Thu, 11 Mar 2010 21:38:13 +0000 (21:38 +0000)
- Recreate resource file with visual studio
- Fix compilation with msvc
- Copy extra format buffer in IEnumMediaTypes::Next
- Create the pin handle in IPin::ReceiveConnection
- Implement IPin::Disconnect for the input pin
- Enumerate media formats and pass it to constructor of CEnumMediaTypes
- Check if the passed format is null in CInputPin::CheckFormat
- Copy extra format buffer after KSDATAFORMAT in the pin connection request
- Implement KsGetMediaType function
- Implement ISpecifyPropertyPages, IKsPropertySet, IKsControl, IStreamBuilder, IKsPinFactory for the output pin
- Implement IPin::ReceiveConnection, IPin::EnumMediaTypes for output pin
- Stub interfaces for IReferenceClock, IMediaSeeking, IKsTopology, IKsAggregateControl, IKsClockPropertySet, ISpecifyPropertyPages, IPersistStream for proxy filter
- Implement IAMDeviceRemoval, IKsControl, IAMFilterMiscFlags, IKsPropertySet interface for proxy filter

svn path=/trunk/; revision=46116

reactos/dll/directx/ksproxy/clockforward.cpp
reactos/dll/directx/ksproxy/datatype.cpp
reactos/dll/directx/ksproxy/enum_mediatypes.cpp
reactos/dll/directx/ksproxy/input_pin.cpp
reactos/dll/directx/ksproxy/ksproxy.cpp
reactos/dll/directx/ksproxy/ksproxy.rc
reactos/dll/directx/ksproxy/output_pin.cpp
reactos/dll/directx/ksproxy/precomp.h
reactos/dll/directx/ksproxy/proxy.cpp
reactos/dll/directx/ksproxy/qualityforward.cpp

index cba65b3..80bf00f 100644 (file)
@@ -8,7 +8,9 @@
  */
 #include "precomp.h"
 
+#ifndef _MSC_VER
 const GUID KSCATEGORY_CLOCK       = {0x53172480, 0x4791, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
+#endif
 
 class CKsClockForwarder : public IDistributorNotify,
                           public IKsObject
index 3d2d925..3d13289 100644 (file)
@@ -9,7 +9,9 @@
 #include "precomp.h"
 
 /* FIXME guid mess */
+#ifndef _MSC_VER
 const GUID IID_IUnknown           = {0x00000000, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
+#endif
 const GUID IID_IClassFactory      = {0x00000001, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
 
 class CKsDataTypeHandler : public IKsDataTypeHandler
index 9895c22..462ffda 100644 (file)
@@ -103,7 +103,31 @@ CEnumMediaTypes::Next(
         if (!MediaType)
             break;
 
-        CopyMemory(MediaType, &m_MediaTypes[m_Index + i], sizeof(AM_MEDIA_TYPE));
+        if (m_MediaTypes[m_Index + i].cbFormat)
+        {
+            LPBYTE pFormat = (LPBYTE)CoTaskMemAlloc(m_MediaTypes[m_Index + i].cbFormat);
+            if (!pFormat)
+            {
+                CoTaskMemFree(MediaType);
+                break;
+            }
+
+            CopyMemory(MediaType, &m_MediaTypes[m_Index + i], sizeof(AM_MEDIA_TYPE));
+            MediaType->pbFormat = pFormat;
+            CopyMemory(MediaType->pbFormat, m_MediaTypes[m_Index + i].pbFormat, m_MediaTypes[m_Index + i].cbFormat);
+            MediaType->pUnk = (IUnknown *)this;
+            MediaType->pUnk->AddRef();
+        }
+        else
+        {
+            CopyMemory(MediaType, &m_MediaTypes[m_Index + i], sizeof(AM_MEDIA_TYPE));
+        }
+
+        if (MediaType->pUnk)
+        {
+            MediaType->pUnk->AddRef();
+        }
+
         ppMediaTypes[i] = MediaType;
         i++;
     }
@@ -114,7 +138,6 @@ CEnumMediaTypes::Next(
     }
 
     m_Index += i;
-
     if (i < cMediaTypes)
         return S_FALSE;
     else
index 2b08b16..ce2cef4 100644 (file)
@@ -9,8 +9,12 @@
 #include "precomp.h"
 
 const GUID IID_IKsPinEx = {0x7bb38260L, 0xd19c, 0x11d2, {0xb3, 0x8a, 0x00, 0xa0, 0xc9, 0x5e, 0xc2, 0x2e}};
+
+#ifndef _MSC_VER
 const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
+#endif
 
+#ifndef _MSC_VER
 KSPIN_INTERFACE StandardPinInterface = 
 {
     {STATIC_KSINTERFACESETID_Standard},
@@ -25,6 +29,23 @@ KSPIN_MEDIUM StandardPinMedium =
     0
 };
 
+#else
+
+KSPIN_INTERFACE StandardPinInterface = 
+{
+    STATIC_KSINTERFACESETID_Standard,
+    KSINTERFACE_STANDARD_STREAMING,
+    0
+};
+
+KSPIN_MEDIUM StandardPinMedium =
+{
+    STATIC_KSMEDIUMSETID_Standard,
+    KSMEDIUM_TYPE_ANYINSTANCE,
+    0
+};
+
+#endif
 
 class CInputPin : public IPin,
                   public IKsPropertySet,
@@ -117,9 +138,9 @@ public:
 
     //---------------------------------------------------------------
     HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt);
-    HRESULT STDMETHODCALLTYPE CreatePin();
-    HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, PKSDATAFORMAT DataFormat);
-    CInputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, HANDLE hFilter, ULONG PinId, KSPIN_COMMUNICATION Communication) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName), m_hFilter(hFilter), m_hPin(0), m_PinId(PinId), m_MemAllocator(0), m_IoCount(0), m_Communication(Communication), m_Pin(0){};
+    HRESULT STDMETHODCALLTYPE CreatePin(const AM_MEDIA_TYPE *pmt);
+    HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt);
+    CInputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, HANDLE hFilter, ULONG PinId, KSPIN_COMMUNICATION Communication) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName), m_hFilter(hFilter), m_hPin(0), m_PinId(PinId), m_MemAllocator(0), m_IoCount(0), m_Communication(Communication), m_Pin(0), m_ReadOnly(0){};
     virtual ~CInputPin(){};
 
 protected:
@@ -135,6 +156,7 @@ protected:
     KSPIN_INTERFACE m_Interface;
     KSPIN_MEDIUM m_Medium;
     IPin * m_Pin;
+    BOOL m_ReadOnly;
 };
 
 HRESULT
@@ -160,39 +182,18 @@ CInputPin::QueryInterface(
     }
     else if (IsEqualGUID(refiid, IID_IKsObject))
     {
-        if (!m_hPin)
-        {
-            HRESULT hr = CreatePin();
-            if (FAILED(hr))
-                return hr;
-        }
-
         *Output = (IKsObject*)(this);
         reinterpret_cast<IKsObject*>(*Output)->AddRef();
         return NOERROR;
     }
     else if (IsEqualGUID(refiid, IID_IKsPropertySet))
     {
-        if (!m_hPin)
-        {
-            HRESULT hr = CreatePin();
-            if (FAILED(hr))
-                return hr;
-        }
-
         *Output = (IKsPropertySet*)(this);
         reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
         return NOERROR;
     }
     else if (IsEqualGUID(refiid, IID_IKsControl))
     {
-        if (!m_hPin)
-        {
-            HRESULT hr = CreatePin();
-            if (FAILED(hr))
-                return hr;
-        }
-
         *Output = (IKsControl*)(this);
         reinterpret_cast<IKsControl*>(*Output)->AddRef();
         return NOERROR;
@@ -200,13 +201,6 @@ CInputPin::QueryInterface(
     else if (IsEqualGUID(refiid, IID_IKsPin) ||
              IsEqualGUID(refiid, IID_IKsPinEx))
     {
-        if (!m_hPin)
-        {
-            HRESULT hr = CreatePin();
-            if (FAILED(hr))
-                return hr;
-        }
-
         *Output = (IKsPinEx*)(this);
         reinterpret_cast<IKsPinEx*>(*Output)->AddRef();
         return NOERROR;
@@ -227,7 +221,7 @@ CInputPin::QueryInterface(
 // IMemInputPin
 //
 
-    //
+
 HRESULT
 STDMETHODCALLTYPE
 CInputPin::GetAllocator(IMemAllocator **ppAllocator)
@@ -251,6 +245,7 @@ CInputPin::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly)
     }
 
     m_MemAllocator = pAllocator;
+    m_ReadOnly = bReadOnly;
     return NOERROR;
 }
 
@@ -466,7 +461,7 @@ CInputPin::KsNotifyError(
 
 
 //-------------------------------------------------------------------
-// IKsPropertySet
+// IKsControl
 //
 HRESULT
 STDMETHODCALLTYPE
@@ -477,6 +472,7 @@ CInputPin::KsProperty(
     ULONG DataLength,
     ULONG* BytesReturned)
 {
+    assert(m_hPin != 0);
     return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
 }
 
@@ -489,6 +485,7 @@ CInputPin::KsMethod(
     ULONG DataLength,
     ULONG* BytesReturned)
 {
+    assert(m_hPin != 0);
     return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
 }
 
@@ -501,6 +498,8 @@ CInputPin::KsEvent(
     ULONG DataLength,
     ULONG* BytesReturned)
 {
+    assert(m_hPin != 0);
+
     if (EventLength)
         return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
     else
@@ -619,10 +618,7 @@ HANDLE
 STDMETHODCALLTYPE
 CInputPin::KsGetObjectHandle()
 {
-    OutputDebugStringW(L"CInputPin::KsGetObjectHandle CALLED\n");
-
-    //FIXME
-    // return pin handle
+    assert(m_hPin);
     return m_hPin;
 }
 
@@ -645,7 +641,6 @@ CInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
 
     if (m_Pin)
     {
-        OutputDebugStringW(L"CInputPin::ReceiveConnection already connected\n");
         return VFW_E_ALREADY_CONNECTED;
     }
 
@@ -657,19 +652,36 @@ CInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
     if (FAILED(CheckFormat(pmt)))
         return hr;
 
+    hr = CreatePin(pmt);
+    if (FAILED(hr))
+    {
+        return hr;
+    }
+
     //FIXME create pin
    m_Pin = pConnector;
    m_Pin->AddRef();
 
-    OutputDebugStringW(L"CInputPin::ReceiveConnection NotImplemented\n");
     return S_OK;
 }
 HRESULT
 STDMETHODCALLTYPE
 CInputPin::Disconnect( void)
 {
-    OutputDebugStringW(L"CInputPin::Disconnect NotImplemented\n");
-    return E_NOTIMPL;
+    if (!m_Pin)
+    {
+        // pin was not connected
+        return S_FALSE;
+    }
+
+    //FIXME
+    //check if filter is active
+
+    m_Pin->Release();
+    m_Pin = NULL;
+
+    OutputDebugStringW(L"CInputPin::Disconnect\n");
+    return S_OK;
 }
 HRESULT
 STDMETHODCALLTYPE
@@ -693,6 +705,9 @@ HRESULT
 STDMETHODCALLTYPE
 CInputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
 {
+    if (!m_Pin)
+        return VFW_E_NOT_CONNECTED;
+
     OutputDebugStringW(L"CInputPin::ConnectionMediaType NotImplemented\n");
     return E_NOTIMPL;
 }
@@ -742,8 +757,41 @@ HRESULT
 STDMETHODCALLTYPE
 CInputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
 {
-    return CEnumMediaTypes_fnConstructor(0, NULL, IID_IEnumMediaTypes, (void**)ppEnum);
+    HRESULT hr;
+    ULONG MediaTypeCount = 0, Index;
+    AM_MEDIA_TYPE * MediaTypes;
+
+    // query media type count
+    hr = KsGetMediaTypeCount(m_hFilter, m_PinId, &MediaTypeCount);
+    if (FAILED(hr) || !MediaTypeCount)
+        return hr;
+
+    // allocate media types
+    MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
+    if (!MediaTypes)
+    {
+        // not enough memory
+        return E_OUTOFMEMORY;
+    }
+
+    // zero media types
+    ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
+
+    for(Index = 0; Index < MediaTypeCount; Index++)
+    {
+        // get media type
+        hr = KsGetMediaType(Index, &MediaTypes[Index], m_hFilter, m_PinId);
+        if (FAILED(hr))
+        {
+            // failed
+            CoTaskMemFree(MediaTypes);
+            return hr;
+        }
+    }
+
+    return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum);
 }
+
 HRESULT
 STDMETHODCALLTYPE
 CInputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
@@ -799,6 +847,9 @@ CInputPin::CheckFormat(
     Property.PinId = m_PinId;
     Property.Reserved = 0;
 
+    if (!pmt)
+        return E_POINTER;
+
     // query for size of dataranges
     hr = KsSynchronousDeviceControl(m_hFilter, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
 
@@ -842,13 +893,12 @@ CInputPin::CheckFormat(
 
 HRESULT
 STDMETHODCALLTYPE
-CInputPin::CreatePin()
+CInputPin::CreatePin(
+    const AM_MEDIA_TYPE *pmt)
 {
     PKSMULTIPLE_ITEM MediumList;
     PKSMULTIPLE_ITEM InterfaceList;
-    PKSMULTIPLE_ITEM DataFormatList = NULL;
     PKSPIN_MEDIUM Medium;
-    PKSDATAFORMAT DataFormat;
     PKSPIN_INTERFACE Interface;
     HRESULT hr;
 
@@ -866,19 +916,6 @@ CInputPin::CreatePin()
         return hr;
     }
 
-    // get data ranges
-    hr = KsGetMultiplePinFactoryItems(m_hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&DataFormatList);
-    if (FAILED(hr) || DataFormatList->Count == 0)
-    {
-        // failed
-        CoTaskMemFree(MediumList);
-        CoTaskMemFree(InterfaceList);
-        if (DataFormatList)
-            CoTaskMemFree(DataFormatList);
-
-        return hr;
-    }
-
     if (MediumList->Count)
     {
         //use first available medium
@@ -901,15 +938,10 @@ CInputPin::CreatePin()
         Interface = &StandardPinInterface;
     }
 
-    //FIXME determine format
-    // use first available format
-    DataFormat = (PKSDATAFORMAT) (DataFormatList + 1);
-
     // now create pin
-    hr = CreatePinHandle(Medium, Interface, DataFormat);
+    hr = CreatePinHandle(Medium, Interface, pmt);
 
     // free medium / interface / dataformat
-    CoTaskMemFree(DataFormatList);
     CoTaskMemFree(MediumList);
     CoTaskMemFree(InterfaceList);
 
@@ -921,14 +953,15 @@ STDMETHODCALLTYPE
 CInputPin::CreatePinHandle(
     PKSPIN_MEDIUM Medium,
     PKSPIN_INTERFACE Interface,
-    PKSDATAFORMAT DataFormat)
+    const AM_MEDIA_TYPE *pmt)
 {
     PKSPIN_CONNECT PinConnect;
+    PKSDATAFORMAT DataFormat;
     ULONG Length;
     HRESULT hr;
 
     // calc format size
-    Length = sizeof(KSPIN_CONNECT) + DataFormat->FormatSize;
+    Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat;
 
     // allocate pin connect
     PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length);
@@ -945,7 +978,24 @@ CInputPin::CreatePinHandle(
     PinConnect->PinToHandle = NULL;
     PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
     PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL;
-    CopyMemory((PinConnect + 1), DataFormat, DataFormat->FormatSize);
+
+    // get dataformat offset
+    DataFormat = (PKSDATAFORMAT)(PinConnect + 1);
+
+    // copy data format
+    DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat;
+    DataFormat->Flags = 0;
+    DataFormat->SampleSize = pmt->lSampleSize;
+    DataFormat->Reserved = 0;
+    CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID));
+    CopyMemory(&DataFormat->SubFormat,  &pmt->subtype, sizeof(GUID));
+    CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID));
+
+    if (pmt->cbFormat)
+    {
+        // copy extended format
+        CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat);
+    }
 
     // create pin
     hr = KsCreatePin(m_hFilter, PinConnect, GENERIC_WRITE, &m_hPin);
index 927a1dc..237b039 100644 (file)
 
 #include "precomp.h"
 
-const GUID KSPROPSETID_Pin                     = {0x8C134960, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
-const GUID KSINTERFACESETID_Standard           = {STATIC_KSINTERFACESETID_Standard};
+
 const GUID CLSID_KsClockForwarder              = {0x877e4351, 0x6fea, 0x11d0, {0xb8, 0x63, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}};
 const GUID CLSID_KsQualityForwarder            = {0xe05592e4, 0xc0b5, 0x11d0, {0xa4, 0x39, 0x00, 0xa0, 0xc9, 0x22, 0x31, 0x96}};
 const GUID CLSID_KsIBasicAudioInterfaceHandler = {0xb9f8ac3e, 0x0f71, 0x11d2, {0xb7, 0x2c, 0x00, 0xc0, 0x4f, 0xb6, 0xbd, 0x3d}};
-const GUID CLSID_Proxy                         = {0x17CCA71B, 0xECD7, 0x11D0, {0xB9, 0x08, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
 
 
+#ifndef _MSC_VER
+const GUID KSPROPSETID_Pin                     = {0x8C134960, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
+const GUID KSINTERFACESETID_Standard           = {STATIC_KSINTERFACESETID_Standard};
+const GUID CLSID_Proxy                         = {0x17CCA71B, 0xECD7, 0x11D0, {0xB9, 0x08, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+#endif
+
 static INTERFACE_TABLE InterfaceTable[] =
 {
     {&MEDIATYPE_Audio, CKsDataTypeHandler_Constructor},
@@ -258,7 +262,78 @@ KsGetMediaType(
     HANDLE         FilterHandle,
     ULONG          PinFactoryId)
 {
-    //UNIMPLEMENTED
+    HRESULT hr;
+    PKSMULTIPLE_ITEM ItemList;
+    int i = 0;
+    PKSDATAFORMAT DataFormat;
+
+    if (Position < 0)
+        return E_INVALIDARG;
+
+    // get current supported ranges
+    hr = KsGetMultiplePinFactoryItems(FilterHandle, PinFactoryId, KSPROPERTY_PIN_CONSTRAINEDDATARANGES, (PVOID*)&ItemList);
+    if (FAILED(hr))
+    {
+        // get standard dataranges
+        hr = KsGetMultiplePinFactoryItems(FilterHandle, PinFactoryId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&ItemList);
+
+        //check for success
+        if (FAILED(hr))
+            return hr;
+    }
+
+    if ((ULONG)Position >= ItemList->Count)
+    {
+        // out of bounds
+        CoTaskMemFree(ItemList);
+        return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NO_MORE_ITEMS);
+    }
+
+    // goto first datarange
+    DataFormat = (PKSDATAFORMAT)(ItemList + 1);
+
+    while(i != Position)
+    {
+        // goto next format;
+        DataFormat = (PKSDATAFORMAT)(ULONG_PTR)(DataFormat + DataFormat->FormatSize);
+        i++;
+    }
+
+
+    DataFormat->FormatSize -= sizeof(KSDATAFORMAT);
+    if (DataFormat->FormatSize)
+    {
+         // copy extra format buffer
+        AmMediaType->pbFormat = (BYTE*)CoTaskMemAlloc(DataFormat->FormatSize);
+        if (!AmMediaType->pbFormat)
+        {
+            // not enough memory
+            CoTaskMemFree(ItemList);
+            return E_OUTOFMEMORY;
+        }
+        // copy format buffer
+        CopyMemory(AmMediaType->pbFormat, (DataFormat + 1), DataFormat->FormatSize);
+        AmMediaType->cbFormat = DataFormat->FormatSize;
+    }
+    else
+    {
+        // no format buffer
+        AmMediaType->pbFormat = NULL;
+        AmMediaType->cbFormat = 0;
+    }
+
+    // copy type info
+    CopyMemory(&AmMediaType->majortype, &DataFormat->MajorFormat, sizeof(GUID));
+    CopyMemory(&AmMediaType->subtype, &DataFormat->SubFormat, sizeof(GUID));
+    CopyMemory(&AmMediaType->formattype, &DataFormat->Specifier, sizeof(GUID));
+    AmMediaType->bTemporalCompression = FALSE; //FIXME verify
+    AmMediaType->pUnk = NULL; //FIXME
+    AmMediaType->lSampleSize = DataFormat->SampleSize;
+    AmMediaType->bFixedSizeSamples = (AmMediaType->lSampleSize) ? TRUE : FALSE;
+
+    // free dataformat list
+    CoTaskMemFree(ItemList);
+
     return NOERROR;
 }
 
index cf8ecb4..f917d67 100644 (file)
@@ -1,9 +1,98 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource."
 
-#define REACTOS_VERSION_DLL
-#define REACTOS_STR_FILE_DESCRIPTION   "ReactOS WDM Streaming ActiveMovie Proxy\0"
-#define REACTOS_STR_INTERNAL_NAME      "ksproxy\0"
-#define REACTOS_STR_ORIGINAL_FILENAME  "ksproxy.ax\0"
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
 
-#include <reactos/reactx.h>
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Deutsch (Deutschland) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
+#ifdef _WIN32
+LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE 
+BEGIN
+    "resource.\0"
+END
+
+3 TEXTINCLUDE 
+BEGIN
+    "\r\0"
+END
+
+2 TEXTINCLUDE 
+BEGIN
+    "#include ""afxres.h""\r\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 5,3,2600,3264
+ PRODUCTVERSION 5,3,2600,3264
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040704b0"
+        BEGIN
+            VALUE "CompanyName", "ReactOS WDM Streaming ActiveMovie Proxy"
+            VALUE "FileDescription", "ReactOS WDM Streaming ActiveMovie Proxy"
+            VALUE "FileVersion", "5, 3, 2600, 3264"
+            VALUE "InternalName", "ksproxy"
+            VALUE "LegalCopyright", "Copyright (C) 2010"
+            VALUE "OriginalFilename", "ksproxy.dll"
+            VALUE "ProductName", "ReactOS WDM Streaming ActiveMovie Proxy"
+            VALUE "ProductVersion", "5, 3, 2600, 3264"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x407, 1200
+    END
+END
+
+#endif    // Deutsch (Deutschland) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+ /////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
 
-#include <reactos/version.rc>
index b29d12a..d21f383 100644 (file)
@@ -8,17 +8,21 @@
  */
 #include "precomp.h"
 
+#ifndef _MSC_VER
+const GUID IID_IKsPinFactory = {0xCD5EBE6BL, 0x8B6E, 0x11D1, {0x8A, 0xE0, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+#endif
+
 class COutputPin : public IPin,
-                  public IKsObject
+                   public IKsObject,
+                   public IKsPropertySet,
+                   public IStreamBuilder,
+                   public IKsPinFactory,
+                   public ISpecifyPropertyPages,
+//                   public IKsPinPipe,
+                   public IKsControl
 /*
                   public IQualityControl,
                   public IKsPinEx,
-                  public IKsPinPipe,
-                  public ISpecifyPropertyPages,
-                  public IStreamBuilder,
-                  public IKsPropertySet,
-                  public IKsPinFactory,
-                  public IKsControl,
                   public IKsAggregateControl
                   public IMediaSeeking,
                   public IAMStreamConfig,
@@ -38,12 +42,25 @@ public:
         InterlockedDecrement(&m_Ref);
         if (!m_Ref)
         {
-            delete this;
+            //delete this;
             return 0;
         }
         return m_Ref;
     }
 
+    //IKsPinPipe
+    HRESULT STDMETHODCALLTYPE KsGetPinFramingCache(PKSALLOCATOR_FRAMING_EX *FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
+    HRESULT STDMETHODCALLTYPE KsSetPinFramingCache(PKSALLOCATOR_FRAMING_EX FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
+    IPin* STDMETHODCALLTYPE KsGetConnectedPin();
+    IKsAllocatorEx* STDMETHODCALLTYPE KsGetPipe(KSPEEKOPERATION Operation);
+    HRESULT STDMETHODCALLTYPE KsSetPipe(IKsAllocatorEx *KsAllocator);
+    ULONG STDMETHODCALLTYPE KsGetPipeAllocatorFlag();
+    HRESULT STDMETHODCALLTYPE KsSetPipeAllocatorFlag(ULONG Flag);
+    GUID STDMETHODCALLTYPE KsGetPinBusCache();
+    HRESULT STDMETHODCALLTYPE KsSetPinBusCache(GUID Bus);
+    PWCHAR STDMETHODCALLTYPE KsGetPinName();
+    PWCHAR STDMETHODCALLTYPE KsGetFilterName();
+
     //IPin methods
     HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
     HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
@@ -61,17 +78,58 @@ public:
     HRESULT STDMETHODCALLTYPE EndFlush();
     HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
 
+    // ISpecifyPropertyPages
+    HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
+
     //IKsObject methods
     HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
 
+    //IKsPropertySet
+    HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData);
+    HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned);
+    HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport);
+
+    //IKsControl
+    HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned);
+    HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned);
+    HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned);
+
+    //IStreamBuilder
+    HRESULT STDMETHODCALLTYPE Render(IPin *ppinOut, IGraphBuilder *pGraph);
+    HRESULT STDMETHODCALLTYPE Backout(IPin *ppinOut, IGraphBuilder *pGraph);
+
+    //IKsPinFactory
+    HRESULT STDMETHODCALLTYPE KsPinFactory(ULONG* PinFactory);
 
-    COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName){};
-    virtual ~COutputPin(){};
+    COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId);
+    virtual ~COutputPin();
 
 protected:
     LONG m_Ref;
     IBaseFilter * m_ParentFilter;
     LPCWSTR m_PinName;
+    HANDLE m_hPin;
+    ULONG m_PinId;
+    IKsObject * m_KsObjectParent;
+    IPin * m_Pin;
+};
+
+COutputPin::~COutputPin()
+{
+    if (m_KsObjectParent)
+        m_KsObjectParent->Release();
+}
+
+COutputPin::COutputPin(
+    IBaseFilter * ParentFilter,
+    LPCWSTR PinName,
+    ULONG PinId) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName), m_hPin(0), m_PinId(PinId), m_KsObjectParent(0), m_Pin(0)
+{
+    HRESULT hr;
+
+    hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&m_KsObjectParent);
+    assert(hr == S_OK);
+
 };
 
 HRESULT
@@ -94,6 +152,41 @@ COutputPin::QueryInterface(
         reinterpret_cast<IKsObject*>(*Output)->AddRef();
         return NOERROR;
     }
+    else if (IsEqualGUID(refiid, IID_IKsPropertySet))
+    {
+        *Output = (IKsPropertySet*)(this);
+        reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IKsControl))
+    {
+        *Output = (IKsControl*)(this);
+        reinterpret_cast<IKsControl*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IStreamBuilder))
+    {
+        *Output = (IStreamBuilder*)(this);
+        reinterpret_cast<IStreamBuilder*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IKsPinFactory))
+    {
+        *Output = (IKsPinFactory*)(this);
+        reinterpret_cast<IKsPinFactory*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
+    {
+        *Output = (ISpecifyPropertyPages*)(this);
+        reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IBaseFilter))
+    {
+        OutputDebugStringW(L"COutputPin::QueryInterface query IID_IBaseFilter\n");
+        DebugBreak();
+    }
 
     WCHAR Buffer[MAX_PATH];
     LPOLESTR lpstr;
@@ -105,6 +198,60 @@ COutputPin::QueryInterface(
     return E_NOINTERFACE;
 }
 
+//-------------------------------------------------------------------
+// ISpecifyPropertyPages
+//
+
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::GetPages(CAUUID *pPages)
+{
+    OutputDebugStringW(L"COutputPin::GetPages NotImplemented\n");
+
+    if (!pPages)
+        return E_POINTER;
+
+    pPages->cElems = 0;
+    pPages->pElems = NULL;
+
+    return S_OK;
+}
+
+//-------------------------------------------------------------------
+// IKsPinFactory
+//
+
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::KsPinFactory(
+    ULONG* PinFactory)
+{
+    *PinFactory = m_PinId;
+    return S_OK;
+}
+
+
+//-------------------------------------------------------------------
+// IStreamBuilder
+//
+
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::Render(
+    IPin *ppinOut,
+    IGraphBuilder *pGraph)
+{
+    return S_OK;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::Backout(
+    IPin *ppinOut, 
+    IGraphBuilder *pGraph)
+{
+    return S_OK;
+}
 //-------------------------------------------------------------------
 // IKsObject
 //
@@ -112,13 +259,161 @@ HANDLE
 STDMETHODCALLTYPE
 COutputPin::KsGetObjectHandle()
 {
-    OutputDebugStringW(L"COutputPin::KsGetObjectHandle CALLED\n");
+    assert(m_hPin);
+    return m_hPin;
+}
 
-    //FIXME
-    // return pin handle
-    return NULL;
+//-------------------------------------------------------------------
+// IKsControl
+//
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::KsProperty(
+    PKSPROPERTY Property,
+    ULONG PropertyLength,
+    LPVOID PropertyData,
+    ULONG DataLength,
+    ULONG* BytesReturned)
+{
+    assert(m_hPin != 0);
+    return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
+}
+
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::KsMethod(
+    PKSMETHOD Method,
+    ULONG MethodLength,
+    LPVOID MethodData,
+    ULONG DataLength,
+    ULONG* BytesReturned)
+{
+    assert(m_hPin != 0);
+    return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
 }
 
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::KsEvent(
+    PKSEVENT Event,
+    ULONG EventLength,
+    LPVOID EventData,
+    ULONG DataLength,
+    ULONG* BytesReturned)
+{
+    assert(m_hPin != 0);
+
+    if (EventLength)
+        return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
+    else
+        return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
+}
+
+
+//-------------------------------------------------------------------
+// IKsPropertySet
+//
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::Set(
+    REFGUID guidPropSet,
+    DWORD dwPropID,
+    LPVOID pInstanceData,
+    DWORD cbInstanceData,
+    LPVOID pPropData,
+    DWORD cbPropData)
+{
+    ULONG BytesReturned;
+
+    if (cbInstanceData)
+    {
+        PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
+        if (!Property)
+            return E_OUTOFMEMORY;
+
+        Property->Set = guidPropSet;
+        Property->Id = dwPropID;
+        Property->Flags = KSPROPERTY_TYPE_SET;
+
+        CopyMemory((Property+1), pInstanceData, cbInstanceData);
+
+        HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
+        CoTaskMemFree(Property);
+        return hr;
+    }
+    else
+    {
+        KSPROPERTY Property;
+
+        Property.Set = guidPropSet;
+        Property.Id = dwPropID;
+        Property.Flags = KSPROPERTY_TYPE_SET;
+
+        HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
+        return hr;
+    }
+}
+
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::Get(
+    REFGUID guidPropSet,
+    DWORD dwPropID,
+    LPVOID pInstanceData,
+    DWORD cbInstanceData,
+    LPVOID pPropData,
+    DWORD cbPropData,
+    DWORD *pcbReturned)
+{
+    ULONG BytesReturned;
+
+    if (cbInstanceData)
+    {
+        PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
+        if (!Property)
+            return E_OUTOFMEMORY;
+
+        Property->Set = guidPropSet;
+        Property->Id = dwPropID;
+        Property->Flags = KSPROPERTY_TYPE_GET;
+
+        CopyMemory((Property+1), pInstanceData, cbInstanceData);
+
+        HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
+        CoTaskMemFree(Property);
+        return hr;
+    }
+    else
+    {
+        KSPROPERTY Property;
+
+        Property.Set = guidPropSet;
+        Property.Id = dwPropID;
+        Property.Flags = KSPROPERTY_TYPE_GET;
+
+        HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
+        return hr;
+    }
+}
+
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::QuerySupported(
+    REFGUID guidPropSet,
+    DWORD dwPropID,
+    DWORD *pTypeSupport)
+{
+    KSPROPERTY Property;
+    ULONG BytesReturned;
+
+    Property.Set = guidPropSet;
+    Property.Id = dwPropID;
+    Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
+
+    return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
+}
+
+
 //-------------------------------------------------------------------
 // IPin interface
 //
@@ -126,30 +421,92 @@ HRESULT
 STDMETHODCALLTYPE
 COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
 {
+    AM_MEDIA_TYPE MediaType;
+    HRESULT hr;
+    HANDLE hFilter;
+
     OutputDebugStringW(L"COutputPin::Connect called\n");
-    return E_NOTIMPL;
+    if (pmt)
+    {
+        hr = pReceivePin->QueryAccept(pmt);
+        if (FAILED(hr))
+            return hr;
+    }
+    else
+    {
+        // get parent filter handle
+        hFilter = m_KsObjectParent->KsGetObjectHandle();
+
+        // get media type count
+        ZeroMemory(&MediaType, sizeof(AM_MEDIA_TYPE));
+        hr = KsGetMediaType(0, &MediaType, hFilter, m_PinId);
+        if (FAILED(hr))
+            return hr;
+
+        // query accept
+        hr = pReceivePin->QueryAccept(&MediaType);
+        if (FAILED(hr))
+            return hr;
+
+         pmt = &MediaType;
+    }
+
+    //FIXME create pin handle
+
+    // receive connection;
+    hr = pReceivePin->ReceiveConnection((IPin*)this, pmt);
+    if (SUCCEEDED(hr))
+    {
+        // increment reference count
+        pReceivePin->AddRef();
+        m_Pin = pReceivePin;
+        OutputDebugStringW(L"COutputPin::Connect success\n");
+    }
+
+    return hr;
 }
 
 HRESULT
 STDMETHODCALLTYPE
 COutputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
 {
-    OutputDebugStringW(L"COutputPin::ReceiveConnection called\n");
-    return E_NOTIMPL;
+    return E_UNEXPECTED;
 }
 HRESULT
 STDMETHODCALLTYPE
 COutputPin::Disconnect( void)
 {
-    OutputDebugStringW(L"COutputPin::Disconnect called\n");
-    return E_NOTIMPL;
+    if (!m_Pin)
+    {
+        // pin was not connected
+        return S_FALSE;
+    }
+
+    //FIXME
+    //check if filter is active
+
+    m_Pin->Release();
+    m_Pin = NULL;
+
+    OutputDebugStringW(L"COutputPin::Disconnect\n");
+    return S_OK;
 }
 HRESULT
 STDMETHODCALLTYPE
 COutputPin::ConnectedTo(IPin **pPin)
 {
+    if (!pPin)
+        return E_POINTER;
+
+    if (m_Pin)
+    {
+        // increment reference count
+        m_Pin->AddRef();
+        *pPin = m_Pin;
+        return S_OK;
+    }
+
     *pPin = NULL;
-    OutputDebugStringW(L"COutputPin::ConnectedTo called\n");
     return VFW_E_NOT_CONNECTED;
 }
 HRESULT
@@ -204,8 +561,56 @@ HRESULT
 STDMETHODCALLTYPE
 COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
 {
+    HRESULT hr;
+    ULONG MediaTypeCount = 0, Index;
+    AM_MEDIA_TYPE * MediaTypes;
+    HANDLE hFilter;
+
     OutputDebugStringW(L"COutputPin::EnumMediaTypes called\n");
-    return E_NOTIMPL;
+
+    if (!m_KsObjectParent)
+    {
+        // no interface
+        return E_NOINTERFACE;
+    }
+
+    // get parent filter handle
+    hFilter = m_KsObjectParent->KsGetObjectHandle();
+
+    // query media type count
+    hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount);
+    if (FAILED(hr) || !MediaTypeCount)
+       {
+        OutputDebugStringW(L"COutputPin::EnumMediaTypes failed1\n");
+        return hr;
+       }
+
+    // allocate media types
+    MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
+    if (!MediaTypes)
+    {
+        // not enough memory
+        OutputDebugStringW(L"COutputPin::EnumMediaTypes CoTaskMemAlloc\n");
+        return E_OUTOFMEMORY;
+    }
+
+    // zero media types
+    ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
+
+    for(Index = 0; Index < MediaTypeCount; Index++)
+    {
+        // get media type
+        hr = KsGetMediaType(Index, &MediaTypes[Index], hFilter, m_PinId);
+        if (FAILED(hr))
+        {
+            // failed
+            CoTaskMemFree(MediaTypes);
+        OutputDebugStringW(L"COutputPin::EnumMediaTypes failed2\n");
+            return hr;
+        }
+    }
+
+    return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum);
 }
 HRESULT
 STDMETHODCALLTYPE
@@ -248,10 +653,11 @@ WINAPI
 COutputPin_Constructor(
     IBaseFilter * ParentFilter,
     LPCWSTR PinName,
+    ULONG PinId,
     REFIID riid,
     LPVOID * ppv)
 {
-    COutputPin * handler = new COutputPin(ParentFilter, PinName);
+    COutputPin * handler = new COutputPin(ParentFilter, PinName, PinId);
 
     if (!handler)
         return E_OUTOFMEMORY;
index 32953e9..5078dae 100644 (file)
@@ -18,6 +18,7 @@
 #include <setupapi.h>
 #include <stdio.h>
 #include <vector>
+#include <assert.h>
 //#include <debug.h>
 
 typedef HRESULT (CALLBACK *LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
@@ -117,6 +118,7 @@ WINAPI
 COutputPin_Constructor(
     IBaseFilter * ParentFilter,
     LPCWSTR PinName,
+    ULONG PinId,
     REFIID riid,
     LPVOID * ppv);
 
@@ -137,4 +139,4 @@ CEnumMediaTypes_fnConstructor(
     REFIID riid,
     LPVOID * ppv);
 
-
+extern const GUID IID_IKsObject;
index 0ff397c..d613962 100644 (file)
  */
 #include "precomp.h"
 
+#ifndef _MSC_VER
 const GUID IID_IPersistPropertyBag = {0x37D84F60, 0x42CB, 0x11CE, {0x81, 0x35, 0x00, 0xAA, 0x00, 0x4B, 0xB8, 0x51}};
 const GUID GUID_NULL                     = {0x00000000L, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+#endif
+
 const GUID IID_IBDA_DeviceControl = {0xFD0A5AF3, 0xB41D, 0x11d2, {0x9C, 0x95, 0x00, 0xC0, 0x4F, 0x79, 0x71, 0xE0}};
+const GUID IID_IKsAggregateControl = {0x7F40EAC0, 0x3947, 0x11D2, {0x87, 0x4E, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID IID_IKsClockPropertySet = {0x5C5CBD84, 0xE755, 0x11D0, {0xAC, 0x18, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID IID_IKsTopology             = {0x28F54683, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+
 /*
     Needs IKsClock, IKsNotifyEvent
 */
 
-class CKsProxy : public IBaseFilter,
-                 public IAMovieSetup,
-                 public IPersistPropertyBag,
-                 public IKsObject
-/*
-                 public IPersistStream,
-                 public ISpecifyPropertyPages,
-                 public IReferenceClock,
-                 public IMediaSeeking,
-                 public IKsObject,
-                 public IKsPropertySet,
-                 public IKsClockPropertySet,
-                 public IAMFilterMiscFlags,
-                 public IKsControl,
-                 public IKsTopology,
-                 public IKsAggregateControl,
-                 public IAMDeviceRemoval
-*/
+class CKsProxy : public IBaseFilter,
+                 public IAMovieSetup,
+                 public IPersistPropertyBag,
+                 public IKsObject,
+                 public IPersistStream,
+                 public IAMDeviceRemoval,
+                 public ISpecifyPropertyPages,
+                 public IReferenceClock,
+                 public IMediaSeeking,
+                 public IKsPropertySet,
+                 public IKsClockPropertySet,
+                 public IAMFilterMiscFlags,
+                 public IKsControl,
+                 public IKsTopology,
+                 public IKsAggregateControl
+
+{
+public:
+    typedef std::vector<IUnknown *>ProxyPluginVector;
+    typedef std::vector<IPin *> PinVector;
+
+    STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
+
+    STDMETHODIMP_(ULONG) AddRef()
+    {
+        InterlockedIncrement(&m_Ref);
+        return m_Ref;
+    }
+    STDMETHODIMP_(ULONG) Release()
+    {
+        InterlockedDecrement(&m_Ref);
+        if (!m_Ref)
+        {
+            delete this;
+            return 0;
+        }
+        return m_Ref;
+    }
+
+    // IBaseFilter methods
+    HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
+    HRESULT STDMETHODCALLTYPE Stop( void);
+    HRESULT STDMETHODCALLTYPE Pause( void);
+    HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart);
+    HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *State);
+    HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock);
+    HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **pClock);
+    HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum);
+    HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin);
+    HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo);
+    HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName);
+    HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo);
+
+    //IReferenceClock
+    HRESULT STDMETHODCALLTYPE GetTime(REFERENCE_TIME *pTime);
+    HRESULT STDMETHODCALLTYPE AdviseTime(REFERENCE_TIME baseTime, REFERENCE_TIME streamTime, HEVENT hEvent, DWORD_PTR *pdwAdviseCookie);
+    HRESULT STDMETHODCALLTYPE AdvisePeriodic(REFERENCE_TIME startTime, REFERENCE_TIME periodTime, HSEMAPHORE hSemaphore, DWORD_PTR *pdwAdviseCookie);
+    HRESULT STDMETHODCALLTYPE Unadvise(DWORD_PTR dwAdviseCookie);
+
+    //IMediaSeeking
+    HRESULT STDMETHODCALLTYPE GetCapabilities(DWORD *pCapabilities);
+    HRESULT STDMETHODCALLTYPE CheckCapabilities(DWORD *pCapabilities);
+    HRESULT STDMETHODCALLTYPE IsFormatSupported(const GUID *pFormat);
+    HRESULT STDMETHODCALLTYPE QueryPreferredFormat(GUID *pFormat);
+    HRESULT STDMETHODCALLTYPE GetTimeFormat(GUID *pFormat);
+    HRESULT STDMETHODCALLTYPE IsUsingTimeFormat(const GUID *pFormat);
+    HRESULT STDMETHODCALLTYPE SetTimeFormat(const GUID *pFormat);
+    HRESULT STDMETHODCALLTYPE GetDuration(LONGLONG *pDuration);
+    HRESULT STDMETHODCALLTYPE GetStopPosition(LONGLONG *pStop);
+    HRESULT STDMETHODCALLTYPE GetCurrentPosition(LONGLONG *pCurrent);
+    HRESULT STDMETHODCALLTYPE ConvertTimeFormat(LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat);
+    HRESULT STDMETHODCALLTYPE SetPositions(LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags);
+    HRESULT STDMETHODCALLTYPE GetPositions(LONGLONG *pCurrent, LONGLONG *pStop);
+    HRESULT STDMETHODCALLTYPE GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest);
+    HRESULT STDMETHODCALLTYPE SetRate(double dRate);
+    HRESULT STDMETHODCALLTYPE GetRate(double *pdRate);
+    HRESULT STDMETHODCALLTYPE GetPreroll(LONGLONG *pllPreroll);
+
+    //IKsPropertySet
+    HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData);
+    HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned);
+    HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport);
+
+    //IAMFilterMiscFlags
+    ULONG STDMETHODCALLTYPE GetMiscFlags( void);
+
+    //IKsControl
+    HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned);
+    HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned);
+    HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned);
+
+    //IKsTopolology
+    HRESULT STDMETHODCALLTYPE CreateNodeInstance(ULONG NodeId, ULONG Flags, ACCESS_MASK DesiredAccess, IUnknown* UnkOuter, REFGUID InterfaceId, LPVOID* Interface);
+
+    //IKsAggregateControl
+    HRESULT STDMETHODCALLTYPE KsAddAggregate(IN REFGUID AggregateClass);
+    HRESULT STDMETHODCALLTYPE KsRemoveAggregate(REFGUID AggregateClass);
+
+    //IKsClockPropertySet
+    HRESULT STDMETHODCALLTYPE KsGetTime(LONGLONG* Time);
+    HRESULT STDMETHODCALLTYPE KsSetTime(LONGLONG Time);
+    HRESULT STDMETHODCALLTYPE KsGetPhysicalTime(LONGLONG* Time);
+    HRESULT STDMETHODCALLTYPE KsSetPhysicalTime(LONGLONG Time);
+    HRESULT STDMETHODCALLTYPE KsGetCorrelatedTime(KSCORRELATED_TIME* CorrelatedTime);
+    HRESULT STDMETHODCALLTYPE KsSetCorrelatedTime(KSCORRELATED_TIME* CorrelatedTime);
+    HRESULT STDMETHODCALLTYPE KsGetCorrelatedPhysicalTime(KSCORRELATED_TIME* CorrelatedTime);
+    HRESULT STDMETHODCALLTYPE KsSetCorrelatedPhysicalTime(KSCORRELATED_TIME* CorrelatedTime);
+    HRESULT STDMETHODCALLTYPE KsGetResolution(KSRESOLUTION* Resolution);
+    HRESULT STDMETHODCALLTYPE KsGetState(KSSTATE* State);
+
+
+    //IAMovieSetup methods
+    HRESULT STDMETHODCALLTYPE Register( void);
+    HRESULT STDMETHODCALLTYPE Unregister( void);
+
+    // IPersistPropertyBag methods
+    HRESULT STDMETHODCALLTYPE InitNew( void);
+    HRESULT STDMETHODCALLTYPE Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog);
+    HRESULT STDMETHODCALLTYPE Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties);
+
+    // IKsObject
+    HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
+
+    //IAMDeviceRemoval
+    HRESULT STDMETHODCALLTYPE DeviceInfo(CLSID *pclsidInterfaceClass, LPWSTR *pwszSymbolicLink);
+    HRESULT STDMETHODCALLTYPE Reassociate(void);
+    HRESULT STDMETHODCALLTYPE Disassociate( void);
+
+    //IPersistStream
+    HRESULT STDMETHODCALLTYPE IsDirty( void);
+    HRESULT STDMETHODCALLTYPE Load(IStream *pStm);
+    HRESULT STDMETHODCALLTYPE Save(IStream *pStm, BOOL fClearDirty);
+    HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize);
+
+    // ISpecifyPropertyPages
+    HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
+
+
+    CKsProxy() : m_Ref(0), m_pGraph(0), m_ReferenceClock(0), m_FilterState(State_Stopped), m_hDevice(0), m_Plugins(), m_Pins(), m_DevicePath(0) {};
+    ~CKsProxy()
+    {
+        if (m_hDevice)
+            CloseHandle(m_hDevice);
+    };
+
+    HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids);
+    HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids);
+    HRESULT STDMETHODCALLTYPE GetNumberOfPins(PULONG NumPins);
+    HRESULT STDMETHODCALLTYPE GetPinInstanceCount(ULONG PinId, PKSPIN_CINSTANCES Instances);
+    HRESULT STDMETHODCALLTYPE GetPinDataflow(ULONG PinId, KSPIN_DATAFLOW * DataFlow);
+    HRESULT STDMETHODCALLTYPE GetPinName(ULONG PinId, KSPIN_DATAFLOW DataFlow, ULONG PinCount, LPWSTR * OutPinName);
+    HRESULT STDMETHODCALLTYPE GetPinCommunication(ULONG PinId, KSPIN_COMMUNICATION * Communication);
+    HRESULT STDMETHODCALLTYPE CreatePins();
+protected:
+    LONG m_Ref;
+    IFilterGraph *m_pGraph;
+    IReferenceClock * m_ReferenceClock;
+    FILTER_STATE m_FilterState;
+    HANDLE m_hDevice;
+    ProxyPluginVector m_Plugins;
+    PinVector m_Pins;
+    LPWSTR m_DevicePath;
+    CLSID m_DeviceInterfaceGUID;
+};
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::QueryInterface(
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    *Output = (PVOID)0xDEADDEAD;//NULL;
+
+    if (IsEqualGUID(refiid, IID_IUnknown) ||
+        IsEqualGUID(refiid, IID_IBaseFilter))
+    {
+        *Output = PVOID(this);
+        reinterpret_cast<IUnknown*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IPersistPropertyBag))
+    {
+        *Output = (IPersistPropertyBag*)(this);
+        reinterpret_cast<IPersistPropertyBag*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IAMDeviceRemoval))
+    {
+        *Output = (IAMDeviceRemoval*)(this);
+        reinterpret_cast<IAMDeviceRemoval*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IPersistStream))
+    {
+        *Output = (IPersistStream*)(this);
+        reinterpret_cast<IPersistStream*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IKsObject))
+    {
+        *Output = (IKsObject*)(this);
+        reinterpret_cast<IKsObject*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IReferenceClock))
+    {
+        *Output = (IReferenceClock*)(this);
+        reinterpret_cast<IReferenceClock*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IMediaSeeking))
+    {
+        *Output = (IMediaSeeking*)(this);
+        reinterpret_cast<IMediaSeeking*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IAMFilterMiscFlags))
+    {
+        *Output = (IAMFilterMiscFlags*)(this);
+        reinterpret_cast<IAMFilterMiscFlags*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IKsControl))
+    {
+        *Output = (IKsControl*)(this);
+        reinterpret_cast<IKsControl*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IKsPropertySet))
+    {
+        *Output = (IKsPropertySet*)(this);
+        reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IKsTopology))
+    {
+        *Output = (IKsTopology*)(this);
+        reinterpret_cast<IKsTopology*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IKsAggregateControl))
+    {
+        *Output = (IKsAggregateControl*)(this);
+        reinterpret_cast<IKsAggregateControl*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IKsClockPropertySet))
+    {
+        *Output = (IKsClockPropertySet*)(this);
+        reinterpret_cast<IKsClockPropertySet*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
+    {
+        *Output = (ISpecifyPropertyPages*)(this);
+        reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef();
+        return NOERROR;
+    }
+
+    for(ULONG Index = 0; Index < m_Plugins.size(); Index++)
+    {
+        if (m_Pins[Index])
+        {
+            HRESULT hr = m_Plugins[Index]->QueryInterface(refiid, Output);
+            if (SUCCEEDED(hr))
+            {
+                WCHAR Buffer[100];
+                LPOLESTR lpstr;
+                StringFromCLSID(refiid, &lpstr);
+                swprintf(Buffer, L"CKsProxy::QueryInterface plugin %lu supports interface %s\n", Index, lpstr);
+                OutputDebugStringW(Buffer);
+                CoTaskMemFree(lpstr);
+                return hr;
+            }
+        }
+    }
+
+    WCHAR Buffer[MAX_PATH];
+    LPOLESTR lpstr;
+    StringFromCLSID(refiid, &lpstr);
+    swprintf(Buffer, L"CKsProxy::QueryInterface: NoInterface for %s !!!\n", lpstr);
+    OutputDebugStringW(Buffer);
+    CoTaskMemFree(lpstr);
+
+
+    return E_NOINTERFACE;
+}
+
+//-------------------------------------------------------------------
+// ISpecifyPropertyPages
+//
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::GetPages(CAUUID *pPages)
+{
+    OutputDebugStringW(L"CKsProxy::GetPages NotImplemented\n");
+
+    if (!pPages)
+        return E_POINTER;
+
+    pPages->cElems = 0;
+    pPages->pElems = NULL;
+
+    return S_OK;
+}
+
+//-------------------------------------------------------------------
+// IKsClockPropertySet interface
+//
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::KsGetTime(
+    LONGLONG* Time)
+{
+    OutputDebugStringW(L"CKsProxy::KsGetTime NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::KsSetTime(
+    LONGLONG Time)
+{
+    OutputDebugStringW(L"CKsProxy::KsSetTime NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::KsGetPhysicalTime(
+    LONGLONG* Time)
+{
+    OutputDebugStringW(L"CKsProxy::KsGetPhysicalTime NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::KsSetPhysicalTime(
+    LONGLONG Time)
+{
+    OutputDebugStringW(L"CKsProxy::KsSetPhysicalTime NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::KsGetCorrelatedTime(
+    KSCORRELATED_TIME* CorrelatedTime)
+{
+    OutputDebugStringW(L"CKsProxy::KsGetCorrelatedTime NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::KsSetCorrelatedTime(
+    KSCORRELATED_TIME* CorrelatedTime)
+{
+    OutputDebugStringW(L"CKsProxy::KsSetCorrelatedTime NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::KsGetCorrelatedPhysicalTime(
+    KSCORRELATED_TIME* CorrelatedTime)
+{
+    OutputDebugStringW(L"CKsProxy::KsGetCorrelatedPhysicalTime NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::KsSetCorrelatedPhysicalTime(
+    KSCORRELATED_TIME* CorrelatedTime)
+{
+    OutputDebugStringW(L"CKsProxy::KsSetCorrelatedPhysicalTime NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::KsGetResolution(
+    KSRESOLUTION* Resolution)
+{
+    OutputDebugStringW(L"CKsProxy::KsGetResolution NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::KsGetState(
+    KSSTATE* State)
+{
+    OutputDebugStringW(L"CKsProxy::KsGetState NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+//-------------------------------------------------------------------
+// IReferenceClock interface
+//
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::GetTime(
+    REFERENCE_TIME *pTime)
+{
+    OutputDebugStringW(L"CKsProxy::GetTime NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::AdviseTime(
+    REFERENCE_TIME baseTime,
+    REFERENCE_TIME streamTime,
+    HEVENT hEvent,
+    DWORD_PTR *pdwAdviseCookie)
+{
+    OutputDebugStringW(L"CKsProxy::AdviseTime NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::AdvisePeriodic(
+    REFERENCE_TIME startTime,
+    REFERENCE_TIME periodTime,
+    HSEMAPHORE hSemaphore,
+    DWORD_PTR *pdwAdviseCookie)
+{
+    OutputDebugStringW(L"CKsProxy::AdvisePeriodic NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::Unadvise(
+    DWORD_PTR dwAdviseCookie)
+{
+    OutputDebugStringW(L"CKsProxy::Unadvise NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+//-------------------------------------------------------------------
+// IMediaSeeking interface
+//
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::GetCapabilities(
+    DWORD *pCapabilities)
+{
+    OutputDebugStringW(L"CKsProxy::GetCapabilities NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::CheckCapabilities(
+    DWORD *pCapabilities)
+{
+    OutputDebugStringW(L"CKsProxy::CheckCapabilities NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::IsFormatSupported(
+    const GUID *pFormat)
+{
+    KSPROPERTY Property;
+    PKSMULTIPLE_ITEM FormatList;
+    LPGUID pGuid;
+    ULONG Index;
+    HRESULT hr = S_FALSE;
+    ULONG BytesReturned;
+
+    OutputDebugStringW(L"CKsProxy::IsFormatSupported\n");
+
+    if (!pFormat)
+        return E_POINTER;
+
+    Property.Set = KSPROPSETID_MediaSeeking;
+    Property.Id = KSPROPERTY_MEDIASEEKING_FORMATS;
+    Property.Flags = KSPROPERTY_TYPE_GET;
+
+    // query for format size list
+    hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &BytesReturned);
+
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA))
+    {
+        // allocate format list
+        FormatList = (PKSMULTIPLE_ITEM)CoTaskMemAlloc(BytesReturned);
+        if (!FormatList)
+        {
+            // not enough memory
+            return E_OUTOFMEMORY;
+        }
+
+        // get format list
+        hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)FormatList, BytesReturned, &BytesReturned);
+        if (FAILED(hr))
+        {
+            // failed to query format list
+            CoTaskMemFree(FormatList);
+            return hr;
+        }
+
+        //iterate through format list
+        pGuid = (LPGUID)(FormatList + 1);
+        for(Index = 0; Index < FormatList->Count; Index++)
+        {
+            if (IsEqualGUID(*pGuid, *pFormat))
+            {
+                OutputDebugStringW(L"CKsProxy::IsFormatSupported found format\n");
+                CoTaskMemFree(FormatList);
+                return S_OK;
+            }
+            pGuid++;
+        }
+
+        OutputDebugStringW(L"CKsProxy::IsFormatSupported FormatNotFound\n");
+        // free format list
+        CoTaskMemFree(FormatList);
+    }
+
+    // check if all plugins support it
+    for(Index = 0; Index < m_Plugins.size(); Index++)
+    {
+        // get plugin
+        IUnknown * Plugin = m_Plugins[Index];
+
+        if (!Plugin)
+            continue;
+
+        // query for IMediaSeeking interface
+        IMediaSeeking *pSeek = NULL;
+        hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+        if (FAILED(hr))
+        {
+            // plugin does not support interface
+            hr = S_FALSE;
+            OutputDebugStringW(L"CKsProxy::IsFormatSupported plugin does not support IMediaSeeking interface\n");
+            break;
+        }
+
+        // query if it is supported
+        hr = pSeek->IsFormatSupported(pFormat);
+        // release interface
+        pSeek->Release();
+
+        if (FAILED(hr) || hr == S_FALSE)
+            break;
+    }
+
+    return hr;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::QueryPreferredFormat(
+    GUID *pFormat)
+{
+    OutputDebugStringW(L"CKsProxy::QueryPreferredFormat NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::GetTimeFormat(
+    GUID *pFormat)
+{
+    OutputDebugStringW(L"CKsProxy::GetTimeFormat NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::IsUsingTimeFormat(
+    const GUID *pFormat)
+{
+    OutputDebugStringW(L"CKsProxy::IsUsingTimeFormat NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::SetTimeFormat(
+    const GUID *pFormat)
+{
+    OutputDebugStringW(L"CKsProxy::SetTimeFormat NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::GetDuration(
+    LONGLONG *pDuration)
+{
+    OutputDebugStringW(L"CKsProxy::GetDuration NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::GetStopPosition(
+    LONGLONG *pStop)
+{
+    OutputDebugStringW(L"CKsProxy::GetStopPosition NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::GetCurrentPosition(
+    LONGLONG *pCurrent)
+{
+    OutputDebugStringW(L"CKsProxy::GetCurrentPosition NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::ConvertTimeFormat(
+    LONGLONG *pTarget,
+    const GUID *pTargetFormat,
+    LONGLONG Source,
+    const GUID *pSourceFormat)
+{
+    OutputDebugStringW(L"CKsProxy::ConvertTimeFormat NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::SetPositions(
+    LONGLONG *pCurrent,
+    DWORD dwCurrentFlags,
+    LONGLONG *pStop,
+    DWORD dwStopFlags)
+{
+    OutputDebugStringW(L"CKsProxy::SetPositions NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::GetPositions(
+    LONGLONG *pCurrent,
+    LONGLONG *pStop)
+{
+    OutputDebugStringW(L"CKsProxy::GetPositions NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::GetAvailable(
+    LONGLONG *pEarliest,
+    LONGLONG *pLatest)
+{
+    OutputDebugStringW(L"CKsProxy::GetAvailable NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::SetRate(
+    double dRate)
+{
+    OutputDebugStringW(L"CKsProxy::SetRate NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::GetRate(
+    double *pdRate)
+{
+    OutputDebugStringW(L"CKsProxy::GetRate NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::GetPreroll(
+    LONGLONG *pllPreroll)
+{
+    OutputDebugStringW(L"CKsProxy::GetPreroll NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+//-------------------------------------------------------------------
+// IAMFilterMiscFlags interface
+//
+
+ULONG
+STDMETHODCALLTYPE
+CKsProxy::GetMiscFlags()
+{
+    ULONG Index;
+    ULONG Flags = 0;
+    HRESULT hr;
+    PIN_DIRECTION PinDirection;
+    KSPIN_COMMUNICATION Communication;
+
+    for(Index = 0; Index < m_Pins.size(); Index++)
+    {
+        // get current pin
+        IPin * pin = m_Pins[Index];
+        // query direction
+        hr = pin->QueryDirection(&PinDirection);
+        if (SUCCEEDED(hr))
+        {
+            if (PinDirection == PINDIR_INPUT)
+            {
+                if (SUCCEEDED(GetPinCommunication(Index, //FIXME verify PinId
+                                        &Communication)))
+                {
+                    if (Communication == KSPIN_COMMUNICATION_NONE || Communication == KSPIN_COMMUNICATION_BRIDGE)
+                    {
+                        Flags |= AM_FILTER_MISC_FLAGS_IS_SOURCE;
+                    }
+                }
+            }
+        }
+    }
+
+    OutputDebugStringW(L"CKsProxy::GetMiscFlags stub\n");
+    return Flags;
+}
+
+//-------------------------------------------------------------------
+// IKsControl
+//
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::KsProperty(
+    PKSPROPERTY Property,
+    ULONG PropertyLength,
+    LPVOID PropertyData,
+    ULONG DataLength,
+    ULONG* BytesReturned)
+{
+    assert(m_hDevice != 0);
+    return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::KsMethod(
+    PKSMETHOD Method,
+    ULONG MethodLength,
+    LPVOID MethodData,
+    ULONG DataLength,
+    ULONG* BytesReturned)
+{
+    assert(m_hDevice != 0);
+    return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::KsEvent(
+    PKSEVENT Event,
+    ULONG EventLength,
+    LPVOID EventData,
+    ULONG DataLength,
+    ULONG* BytesReturned)
+{
+    assert(m_hDevice != 0);
+
+    if (EventLength)
+        return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
+    else
+        return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
+}
+
+
+//-------------------------------------------------------------------
+// IKsPropertySet
+//
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::Set(
+    REFGUID guidPropSet,
+    DWORD dwPropID,
+    LPVOID pInstanceData,
+    DWORD cbInstanceData,
+    LPVOID pPropData,
+    DWORD cbPropData)
+{
+    ULONG BytesReturned;
+
+    if (cbInstanceData)
+    {
+        PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
+        if (!Property)
+            return E_OUTOFMEMORY;
+
+        Property->Set = guidPropSet;
+        Property->Id = dwPropID;
+        Property->Flags = KSPROPERTY_TYPE_SET;
+
+        CopyMemory((Property+1), pInstanceData, cbInstanceData);
+
+        HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
+        CoTaskMemFree(Property);
+        return hr;
+    }
+    else
+    {
+        KSPROPERTY Property;
+
+        Property.Set = guidPropSet;
+        Property.Id = dwPropID;
+        Property.Flags = KSPROPERTY_TYPE_SET;
+
+        HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
+        return hr;
+    }
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::Get(
+    REFGUID guidPropSet,
+    DWORD dwPropID,
+    LPVOID pInstanceData,
+    DWORD cbInstanceData,
+    LPVOID pPropData,
+    DWORD cbPropData,
+    DWORD *pcbReturned)
 {
-public:
-    typedef std::vector<IUnknown *>ProxyPluginVector;
-    typedef std::vector<IPin *> PinVector;
+    ULONG BytesReturned;
 
-    STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
+    if (cbInstanceData)
+    {
+        PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
+        if (!Property)
+            return E_OUTOFMEMORY;
 
-    STDMETHODIMP_(ULONG) AddRef()
+        Property->Set = guidPropSet;
+        Property->Id = dwPropID;
+        Property->Flags = KSPROPERTY_TYPE_GET;
+
+        CopyMemory((Property+1), pInstanceData, cbInstanceData);
+
+        HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
+        CoTaskMemFree(Property);
+        return hr;
+    }
+    else
     {
-        InterlockedIncrement(&m_Ref);
-        return m_Ref;
+        KSPROPERTY Property;
+
+        Property.Set = guidPropSet;
+        Property.Id = dwPropID;
+        Property.Flags = KSPROPERTY_TYPE_GET;
+
+        HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
+        return hr;
     }
-    STDMETHODIMP_(ULONG) Release()
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::QuerySupported(
+    REFGUID guidPropSet,
+    DWORD dwPropID,
+    DWORD *pTypeSupport)
+{
+    KSPROPERTY Property;
+    ULONG BytesReturned;
+
+    Property.Set = guidPropSet;
+    Property.Id = dwPropID;
+    Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
+
+    return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
+}
+
+
+//-------------------------------------------------------------------
+// IKsTopology interface
+//
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::CreateNodeInstance(
+    ULONG NodeId,
+    ULONG Flags,
+    ACCESS_MASK DesiredAccess,
+    IUnknown* UnkOuter,
+    REFGUID InterfaceId,
+    LPVOID* Interface)
+{
+    OutputDebugStringW(L"CKsProxy::CreateNodeInstance NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+//-------------------------------------------------------------------
+// IKsAggregateControl interface
+//
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::KsAddAggregate(
+    IN REFGUID AggregateClass)
+{
+    OutputDebugStringW(L"CKsProxy::KsAddAggregate NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::KsRemoveAggregate(
+    REFGUID AggregateClass)
+{
+    OutputDebugStringW(L"CKsProxy::KsRemoveAggregate NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+
+//-------------------------------------------------------------------
+// IPersistStream interface
+//
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::IsDirty()
+{
+    OutputDebugStringW(L"CKsProxy::IsDirty Notimplemented\n");
+    DebugBreak();
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::Load(
+    IStream *pStm)
+{
+    HRESULT hr;
+    WCHAR Buffer[1000];
+    AM_MEDIA_TYPE MediaType;
+    ULONG BytesReturned;
+    LONG Length;
+
+    ULONG PinId;
+    LPOLESTR pMajor, pSub, pFormat;
+
+    OutputDebugStringW(L"CKsProxy::Load\n");
+
+#if 0
+    ULONG Version = ReadInt(pStm, hr);
+    if (Version != 1)
+        return E_FAIL;
+#endif
+
+    hr = pStm->Read(&Length, sizeof(ULONG), &BytesReturned);
+    swprintf(Buffer, L"Length hr %x hr length %lu\n", hr, Length);
+    OutputDebugStringW(Buffer);
+
+    do
     {
-        InterlockedDecrement(&m_Ref);
-        if (!m_Ref)
+        hr = pStm->Read(&PinId, sizeof(ULONG), &BytesReturned);
+        swprintf(Buffer, L"Read: hr %08x PinId %lx BytesReturned %lu\n", hr, PinId, BytesReturned);
+        OutputDebugStringW(Buffer);
+
+        if (FAILED(hr) || !BytesReturned)
+            break;
+
+        Length -= BytesReturned;
+
+        hr = pStm->Read(&MediaType, sizeof(AM_MEDIA_TYPE), &BytesReturned);
+        if (FAILED(hr) || BytesReturned != sizeof(AM_MEDIA_TYPE))
         {
-            delete this;
-            return 0;
+            swprintf(Buffer, L"Read failed with %lx\n", hr);
+            OutputDebugStringW(Buffer);
+            break;
         }
-        return m_Ref;
-    }
 
-    // IBaseFilter methods
-    HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
-    HRESULT STDMETHODCALLTYPE Stop( void);
-    HRESULT STDMETHODCALLTYPE Pause( void);
-    HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart);
-    HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *State);
-    HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock);
-    HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **pClock);
-    HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum);
-    HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin);
-    HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo);
-    HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName);
-    HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo);
 
-    //IAMovieSetup methods
-    HRESULT STDMETHODCALLTYPE Register( void);
-    HRESULT STDMETHODCALLTYPE Unregister( void);
+        StringFromIID(MediaType.majortype, &pMajor);
+        StringFromIID(MediaType.subtype , &pSub);
+        StringFromIID(MediaType.formattype, &pFormat);
 
-    // IPersistPropertyBag methods
-    HRESULT STDMETHODCALLTYPE InitNew( void);
-    HRESULT STDMETHODCALLTYPE Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog);
-    HRESULT STDMETHODCALLTYPE Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties);
+        swprintf(Buffer, L"BytesReturned %lu majortype %s subtype %s bFixedSizeSamples %u bTemporalCompression %u lSampleSize %u formattype %s, pUnk %p cbFormat %u pbFormat %p\n", BytesReturned, pMajor, pSub, MediaType.bFixedSizeSamples, MediaType.bTemporalCompression, MediaType.lSampleSize, pFormat, MediaType.pUnk, MediaType.cbFormat, MediaType.pbFormat);
+        OutputDebugStringW(Buffer);
 
-    // IKsObject
-    HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
+        Length -= BytesReturned;
 
-    CKsProxy() : m_Ref(0), m_pGraph(0), m_ReferenceClock(0), m_FilterState(State_Stopped), m_hDevice(0), m_Plugins(), m_Pins() {};
-    virtual ~CKsProxy()
-    {
-        if (m_hDevice)
-            CloseHandle(m_hDevice);
-    };
 
-    HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids);
-    HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids);
-    HRESULT STDMETHODCALLTYPE GetNumberOfPins(PULONG NumPins);
-    HRESULT STDMETHODCALLTYPE GetPinInstanceCount(ULONG PinId, PKSPIN_CINSTANCES Instances);
-    HRESULT STDMETHODCALLTYPE GetPinDataflow(ULONG PinId, KSPIN_DATAFLOW * DataFlow);
-    HRESULT STDMETHODCALLTYPE GetPinName(ULONG PinId, KSPIN_DATAFLOW DataFlow, ULONG PinCount, LPWSTR * OutPinName);
-    HRESULT STDMETHODCALLTYPE GetPinCommunication(ULONG PinId, KSPIN_COMMUNICATION * Communication);
-    HRESULT STDMETHODCALLTYPE CreatePins();
-protected:
-    LONG m_Ref;
-    IFilterGraph *m_pGraph;
-    IReferenceClock * m_ReferenceClock;
-    FILTER_STATE m_FilterState;
-    HANDLE m_hDevice;
-    ProxyPluginVector m_Plugins;
-    PinVector m_Pins;
-};
+        if (MediaType.cbFormat)
+        {
+            MediaType.pbFormat = (BYTE*)CoTaskMemAlloc(MediaType.cbFormat);
+            if (!MediaType.pbFormat)
+                return E_OUTOFMEMORY;
+
+            hr = pStm->Read(&MediaType.pbFormat, sizeof(MediaType.cbFormat), &BytesReturned);
+            if (FAILED(hr))
+            {
+                swprintf(Buffer, L"ReadFormat failed with %lx\n", hr);
+                OutputDebugStringW(Buffer);
+                break;
+            }
+            Length -= BytesReturned;
+        }
+
+    }while(Length > 0);
+
+    DebugBreak();
+    return S_OK;
+}
 
 HRESULT
 STDMETHODCALLTYPE
-CKsProxy::QueryInterface(
-    IN  REFIID refiid,
-    OUT PVOID* Output)
+CKsProxy::Save(
+    IStream *pStm,
+    BOOL fClearDirty)
 {
-    *Output = NULL;
+    OutputDebugStringW(L"CKsProxy::Save Notimplemented\n");
+    return E_NOTIMPL;
+}
 
-    if (IsEqualGUID(refiid, IID_IUnknown) ||
-        IsEqualGUID(refiid, IID_IBaseFilter))
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::GetSizeMax(
+    ULARGE_INTEGER *pcbSize)
+{
+    OutputDebugStringW(L"CKsProxy::GetSizeMax Notimplemented\n");
+    DebugBreak();
+    return E_NOTIMPL;
+}
+
+//-------------------------------------------------------------------
+// IAMDeviceRemoval interface
+//
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::DeviceInfo(CLSID *pclsidInterfaceClass, LPWSTR *pwszSymbolicLink)
+{
+    if (!m_DevicePath)
     {
-        *Output = PVOID(this);
-        reinterpret_cast<IUnknown*>(*Output)->AddRef();
-        return NOERROR;
+        // object not initialized
+        return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND);
     }
-    else if (IsEqualGUID(refiid, IID_IPersistPropertyBag))
+
+    // copy device interface guid
+    CopyMemory(pclsidInterfaceClass, &m_DeviceInterfaceGUID, sizeof(GUID));
+
+    if (pwszSymbolicLink)
     {
-        *Output = (IPersistPropertyBag*)(this);
-        reinterpret_cast<IPersistPropertyBag*>(*Output)->AddRef();
-        return NOERROR;
+        *pwszSymbolicLink = (LPWSTR)CoTaskMemAlloc((wcslen(m_DevicePath)+1) * sizeof(WCHAR));
+        if (!*pwszSymbolicLink)
+            return E_OUTOFMEMORY;
+
+        wcscpy(*pwszSymbolicLink, m_DevicePath);
     }
-    if (IsEqualGUID(refiid, IID_IKsObject))
+    return S_OK;
+}
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::Reassociate(void)
+{
+    if (!m_DevicePath || m_hDevice)
     {
-        *Output = (IKsObject*)(this);
-        reinterpret_cast<IKsObject*>(*Output)->AddRef();
-        return NOERROR;
+        // file path not available
+        return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND);
     }
 
-    for(ULONG Index = 0; Index < m_Plugins.size(); Index++)
+    m_hDevice = CreateFileW(m_DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
+    if (!m_hDevice)
     {
-        if (m_Pins[Index])
-        {
-            HRESULT hr = m_Plugins[Index]->QueryInterface(refiid, Output);
-            if (SUCCEEDED(hr))
-            {
-                WCHAR Buffer[100];
-                LPOLESTR lpstr;
-                StringFromCLSID(refiid, &lpstr);
-                swprintf(Buffer, L"CKsProxy::QueryInterface plugin %lu supports interface %s\n", Index, lpstr);
-                OutputDebugStringW(Buffer);
-                CoTaskMemFree(lpstr);
-                return hr;
-            }
-        }
+        // failed to open device
+        return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
     }
 
-    WCHAR Buffer[MAX_PATH];
-    LPOLESTR lpstr;
-    StringFromCLSID(refiid, &lpstr);
-    swprintf(Buffer, L"CKsProxy::QueryInterface: NoInterface for %s !!!\n", lpstr);
-    OutputDebugStringW(Buffer);
-    CoTaskMemFree(lpstr);
+    // success
+    return NOERROR;
+}
 
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::Disassociate(void)
+{
+    if (!m_hDevice)
+        return E_HANDLE;
 
-    return E_NOINTERFACE;
+    CloseHandle(m_hDevice);
+    m_hDevice = NULL;
+    return NOERROR;
 }
 
+
+
+
 //-------------------------------------------------------------------
 // IKsObject interface
 //
@@ -523,7 +1478,7 @@ CKsProxy::CreatePins()
         }
         else
         {
-            hr = COutputPin_Constructor((IBaseFilter*)this, PinName, IID_IPin, (void**)&pPin);
+            hr = COutputPin_Constructor((IBaseFilter*)this, PinName, Index, IID_IPin, (void**)&pPin);
             if (FAILED(hr))
             {
                 CoTaskMemFree(PinName);
@@ -551,6 +1506,9 @@ CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
     VARIANT varName;
     LPGUID pGuid;
     ULONG NumGuids = 0;
+    HDEVINFO hList;
+    SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
+
 
     // read device path
     varName.vt = VT_BSTR;
@@ -563,6 +1521,27 @@ CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
         return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
     }
 
+    // create device list
+    hList = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
+    if (hList == INVALID_HANDLE_VALUE)
+    {
+        // failed to create device list
+        return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
+    }
+
+    DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+    if (!SetupDiOpenDeviceInterfaceW(hList, (PCWSTR)varName.bstrVal, 0, &DeviceInterfaceData))
+    {
+        // failed to open device interface
+        SetupDiDestroyDeviceInfoList(hList);
+    }
+
+    // FIXME handle device interface links(aliases)
+    CopyMemory(&m_DeviceInterfaceGUID, &DeviceInterfaceData.InterfaceClassGuid, sizeof(GUID));
+
+    // close device info list
+   SetupDiDestroyDeviceInfoList(hList);
+
     // open device
     m_hDevice = CreateFileW(varName.bstrVal, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
 
@@ -575,6 +1554,9 @@ CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
         return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
     }
 
+    // store device path
+    m_DevicePath = varName.bstrVal;
+
     // get all supported sets
     hr = GetSupportedSets(&pGuid, &NumGuids);
     if (FAILED(hr))
@@ -611,7 +1593,7 @@ CKsProxy::Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties
 
 //-------------------------------------------------------------------
 // IBaseFilter interface
-//
+//     
 
 HRESULT
 STDMETHODCALLTYPE
index 3081d83..88459d8 100644 (file)
@@ -8,7 +8,11 @@
  */
 #include "precomp.h"
 
+#ifndef _MSC_VER
 const GUID KSCATEGORY_QUALITY = {0x97EBAACB, 0x95BD, 0x11D0, {0xA3, 0xEA, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+#endif
+
+#define IID_IKsQualityForwarder KSCATEGORY_QUALITY
 
 class CKsQualityForwarder : public IKsQualityForwarder
 {