/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy * FILE: dll/directx/ksproxy/proxy.cpp * PURPOSE: IKsProxy interface * * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org) */ #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}}; const GUID IID_ISpecifyPropertyPages = {0xB196B28B, 0xBAB4, 0x101A, {0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07}}; const GUID IID_IPersistStream = {0x00000109, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}; const GUID KSPROPSETID_MediaSeeking = {0xEE904F0CL, 0xD09B, 0x11D0, {0xAB, 0xE9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; #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 IAMDeviceRemoval, public ISpecifyPropertyPages, public IReferenceClock, public IMediaSeeking, public IKsPropertySet, public IKsClockPropertySet, public IAMFilterMiscFlags, public IKsControl, public IKsTopology, public IKsAggregateControl { public: typedef std::vectorProxyPluginVector; typedef std::vector 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(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IPersistPropertyBag)) { *Output = (IPersistPropertyBag*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IAMDeviceRemoval)) { *Output = (IAMDeviceRemoval*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IPersistStream)) { *Output = (IPersistStream*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IKsObject)) { *Output = (IKsObject*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IReferenceClock)) { *Output = (IReferenceClock*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IMediaSeeking)) { *Output = (IMediaSeeking*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IAMFilterMiscFlags)) { *Output = (IAMFilterMiscFlags*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IKsControl)) { *Output = (IKsControl*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IKsPropertySet)) { *Output = (IKsPropertySet*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IKsTopology)) { *Output = (IKsTopology*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IKsAggregateControl)) { *Output = (IKsAggregateControl*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IKsClockPropertySet)) { *Output = (IKsClockPropertySet*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages)) { *Output = (ISpecifyPropertyPages*)(this); reinterpret_cast(*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) { 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 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 { 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)) { swprintf(Buffer, L"Read failed with %lx\n", hr); OutputDebugStringW(Buffer); break; } StringFromIID(MediaType.majortype, &pMajor); StringFromIID(MediaType.subtype , &pSub); StringFromIID(MediaType.formattype, &pFormat); 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); Length -= BytesReturned; 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::Save( IStream *pStm, BOOL fClearDirty) { OutputDebugStringW(L"CKsProxy::Save Notimplemented\n"); return E_NOTIMPL; } 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) { // object not initialized return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND); } // copy device interface guid CopyMemory(pclsidInterfaceClass, &m_DeviceInterfaceGUID, sizeof(GUID)); if (pwszSymbolicLink) { *pwszSymbolicLink = (LPWSTR)CoTaskMemAlloc((wcslen(m_DevicePath)+1) * sizeof(WCHAR)); if (!*pwszSymbolicLink) return E_OUTOFMEMORY; wcscpy(*pwszSymbolicLink, m_DevicePath); } return S_OK; } HRESULT STDMETHODCALLTYPE CKsProxy::Reassociate(void) { if (!m_DevicePath || m_hDevice) { // file path not available return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND); } m_hDevice = CreateFileW(m_DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (!m_hDevice) { // failed to open device return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); } // success return NOERROR; } HRESULT STDMETHODCALLTYPE CKsProxy::Disassociate(void) { if (!m_hDevice) return E_HANDLE; CloseHandle(m_hDevice); m_hDevice = NULL; return NOERROR; } //------------------------------------------------------------------- // IKsObject interface // HANDLE STDMETHODCALLTYPE CKsProxy::KsGetObjectHandle() { return m_hDevice; } //------------------------------------------------------------------- // IPersistPropertyBag interface // HRESULT STDMETHODCALLTYPE CKsProxy::InitNew( void) { return S_OK; } HRESULT STDMETHODCALLTYPE CKsProxy::GetSupportedSets( LPGUID * pOutGuid, PULONG NumGuids) { KSPROPERTY Property; LPGUID pGuid; ULONG NumProperty = 0; ULONG NumMethods = 0; ULONG NumEvents = 0; ULONG Length; ULONG BytesReturned; HRESULT hr; Property.Set = GUID_NULL; Property.Id = 0; Property.Flags = KSPROPERTY_TYPE_SETSUPPORT; KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty); KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods); KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents); Length = NumProperty + NumMethods + NumEvents; // allocate guid buffer pGuid = (LPGUID)CoTaskMemAlloc(Length); if (!pGuid) { // failed return E_OUTOFMEMORY; } NumProperty /= sizeof(GUID); NumMethods /= sizeof(GUID); NumEvents /= sizeof(GUID); // get all properties hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned); if (FAILED(hr)) { CoTaskMemFree(pGuid); return E_FAIL; } Length -= BytesReturned; // get all methods if (Length) { hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned); if (FAILED(hr)) { CoTaskMemFree(pGuid); return E_FAIL; } Length -= BytesReturned; } // get all events if (Length) { hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned); if (FAILED(hr)) { CoTaskMemFree(pGuid); return E_FAIL; } Length -= BytesReturned; } #ifdef KSPROXY_TRACE WCHAR Buffer[200]; swprintf(Buffer, L"NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents); OutputDebugStringW(Buffer); #endif *pOutGuid = pGuid; *NumGuids = NumProperty+NumEvents+NumMethods; return S_OK; } HRESULT STDMETHODCALLTYPE CKsProxy::LoadProxyPlugins( LPGUID pGuids, ULONG NumGuids) { ULONG Index; LPOLESTR pStr; HKEY hKey, hSubKey; HRESULT hr; IUnknown * pUnknown; if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS) { OutputDebugStringW(L"CKsProxy::LoadProxyPlugins failed to open MediaInterfaces key\n"); return E_FAIL; } // enumerate all sets for(Index = 0; Index < NumGuids; Index++) { // convert to string hr = StringFromCLSID(pGuids[Index], &pStr); if (FAILED(hr)) return E_FAIL; // now try open class key if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS) { // no plugin for that set exists CoTaskMemFree(pStr); continue; } // try load plugin hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown); if (SUCCEEDED(hr)) { // store plugin m_Plugins.push_back(pUnknown); } // close key RegCloseKey(hSubKey); } // close media interfaces key RegCloseKey(hKey); return S_OK; } HRESULT STDMETHODCALLTYPE CKsProxy::GetNumberOfPins( PULONG NumPins) { KSPROPERTY Property; ULONG BytesReturned; // setup request Property.Set = KSPROPSETID_Pin; Property.Id = KSPROPERTY_PIN_CTYPES; Property.Flags = KSPROPERTY_TYPE_GET; return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)NumPins, sizeof(ULONG), &BytesReturned); } HRESULT STDMETHODCALLTYPE CKsProxy::GetPinInstanceCount( ULONG PinId, PKSPIN_CINSTANCES Instances) { KSP_PIN Property; ULONG BytesReturned; // setup request Property.Property.Set = KSPROPSETID_Pin; Property.Property.Id = KSPROPERTY_PIN_CINSTANCES; Property.Property.Flags = KSPROPERTY_TYPE_GET; Property.PinId = PinId; Property.Reserved = 0; return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)Instances, sizeof(KSPIN_CINSTANCES), &BytesReturned); } HRESULT STDMETHODCALLTYPE CKsProxy::GetPinCommunication( ULONG PinId, KSPIN_COMMUNICATION * Communication) { KSP_PIN Property; ULONG BytesReturned; // setup request Property.Property.Set = KSPROPSETID_Pin; Property.Property.Id = KSPROPERTY_PIN_COMMUNICATION; Property.Property.Flags = KSPROPERTY_TYPE_GET; Property.PinId = PinId; Property.Reserved = 0; return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned); } HRESULT STDMETHODCALLTYPE CKsProxy::GetPinDataflow( ULONG PinId, KSPIN_DATAFLOW * DataFlow) { KSP_PIN Property; ULONG BytesReturned; // setup request Property.Property.Set = KSPROPSETID_Pin; Property.Property.Id = KSPROPERTY_PIN_DATAFLOW; Property.Property.Flags = KSPROPERTY_TYPE_GET; Property.PinId = PinId; Property.Reserved = 0; return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned); } HRESULT STDMETHODCALLTYPE CKsProxy::GetPinName( ULONG PinId, KSPIN_DATAFLOW DataFlow, ULONG PinCount, LPWSTR * OutPinName) { KSP_PIN Property; LPWSTR PinName; ULONG BytesReturned; HRESULT hr; WCHAR Buffer[100]; // setup request Property.Property.Set = KSPROPSETID_Pin; Property.Property.Id = KSPROPERTY_PIN_NAME; Property.Property.Flags = KSPROPERTY_TYPE_GET; Property.PinId = PinId; Property.Reserved = 0; // #1 try get it from pin directly hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned); if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA)) { // allocate pin name PinName = (LPWSTR)CoTaskMemAlloc(BytesReturned); if (!PinName) return E_OUTOFMEMORY; // retry with allocated buffer hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), PinName, BytesReturned, &BytesReturned); if (SUCCEEDED(hr)) { *OutPinName = PinName; return hr; } //free buffer CoTaskMemFree(PinName); } // // TODO: retrieve pin name from topology node // if (DataFlow == KSPIN_DATAFLOW_IN) { swprintf(Buffer, L"Input%lu", PinCount); } else { swprintf(Buffer, L"Output%lu", PinCount); } // allocate pin name PinName = (LPWSTR)CoTaskMemAlloc((wcslen(Buffer)+1) * sizeof(WCHAR)); if (!PinName) return E_OUTOFMEMORY; // copy pin name wcscpy(PinName, Buffer); // store result *OutPinName = PinName; // done return S_OK; } HRESULT STDMETHODCALLTYPE CKsProxy::CreatePins() { ULONG NumPins, Index; KSPIN_CINSTANCES Instances; KSPIN_DATAFLOW DataFlow; KSPIN_COMMUNICATION Communication; HRESULT hr; WCHAR Buffer[100]; LPWSTR PinName; IPin * pPin; ULONG InputPin = 0; ULONG OutputPin = 0; // get number of pins hr = GetNumberOfPins(&NumPins); if (FAILED(hr)) return hr; for(Index = 0; Index < NumPins; Index++) { // query current instance count hr = GetPinInstanceCount(Index, &Instances); if (FAILED(hr)) continue; // query pin communication; hr = GetPinCommunication(Index, &Communication); if (FAILED(hr)) continue; if (Instances.CurrentCount == Instances.PossibleCount) { // already maximum reached for this pin continue; } // get direction of pin hr = GetPinDataflow(Index, &DataFlow); if (FAILED(hr)) continue; if (DataFlow == KSPIN_DATAFLOW_IN) hr = GetPinName(Index, DataFlow, InputPin, &PinName); else hr = GetPinName(Index, DataFlow, OutputPin, &PinName); if (FAILED(hr)) continue; // construct the pins if (DataFlow == KSPIN_DATAFLOW_IN) { hr = CInputPin_Constructor((IBaseFilter*)this, PinName, m_hDevice, Index, Communication, IID_IPin, (void**)&pPin); if (FAILED(hr)) { CoTaskMemFree(PinName); continue; } InputPin++; } else { hr = COutputPin_Constructor((IBaseFilter*)this, PinName, Index, IID_IPin, (void**)&pPin); if (FAILED(hr)) { CoTaskMemFree(PinName); continue; } OutputPin++; } // store pins m_Pins.push_back(pPin); swprintf(Buffer, L"Index %lu DataFlow %lu Name %s\n", Index, DataFlow, PinName); OutputDebugStringW(Buffer); } return S_OK; } HRESULT STDMETHODCALLTYPE CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog) { HRESULT hr; WCHAR Buffer[100]; VARIANT varName; LPGUID pGuid; ULONG NumGuids = 0; HDEVINFO hList; SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; // read device path varName.vt = VT_BSTR; hr = pPropBag->Read(L"DevicePath", &varName, pErrorLog); if (FAILED(hr)) { swprintf(Buffer, L"CKsProxy::Load Read %lx\n", hr); OutputDebugStringW(Buffer); 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); if (m_hDevice == INVALID_HANDLE_VALUE) { // failed to open device swprintf(Buffer, L"CKsProxy:: failed to open device with %lx\n", GetLastError()); OutputDebugStringW(Buffer); 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)) { CloseHandle(m_hDevice); m_hDevice = NULL; return hr; } // load all proxy plugins hr = LoadProxyPlugins(pGuid, NumGuids); if (FAILED(hr)) { CloseHandle(m_hDevice); m_hDevice = NULL; return hr; } // free sets CoTaskMemFree(pGuid); // now create the input / output pins hr = CreatePins(); return hr; } HRESULT STDMETHODCALLTYPE CKsProxy::Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties) { return E_NOTIMPL; } //------------------------------------------------------------------- // IBaseFilter interface // HRESULT STDMETHODCALLTYPE CKsProxy::GetClassID( CLSID *pClassID) { OutputDebugStringW(L"CKsProxy::GetClassID : NotImplemented\n"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CKsProxy::Stop() { OutputDebugStringW(L"CKsProxy::Stop : NotImplemented\n"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CKsProxy::Pause() { OutputDebugStringW(L"CKsProxy::Pause : NotImplemented\n"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CKsProxy::Run( REFERENCE_TIME tStart) { OutputDebugStringW(L"CKsProxy::Run : NotImplemented\n"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CKsProxy::GetState( DWORD dwMilliSecsTimeout, FILTER_STATE *State) { *State = m_FilterState; return S_OK; } HRESULT STDMETHODCALLTYPE CKsProxy::SetSyncSource( IReferenceClock *pClock) { if (pClock) { pClock->AddRef(); } if (m_ReferenceClock) { m_ReferenceClock->Release(); } m_ReferenceClock = pClock; return S_OK; } HRESULT STDMETHODCALLTYPE CKsProxy::GetSyncSource( IReferenceClock **pClock) { if (!pClock) return E_POINTER; if (m_ReferenceClock) m_ReferenceClock->AddRef(); *pClock = m_ReferenceClock; return S_OK; } HRESULT STDMETHODCALLTYPE CKsProxy::EnumPins( IEnumPins **ppEnum) { return CEnumPins_fnConstructor(m_Pins, IID_IEnumPins, (void**)ppEnum); } HRESULT STDMETHODCALLTYPE CKsProxy::FindPin( LPCWSTR Id, IPin **ppPin) { ULONG PinId; if (!ppPin) return E_POINTER; // convert to pin int ret = swscanf(Id, L"%u", &PinId); if (!ret || ret == EOF) { // invalid id return VFW_E_NOT_FOUND; } if (PinId >= m_Pins.size() || m_Pins[PinId] == NULL) { // invalid id return VFW_E_NOT_FOUND; } // found pin *ppPin = m_Pins[PinId]; m_Pins[PinId]->AddRef(); return S_OK; } HRESULT STDMETHODCALLTYPE CKsProxy::QueryFilterInfo( FILTER_INFO *pInfo) { if (!pInfo) return E_POINTER; pInfo->achName[0] = L'\0'; pInfo->pGraph = m_pGraph; return S_OK; } HRESULT STDMETHODCALLTYPE CKsProxy::JoinFilterGraph( IFilterGraph *pGraph, LPCWSTR pName) { if (pGraph) { // joining filter graph m_pGraph = pGraph; } else { // leaving graph m_pGraph = 0; } return S_OK; } HRESULT STDMETHODCALLTYPE CKsProxy::QueryVendorInfo( LPWSTR *pVendorInfo) { OutputDebugStringW(L"CKsProxy::QueryVendorInfo : NotImplemented\n"); return E_NOTIMPL; } //------------------------------------------------------------------- // IAMovieSetup interface // HRESULT STDMETHODCALLTYPE CKsProxy::Register() { OutputDebugStringW(L"CKsProxy::Register : NotImplemented\n"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CKsProxy::Unregister() { OutputDebugStringW(L"CKsProxy::Unregister : NotImplemented\n"); return E_NOTIMPL; } HRESULT WINAPI CKsProxy_Constructor( IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv) { WCHAR Buffer[100]; LPOLESTR pstr; StringFromCLSID(riid, &pstr); swprintf(Buffer, L"CKsProxy_Constructor pUnkOuter %p riid %s\n", pUnkOuter, pstr); OutputDebugStringW(Buffer); CKsProxy * handler = new CKsProxy(); if (!handler) return E_OUTOFMEMORY; if (FAILED(handler->QueryInterface(riid, ppv))) { /* not supported */ delete handler; return E_NOINTERFACE; } return S_OK; }