source: trunk/DirectShowSpy/FilterGraphSpy.h @ 937

Last change on this file since 937 was 839, checked in by roman, 4 years ago
  • Property svn:keywords set to Id
File size: 62.0 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2008-2015
3// Created by Roman Ryltsov roman@alax.info, http://alax.info
4//
5// This source code is published to complement DirectShowSpy developer powertoy
6// and demonstrate the internal use of APIs and tricks powering the tool. It is
7// allowed to freely re-use the portions of the code in other projects, commercial
8// or otherwise (provided that you don’t pretend that you wrote the original tool).
9//
10// Please keep in mind that DirectShowSpy is a developer tool, it is strongly recommended
11// that it is not shipped with release grade software. It is allowed to distribute
12// DirectShowSpy if only it is not registered with Windows by default and either
13// used privately, or registered on specific throubleshooting request. The advice applies
14// to hooking methods used by DirectShowSpy in general as well.
15
16#pragma once
17
18#include "rodshow.h"
19#include "Module_i.h"
20#include "Common.h"
21#include "RunPropertyBag.h"
22#include "MediaSampleTrace.h"
23#include "FilterGraphTable.h"
24
25HRESULT FilterGraphHelper_OpenGraphStudioNext(LONG nParentWindowHandle, LPCWSTR pszMonikerDisplayName, VARIANT_BOOL* pbResult);
26HRESULT FilterGraphHelper_OpenGraphEdit(LONG nParentWindowHandle, LPCWSTR pszMonikerDisplayName, VARIANT_BOOL* pbResult);
27
28////////////////////////////////////////////////////////////
29// CFilterGraphMemoryAllocatorData
30
31template <typename T>
32class ATL_NO_VTABLE CFilterGraphMemoryAllocatorDataT :
33        public IDispatchImpl<IFilterGraphMemoryAllocatorData>
34{
35public:
36
37        ////////////////////////////////////////////////////////
38        // CMemoryAllocatorData
39
40        class CMemoryAllocatorData
41        {
42        public:
43                CComPtr<IMemAllocator> m_pMemAllocator;
44                CRoArrayT<CString> m_NameArray;
45
46        public:
47        // CMemoryAllocatorData
48                CComVariantArray GetAsVariant() const
49                {
50                        CRoArrayT<CComVariantArray> Array;
51                        Array.Add(CComVariant((LONG) (LONG_PTR) (IMemAllocator*) m_pMemAllocator));
52                        Array.Add(CComVariant(_StringHelper::Join(m_NameArray, _T(", "))));
53                        #pragma region IMemAllocator, ALLOCATOR_PROPERTIES
54                        _ATLTRY
55                        {
56                                ALLOCATOR_PROPERTIES Properties;
57                                const HRESULT nGetPropertiesResult = m_pMemAllocator->GetProperties(&Properties);
58                                __C(nGetPropertiesResult);
59                                Array.Add(CComVariant());
60                                Array.Add(CComVariant(Properties.cBuffers));
61                                Array.Add(CComVariant(Properties.cbBuffer));
62                                Array.Add(CComVariant(Properties.cbAlign));
63                                Array.Add(CComVariant(Properties.cbPrefix));
64                        }
65                        _ATLCATCH(Exception)
66                        {
67                                _Z_ATLEXCEPTION(Exception);
68                                Array.Add(CComVariant((LONG) (HRESULT) Exception));
69                        }
70                        #pragma endregion
71                        #pragma region IMemAllocatorCallbackTemp
72                        const CComQIPtr<IMemAllocatorCallbackTemp> pMemAllocatorCallbackTemp = m_pMemAllocator;
73                        if(pMemAllocatorCallbackTemp)
74                        {
75                                _ATLTRY
76                                {
77                                        LONG nFreeCount = 0;
78                                        __C(pMemAllocatorCallbackTemp->GetFreeCount(&nFreeCount));
79                                        Array.Add(CComVariant());
80                                        Array.Add(CComVariant(nFreeCount));
81                                }
82                                _ATLCATCH(Exception)
83                                {
84                                        _Z_ATLEXCEPTION(Exception);
85                                        Array.Add(CComVariant((LONG) (HRESULT) Exception));
86                                }
87                        } else
88                                Array.Add(CComVariant((LONG) (HRESULT) E_NOINTERFACE));
89                        #pragma endregion
90                        CComVariantArray vResult;
91                        return vResult.FromElementArray(Array);
92                }
93        };
94
95public:
96// CFilterGraphMemoryAllocatorDataT
97        static BOOL CompareMemAllocator(const CMemoryAllocatorData& Data, IMemAllocator* pMemAllocator)
98        {
99                return Data.m_pMemAllocator == pMemAllocator;
100        }
101        CComVariantArray GetValue()
102        {
103                #pragma region Enumerate
104                CRoArrayT<CMemoryAllocatorData> DataArray;
105                {
106                        _FilterGraphHelper::CFilterArray FilterArray;
107                        _FilterGraphHelper::GetGraphFilters((IFilterGraph2*) static_cast<T*>(this), FilterArray);
108                        for(auto&& pBaseFilter: FilterArray)
109                        {
110                                _ATLTRY
111                                {
112                                        _FilterGraphHelper::CPinArray PinArray;
113                                        _FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_INPUT, PinArray);
114                                        for(auto&& pInputPin: PinArray)
115                                        {
116                                                _ATLTRY
117                                                {
118                                                        const CComPtr<IPin> pOutputPin = _FilterGraphHelper::GetPeerPin(pInputPin);
119                                                        if(!pOutputPin)
120                                                                continue;
121                                                        const CComQIPtr<IMemInputPin> pMemInputPin = pInputPin;
122                                                        if(!pMemInputPin)
123                                                                continue;
124                                                        CComPtr<IMemAllocator> pMemAllocator;
125                                                        pMemInputPin->GetAllocator(&pMemAllocator);
126                                                        if(!pMemAllocator)
127                                                                continue;
128                                                        SIZE_T nIndex;
129                                                        if(!DataArray.FindFirstThatT<IMemAllocator*>(&CFilterGraphMemoryAllocatorDataT<T>::CompareMemAllocator, pMemAllocator, &nIndex))
130                                                        {
131                                                                nIndex = DataArray.Add();
132                                                                DataArray[nIndex].m_pMemAllocator = pMemAllocator;
133                                                        }
134                                                        CMemoryAllocatorData& Data = DataArray[nIndex];
135                                                        Data.m_NameArray.Add(AtlFormatString(_T("%ls - %ls"), _FilterGraphHelper::GetPinFullName(pOutputPin), _FilterGraphHelper::GetPinFullName(pInputPin)));
136                                                }
137                                                _ATLCATCHALL()
138                                                {
139                                                        _Z_EXCEPTION();
140                                                }
141                                        }
142                                }
143                                _ATLCATCHALL()
144                                {
145                                        _Z_EXCEPTION();
146                                }
147                        }
148                }
149                #pragma endregion
150                CRoArrayT<CComVariantArray> Array;
151                for(auto&& Data: DataArray)
152                        Array.Add(Data.GetAsVariant());
153                CComVariantArray vResult;
154                return vResult.FromElementArray(Array);
155        }
156
157// IFilterGraphMemoryAllocatorData
158        STDMETHOD(get_Value)(VARIANT* pvValue)
159        {
160                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
161                _ATLTRY
162                {
163                        __D(pvValue, E_POINTER);
164                        VariantInit(pvValue);
165                        _V(GetValue().Detach(pvValue));
166                }
167                _ATLCATCH(Exception)
168                {
169                        _C(Exception);
170                }
171                return S_OK;
172        }
173};
174
175////////////////////////////////////////////////////////////
176// CSpyT
177
178extern LPCTSTR g_pszAddRemoveHookName;
179extern LPCTSTR g_pszConnectHookName;
180extern LPCTSTR g_pszStateControlHookName;
181
182__declspec(selectany) LPCTSTR g_pszAddRemoveHookName = _T("Add/Remove Hooks");
183__declspec(selectany) LPCTSTR g_pszConnectHookName = _T("Connect Hooks");
184__declspec(selectany) LPCTSTR g_pszStateControlHookName = _T("State Control Hooks");
185
186template <typename T, const CLSID* t_pFilterGraphClassIdentifier>
187class ATL_NO_VTABLE CSpyT :
188        public CComObjectRootEx<CComMultiThreadModel>,
189        //public CComCoClass<CSpyT, &CLSID_Spy>,
190        public CTransparentCoClassT<T, t_pFilterGraphClassIdentifier>,
191        public IDispatchImpl<ISpy>,
192        public ISpyEx,
193        public IFilterGraph3,
194        public IDispatchImpl<IMediaControl, &__uuidof(IMediaControl), &__uuidof(Quartz::__QuartzTypeLib)>,
195        public IMediaEventSink,
196        public IDispatchImpl<IMediaEventEx, &__uuidof(IMediaEventEx), &__uuidof(Quartz::__QuartzTypeLib)>,
197        public IObjectWithSite,
198        public CModuleVersionInformationT<T>,
199        public CFilterGraphMemoryAllocatorDataT<T>,
200        public CHookHostT<T, IFilterGraphAddRemoveHook, &g_pszAddRemoveHookName>,
201        public CHookHostT<T, IFilterGraphConnectHook, &g_pszConnectHookName>,
202        public CHookHostT<T, IFilterGraphStateControlHook, &g_pszStateControlHookName>
203{
204        typedef CSpyT<T, t_pFilterGraphClassIdentifier> CSpy;
205        typedef CHookHostT<T, IFilterGraphAddRemoveHook, &g_pszAddRemoveHookName> CFilterGraphAddRemoveHookHost;
206        typedef CHookHostT<T, IFilterGraphConnectHook, &g_pszConnectHookName> CFilterGraphConnectHookHost;
207        typedef CHookHostT<T, IFilterGraphStateControlHook, &g_pszStateControlHookName> CFilterGraphStateControlHookHost;
208
209public:
210        //enum { IDR = IDR_FILTERGRAPHSPY };
211
212//DECLARE_CLASSFACTORY(...
213
214//DECLARE_AGGREGATABLE(...
215
216//DECLARE_REGISTRY_RESOURCEID(IDR)
217
218DECLARE_PROTECT_FINAL_CONSTRUCT()
219
220DECLARE_GET_CONTROLLING_UNKNOWN()
221
222DECLARE_QI_TRACE(CSpy)
223
224BEGIN_COM_MAP(CSpy)
225        COM_INTERFACE_ENTRY(ISpy)
226        COM_INTERFACE_ENTRY_FUNC(__uuidof(IFilterGraph3), 0, QueryFilterGraph3Interface)
227        COM_INTERFACE_ENTRY(ISpyEx)
228        COM_INTERFACE_ENTRY(IFilterGraph2)
229        COM_INTERFACE_ENTRY(IFilterGraph3)
230        COM_INTERFACE_ENTRY(IGraphBuilder)
231        COM_INTERFACE_ENTRY(IFilterGraph)
232        COM_INTERFACE_ENTRY(IMediaControl)
233        COM_INTERFACE_ENTRY(IMediaEventSink)
234        COM_INTERFACE_ENTRY(IMediaEventEx)
235        COM_INTERFACE_ENTRY(IMediaEvent)
236        COM_INTERFACE_ENTRY_FUNC(__uuidof(IObjectWithSite), 0, QueryObjectWithSiteInterface)
237        COM_INTERFACE_ENTRY(IModuleVersionInformation)
238        COM_INTERFACE_ENTRY(IFilterGraphMemoryAllocatorData)
239        COM_INTERFACE_ENTRY_AGGREGATE_BLIND(m_pInnerUnknown)
240        //COM_INTERFACE_ENTRY(IDispatch)
241END_COM_MAP()
242
243public:
244
245        ////////////////////////////////////////////////////////
246        // CAmGraphBuilderCallback
247
248        class ATL_NO_VTABLE CAmGraphBuilderCallback :
249                public CComObjectRootEx<CComMultiThreadModelNoCS>,
250                public IAMGraphBuilderCallback
251        {
252        public:
253
254        BEGIN_COM_MAP(CAmGraphBuilderCallback)
255                COM_INTERFACE_ENTRY(IAMGraphBuilderCallback)
256        END_COM_MAP()
257
258        private:
259                mutable CRoCriticalSection m_DataCriticalSection;
260                T* m_pSpy;
261
262                CObjectPtr<T> GetSpy() const
263                {
264                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
265                        return m_pSpy;
266                }
267
268        public:
269        // CAmGraphBuilderCallback
270                CAmGraphBuilderCallback() :
271                        m_pSpy(NULL)
272                {
273                        _Z5_THIS();
274                }
275                ~CAmGraphBuilderCallback()
276                {
277                        _Z5_THIS();
278                }
279                VOID Initialize(T* pSpy)
280                {
281                        _A(pSpy);
282                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
283                        _Z4(atlTraceRefcount, 4, _T("this 0x%p, pSpy 0x%p\n"), this, pSpy);
284                        _A(!m_pSpy);
285                        m_pSpy = pSpy;
286                }
287                VOID Terminate()
288                {
289                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
290                        m_pSpy = NULL;
291                }
292                BOOL SetGraphBuilder(const CComQIPtr<IObjectWithSite> pObjectWithSite)
293                {
294                        if(!pObjectWithSite)
295                                return FALSE;
296                        const HRESULT nSetSiteResult = pObjectWithSite->SetSite(this);
297                        if(SUCCEEDED(nSetSiteResult))
298                                return TRUE;
299                        _Z4_HRESULT(nSetSiteResult);
300                        return FALSE;
301                }
302                BOOL SetGraphBuilder(IUnknown* pObjectWithSiteUnknown)
303                {
304                        return SetGraphBuilder(CComQIPtr<IObjectWithSite>(pObjectWithSiteUnknown));
305                }
306
307        // IAMGraphBuilderCallback
308        STDMETHOD(SelectedFilter)(IMoniker* pMoniker)
309                {
310                        _Z4(atlTraceCOM, 4, _T("this 0x%p, pMoniker %ls\n"), this, _FilterGraphHelper::GetMonikerDisplayName(pMoniker));
311                        _ATLTRY
312                        {
313                                _A(pMoniker);
314                                const CObjectPtr<T> pSpy = GetSpy();
315                                HRESULT nSelectedFilterResult;
316                                if(pSpy)
317                                        if(pSpy->SelectedFilter(pMoniker, nSelectedFilterResult))
318                                        {
319                                                _Z4(atlTraceGeneral, 4, _T("this 0x%p, nSelectedFilterResult 0x%08X\n"), this, nSelectedFilterResult);
320                                                return nSelectedFilterResult;
321                                        }
322                        }
323                        _ATLCATCH(Exception)
324                        {
325                                _C(Exception);
326                        }
327                        return S_OK;
328                }
329                STDMETHOD(CreatedFilter)(IBaseFilter* pBaseFilter)
330                {
331                        _Z4(atlTraceCOM, 4, _T("this 0x%p, pBaseFilter 0x%p %ls \"%ls\"\n"), this, pBaseFilter, _FilterGraphHelper::GetFilterClassIdentifierString(pBaseFilter), _FilterGraphHelper::GetFilterName(pBaseFilter));
332                        _ATLTRY
333                        {
334                                _A(pBaseFilter);
335                                const CObjectPtr<T> pSpy = GetSpy();
336                                HRESULT nCreatedFilterResult;
337                                if(pSpy)
338                                        if(pSpy->CreatedFilter(pBaseFilter, nCreatedFilterResult))
339                                        {
340                                                _Z4(atlTraceGeneral, 4, _T("this 0x%p, nCreatedFilterResult 0x%08X\n"), this, nCreatedFilterResult);
341                                                return nCreatedFilterResult;
342                                        }
343                        }
344                        _ATLCATCH(Exception)
345                        {
346                                _C(Exception);
347                        }
348                        return S_OK;
349                }
350        };
351
352        ////////////////////////////////////////////////////////
353        // CLogFilter
354
355        class __declspec(uuid("{DC544824-CC2C-4CEF-AABC-9FA815530733}")) CLogFilterBase;
356
357        class ATL_NO_VTABLE CLogFilter :
358                public CComObjectRootEx<CComMultiThreadModelNoCS>,
359                public CComCoClass<CLogFilter, &__uuidof(CLogFilterBase)>,
360                public CTransformFilterT<CLogFilter>,
361                public CBasePersistT<CLogFilter>
362        {
363        public:
364                //enum { IDR =  };
365
366        //DECLARE_REGISTRY_RESOURCEID(IDR)
367
368        DECLARE_PROTECT_FINAL_CONSTRUCT()
369
370        //DECLARE_QI_TRACE(CLogFilter)
371
372        BEGIN_COM_MAP(CLogFilter)
373                COM_INTERFACE_ENTRY(IBaseFilter)
374                COM_INTERFACE_ENTRY(IMediaFilter)
375                COM_INTERFACE_ENTRY_IID(__uuidof(IPersist), IBaseFilter)
376        END_COM_MAP()
377
378        BEGIN_PROP_MAP(CLogFilter)
379        END_PROP_MAP()
380
381        public:
382
383                ////////////////////////////////////////////////////////
384                // CInputPin
385
386                class ATL_NO_VTABLE CInputPin :
387                        public CComObjectRootEx<CComMultiThreadModelNoCS>,
388                        public CInputPinT<CInputPin, CLogFilter>
389                {
390                public:
391
392                //DECLARE_QI_TRACE(CInspectionFilter::CLogFilter)
393
394                BEGIN_COM_MAP(CInputPin)
395                        COM_INTERFACE_ENTRY(IPin)
396                        COM_INTERFACE_ENTRY(IMemInputPin)
397                END_COM_MAP()
398
399                public:
400                // CInputPin
401                        CInputPin()
402                        {
403                                _Z5_THIS();
404                        }
405                        ~CInputPin()
406                        {
407                                _Z5_THIS();
408                        }
409                        BOOL CheckMediaType(const CMediaType& pMediaType) const
410                        {
411                                _A(pMediaType);
412                                return TRUE;
413                        }
414                        VOID ResetPeerPin()
415                        {
416                                CRoCriticalSectionLock DataLock(GetDataCriticalSection());
417                                __super::ResetPeerPin();
418                                GetFilter()->DisconnectPin(GetFilter()->GetOutputPin());
419                        }
420                };
421
422                ////////////////////////////////////////////////////////
423                // COutputPin
424
425                class ATL_NO_VTABLE COutputPin :
426                        public CComObjectRootEx<CComMultiThreadModelNoCS>,
427                        public COutputPinT<COutputPin, CLogFilter>,
428                        public CUpstreamMediaPositionAwareOutputPinT<COutputPin>
429                {
430                public:
431
432                //DECLARE_QI_TRACE(CInspectionFilter::COutputPin)
433
434                BEGIN_COM_MAP(COutputPin)
435                        COM_INTERFACE_ENTRY(IPin)
436                        COM_INTERFACE_ENTRY_FUNC(__uuidof(IMediaSeeking), 0, QueryUpstreamMediaPositionInterface)
437                        COM_INTERFACE_ENTRY_FUNC(__uuidof(IMediaPosition), 0, QueryUpstreamMediaPositionInterface)
438                        COM_INTERFACE_ENTRY_FUNC(__uuidof(IDispatch), 0, QueryUpstreamMediaPositionInterface)
439                END_COM_MAP()
440
441                public:
442                // COutputPin
443                        COutputPin()
444                        {
445                                _Z5_THIS();
446                        }
447                        ~COutputPin()
448                        {
449                                _Z5_THIS();
450                        }
451                        HRESULT FinalConstruct()
452                        {
453                                _ATLTRY
454                                {
455                                        CreateUpstreamMediaPosition();
456                                }
457                                _ATLCATCH(Exception)
458                                {
459                                        _C(Exception);
460                                }
461                                return S_OK;
462                        }
463                        VOID FinalRelease()
464                        {
465                                DestroyUpstreamMediaPosition();
466                        }
467                        VOID EnumerateMediaTypes(CRoListT<CMediaType>& MediaTypeList) const
468                        {
469                                CRoCriticalSectionLock DataLock(GetDataCriticalSection());
470                                const CMediaType& pInputMediaType = GetFilter()->GetInputPin()->GetMediaTypeReference();
471                                if(pInputMediaType)
472                                        _W(MediaTypeList.AddTail(pInputMediaType));
473                        }
474                        BOOL CheckMediaType(const CMediaType& pMediaType) const
475                        {
476                                _A(pMediaType);
477                                const CObjectPtr<CInputPin>& pInputPin = GetFilter()->GetInputPin();
478                                CRoCriticalSectionLock DataLock(GetDataCriticalSection());
479                                const CComPtr<IPin>& pInputPeerPin = pInputPin->GetPeerPinReference();
480                                if(!pInputPeerPin)
481                                        return FALSE; // No Input Connected
482                                const CMediaType& pInputMediaType = pInputPin->GetMediaTypeReference();
483                                if(!pInputMediaType.Compare(pMediaType))
484                                        return FALSE; // Input Media Type Mismatch
485                                return TRUE;
486                        }
487                        BOOL DecideMemAllocator(const CMediaType& pMediaType)
488                        {
489                                _A(VerifyCriticalSectionLocked(GetDataCriticalSection()));
490                                _A(GetPeerMemInputPinReference());
491                                const CObjectPtr<CInputPin>& pInputPin = GetFilter()->GetInputPin();
492                                const CComPtr<IMemAllocator>& pMemAllocator = pInputPin->GetMemAllocatorReference();
493                                const HRESULT nNotifyAllocatorResult = GetPeerMemInputPinReference()->NotifyAllocator(pMemAllocator, pInputPin->GetMemAllocatorReadOnly());
494                                _Z45_DSHRESULT(nNotifyAllocatorResult);
495                                if(FAILED(nNotifyAllocatorResult))
496                                        return FALSE;
497                                SetMemAllocator(pMemAllocator);
498                                return TRUE;
499                        }
500                };
501
502        private:
503                CObjectPtr<CInputPin> m_pInputPin;
504                CObjectPtr<COutputPin> m_pOutputPin;
505
506        public:
507        // CLogFilter
508                CLogFilter() :
509                        CBasePersistT<CLogFilter>(GetDataCriticalSection())
510                {
511                        _Z4_THIS();
512                }
513                ~CLogFilter()
514                {
515                        _Z4_THIS();
516                }
517                HRESULT FinalConstruct()
518                {
519                        _ATLTRY
520                        {
521                                m_pInputPin.Construct()->Initialize(this, L"Input");
522                                m_pOutputPin.Construct()->Initialize(this, L"Output");
523                                AddPins(2, (IPin*) m_pInputPin, (IPin*) m_pOutputPin);
524                        }
525                        _ATLCATCH(Exception)
526                        {
527                                _C(Exception);
528                        }
529                        return S_OK;
530                }
531                VOID FinalRelease()
532                {
533                        m_pInputPin.Release();
534                        m_pOutputPin.Release();
535                }
536                VOID DeliverEndOfStream(CInputPin*)
537                {
538                        _Z2(atlTraceGeneral, 2, _T("this 0x%p, \"%ls\"\n"), this, GetName());
539                        CRoCriticalSectionLock ReceiveLock(GetReceiveCriticalSection());
540                        m_pOutputPin->DeliverEndOfStream();
541                }
542                VOID DeliverBeginFlush(CInputPin*)
543                {
544                        _Z2(atlTraceGeneral, 2, _T("this 0x%p, \"%ls\"\n"), this, GetName());
545                        m_pOutputPin->DeliverBeginFlush();
546                }
547                VOID DeliverEndFlush(CInputPin*)
548                {
549                        _Z2(atlTraceGeneral, 2, _T("this 0x%p, \"%ls\"\n"), this, GetName());
550                        m_pOutputPin->DeliverEndFlush();
551                }
552                VOID DeliverNewSegment(CInputPin*, REFERENCE_TIME nStartTime, REFERENCE_TIME nStopTime, DOUBLE fRate)
553                {
554                        _Z2(atlTraceGeneral, 2, _T("this 0x%p, \"%ls\", nStartTime %s, nStopTime %s, fRate %.3f\n"), this, GetName(), _FilterGraphHelper::FormatReferenceTime(nStartTime), _FilterGraphHelper::FormatReferenceTime(nStopTime), fRate);
555                        m_pOutputPin->DeliverNewSegment(nStartTime, nStopTime, fRate);
556                }
557                VOID CueFilter()
558                {
559                        _Z2(atlTraceGeneral, 2, _T("this 0x%p, \"%ls\"\n"), this, GetName());
560                        CRoCriticalSectionLock ReceiveLock(GetReceiveCriticalSection());
561                        StartStreaming();
562                }
563                VOID RunFilter(REFERENCE_TIME nStartTime)
564                {
565                        _Z2(atlTraceGeneral, 2, _T("this 0x%p, \"%ls\"\n"), this, GetName());
566                        nStartTime;
567                }
568                VOID PauseFilter()
569                {
570                        _Z2(atlTraceGeneral, 2, _T("this 0x%p, \"%ls\"\n"), this, GetName());
571                }
572                VOID StopFilter()
573                {
574                        _Z2(atlTraceGeneral, 2, _T("this 0x%p, \"%ls\"\n"), this, GetName());
575                        CRoCriticalSectionLock ReceiveLock(GetReceiveCriticalSection());
576                        StopStreaming();
577                }
578                VOID ReceiveMediaSample(CInputPin* pInputPin, IMediaSample2* pMediaSample, HRESULT& nReceiveResult)
579                {
580                        _A(pInputPin == m_pInputPin);
581                        _A(pMediaSample);
582                        CRoCriticalSectionLock ReceiveLock(GetReceiveCriticalSection());
583                        if(!IsStreaming())
584                                return;
585                        CMediaSampleProperties Properties(pMediaSample);
586                        {
587                                CRoArrayT<CString> Array1, Array2;
588                                Array2.Add(AtlFormatString(_T("%d"), GetTickCount()));
589                                Array2.Add(GetName());
590                                Array1.Add(AtlFormatString(_T("dwSampleFlags %s"), _FilterGraphHelper::FormatSampleFlags(Properties.dwSampleFlags)));
591                                Array2.Add(AtlFormatString(_T("0x%X"), Properties.dwSampleFlags));
592                                if(Properties.dwSampleFlags & AM_SAMPLE_TIMEVALID)
593                                {
594                                        Array1.Add(AtlFormatString(_T("tStart %s"), _FilterGraphHelper::FormatReferenceTime(Properties.tStart)));
595                                        Array2.Add(AtlFormatString(_T("%I64d"), Properties.tStart));
596                                        if(Properties.dwSampleFlags & AM_SAMPLE_STOPVALID)
597                                        {
598                                                Array1.Add(AtlFormatString(_T("tStop %s (+ %s)"), _FilterGraphHelper::FormatReferenceTime(Properties.tStop), _FilterGraphHelper::FormatReferenceTime(Properties.tStop - Properties.tStart)));
599                                                Array2.Add(AtlFormatString(_T("%I64d"), Properties.tStop));
600                                                Array2.Add(AtlFormatString(_T("%I64d"), Properties.tStop - Properties.tStart));
601                                        }
602                                }
603                                Array1.Add(AtlFormatString(_T("lActual %s"), _StringHelper::FormatNumber(Properties.lActual)));
604                                _Z2(atlTraceGeneral, 2, _T("this 0x%p, \"%ls\", %s") _T("\t\t%s\t") _T("\n"), this, GetName(), _StringHelper::Join(Array1, _T(", ")), _StringHelper::Join(Array2, _T("\t")));
605                        }
606                        HandleMediaTypeChange<CInputPin, COutputPin>(Properties, m_pInputPin, m_pOutputPin);
607                        DeliverMediaSample(m_pOutputPin->GetPeerMemInputPin(), pMediaSample, nReceiveResult);
608                }
609                const CObjectPtr<CInputPin>& GetInputPin() const
610                {
611                        return m_pInputPin;
612                }
613                const CObjectPtr<COutputPin>& GetOutputPin() const
614                {
615                        return m_pOutputPin;
616                }
617        };
618
619private:
620        BOOL m_bIsAggregated;
621        HINSTANCE m_hQuartzModule;
622        CComPtr<IUnknown> m_pInnerUnknown;
623        CComPtr<IFilterGraph2> m_pInnerFilterGraph2;
624        CComPtr<IFilterGraph3> m_pInnerFilterGraph3;
625        CComPtr<IMediaControl> m_pInnerMediaControl;
626        CComPtr<IMediaEventSink> m_pInnerMediaEventSink;
627        CComPtr<IMediaEventEx> m_pInnerMediaEventEx;
628        _FilterGraphHelper::CRotRunningFilterGraph m_RunningFilterGraph;
629        INT m_nRunningFilterGraphReference;
630        #if defined(AVAILABILITY_FILTERGRAPHTABLE)
631                CLocalObjectPtr<CFilterGraphTableItem> m_pFilterGraphTableItem;
632        #endif // defined(AVAILABILITY_FILTERGRAPHTABLE)
633        SYSTEMTIME m_Time;
634        CStringW m_sMonikerDisplayName;
635        CComPtr<IUnknown> m_pTemporaryUnknown;
636        CObjectPtr<CAmGraphBuilderCallback> m_pPrivateAmGraphBuilderCallback;
637        mutable CRoCriticalSection m_DataCriticalSection;
638        CComPtr<IUnknown> m_pSite;
639        CStringW m_sFriendlyName;
640
641        static VOID TraceProcessPerformance(LPCTSTR pszDescription = NULL, BOOL bForce = FALSE)
642        {
643                pszDescription;
644                #if _DEVELOPMENT || _TRACE
645                        const ULONG nTime = GetTickCount();
646                        MEMORYSTATUSEX MemoryStatus = { sizeof MemoryStatus };
647                        const BOOL bGlobalMemoryStatusExResult = GlobalMemoryStatusEx(&MemoryStatus);
648                        PROCESS_MEMORY_COUNTERS_EX Counters = { sizeof Counters };
649                        const BOOL bGetProcessMemoryInfoResult = GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*) &Counters, sizeof Counters);
650                        _A(bGlobalMemoryStatusExResult && bGetProcessMemoryInfoResult);
651                        BOOL bReportGlobalMemoryStatusEx = FALSE, bReportGetProcessMemoryInfo = FALSE;
652                        #pragma region Reduce Similar Traces
653                        {
654                                _A(_pAtlModule);
655                                CComCritSecLock<CComCriticalSection> Lock(_pAtlModule->m_csStaticDataInitAndTypeInfo);
656                                static ULONG g_nReportTime = 0;
657                                static MEMORYSTATUSEX g_MemoryStatus;
658                                static PROCESS_MEMORY_COUNTERS_EX g_Counters;
659                                #if !defined(_DEBUG)
660                                        if(bForce || !g_nReportTime || nTime - g_nReportTime >= 15 * 1000) // 15 seconds
661                                        {
662                                                bReportGlobalMemoryStatusEx = bGlobalMemoryStatusExResult;
663                                                bReportGetProcessMemoryInfo = bGetProcessMemoryInfoResult;
664                                        } else
665                                        {
666                                                #pragma region MEMORYSTATUSEX
667                                                if(fabs(((DOUBLE) MemoryStatus.dwMemoryLoad - g_MemoryStatus.dwMemoryLoad) / ((MemoryStatus.dwMemoryLoad + g_MemoryStatus.dwMemoryLoad) / 2)) > 0.05) // 5%
668                                                        bReportGlobalMemoryStatusEx = TRUE;
669                                                else
670                                                if(fabs(((DOUBLE) MemoryStatus.ullAvailVirtual - g_MemoryStatus.ullAvailVirtual) / ((MemoryStatus.ullAvailVirtual + g_MemoryStatus.ullAvailVirtual) / 2)) > 0.05) // 5%
671                                                        bReportGlobalMemoryStatusEx = TRUE;
672                                                #pragma endregion
673                                                #pragma region PROCESS_MEMORY_COUNTERS_EX
674                                                if(fabs(((DOUBLE) Counters.WorkingSetSize - g_Counters.WorkingSetSize) / ((Counters.WorkingSetSize + g_Counters.WorkingSetSize) / 2)) > 0.05) // 5%
675                                                        bReportGetProcessMemoryInfo = TRUE;
676                                                else 
677                                                if(fabs(((DOUBLE) Counters.PrivateUsage - g_Counters.PrivateUsage) / ((Counters.PrivateUsage + g_Counters.PrivateUsage) / 2)) > 0.05) // 5%
678                                                        bReportGetProcessMemoryInfo = TRUE;
679                                                #pragma endregion
680                                        }
681                                #else
682                                        bReportGlobalMemoryStatusEx = bGlobalMemoryStatusExResult;
683                                        bReportGetProcessMemoryInfo = bGetProcessMemoryInfoResult;
684                                #endif // !defined(_DEBUG)
685                                if(bReportGlobalMemoryStatusEx)
686                                        g_MemoryStatus = MemoryStatus;
687                                if(bReportGetProcessMemoryInfo)
688                                        g_Counters = Counters;
689                                if(bReportGlobalMemoryStatusEx || bReportGetProcessMemoryInfo)
690                                        g_nReportTime = nTime;
691                        }
692                        #pragma endregion
693                        CString sDescription = pszDescription;
694                        if(!sDescription.IsEmpty())
695                                sDescription.Append(_T(": "));
696                        if(bReportGlobalMemoryStatusEx)
697                        {
698                                _Z2(atlTraceGeneral, 2, _T("%s") _T("Memory Status, ") 
699                                        _T("dwMemoryLoad %d") _T(", ")
700                                        _T("ullTotalVirtual %s MB") _T(", ")
701                                        _T("ullAvailVirtual %s MB (in use %s MB)") //_T(", ")
702                                        _T("\n"), 
703                                        sDescription,
704                                        MemoryStatus.dwMemoryLoad,
705                                        _StringHelper::FormatNumber((LONGLONG) MemoryStatus.ullTotalVirtual >> 20),
706                                        _StringHelper::FormatNumber((LONGLONG) MemoryStatus.ullAvailVirtual >> 20), _StringHelper::FormatNumber((LONGLONG) (MemoryStatus.ullTotalVirtual - MemoryStatus.ullAvailVirtual) >> 20),
707                                        0);
708                        }
709                        if(bReportGetProcessMemoryInfo)
710                        {
711                                _Z2(atlTraceGeneral, 2, _T("%s") _T("Process Performance, ") 
712                                        _T("WorkingSetSize %s MB (peak %s MB)") _T(", ")
713                                        _T("PrivateUsage %s MB") //_T(", ")
714                                        _T("\n"), 
715                                        sDescription,
716                                        _StringHelper::FormatNumber((LONGLONG) Counters.WorkingSetSize >> 20), _StringHelper::FormatNumber((LONGLONG) Counters.PeakWorkingSetSize >> 20),
717                                        _StringHelper::FormatNumber((LONGLONG) Counters.PrivateUsage >> 20), 
718                                        0);
719                        }
720                #endif // _DEVELOPMENT || _TRACE
721        }
722
723        BOOL IsAggregated() const
724        {
725                return (ULONG) m_dwRef >= 0x00001000;
726        }
727        VOID ReleaseTemporaryUnknown()
728        {
729                CComPtr<IUnknown> pUnknown;
730                Lock();
731                SwapMemory(&m_pTemporaryUnknown.p, &pUnknown.p);
732                Unlock();
733        }
734        VOID SetRunningFilterGraph()
735        {
736                if(m_RunningFilterGraph.GetCookie())
737                        return;
738                _Z4(atlTraceRefcount, 4, _T("this 0x%p, m_dwRef %d\n"), this, m_dwRef);
739                m_nRunningFilterGraphReference = 0;
740                CInterlockedLong& nReferenceCount = reinterpret_cast<CInterlockedLong&>(m_dwRef);
741                const LONG nBeforeReferenceCount = m_dwRef;
742                SYSTEMTIME Time;
743                GetLocalTime(&Time);
744                CStringW sMonikerDisplayName;
745                static CConstIntegerRegistryValue g_nEnableRotMonikerItemNameSuffix(_T("Enable ROT Moniker Item Name Suffix")); // 0 Default (Enabled), 1 Disabled, 2 Enabled
746                if(g_nEnableRotMonikerItemNameSuffix != 1) // Disabled
747                {
748                        TCHAR pszPath[MAX_PATH] = { 0 };
749                        _W(GetModuleFileName(NULL, pszPath, DIM(pszPath)));
750                        LPCTSTR pszName = FindFileName(pszPath);
751                        CString sItemName = AtlFormatString(_T("%s; process: %s, time: %02d-%02d-%02d"), m_RunningFilterGraph.GetDefaultMonikerItemName(GetControllingUnknown()), pszName, Time.wHour, Time.wMinute, Time.wSecond);
752                        m_RunningFilterGraph.SetFilterGraph(GetControllingUnknown(), CStringW(sItemName), &sMonikerDisplayName);
753                } else
754                        m_RunningFilterGraph.SetFilterGraph(GetControllingUnknown(), &sMonikerDisplayName);
755                _Z4(atlTraceRefcount, 4, _T("this 0x%p, m_bIsAggregated %d, m_dwRef %d, sMonikerDisplayName \"%ls\"\n"), this, m_bIsAggregated, m_dwRef, sMonikerDisplayName);
756                {
757                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
758                        m_Time = Time;
759                        m_sMonikerDisplayName = sMonikerDisplayName;
760                }
761                #pragma region Filter Graph Table Item
762                #if defined(AVAILABILITY_FILTERGRAPHTABLE)
763                        static CConstIntegerRegistryValue g_nAutomaticFilterGraphTableItem(_T("Automatic Filter Graph Table Item")); // 0 Default (Disabled), 1 Disabled, 2 Enabled
764                        if(g_nAutomaticFilterGraphTableItem == 2) // Enabled
765                                _ATLTRY
766                                {
767                                        _A(!m_pFilterGraphTableItem->IsFilterGraphAvailable());
768                                        m_pFilterGraphTableItem->SetFilterGraph(this);
769                                        Release();
770                                }
771                                _ATLCATCHALL()
772                                {
773                                        _Z_EXCEPTION();
774                                }
775                #endif // defined(AVAILABILITY_FILTERGRAPHTABLE)
776                #pragma endregion
777                if(!m_bIsAggregated)
778                {
779                        m_nRunningFilterGraphReference++;
780                        const LONG nAfterReferenceCount = m_dwRef;
781                        if(nBeforeReferenceCount == nAfterReferenceCount)
782                        {
783                                // NOTE: Putting onto Running Object Table succeeded, however no external reference detected which we need to compensate by self-releasing
784                                m_nRunningFilterGraphReference++;
785                                return;
786                        }
787                }
788                Release();
789        }
790        VOID ResetRunningFilterGraph()
791        {
792                if(!m_RunningFilterGraph.GetCookie())
793                        return;
794                #pragma region Filter Graph Table Item
795                #if defined(AVAILABILITY_FILTERGRAPHTABLE)
796                        _ATLTRY
797                        {
798                                if(m_pFilterGraphTableItem->IsFilterGraphAvailable())
799                                {
800                                        AddRef();
801                                        m_pFilterGraphTableItem->SetFilterGraph(NULL);
802                                }
803                        }
804                        _ATLCATCHALL()
805                        {
806                                _Z_EXCEPTION();
807                        }
808                #endif // defined(AVAILABILITY_FILTERGRAPHTABLE)
809                #pragma endregion
810                if(m_nRunningFilterGraphReference != 2)
811                        AddRef();
812                _Z4(atlTraceRefcount, 4, _T("this 0x%p, m_dwRef 0x%X\n"), this, m_dwRef);
813                m_RunningFilterGraph.SetFilterGraph(NULL);
814                {
815                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
816                        m_sMonikerDisplayName.Empty();
817                }
818                _Z4(atlTraceRefcount, 4, _T("this 0x%p, m_dwRef 0x%X\n"), this, m_dwRef);
819        }
820        HRESULT InternalQueryFilterGraph3Interface(REFIID InterfaceIdentifier, VOID** ppvObject)
821        {
822                _A(InterfaceIdentifier == __uuidof(IFilterGraph3));
823                _A(ppvObject);
824                if(!m_pInnerFilterGraph3)
825                {
826                        *ppvObject = NULL;
827                        return E_NOINTERFACE;
828                }
829                T* pT = static_cast<T*>(this);
830                *ppvObject = (IFilterGraph3*) pT;
831                pT->InternalAddRef();
832                return S_OK;
833        }
834        static HRESULT WINAPI QueryFilterGraph3Interface(VOID* pvThis, REFIID InterfaceIdentifier, VOID** ppvObject, DWORD_PTR)
835        {
836                return ((CSpy*) pvThis)->InternalQueryFilterGraph3Interface(InterfaceIdentifier, ppvObject);
837        }
838        HRESULT HookMediaControlAddSourceFilter(BSTR sFileName, IBaseFilter** ppBaseFilter, BOOL* pbDefault)
839        {
840                _A(pbDefault);
841                HOOK_PROLOG(CFilterGraphAddRemoveHookHost)
842                        OnAddSourceFilter(pT, sFileName, NULL, reinterpret_cast<IUnknown**>(ppBaseFilter), &bDefault);
843                        *pbDefault = bDefault;
844                HOOK_EPILOG()
845                return S_OK;
846        }
847
848public:
849// CSpyT
850        static LPCTSTR GetOriginalLibraryName()
851        {
852                return _T("quartz.dll");
853        }
854        static CString GetObjectFriendlyName()
855        {
856                return _StringHelper::GetLine(T::IDR, 2);
857        }
858        static HRESULT WINAPI UpdateRegistry(BOOL bRegister)
859        {
860                _Z2(atlTraceRegistrar, 2, _T("bRegister %d\n"), bRegister);
861                _ATLTRY
862                {
863                        TreatAsUpdateRegistryFromResource<T>(*t_pFilterGraphClassIdentifier, bRegister);
864                }
865                _ATLCATCH(Exception)
866                {
867                        _C(Exception);
868                }
869                return S_OK;
870        }
871        CSpyT() :
872                m_hQuartzModule(NULL)
873        {
874                _Z4_THIS();
875                ZeroMemory(&m_Time, sizeof m_Time);
876        }
877        ~CSpyT()
878        {
879                _Z4_THIS();
880        }
881        HRESULT FinalConstruct()
882        {
883                m_bIsAggregated = IsAggregated();
884                if(!m_bIsAggregated)
885                        InternalAddRef();
886                _ATLTRY
887                {
888                        TCHAR pszPath[MAX_PATH] = { 0 };
889                        _W(GetModuleFileName(NULL, pszPath, DIM(pszPath)));
890                        _Z4(atlTraceRefcount, 4, _T("pszPath \"%s\", this 0x%p, m_dwRef %d, m_bIsAggregated %d\n"), pszPath, this, m_dwRef, m_bIsAggregated);
891                        const HINSTANCE hModule = CoLoadOriginalLibrary();
892                        _ATLTRY
893                        {
894                                _A(hModule);
895                                const CComPtr<IUnknown> pControllingUnknown = GetControllingUnknown();
896                                #pragma region Instantiation
897                                {
898                                        { const ULONG nAddRefCount = pControllingUnknown.p->AddRef(); const ULONG nReleaseCount = pControllingUnknown.p->Release(); _Z5(atlTraceRefcount, 5, _T("m_dwRef 0x%X, AddRef %d, Release %d\n"), m_dwRef, nAddRefCount, nReleaseCount); }
899                                        const CComPtr<IUnknown> pUnknown = CoCreateOriginalInstance(hModule, pControllingUnknown);
900                                        // NOTE: DirectShow FilterGraph is incorrectly implementing COM aggregation adding outer reference to interfaces queried from private IUnknown
901                                        const CComQIPtr<IFilterGraph2> pFilterGraph2 = pUnknown;
902                                        __D(pFilterGraph2, E_NOINTERFACE);
903                                        pFilterGraph2.p->Release();
904                                        const CComQIPtr<IFilterGraph3> pFilterGraph3 = pUnknown;
905                                        if(pFilterGraph3)
906                                                pFilterGraph3.p->Release();
907                                        const CComQIPtr<IMediaControl> pMediaControl = pUnknown;
908                                        __D(pMediaControl, E_NOINTERFACE);
909                                        pMediaControl.p->Release();
910                                        const CComQIPtr<IMediaEventSink> pMediaEventSink = pUnknown;
911                                        __D(pMediaEventSink, E_NOINTERFACE);
912                                        pMediaEventSink.p->Release();
913                                        const CComQIPtr<IMediaEventEx> pMediaEventEx = pUnknown;
914                                        __D(pMediaEventEx, E_NOINTERFACE);
915                                        pMediaEventEx.p->Release();
916                                        #pragma region ROT Registration
917                                        { const ULONG nAddRefCount = pControllingUnknown.p->AddRef(); const ULONG nReleaseCount = pControllingUnknown.p->Release(); _Z5(atlTraceRefcount, 5, _T("m_dwRef 0x%X, AddRef %d, Release %d\n"), m_dwRef, nAddRefCount, nReleaseCount); }
918                                        SetRunningFilterGraph();
919                                        { const ULONG nAddRefCount = pControllingUnknown.p->AddRef(); const ULONG nReleaseCount = pControllingUnknown.p->Release(); _Z5(atlTraceRefcount, 5, _T("m_dwRef 0x%X, AddRef %d, Release %d\n"), m_dwRef, nAddRefCount, nReleaseCount); }
920                                        #pragma endregion
921                                        m_pInnerUnknown = pUnknown;
922                                        m_pInnerFilterGraph2 = pFilterGraph2;
923                                        m_pInnerFilterGraph3 = pFilterGraph3;
924                                        m_pInnerMediaControl = pMediaControl;
925                                        m_pInnerMediaEventSink = pMediaEventSink;
926                                        m_pInnerMediaEventEx = pMediaEventEx;
927                                }
928                                #pragma endregion
929                                #pragma region Set Private IAMGraphBuilderCallback
930                                static CConstIntegerRegistryValue g_nSetPrivateCallback(_T("Set Private CSpyT IAMGraphBuilderCallback")); // 0 Default (Enabled), 1 Disabled, 2 Enabled
931                                const DWORD nSetPrivateCallback = g_nSetPrivateCallback;
932                                if(nSetPrivateCallback != 1)
933                                {
934                                        CObjectPtr<CAmGraphBuilderCallback> pAmGraphBuilderCallback;
935                                        pAmGraphBuilderCallback.Construct();
936                                        pAmGraphBuilderCallback->Initialize(static_cast<T*>(this));
937                                        // WARN: Private site only forwards IAMGraphBuilderCallback interface and indicates other as not implemented
938                                        //       even if the external site does provide such implementation
939                                        if(pAmGraphBuilderCallback->SetGraphBuilder(pControllingUnknown))
940                                                m_pPrivateAmGraphBuilderCallback = pAmGraphBuilderCallback;
941                                        else
942                                                pAmGraphBuilderCallback->Terminate();
943                                }
944                                #pragma endregion
945                                #pragma region Temporary Reference for Aggregated Instantiation
946                                if(m_bIsAggregated)
947                                {
948                                        pControllingUnknown.p->AddRef();
949                                        const ULONG nReferenceCount = pControllingUnknown.p->Release();
950                                        if(nReferenceCount == 1)
951                                                m_pTemporaryUnknown = pControllingUnknown;
952                                }
953                                #pragma endregion
954                        }
955                        _ATLCATCHALL()
956                        {
957                                CoFreeLibrary(hModule);
958                                _ATLRETHROW;
959                        }
960                        #if defined(_DEBUG) && FALSE
961                                typedef HRESULT (WINAPI *DLLCANUNLOADNOW)();
962                                DLLCANUNLOADNOW DllCanUnloadNow = (DLLCANUNLOADNOW) GetProcAddress(hModule, "DllCanUnloadNow");
963                                __E(DllCanUnloadNow);
964                                const HRESULT nDllCanUnloadNowResult = DllCanUnloadNow();
965                                _Z4_HRESULT(nDllCanUnloadNowResult); 
966                        #endif // defined(_DEBUG)
967                        _A(!m_hQuartzModule);
968                        m_hQuartzModule = hModule;
969                        #pragma region Extra Reference
970                        // NOTE: This feature allows to leave an extra COM reference on the object to extend its lifetime and work around early destruction issues
971                        static CConstIntegerRegistryValue g_nAddExtraReference(_T("Add Extra CSpyT Reference")); // 0 Default (Disabled), 1 Not Aggregated Only, 2 Aggregated Only, 3 Both
972                        const DWORD nAddExtraReference = g_nAddExtraReference;
973                        if(!m_bIsAggregated)
974                        {
975                                if(nAddExtraReference & 1)
976                                        InternalAddRef();
977                        } else
978                                if(nAddExtraReference & 2)
979                                        GetControllingUnknown()->AddRef();
980                        #pragma endregion
981                }
982                _ATLCATCH(Exception)
983                {
984                        if(!m_bIsAggregated)
985                                _W(InternalRelease() > 0);
986                        _C(Exception);
987                }
988                // NOTE: x64 build experiences a problem under COM Surrogate process that we're already being released to zero while still in this method
989                if(!m_bIsAggregated)
990                        if(InternalRelease() <= 0)
991                                return E_UNEXPECTED;
992                return S_OK;
993        }
994        VOID FinalRelease()
995        {
996                _Z5(atlTraceRefcount, 5, _T("m_dwRef 0x%X\n"), m_dwRef);
997                _A(!m_pTemporaryUnknown);
998                const CComPtr<IUnknown> pControllingUnknown = GetControllingUnknown();
999                #pragma region Reset Private IAMGraphBuilderCallback
1000                if(m_pPrivateAmGraphBuilderCallback)
1001                {
1002                        m_pPrivateAmGraphBuilderCallback->Terminate();
1003                        m_pPrivateAmGraphBuilderCallback = NULL;
1004                }
1005                #pragma endregion
1006                ResetRunningFilterGraph();
1007                #pragma region Release Secondary Inner Interfaces
1008                if(m_pInnerMediaEventEx)
1009                {
1010                        pControllingUnknown.p->AddRef();
1011                        m_pInnerMediaEventEx = NULL;
1012                }
1013                if(m_pInnerMediaEventSink)
1014                {
1015                        pControllingUnknown.p->AddRef();
1016                        m_pInnerMediaEventSink = NULL;
1017                }
1018                if(m_pInnerMediaControl)
1019                {
1020                        pControllingUnknown.p->AddRef();
1021                        m_pInnerMediaControl = NULL;
1022                }
1023                if(m_pInnerFilterGraph3)
1024                {
1025                        pControllingUnknown.p->AddRef();
1026                        m_pInnerFilterGraph3 = NULL;
1027                }
1028                if(m_pInnerFilterGraph2)
1029                {
1030                        pControllingUnknown.p->AddRef();
1031                        m_pInnerFilterGraph2 = NULL;
1032                }
1033                #pragma endregion
1034                #pragma region Release Primary Inner IUnknown
1035                _ATLTRY
1036                {
1037                        m_pInnerUnknown = NULL;
1038                }
1039                _ATLCATCHALL()
1040                {
1041                        _Z_EXCEPTION();
1042                        // NOTE: For some unidentified reason Quartz's FilterGraph may crash during final release, to smooth the effect the exception is silently caught
1043                        m_pInnerUnknown.p = NULL;
1044                }
1045                #pragma endregion
1046                #pragma region Release Quartz Library
1047                if(m_hQuartzModule)
1048                {
1049                        CoFreeLibrary(m_hQuartzModule);
1050                        m_hQuartzModule = NULL;
1051                }
1052                #pragma endregion
1053        }
1054        HRESULT QueryObjectWithSiteInterface(REFIID InterfaceIdentifier, LPVOID* ppvObject)
1055        {
1056                _A(InterfaceIdentifier == __uuidof(IObjectWithSite));
1057                _A(ppvObject);
1058                if(m_pPrivateAmGraphBuilderCallback)
1059                {
1060                        *ppvObject = CComPtr<IObjectWithSite>(static_cast<T*>(this)).Detach();
1061                        return S_OK;
1062                }
1063                _A(m_pInnerUnknown);
1064                return m_pInnerUnknown->QueryInterface(InterfaceIdentifier, ppvObject);
1065        }
1066        static HRESULT WINAPI QueryObjectWithSiteInterface(VOID* pvInstance, REFIID InterfaceIdentifier, LPVOID* ppvObject, DWORD_PTR)
1067        {
1068                return ((CSpy*) pvInstance)->QueryObjectWithSiteInterface(InterfaceIdentifier, ppvObject);
1069        }
1070        CComPtr<IUnknown> GetSite() const
1071        {
1072                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1073                return m_pSite;
1074        }
1075        BOOL SelectedFilter(IMoniker* pMoniker, HRESULT& nSelectedFilterResult)
1076        {
1077                const CComQIPtr<IAMGraphBuilderCallback> pAmGraphBuilderCallback = GetSite();
1078                if(pAmGraphBuilderCallback)
1079                {
1080                        nSelectedFilterResult = pAmGraphBuilderCallback->SelectedFilter(pMoniker);
1081                        return TRUE;
1082                }
1083                return FALSE;
1084        }
1085        BOOL CreatedFilter(IBaseFilter* pBaseFilter, HRESULT& nCreatedFilterResult)
1086        {
1087                const CComQIPtr<IAMGraphBuilderCallback> pAmGraphBuilderCallback = GetSite();
1088                if(pAmGraphBuilderCallback)
1089                {
1090                        nCreatedFilterResult = pAmGraphBuilderCallback->CreatedFilter(pBaseFilter);
1091                        return TRUE;
1092                }
1093                return FALSE;
1094        }
1095        CStringW GetMonikerDisplayName() const
1096        {
1097                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1098                return m_sMonikerDisplayName;
1099        }
1100
1101// ISpy
1102    STDMETHOD(get_MonikerDisplayName)(BSTR* psMonikerDisplayName) override
1103        {
1104                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1105                _ATLTRY
1106                {
1107                        __D(psMonikerDisplayName, E_POINTER);
1108                        *psMonikerDisplayName = CComBSTR(GetMonikerDisplayName()).Detach();
1109                }
1110                _ATLCATCHALL()
1111                {
1112                        _Z_EXCEPTION();
1113                }
1114                return S_OK;
1115        }
1116        STDMETHOD(get_CreationTime)(DATE* pfTime) override
1117        {
1118                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1119                _ATLTRY
1120                {
1121                        __D(pfTime, E_POINTER);
1122                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1123                        FILETIME LocalFileTime, FileTime;
1124                        _W(SystemTimeToFileTime(&m_Time, &LocalFileTime));
1125                        _W(LocalFileTimeToFileTime(&LocalFileTime, &FileTime));
1126                        SYSTEMTIME Time;
1127                        _W(FileTimeToSystemTime(&FileTime, &Time));
1128                        _W(SystemTimeToVariantTime(&Time, pfTime));
1129                }
1130                _ATLCATCHALL()
1131                {
1132                        _Z_EXCEPTION();
1133                }
1134                return S_OK;
1135        }
1136        STDMETHOD(get_FriendlyName)(BSTR* psFriendlyName) override
1137        {
1138                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1139                _ATLTRY
1140                {
1141                        __D(psFriendlyName, E_POINTER);
1142                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1143                        *psFriendlyName = CComBSTR(m_sFriendlyName).Detach();
1144                }
1145                _ATLCATCHALL()
1146                {
1147                        _Z_EXCEPTION();
1148                }
1149                return S_OK;
1150        }
1151        STDMETHOD(put_FriendlyName)(BSTR sFriendlyName) override
1152        {
1153                _Z4(atlTraceCOM, 4, _T("this 0x%p, sFriendlyName \"%s\"\n"), this, CString(sFriendlyName));
1154                _ATLTRY
1155                {
1156                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1157                        m_sFriendlyName = sFriendlyName;
1158                }
1159                _ATLCATCHALL()
1160                {
1161                        _Z_EXCEPTION();
1162                }
1163                return S_OK;
1164        }
1165        STDMETHOD(DoPropertyFrameModal)(LONG nParentWindowHandle) override
1166        {
1167                _Z4(atlTraceCOM, 4, _T("this 0x%p, nParentWindowHandle 0x%08X\n"), this, nParentWindowHandle);
1168                _ATLTRY
1169                {
1170                        T* pT = static_cast<T*>(this);
1171                        return FilterGraphHelper_DoPropertyFrameModal(nParentWindowHandle, (IFilterGraph*) CComQIPtr<IFilterGraph>(pT));
1172                }
1173                _ATLCATCHALL()
1174                {
1175                        _Z_EXCEPTION();
1176                }
1177                return S_OK;
1178        }
1179        STDMETHOD(DoFilterGraphListModal)(LONG nParentWindowHandle) override
1180        {
1181                _Z4(atlTraceCOM, 4, _T("this 0x%p, nParentWindowHandle 0x%08X\n"), this, nParentWindowHandle);
1182                _ATLTRY
1183                {
1184                        return FilterGraphHelper_DoFilterGraphListModal(nParentWindowHandle);
1185                }
1186                _ATLCATCHALL()
1187                {
1188                        _Z_EXCEPTION();
1189                }
1190                return S_OK;
1191        }
1192        STDMETHOD(OpenGraphStudioNext)(LONG nParentWindowHandle, VARIANT_BOOL* pbResult) override
1193        {
1194                _Z4(atlTraceCOM, 4, _T("this 0x%p, nParentWindowHandle 0x%08X\n"), this, nParentWindowHandle);
1195                _ATLTRY
1196                {
1197                        return FilterGraphHelper_OpenGraphStudioNext(nParentWindowHandle, GetMonikerDisplayName(), pbResult);
1198                }
1199                _ATLCATCHALL()
1200                {
1201                        _Z_EXCEPTION();
1202                }
1203                return S_OK;
1204        }
1205        STDMETHOD(OpenGraphEdit)(LONG nParentWindowHandle, VARIANT_BOOL* pbResult) override
1206        {
1207                _Z4(atlTraceCOM, 4, _T("this 0x%p, nParentWindowHandle 0x%08X\n"), this, nParentWindowHandle);
1208                _ATLTRY
1209                {
1210                        return FilterGraphHelper_OpenGraphEdit(nParentWindowHandle, GetMonikerDisplayName(), pbResult);
1211                }
1212                _ATLCATCHALL()
1213                {
1214                        _Z_EXCEPTION();
1215                }
1216                return S_OK;
1217        }
1218        STDMETHOD(ReadRunPropertyBag)(IUnknown* pBaseFilterUnknown, VARIANT_BOOL bAllowExtension, VARIANT* pvValue) override
1219        {
1220                _Z4(atlTraceCOM, 4, _T("this 0x%p, pBaseFilterUnknown 0x%p, bAllowExtension %d\n"), this, pBaseFilterUnknown, bAllowExtension);
1221                _ATLTRY
1222                {
1223                        __D(pBaseFilterUnknown, E_INVALIDARG);
1224                        __D(pvValue, E_POINTER);
1225                        VariantInit(pvValue);
1226                        _V(CRunPropertyBagHelper::ReadRunPropertyBag(pBaseFilterUnknown, bAllowExtension != ATL_VARIANT_FALSE).Detach(pvValue));
1227                }
1228                _ATLCATCHALL()
1229                {
1230                        _Z_EXCEPTION();
1231                }
1232                return S_OK;
1233        }
1234        STDMETHOD(CreateMediaSampleTrace)(IMediaSampleTrace** ppMediaSampleTrace) override
1235        {
1236                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1237                _ATLTRY
1238                {
1239                        __D(ppMediaSampleTrace, E_POINTER);
1240                        *ppMediaSampleTrace = NULL;
1241                        CObjectPtr<CMediaSampleTrace> pMediaSampleTrace;
1242                        pMediaSampleTrace.Construct()->Initialize(this);
1243                        *ppMediaSampleTrace = pMediaSampleTrace.Detach();
1244                }
1245                _ATLCATCHALL()
1246                {
1247                        _Z_EXCEPTION();
1248                }
1249                return S_OK;
1250        }
1251        STDMETHOD(CreateFilterGraphHelper)(IFilterGraphHelper** ppFilterGraphHelper) override
1252        {
1253                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1254                _ATLTRY
1255                {
1256                        __D(ppFilterGraphHelper, E_POINTER);
1257                        *ppFilterGraphHelper = NULL;
1258                        CObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
1259                        pFilterGraphHelper.Construct()->SetFilterGraph(this);
1260                        *ppFilterGraphHelper = pFilterGraphHelper.Detach();
1261                }
1262                _ATLCATCHALL()
1263                {
1264                        _Z_EXCEPTION();
1265                }
1266                return S_OK;
1267        }
1268
1269// ISpyEx
1270
1271// IFilterGraph
1272        STDMETHOD(AddFilter)(IBaseFilter* pBaseFilter, LPCWSTR pszName) override
1273        {
1274                _Z4(atlTraceCOM, 4, _T("this 0x%p, pBaseFilter 0x%p %ls, pszName \"%s\"\n"), this, pBaseFilter, _FilterGraphHelper::GetFilterClassIdentifierString(pBaseFilter), CString(pszName));
1275                ReleaseTemporaryUnknown();
1276                HOOK_PROLOG(CFilterGraphAddRemoveHookHost)
1277                        OnAddFilter(pT, pBaseFilter, pszName, &bDefault);
1278                HOOK_EPILOG()
1279                const HRESULT nResult = m_pInnerFilterGraph2->AddFilter(pBaseFilter, pszName);
1280                if(SUCCEEDED(nResult))
1281                        _ATLTRY
1282                        {
1283                                const CStringW sName = _FilterGraphHelper::GetFilterName(pBaseFilter);
1284                                _Z4(atlTraceGeneral, 4, _T("this 0x%p, sName \"%ls\"\n"), this, sName);
1285                        }
1286                        _ATLCATCHALL()
1287                        {
1288                                _Z_EXCEPTION();
1289                        }
1290                return nResult;
1291        }
1292    STDMETHOD(RemoveFilter)(IBaseFilter* pBaseFilter) override
1293        {
1294                _Z4(atlTraceCOM, 4, _T("this 0x%p, pBaseFilter 0x%p\n"), this, pBaseFilter);
1295                if(pBaseFilter)
1296                        _ATLTRY
1297                        {
1298                                const CStringW sName = _FilterGraphHelper::GetFilterName(pBaseFilter);
1299                                _Z4(atlTraceGeneral, 4, _T("this 0x%p, sName \"%ls\"\n"), this, sName);
1300                        }
1301                        _ATLCATCHALL()
1302                        {
1303                                _Z_EXCEPTION();
1304                        }
1305                HOOK_PROLOG(CFilterGraphAddRemoveHookHost)
1306                        OnRemoveFilter(pT, pBaseFilter, &bDefault);
1307                HOOK_EPILOG()
1308                return m_pInnerFilterGraph2->RemoveFilter(pBaseFilter);
1309        }
1310    STDMETHOD(EnumFilters)(IEnumFilters** ppEnumFilters) override
1311        {
1312                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1313                return m_pInnerFilterGraph2->EnumFilters(ppEnumFilters);
1314        }
1315    STDMETHOD(FindFilterByName)(LPCWSTR pszName, IBaseFilter** ppFilter) override
1316        {
1317                _Z4(atlTraceCOM, 4, _T("this 0x%p, pszName \"%s\"\n"), this, CString(pszName));
1318                return m_pInnerFilterGraph2->FindFilterByName(pszName, ppFilter);
1319        }
1320    STDMETHOD(ConnectDirect)(IPin* pOutputPin, IPin* pInputPin, const AM_MEDIA_TYPE* pMediaType) override
1321        {
1322                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1323                if(pOutputPin && pInputPin)
1324                        _ATLTRY
1325                        {
1326                                _Z4(atlTraceGeneral, 4, _T("pOutputPin \"%ls\", pInputPin \"%ls\", pMediaType 0x%p\n"), _FilterGraphHelper::GetPinFullName(pOutputPin), _FilterGraphHelper::GetPinFullName(pInputPin), pMediaType);
1327                                if(pMediaType)
1328                                        _FilterGraphHelper::TraceMediaType(pMediaType);
1329                                #pragma region Log Filter
1330                                // NOTE: This inserts additional filter without graph owner's will, for troubleshooting purposes; CLogFilter logs streaming details
1331                                #if FALSE
1332                                        const CComPtr<IBaseFilter> pOutputBaseFilter = _FilterGraphHelper::GetPinFilter(pOutputPin);
1333                                        const CComPtr<IBaseFilter> pInputBaseFilter = _FilterGraphHelper::GetPinFilter(pInputPin);
1334                                        class __declspec(uuid("{09075D10-D7EC-420f-A8F9-940E1602A371}")) AudioSplitter;
1335                                        if(_FilterGraphHelper::GetFilterClassIdentifier(pOutputBaseFilter) == __uuidof(AudioSplitter) || _FilterGraphHelper::GetFilterClassIdentifier(pInputBaseFilter) == __uuidof(AudioSplitter))
1336                                                _ATLTRY
1337                                                {
1338                                                        _A(_FilterGraphHelper::GetPinDirection(pOutputPin) == PINDIR_OUTPUT);
1339                                                        CObjectPtr<CLogFilter> pLogFilter;
1340                                                        pLogFilter.Construct();
1341                                                        CString sName = AtlFormatString(_T("Log (%s; %s)"), _FilterGraphHelper::GetFilterName(pOutputBaseFilter), _FilterGraphHelper::GetFilterName(pInputBaseFilter));
1342                                                        __C(m_pInnerFilterGraph2->AddFilter(pLogFilter, CStringW(sName)));
1343                                                        _ATLTRY
1344                                                        {
1345                                                                __C(m_pInnerFilterGraph2->ConnectDirect(pOutputPin, pLogFilter->GetInputPin(), pMediaType));
1346                                                                __C(m_pInnerFilterGraph2->ConnectDirect(pLogFilter->GetOutputPin(), pInputPin, pMediaType));
1347                                                                _Z4(atlTraceGeneral, 4, _T("this 0x%p, pLogFilter->GetName() \"%ls\"\n"), this, pLogFilter->GetName());
1348                                                                return S_OK;
1349                                                        }
1350                                                        _ATLCATCHALL()
1351                                                        {
1352                                                                __C(m_pInnerFilterGraph2->RemoveFilter(pLogFilter));
1353                                                                _ATLRETHROW;
1354                                                        }
1355                                                }
1356                                                _ATLCATCHALL()
1357                                                {
1358                                                        _Z_EXCEPTION();
1359                                                }
1360                                #endif
1361                                #pragma endregion
1362                        }
1363                        _ATLCATCHALL()
1364                        {
1365                                _Z_EXCEPTION();
1366                        }
1367                HOOK_PROLOG(CFilterGraphConnectHookHost)
1368                        OnConnectDirect(pT, pOutputPin, pInputPin, (const BYTE*) pMediaType, &bDefault);
1369                HOOK_EPILOG()
1370                const HRESULT nConnectDirectResult = m_pInnerFilterGraph2->ConnectDirect(pOutputPin, pInputPin, pMediaType);
1371                _Z4(atlTraceGeneral, 4, _T("this 0x%p, nConnectDirectResult 0x%08X\n"), this, nConnectDirectResult);
1372                return nConnectDirectResult;
1373        }
1374    STDMETHOD(Reconnect)(IPin* pPin) override
1375        {
1376                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1377                HOOK_PROLOG(CFilterGraphConnectHookHost)
1378                        OnReconnect(pT, pPin, &bDefault);
1379                HOOK_EPILOG()
1380                return m_pInnerFilterGraph2->Reconnect(pPin);
1381        }
1382    STDMETHOD(Disconnect)(IPin* pPin) override
1383        {
1384                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1385                HOOK_PROLOG(CFilterGraphConnectHookHost)
1386                        OnDisconnect(pT, pPin, &bDefault);
1387                HOOK_EPILOG()
1388                return m_pInnerFilterGraph2->Disconnect(pPin);
1389        }
1390    STDMETHOD(SetDefaultSyncSource)() override
1391        {
1392                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1393                return m_pInnerFilterGraph2->SetDefaultSyncSource();
1394        }
1395
1396// IGraphBuilder
1397    STDMETHOD(Connect)(IPin* pOutputPin, IPin* pInputPin) override
1398        {
1399                _Z4(atlTraceCOM, 4, _T("this 0x%p, pOutputPin 0x%p, pInputPin 0x%p\n"), this, pOutputPin, pInputPin);
1400                if(pOutputPin && pInputPin)
1401                        _ATLTRY
1402                        {
1403                                _Z4(atlTraceGeneral, 4, _T("pOutputPin 0x%p \"%ls\" (filter 0x%p), pInputPin 0x%p \"%ls\" (filter 0x%p)\n"), 
1404                                        pOutputPin, _FilterGraphHelper::GetPinFullName(pOutputPin), _FilterGraphHelper::GetPinFilter(pOutputPin),
1405                                        pInputPin, _FilterGraphHelper::GetPinFullName(pInputPin), _FilterGraphHelper::GetPinFilter(pInputPin),
1406                                        0);
1407                        }
1408                        _ATLCATCHALL()
1409                        {
1410                                _Z_EXCEPTION();
1411                        }
1412                HOOK_PROLOG(CFilterGraphConnectHookHost)
1413                        OnConnect(pT, pOutputPin, pInputPin, &bDefault);
1414                HOOK_EPILOG()
1415                const HRESULT nConnectResult = m_pInnerFilterGraph2->Connect(pOutputPin, pInputPin);
1416                _Z4(atlTraceGeneral, 4, _T("this 0x%p, nConnectResult 0x%08X\n"), this, nConnectResult);
1417                return nConnectResult;
1418        }
1419    STDMETHOD(Render)(IPin* pOutputPin) override
1420        {
1421                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1422                return m_pInnerFilterGraph2->Render(pOutputPin);
1423        }
1424    STDMETHOD(RenderFile)(LPCWSTR pszFileName, LPCWSTR pszPlayListFileName) override
1425        {
1426                _Z4(atlTraceCOM, 4, _T("this 0x%p, pszFileName \"%s\", pszPlayListFileName \"%s\"\n"), this, CString(pszFileName), CString(pszPlayListFileName));
1427                return m_pInnerFilterGraph2->RenderFile(pszFileName, pszPlayListFileName);
1428        }
1429    STDMETHOD(AddSourceFilter)(LPCWSTR pszFileName, LPCWSTR pszFilterName, IBaseFilter** ppBaseFilter) override
1430        {
1431                _Z4(atlTraceCOM, 4, _T("this 0x%p, pszFileName \"%s\", pszFilterName \"%s\"\n"), this, CString(pszFileName), CString(pszFilterName));
1432                ReleaseTemporaryUnknown();
1433                HOOK_PROLOG(CFilterGraphAddRemoveHookHost)
1434                        OnAddSourceFilter(pT, pszFileName, pszFilterName, reinterpret_cast<IUnknown**>(ppBaseFilter), &bDefault);
1435                HOOK_EPILOG()
1436                return m_pInnerFilterGraph2->AddSourceFilter(pszFileName, pszFilterName, ppBaseFilter);
1437        }
1438        STDMETHOD(SetLogFile)(DWORD_PTR hFile) override
1439        {
1440                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1441                return m_pInnerFilterGraph2->SetLogFile(hFile);
1442        }
1443        STDMETHOD(Abort)() override
1444        {
1445                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1446                return m_pInnerFilterGraph2->Abort();
1447        }
1448        STDMETHOD(ShouldOperationContinue)() override
1449        {
1450                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1451                return m_pInnerFilterGraph2->ShouldOperationContinue();
1452        }
1453
1454// IFilterGraph2
1455        STDMETHOD(AddSourceFilterForMoniker)(IMoniker* pMoniker, IBindCtx* pBindCtx, LPCWSTR pszFilterName, IBaseFilter** ppBaseFilter) override
1456        {
1457                _Z4(atlTraceCOM, 4, _T("this 0x%p, pszFilterName \"%s\"\n"), this, CString(pszFilterName));
1458                ReleaseTemporaryUnknown();
1459                HOOK_PROLOG(CFilterGraphAddRemoveHookHost)
1460                        OnAddSourceFilterForMoniker(pT, pMoniker, pBindCtx, pszFilterName, reinterpret_cast<IUnknown**>(ppBaseFilter), &bDefault);
1461                HOOK_EPILOG()
1462                return m_pInnerFilterGraph2->AddSourceFilterForMoniker(pMoniker, pBindCtx, pszFilterName, ppBaseFilter);
1463        }
1464        STDMETHOD(ReconnectEx)(IPin* pPin, const AM_MEDIA_TYPE* pMediaType) override
1465        {
1466                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1467                HOOK_PROLOG(CFilterGraphConnectHookHost)
1468                        OnReconnectEx(pT, pPin, (const BYTE*) pMediaType, &bDefault);
1469                HOOK_EPILOG()
1470                return m_pInnerFilterGraph2->ReconnectEx(pPin, pMediaType);
1471        }
1472        STDMETHOD(RenderEx)(IPin* pOutputPin, DWORD nFlags, DWORD* pnContext) override
1473        {
1474                _Z4(atlTraceCOM, 4, _T("this 0x%p, nFlags 0x%X\n"), this, nFlags);
1475                return m_pInnerFilterGraph2->RenderEx(pOutputPin, nFlags, pnContext);
1476        }
1477
1478// IFilterGraph3
1479    STDMETHOD(SetSyncSourceEx)(IReferenceClock* pFilterGraphReferenceClock, IReferenceClock* pFilterReferenceClock, IBaseFilter* pBaseFilter) override
1480        {
1481                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1482                _A(m_pInnerFilterGraph3);
1483                return m_pInnerFilterGraph3->SetSyncSourceEx(pFilterGraphReferenceClock, pFilterReferenceClock, pBaseFilter);
1484        }
1485
1486// IMediaControl
1487        STDMETHOD(Run)() override
1488        {
1489                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1490                _ATLTRY
1491                {
1492                        OAFilterState State = (OAFilterState) -1;
1493                        if(SUCCEEDED(m_pInnerMediaControl->GetState(0, &State)) && State == State_Stopped)
1494                                _FilterGraphHelper::TraceGraphBuilder(this);
1495                }
1496                _ATLCATCHALL()
1497                {
1498                        _Z_EXCEPTION();
1499                }
1500                HOOK_PROLOG(CFilterGraphStateControlHookHost)
1501                        OnRun(pT, &bDefault);
1502                HOOK_EPILOG()
1503                TraceProcessPerformance(_T("Before IMediaControl::Run"));
1504                const HRESULT nRunResult = m_pInnerMediaControl->Run();
1505                _Z4_DSHRESULT(nRunResult);
1506                TraceProcessPerformance(_T("After IMediaControl::Run"));
1507                return nRunResult;
1508        }
1509        STDMETHOD(Pause)() override
1510        {
1511                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1512                _ATLTRY
1513                {
1514                        OAFilterState State = (OAFilterState) -1;
1515                        if(SUCCEEDED(m_pInnerMediaControl->GetState(0, &State)) && State == State_Stopped)
1516                                _FilterGraphHelper::TraceGraphBuilder(this);
1517                }
1518                _ATLCATCHALL()
1519                {
1520                        _Z_EXCEPTION();
1521                }
1522                HOOK_PROLOG(CFilterGraphStateControlHookHost)
1523                        OnPause(pT, &bDefault);
1524                HOOK_EPILOG()
1525                TraceProcessPerformance(_T("Before IMediaControl::Pause"));
1526                const HRESULT nPauseResult = m_pInnerMediaControl->Pause();
1527                _Z4_DSHRESULT(nPauseResult);
1528                TraceProcessPerformance(_T("After IMediaControl::Pause"));
1529                return nPauseResult;
1530        }
1531        STDMETHOD(Stop)() override
1532        {
1533                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1534                HOOK_PROLOG(CFilterGraphStateControlHookHost)
1535                        OnStop(pT, &bDefault);
1536                HOOK_EPILOG()
1537                TraceProcessPerformance(_T("Before IMediaControl::Stop"));
1538                const HRESULT nStopResult = m_pInnerMediaControl->Stop();
1539                _Z4_DSHRESULT(nStopResult);
1540                TraceProcessPerformance(_T("After IMediaControl::Stop"));
1541                return nStopResult;
1542        }
1543        STDMETHOD(GetState)(LONG nTimeout, OAFilterState* pState) override
1544        {
1545                _Z5(atlTraceCOM, 5, _T("this 0x%p, nTimeout %d\n"), this, nTimeout);
1546                return m_pInnerMediaControl->GetState(nTimeout, pState);
1547        }
1548        STDMETHOD(RenderFile)(BSTR sFileName) override
1549        {
1550                _Z4(atlTraceCOM, 4, _T("this 0x%p, sFileName \"%s\"\n"), this, CString(sFileName));
1551                return m_pInnerMediaControl->RenderFile(sFileName);
1552        }
1553    STDMETHOD(AddSourceFilter)(BSTR sFileName, IDispatch** ppDispatch) override
1554        {
1555                _Z4(atlTraceCOM, 4, _T("this 0x%p, sFileName \"%s\"\n"), this, CString(sFileName));
1556                ReleaseTemporaryUnknown();
1557                _ATLTRY
1558                {
1559                        CComPtr<IBaseFilter> pBaseFilter;
1560                        BOOL bDefault = TRUE;
1561                        const HRESULT nResult = HookMediaControlAddSourceFilter(sFileName, &pBaseFilter, &bDefault);
1562                        if(!bDefault)
1563                        {
1564                                __D(ppDispatch, E_POINTER);
1565                                *ppDispatch = NULL;
1566                                if(SUCCEEDED(nResult))
1567                                {
1568                                        CComQIPtr<IDispatch> pDispatch = pBaseFilter;
1569                                        __D(pDispatch, E_NOINTERFACE);
1570                                        *ppDispatch = pDispatch.Detach();
1571                                }
1572                                return nResult;
1573                        }
1574                }
1575                _ATLCATCH(Exception)
1576                {
1577                        _C(Exception);
1578                }
1579                return m_pInnerMediaControl->AddSourceFilter(sFileName, ppDispatch);
1580        }
1581        STDMETHOD(get_FilterCollection)(IDispatch** ppDispatch) override
1582        {
1583                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1584                ReleaseTemporaryUnknown();
1585                return m_pInnerMediaControl->get_FilterCollection(ppDispatch);
1586        }
1587        STDMETHOD(get_RegFilterCollection)(IDispatch** ppDispatch) override
1588        {
1589                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1590                ReleaseTemporaryUnknown();
1591                return m_pInnerMediaControl->get_RegFilterCollection(ppDispatch);
1592        }
1593        STDMETHOD(StopWhenReady)() override
1594        {
1595                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1596                return m_pInnerMediaControl->StopWhenReady();
1597        }
1598
1599// IMediaEventSink
1600    STDMETHOD(Notify)(LONG nEventCode, LONG_PTR nParameter1, LONG_PTR nParameter2) override
1601        {
1602                _Z4(atlTraceCOM, 4, _T("this 0x%p, nEventCode %s, nParameter1 0x%p, nParameter2 0x%p\n"), this, _FilterGraphHelper::FormatEventCode(nEventCode), nParameter1, nParameter2);
1603                #pragma region EC_COMPLETE
1604                if(nEventCode == EC_COMPLETE)
1605                        _ATLTRY
1606                        {
1607                                IBaseFilter* pBaseFilter = (IBaseFilter*) nParameter2;
1608                                if(pBaseFilter)
1609                                {
1610                                        const CStringW sName = _FilterGraphHelper::GetFilterName(pBaseFilter);
1611                                        _Z3(atlTraceCOM, 3, _T("Received EC_COMPLETE from filter 0x%p \"%ls\"\n"), pBaseFilter, sName);
1612                                }
1613                                //TCHAR pszComment[64];
1614                                //_stprintf_s(pszComment, _T("DirectShow-Complete-0x%08X"), (HRESULT) nParameter1);
1615                                //TryWriteMiniDump(pszComment);
1616                        }
1617                        _ATLCATCHALL()
1618                        {
1619                                _Z_EXCEPTION();
1620                        }
1621                #pragma endregion
1622                #pragma region EC_ERRORABORT, EC_ERRORABORTEX
1623                if(nEventCode == EC_ERRORABORT || nEventCode == EC_ERRORABORTEX)
1624                {
1625                        if(nEventCode == EC_ERRORABORTEX && nParameter2)
1626                                _Z4(atlTraceGeneral, 4, _T("nParameter2 \"%s\"\n"), CString((BSTR) nParameter2));
1627                        TraceProcessPerformance(_FilterGraphHelper::FormatEventCode(nEventCode), TRUE);
1628                        static CConstIntegerRegistryValue g_nErrorAbortMiniDumpMode(_T("ErrorAbort MiniDump Mode")); // 0 Default (=1), 1 Disabled, 2 Enabled
1629                        if((DWORD) g_nErrorAbortMiniDumpMode == 2) // Enabled
1630                        {
1631                                TCHAR pszComment[64];
1632                                _stprintf_s(pszComment, _T("DirectShow-ErrorAbort-0x%08X"), (HRESULT) nParameter1);
1633                                static LONG g_nCounter = 0;
1634                                TryWriteMiniDump(pszComment, &g_nCounter);
1635                        }
1636                }
1637                #pragma endregion
1638                if(!m_pInnerMediaEventSink)
1639                        return S_FALSE;
1640                return m_pInnerMediaEventSink->Notify(nEventCode, nParameter1, nParameter2);
1641        }
1642
1643// IMediaEvent
1644        STDMETHOD(GetEventHandle)(OAEVENT* pnEventHandle) override
1645        {
1646                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1647                return m_pInnerMediaEventEx->GetEventHandle(pnEventHandle);
1648        }
1649        STDMETHOD(GetEvent)(LONG* pnEventCode, LONG_PTR* pnParameter1, LONG_PTR* pnParameter2, LONG nTimeout) override
1650        {
1651                _Z4(atlTraceCOM, nTimeout ? 4 : 5, _T("this 0x%p, nTimeout %d\n"), this, nTimeout);
1652                const HRESULT nGetEventResult = m_pInnerMediaEventEx->GetEvent(pnEventCode, pnParameter1, pnParameter2, nTimeout);
1653                if(pnEventCode && pnParameter1 && pnParameter2)
1654                        _Z4(atlTraceCOM, (nGetEventResult != E_ABORT) ? 4 : 5, _T("nGetEventResult 0x%08X, *pnEventCode %s, *pnParameter1 0x%p, *pnParameter2 0x%p\n"), nGetEventResult, _FilterGraphHelper::FormatEventCode(*pnEventCode), *pnParameter1, *pnParameter2);
1655                return nGetEventResult;
1656        }
1657        STDMETHOD(WaitForCompletion)(LONG nTimeout, LONG* pnEventCode) override
1658        {
1659                _Z4(atlTraceCOM, 4, _T("this 0x%p, nTimeout %d\n"), this, nTimeout);
1660                const HRESULT nWaitForCompletionResult = m_pInnerMediaEventEx->WaitForCompletion(nTimeout, pnEventCode);
1661                if(pnEventCode)
1662                        _Z4(atlTraceCOM, 4, _T("nWaitForCompletionResult 0x%08X, *pnEventCode %s\n"), nWaitForCompletionResult, _FilterGraphHelper::FormatEventCode(*pnEventCode));
1663                return nWaitForCompletionResult;
1664        }
1665        STDMETHOD(CancelDefaultHandling)(LONG nEventCode) override
1666        {
1667                _Z4(atlTraceCOM, 4, _T("this 0x%p, nEventCode %s\n"), this, _FilterGraphHelper::FormatEventCode(nEventCode));
1668                return m_pInnerMediaEventEx->CancelDefaultHandling(nEventCode);
1669        }
1670        STDMETHOD(RestoreDefaultHandling)(LONG nEventCode) override
1671        {
1672                _Z4(atlTraceCOM, 4, _T("this 0x%p, nEventCode %s\n"), this, _FilterGraphHelper::FormatEventCode(nEventCode));
1673                return m_pInnerMediaEventEx->RestoreDefaultHandling(nEventCode);
1674        }
1675        STDMETHOD(FreeEventParams)(LONG nEventCode, LONG_PTR nParameter1, LONG_PTR nParameter2) override
1676        {
1677                _Z4(atlTraceCOM, 4, _T("this 0x%p, nEventCode %s, nParameter1 0x%p, nParameter2 0x%p\n"), this, _FilterGraphHelper::FormatEventCode(nEventCode), nParameter1, nParameter2);
1678                return m_pInnerMediaEventEx->FreeEventParams(nEventCode, nParameter1, nParameter2);
1679        }
1680       
1681// IMediaEventEx
1682        STDMETHOD(SetNotifyWindow)(OAHWND nWindowHandle, LONG nMessage, LONG_PTR nParameter) override
1683        {
1684                _Z4(atlTraceCOM, 4, _T("this 0x%p, nWindowHandle 0x%08X, nMessage 0x%04x, nParameter %p\n"), this, nWindowHandle, nMessage, nParameter);
1685                return m_pInnerMediaEventEx->SetNotifyWindow(nWindowHandle, nMessage, nParameter);
1686        }
1687        STDMETHOD(SetNotifyFlags)(LONG nNotifyFlags) override
1688        {
1689                _Z4(atlTraceCOM, 4, _T("this 0x%p, nNotifyFlags 0x%X\n"), this, nNotifyFlags);
1690                return m_pInnerMediaEventEx->SetNotifyFlags(nNotifyFlags);
1691        }
1692        STDMETHOD(GetNotifyFlags)(LONG* pnNotifyFlags) override
1693        {
1694                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1695                return m_pInnerMediaEventEx->GetNotifyFlags(pnNotifyFlags);
1696        }
1697
1698// IObjectWithSite
1699        STDMETHOD(SetSite)(IUnknown* pSite) override
1700        {
1701                _Z4(atlTraceCOM, 4, _T("this 0x%p, pSite 0x%p\n"), this, pSite);
1702                _ATLTRY
1703                {
1704                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1705                        m_pSite = pSite;
1706                }
1707                _ATLCATCH(Exception)
1708                {
1709                        _C(Exception);
1710                }
1711                return S_OK;
1712        }
1713    STDMETHOD(GetSite)(REFIID InterfaceIdentifier, VOID** ppvSite) override
1714        {
1715                _Z4(atlTraceCOM, 4, _T("this 0x%p, InterfaceIdentifier %ls\n"), this, _PersistHelper::StringFromInterfaceIdentifier(InterfaceIdentifier));
1716                _ATLTRY
1717                {
1718                        __D(ppvSite, E_POINTER);
1719                        *ppvSite = NULL;
1720                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1721                        _D(m_pSite, E_FAIL);
1722                        return m_pSite->QueryInterface(InterfaceIdentifier, ppvSite);
1723                }
1724                _ATLCATCH(Exception)
1725                {
1726                        _C(Exception);
1727                }
1728                return S_OK;
1729        }
1730};
1731
1732////////////////////////////////////////////////////////////
1733// CSpy
1734
1735class ATL_NO_VTABLE CSpy :
1736        public CSpyT<CSpy, &CLSID_FilterGraph>,
1737        public CComCoClass<CSpy, &CLSID_Spy>
1738{
1739public:
1740        enum { IDR = IDR_FILTERGRAPHSPY };
1741
1742private:
1743        static LPCTSTR g_pszClassName;
1744
1745public:
1746        //typedef CBlackListAwareComCreatorT<CComObjectCached<CSpy>, CSpy, &g_pszClassName> _ClassFactoryCreatorClass; // DECLARE_CLASSFACTORY override
1747        typedef CComCreator2<CBlackListAwareComCreatorT<CComObject<CSpy>, CSpy, &g_pszClassName>, CBlackListAwareComCreatorT<CComAggObject<CSpy>, CSpy, &g_pszClassName> > _CreatorClass; // DECLARE_AGGREGATABLE override
1748
1749public:
1750// CSpy
1751};
1752
1753__declspec(selectany) LPCTSTR CSpy::g_pszClassName = _T("CSpy");
1754
1755OBJECT_ENTRY_AUTO(__uuidof(Spy), CSpy)
1756
1757////////////////////////////////////////////////////////////
1758// CNoThreadSpy
1759
1760class ATL_NO_VTABLE CNoThreadSpy :
1761        public CSpyT<CNoThreadSpy, &CLSID_FilterGraphNoThread>,
1762        public CComCoClass<CNoThreadSpy, &CLSID_NoThreadSpy>
1763{
1764public:
1765        enum { IDR = IDR_NOTHREADFILTERGRAPHSPY };
1766
1767private:
1768        static LPCTSTR g_pszClassName;
1769
1770public:
1771        //typedef CBlackListAwareComCreatorT<CComObjectCached<CNoThreadSpy>, CNoThreadSpy, &g_pszClassName> _ClassFactoryCreatorClass; // DECLARE_CLASSFACTORY override
1772        typedef CComCreator2<CBlackListAwareComCreatorT<CComObject<CNoThreadSpy>, CNoThreadSpy, &g_pszClassName>, CBlackListAwareComCreatorT<CComAggObject<CNoThreadSpy>, CNoThreadSpy, &g_pszClassName> > _CreatorClass; // DECLARE_AGGREGATABLE override
1773
1774public:
1775// CNoThreadSpy
1776};
1777
1778__declspec(selectany) LPCTSTR CNoThreadSpy::g_pszClassName = _T("CNoThreadSpy");
1779
1780OBJECT_ENTRY_AUTO(__uuidof(NoThreadSpy), CNoThreadSpy)
1781
1782////////////////////////////////////////////////////////////
1783// CPrivateThreadSpy
1784
1785class ATL_NO_VTABLE CPrivateThreadSpy :
1786        public CSpyT<CPrivateThreadSpy, &CLSID_FilterGraphPrivateThread>,
1787        public CComCoClass<CPrivateThreadSpy, &CLSID_PrivateThreadSpy>
1788{
1789public:
1790        enum { IDR = IDR_PRIVATETHREADFILTERGRAPHSPY };
1791
1792private:
1793        static LPCTSTR g_pszClassName;
1794
1795public:
1796        //typedef CBlackListAwareComCreatorT<CComObjectCached<CPrivateThreadSpy>, CPrivateThreadSpy, &g_pszClassName> _ClassFactoryCreatorClass; // DECLARE_CLASSFACTORY override
1797        typedef CComCreator2<CBlackListAwareComCreatorT<CComObject<CPrivateThreadSpy>, CPrivateThreadSpy, &g_pszClassName>, CBlackListAwareComCreatorT<CComAggObject<CPrivateThreadSpy>, CPrivateThreadSpy, &g_pszClassName> > _CreatorClass; // DECLARE_AGGREGATABLE override
1798
1799public:
1800// CPrivateThreadSpy
1801};
1802
1803__declspec(selectany) LPCTSTR CPrivateThreadSpy::g_pszClassName = _T("CPrivateThreadSpy");
1804
1805OBJECT_ENTRY_AUTO(__uuidof(PrivateThreadSpy), CPrivateThreadSpy)
Note: See TracBrowser for help on using the repository browser.