source: trunk/DirectShowSpy/FilterGraphSpy.h @ 831

Last change on this file since 831 was 831, checked in by roman, 5 years ago

Upgrade to VS2017; removed exception filter (hook); improved tracing

  • Property svn:keywords set to Id
File size: 57.2 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        BOOL IsAggregated() const
642        {
643                return (ULONG) m_dwRef >= 0x00001000;
644        }
645        VOID ReleaseTemporaryUnknown()
646        {
647                CComPtr<IUnknown> pUnknown;
648                Lock();
649                SwapMemory(&m_pTemporaryUnknown.p, &pUnknown.p);
650                Unlock();
651        }
652        VOID SetRunningFilterGraph()
653        {
654                if(m_RunningFilterGraph.GetCookie())
655                        return;
656                _Z4(atlTraceRefcount, 4, _T("this 0x%p, m_dwRef %d\n"), this, m_dwRef);
657                m_nRunningFilterGraphReference = 0;
658                CInterlockedLong& nReferenceCount = reinterpret_cast<CInterlockedLong&>(m_dwRef);
659                const LONG nBeforeReferenceCount = m_dwRef;
660                SYSTEMTIME Time;
661                GetLocalTime(&Time);
662                CStringW sMonikerDisplayName;
663                static CConstIntegerRegistryValue g_nEnableRotMonikerItemNameSuffix(_T("Enable ROT Moniker Item Name Suffix")); // 0 Default (Enabled), 1 Disabled, 2 Enabled
664                if(g_nEnableRotMonikerItemNameSuffix != 1) // Disabled
665                {
666                        TCHAR pszPath[MAX_PATH] = { 0 };
667                        _W(GetModuleFileName(NULL, pszPath, DIM(pszPath)));
668                        LPCTSTR pszName = FindFileName(pszPath);
669                        CString sItemName = AtlFormatString(_T("%s; process: %s, time: %02d-%02d-%02d"), m_RunningFilterGraph.GetDefaultMonikerItemName(GetControllingUnknown()), pszName, Time.wHour, Time.wMinute, Time.wSecond);
670                        m_RunningFilterGraph.SetFilterGraph(GetControllingUnknown(), CStringW(sItemName), &sMonikerDisplayName);
671                } else
672                        m_RunningFilterGraph.SetFilterGraph(GetControllingUnknown(), &sMonikerDisplayName);
673                _Z4(atlTraceRefcount, 4, _T("this 0x%p, m_bIsAggregated %d, m_dwRef %d, sMonikerDisplayName \"%ls\"\n"), this, m_bIsAggregated, m_dwRef, sMonikerDisplayName);
674                {
675                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
676                        m_Time = Time;
677                        m_sMonikerDisplayName = sMonikerDisplayName;
678                }
679                #pragma region Filter Graph Table Item
680                #if defined(AVAILABILITY_FILTERGRAPHTABLE)
681                        static CConstIntegerRegistryValue g_nAutomaticFilterGraphTableItem(_T("Automatic Filter Graph Table Item")); // 0 Default (Disabled), 1 Disabled, 2 Enabled
682                        if(g_nAutomaticFilterGraphTableItem == 2) // Enabled
683                                _ATLTRY
684                                {
685                                        _A(!m_pFilterGraphTableItem->IsFilterGraphAvailable());
686                                        m_pFilterGraphTableItem->SetFilterGraph(this);
687                                        Release();
688                                }
689                                _ATLCATCHALL()
690                                {
691                                        _Z_EXCEPTION();
692                                }
693                #endif // defined(AVAILABILITY_FILTERGRAPHTABLE)
694                #pragma endregion
695                if(!m_bIsAggregated)
696                {
697                        m_nRunningFilterGraphReference++;
698                        const LONG nAfterReferenceCount = m_dwRef;
699                        if(nBeforeReferenceCount == nAfterReferenceCount)
700                        {
701                                // NOTE: Putting onto Running Object Table succeeded, however no external reference detected which we need to compensate by self-releasing
702                                m_nRunningFilterGraphReference++;
703                                return;
704                        }
705                }
706                Release();
707        }
708        VOID ResetRunningFilterGraph()
709        {
710                if(!m_RunningFilterGraph.GetCookie())
711                        return;
712                #pragma region Filter Graph Table Item
713                #if defined(AVAILABILITY_FILTERGRAPHTABLE)
714                        _ATLTRY
715                        {
716                                if(m_pFilterGraphTableItem->IsFilterGraphAvailable())
717                                {
718                                        AddRef();
719                                        m_pFilterGraphTableItem->SetFilterGraph(NULL);
720                                }
721                        }
722                        _ATLCATCHALL()
723                        {
724                                _Z_EXCEPTION();
725                        }
726                #endif // defined(AVAILABILITY_FILTERGRAPHTABLE)
727                #pragma endregion
728                if(m_nRunningFilterGraphReference != 2)
729                        AddRef();
730                _Z4(atlTraceRefcount, 4, _T("this 0x%p, m_dwRef 0x%X\n"), this, m_dwRef);
731                m_RunningFilterGraph.SetFilterGraph(NULL);
732                {
733                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
734                        m_sMonikerDisplayName.Empty();
735                }
736                _Z4(atlTraceRefcount, 4, _T("this 0x%p, m_dwRef 0x%X\n"), this, m_dwRef);
737        }
738        HRESULT InternalQueryFilterGraph3Interface(REFIID InterfaceIdentifier, VOID** ppvObject)
739        {
740                _A(InterfaceIdentifier == __uuidof(IFilterGraph3));
741                _A(ppvObject);
742                if(!m_pInnerFilterGraph3)
743                {
744                        *ppvObject = NULL;
745                        return E_NOINTERFACE;
746                }
747                T* pT = static_cast<T*>(this);
748                *ppvObject = (IFilterGraph3*) pT;
749                pT->InternalAddRef();
750                return S_OK;
751        }
752        static HRESULT WINAPI QueryFilterGraph3Interface(VOID* pvThis, REFIID InterfaceIdentifier, VOID** ppvObject, DWORD_PTR)
753        {
754                return ((CSpy*) pvThis)->InternalQueryFilterGraph3Interface(InterfaceIdentifier, ppvObject);
755        }
756        HRESULT HookMediaControlAddSourceFilter(BSTR sFileName, IBaseFilter** ppBaseFilter, BOOL* pbDefault)
757        {
758                _A(pbDefault);
759                HOOK_PROLOG(CFilterGraphAddRemoveHookHost)
760                        OnAddSourceFilter(pT, sFileName, NULL, reinterpret_cast<IUnknown**>(ppBaseFilter), &bDefault);
761                        *pbDefault = bDefault;
762                HOOK_EPILOG()
763                return S_OK;
764        }
765
766public:
767// CSpyT
768        static LPCTSTR GetOriginalLibraryName()
769        {
770                return _T("quartz.dll");
771        }
772        static CString GetObjectFriendlyName()
773        {
774                return _StringHelper::GetLine(T::IDR, 2);
775        }
776        static HRESULT WINAPI UpdateRegistry(BOOL bRegister)
777        {
778                _Z2(atlTraceRegistrar, 2, _T("bRegister %d\n"), bRegister);
779                _ATLTRY
780                {
781                        TreatAsUpdateRegistryFromResource<T>(*t_pFilterGraphClassIdentifier, bRegister);
782                }
783                _ATLCATCH(Exception)
784                {
785                        _C(Exception);
786                }
787                return S_OK;
788        }
789        CSpyT() :
790                m_hQuartzModule(NULL)
791        {
792                _Z4_THIS();
793                ZeroMemory(&m_Time, sizeof m_Time);
794        }
795        ~CSpyT()
796        {
797                _Z4_THIS();
798        }
799        HRESULT FinalConstruct()
800        {
801                m_bIsAggregated = IsAggregated();
802                if(!m_bIsAggregated)
803                        InternalAddRef();
804                _ATLTRY
805                {
806                        TCHAR pszPath[MAX_PATH] = { 0 };
807                        _W(GetModuleFileName(NULL, pszPath, DIM(pszPath)));
808                        _Z4(atlTraceRefcount, 4, _T("pszPath \"%s\", this 0x%p, m_dwRef %d, m_bIsAggregated %d\n"), pszPath, this, m_dwRef, m_bIsAggregated);
809                        const HINSTANCE hModule = CoLoadOriginalLibrary();
810                        _ATLTRY
811                        {
812                                _A(hModule);
813                                const CComPtr<IUnknown> pControllingUnknown = GetControllingUnknown();
814                                #pragma region Instantiation
815                                {
816                                        { 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); }
817                                        const CComPtr<IUnknown> pUnknown = CoCreateOriginalInstance(hModule, pControllingUnknown);
818                                        // NOTE: DirectShow FilterGraph is incorrectly implementing COM aggregation adding outer reference to interfaces queried from private IUnknown
819                                        const CComQIPtr<IFilterGraph2> pFilterGraph2 = pUnknown;
820                                        __D(pFilterGraph2, E_NOINTERFACE);
821                                        pFilterGraph2.p->Release();
822                                        const CComQIPtr<IFilterGraph3> pFilterGraph3 = pUnknown;
823                                        if(pFilterGraph3)
824                                                pFilterGraph3.p->Release();
825                                        const CComQIPtr<IMediaControl> pMediaControl = pUnknown;
826                                        __D(pMediaControl, E_NOINTERFACE);
827                                        pMediaControl.p->Release();
828                                        const CComQIPtr<IMediaEventSink> pMediaEventSink = pUnknown;
829                                        __D(pMediaEventSink, E_NOINTERFACE);
830                                        pMediaEventSink.p->Release();
831                                        const CComQIPtr<IMediaEventEx> pMediaEventEx = pUnknown;
832                                        __D(pMediaEventEx, E_NOINTERFACE);
833                                        pMediaEventEx.p->Release();
834                                        #pragma region ROT Registration
835                                        { 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); }
836                                        SetRunningFilterGraph();
837                                        { 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); }
838                                        #pragma endregion
839                                        m_pInnerUnknown = pUnknown;
840                                        m_pInnerFilterGraph2 = pFilterGraph2;
841                                        m_pInnerFilterGraph3 = pFilterGraph3;
842                                        m_pInnerMediaControl = pMediaControl;
843                                        m_pInnerMediaEventSink = pMediaEventSink;
844                                        m_pInnerMediaEventEx = pMediaEventEx;
845                                }
846                                #pragma endregion
847                                #pragma region Set Private IAMGraphBuilderCallback
848                                static CConstIntegerRegistryValue g_nSetPrivateCallback(_T("Set Private CSpyT IAMGraphBuilderCallback")); // 0 Default (Enabled), 1 Disabled, 2 Enabled
849                                const DWORD nSetPrivateCallback = g_nSetPrivateCallback;
850                                if(nSetPrivateCallback != 1)
851                                {
852                                        CObjectPtr<CAmGraphBuilderCallback> pAmGraphBuilderCallback;
853                                        pAmGraphBuilderCallback.Construct();
854                                        pAmGraphBuilderCallback->Initialize(static_cast<T*>(this));
855                                        // WARN: Private site only forwards IAMGraphBuilderCallback interface and indicates other as not implemented
856                                        //       even if the external site does provide such implementation
857                                        if(pAmGraphBuilderCallback->SetGraphBuilder(pControllingUnknown))
858                                                m_pPrivateAmGraphBuilderCallback = pAmGraphBuilderCallback;
859                                        else
860                                                pAmGraphBuilderCallback->Terminate();
861                                }
862                                #pragma endregion
863                                #pragma region Temporary Reference for Aggregated Instantiation
864                                if(m_bIsAggregated)
865                                {
866                                        pControllingUnknown.p->AddRef();
867                                        const ULONG nReferenceCount = pControllingUnknown.p->Release();
868                                        if(nReferenceCount == 1)
869                                                m_pTemporaryUnknown = pControllingUnknown;
870                                }
871                                #pragma endregion
872                        }
873                        _ATLCATCHALL()
874                        {
875                                CoFreeLibrary(hModule);
876                                _ATLRETHROW;
877                        }
878                        #if defined(_DEBUG) && FALSE
879                                typedef HRESULT (WINAPI *DLLCANUNLOADNOW)();
880                                DLLCANUNLOADNOW DllCanUnloadNow = (DLLCANUNLOADNOW) GetProcAddress(hModule, "DllCanUnloadNow");
881                                __E(DllCanUnloadNow);
882                                const HRESULT nDllCanUnloadNowResult = DllCanUnloadNow();
883                                _Z4_HRESULT(nDllCanUnloadNowResult); 
884                        #endif // defined(_DEBUG)
885                        _A(!m_hQuartzModule);
886                        m_hQuartzModule = hModule;
887                        #pragma region Extra Reference
888                        // NOTE: This feature allows to leave an extra COM reference on the object to extend its lifetime and work around early destruction issues
889                        static CConstIntegerRegistryValue g_nAddExtraReference(_T("Add Extra CSpyT Reference")); // 0 Default (Disabled), 1 Not Aggregated Only, 2 Aggregated Only, 3 Both
890                        const DWORD nAddExtraReference = g_nAddExtraReference;
891                        if(!m_bIsAggregated)
892                        {
893                                if(nAddExtraReference & 1)
894                                        InternalAddRef();
895                        } else
896                                if(nAddExtraReference & 2)
897                                        GetControllingUnknown()->AddRef();
898                        #pragma endregion
899                }
900                _ATLCATCH(Exception)
901                {
902                        if(!m_bIsAggregated)
903                                _W(InternalRelease() > 0);
904                        _C(Exception);
905                }
906                // NOTE: x64 build experiences a problem under COM Surrogate process that we're already being released to zero while still in this method
907                if(!m_bIsAggregated)
908                        if(InternalRelease() <= 0)
909                                return E_UNEXPECTED;
910                return S_OK;
911        }
912        VOID FinalRelease()
913        {
914                _Z5(atlTraceRefcount, 5, _T("m_dwRef 0x%X\n"), m_dwRef);
915                _A(!m_pTemporaryUnknown);
916                const CComPtr<IUnknown> pControllingUnknown = GetControllingUnknown();
917                #pragma region Reset Private IAMGraphBuilderCallback
918                if(m_pPrivateAmGraphBuilderCallback)
919                {
920                        m_pPrivateAmGraphBuilderCallback->Terminate();
921                        m_pPrivateAmGraphBuilderCallback = NULL;
922                }
923                #pragma endregion
924                ResetRunningFilterGraph();
925                #pragma region Release Secondary Inner Interfaces
926                if(m_pInnerMediaEventEx)
927                {
928                        pControllingUnknown.p->AddRef();
929                        m_pInnerMediaEventEx = NULL;
930                }
931                if(m_pInnerMediaEventSink)
932                {
933                        pControllingUnknown.p->AddRef();
934                        m_pInnerMediaEventSink = NULL;
935                }
936                if(m_pInnerMediaControl)
937                {
938                        pControllingUnknown.p->AddRef();
939                        m_pInnerMediaControl = NULL;
940                }
941                if(m_pInnerFilterGraph3)
942                {
943                        pControllingUnknown.p->AddRef();
944                        m_pInnerFilterGraph3 = NULL;
945                }
946                if(m_pInnerFilterGraph2)
947                {
948                        pControllingUnknown.p->AddRef();
949                        m_pInnerFilterGraph2 = NULL;
950                }
951                #pragma endregion
952                #pragma region Release Primary Inner IUnknown
953                _ATLTRY
954                {
955                        m_pInnerUnknown = NULL;
956                }
957                _ATLCATCHALL()
958                {
959                        _Z_EXCEPTION();
960                        // NOTE: For some unidentified reason Quartz's FilterGraph may crash during final release, to smooth the effect the exception is silently caught
961                        m_pInnerUnknown.p = NULL;
962                }
963                #pragma endregion
964                #pragma region Release Quartz Library
965                if(m_hQuartzModule)
966                {
967                        CoFreeLibrary(m_hQuartzModule);
968                        m_hQuartzModule = NULL;
969                }
970                #pragma endregion
971        }
972        HRESULT QueryObjectWithSiteInterface(REFIID InterfaceIdentifier, LPVOID* ppvObject)
973        {
974                _A(InterfaceIdentifier == __uuidof(IObjectWithSite));
975                _A(ppvObject);
976                if(m_pPrivateAmGraphBuilderCallback)
977                {
978                        *ppvObject = CComPtr<IObjectWithSite>(static_cast<T*>(this)).Detach();
979                        return S_OK;
980                }
981                _A(m_pInnerUnknown);
982                return m_pInnerUnknown->QueryInterface(InterfaceIdentifier, ppvObject);
983        }
984        static HRESULT WINAPI QueryObjectWithSiteInterface(VOID* pvInstance, REFIID InterfaceIdentifier, LPVOID* ppvObject, DWORD_PTR)
985        {
986                return ((CSpy*) pvInstance)->QueryObjectWithSiteInterface(InterfaceIdentifier, ppvObject);
987        }
988        CComPtr<IUnknown> GetSite() const
989        {
990                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
991                return m_pSite;
992        }
993        BOOL SelectedFilter(IMoniker* pMoniker, HRESULT& nSelectedFilterResult)
994        {
995                const CComQIPtr<IAMGraphBuilderCallback> pAmGraphBuilderCallback = GetSite();
996                if(pAmGraphBuilderCallback)
997                {
998                        nSelectedFilterResult = pAmGraphBuilderCallback->SelectedFilter(pMoniker);
999                        return TRUE;
1000                }
1001                return FALSE;
1002        }
1003        BOOL CreatedFilter(IBaseFilter* pBaseFilter, HRESULT& nCreatedFilterResult)
1004        {
1005                const CComQIPtr<IAMGraphBuilderCallback> pAmGraphBuilderCallback = GetSite();
1006                if(pAmGraphBuilderCallback)
1007                {
1008                        nCreatedFilterResult = pAmGraphBuilderCallback->CreatedFilter(pBaseFilter);
1009                        return TRUE;
1010                }
1011                return FALSE;
1012        }
1013        CStringW GetMonikerDisplayName() const
1014        {
1015                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1016                return m_sMonikerDisplayName;
1017        }
1018
1019// ISpy
1020    STDMETHOD(get_MonikerDisplayName)(BSTR* psMonikerDisplayName) override
1021        {
1022                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1023                _ATLTRY
1024                {
1025                        __D(psMonikerDisplayName, E_POINTER);
1026                        *psMonikerDisplayName = CComBSTR(GetMonikerDisplayName()).Detach();
1027                }
1028                _ATLCATCHALL()
1029                {
1030                        _Z_EXCEPTION();
1031                }
1032                return S_OK;
1033        }
1034        STDMETHOD(get_CreationTime)(DATE* pfTime) override
1035        {
1036                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1037                _ATLTRY
1038                {
1039                        __D(pfTime, E_POINTER);
1040                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1041                        FILETIME LocalFileTime, FileTime;
1042                        _W(SystemTimeToFileTime(&m_Time, &LocalFileTime));
1043                        _W(LocalFileTimeToFileTime(&LocalFileTime, &FileTime));
1044                        SYSTEMTIME Time;
1045                        _W(FileTimeToSystemTime(&FileTime, &Time));
1046                        _W(SystemTimeToVariantTime(&Time, pfTime));
1047                }
1048                _ATLCATCHALL()
1049                {
1050                        _Z_EXCEPTION();
1051                }
1052                return S_OK;
1053        }
1054        STDMETHOD(get_FriendlyName)(BSTR* psFriendlyName) override
1055        {
1056                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1057                _ATLTRY
1058                {
1059                        __D(psFriendlyName, E_POINTER);
1060                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1061                        *psFriendlyName = CComBSTR(m_sFriendlyName).Detach();
1062                }
1063                _ATLCATCHALL()
1064                {
1065                        _Z_EXCEPTION();
1066                }
1067                return S_OK;
1068        }
1069        STDMETHOD(put_FriendlyName)(BSTR sFriendlyName) override
1070        {
1071                _Z4(atlTraceCOM, 4, _T("this 0x%p, sFriendlyName \"%s\"\n"), this, CString(sFriendlyName));
1072                _ATLTRY
1073                {
1074                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1075                        m_sFriendlyName = sFriendlyName;
1076                }
1077                _ATLCATCHALL()
1078                {
1079                        _Z_EXCEPTION();
1080                }
1081                return S_OK;
1082        }
1083        STDMETHOD(DoPropertyFrameModal)(LONG nParentWindowHandle) override
1084        {
1085                _Z4(atlTraceCOM, 4, _T("this 0x%p, nParentWindowHandle 0x%08X\n"), this, nParentWindowHandle);
1086                _ATLTRY
1087                {
1088                        T* pT = static_cast<T*>(this);
1089                        return FilterGraphHelper_DoPropertyFrameModal(nParentWindowHandle, (IFilterGraph*) CComQIPtr<IFilterGraph>(pT));
1090                }
1091                _ATLCATCHALL()
1092                {
1093                        _Z_EXCEPTION();
1094                }
1095                return S_OK;
1096        }
1097        STDMETHOD(DoFilterGraphListModal)(LONG nParentWindowHandle) override
1098        {
1099                _Z4(atlTraceCOM, 4, _T("this 0x%p, nParentWindowHandle 0x%08X\n"), this, nParentWindowHandle);
1100                _ATLTRY
1101                {
1102                        return FilterGraphHelper_DoFilterGraphListModal(nParentWindowHandle);
1103                }
1104                _ATLCATCHALL()
1105                {
1106                        _Z_EXCEPTION();
1107                }
1108                return S_OK;
1109        }
1110        STDMETHOD(OpenGraphStudioNext)(LONG nParentWindowHandle, VARIANT_BOOL* pbResult) override
1111        {
1112                _Z4(atlTraceCOM, 4, _T("this 0x%p, nParentWindowHandle 0x%08X\n"), this, nParentWindowHandle);
1113                _ATLTRY
1114                {
1115                        return FilterGraphHelper_OpenGraphStudioNext(nParentWindowHandle, GetMonikerDisplayName(), pbResult);
1116                }
1117                _ATLCATCHALL()
1118                {
1119                        _Z_EXCEPTION();
1120                }
1121                return S_OK;
1122        }
1123        STDMETHOD(OpenGraphEdit)(LONG nParentWindowHandle, VARIANT_BOOL* pbResult) override
1124        {
1125                _Z4(atlTraceCOM, 4, _T("this 0x%p, nParentWindowHandle 0x%08X\n"), this, nParentWindowHandle);
1126                _ATLTRY
1127                {
1128                        return FilterGraphHelper_OpenGraphEdit(nParentWindowHandle, GetMonikerDisplayName(), pbResult);
1129                }
1130                _ATLCATCHALL()
1131                {
1132                        _Z_EXCEPTION();
1133                }
1134                return S_OK;
1135        }
1136        STDMETHOD(ReadRunPropertyBag)(IUnknown* pBaseFilterUnknown, VARIANT_BOOL bAllowExtension, VARIANT* pvValue) override
1137        {
1138                _Z4(atlTraceCOM, 4, _T("this 0x%p, pBaseFilterUnknown 0x%p, bAllowExtension %d\n"), this, pBaseFilterUnknown, bAllowExtension);
1139                _ATLTRY
1140                {
1141                        __D(pBaseFilterUnknown, E_INVALIDARG);
1142                        __D(pvValue, E_POINTER);
1143                        VariantInit(pvValue);
1144                        _V(CRunPropertyBagHelper::ReadRunPropertyBag(pBaseFilterUnknown, bAllowExtension != ATL_VARIANT_FALSE).Detach(pvValue));
1145                }
1146                _ATLCATCHALL()
1147                {
1148                        _Z_EXCEPTION();
1149                }
1150                return S_OK;
1151        }
1152        STDMETHOD(CreateMediaSampleTrace)(IMediaSampleTrace** ppMediaSampleTrace) override
1153        {
1154                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1155                _ATLTRY
1156                {
1157                        __D(ppMediaSampleTrace, E_POINTER);
1158                        *ppMediaSampleTrace = NULL;
1159                        CObjectPtr<CMediaSampleTrace> pMediaSampleTrace;
1160                        pMediaSampleTrace.Construct()->Initialize(this);
1161                        *ppMediaSampleTrace = pMediaSampleTrace.Detach();
1162                }
1163                _ATLCATCHALL()
1164                {
1165                        _Z_EXCEPTION();
1166                }
1167                return S_OK;
1168        }
1169
1170// ISpyEx
1171
1172// IFilterGraph
1173        STDMETHOD(AddFilter)(IBaseFilter* pBaseFilter, LPCWSTR pszName) override
1174        {
1175                _Z4(atlTraceCOM, 4, _T("this 0x%p, pBaseFilter 0x%p %ls, pszName \"%s\"\n"), this, pBaseFilter, _FilterGraphHelper::GetFilterClassIdentifierString(pBaseFilter), CString(pszName));
1176                ReleaseTemporaryUnknown();
1177                HOOK_PROLOG(CFilterGraphAddRemoveHookHost)
1178                        OnAddFilter(pT, pBaseFilter, pszName, &bDefault);
1179                HOOK_EPILOG()
1180                const HRESULT nResult = m_pInnerFilterGraph2->AddFilter(pBaseFilter, pszName);
1181                if(SUCCEEDED(nResult))
1182                        _ATLTRY
1183                        {
1184                                const CStringW sName = _FilterGraphHelper::GetFilterName(pBaseFilter);
1185                                _Z4(atlTraceGeneral, 4, _T("this 0x%p, sName \"%ls\"\n"), this, sName);
1186                        }
1187                        _ATLCATCHALL()
1188                        {
1189                                _Z_EXCEPTION();
1190                        }
1191                return nResult;
1192        }
1193    STDMETHOD(RemoveFilter)(IBaseFilter* pBaseFilter) override
1194        {
1195                _Z4(atlTraceCOM, 4, _T("this 0x%p, pBaseFilter 0x%p\n"), this, pBaseFilter);
1196                if(pBaseFilter)
1197                        _ATLTRY
1198                        {
1199                                const CStringW sName = _FilterGraphHelper::GetFilterName(pBaseFilter);
1200                                _Z4(atlTraceGeneral, 4, _T("this 0x%p, sName \"%ls\"\n"), this, sName);
1201                        }
1202                        _ATLCATCHALL()
1203                        {
1204                                _Z_EXCEPTION();
1205                        }
1206                HOOK_PROLOG(CFilterGraphAddRemoveHookHost)
1207                        OnRemoveFilter(pT, pBaseFilter, &bDefault);
1208                HOOK_EPILOG()
1209                return m_pInnerFilterGraph2->RemoveFilter(pBaseFilter);
1210        }
1211    STDMETHOD(EnumFilters)(IEnumFilters** ppEnumFilters) override
1212        {
1213                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1214                return m_pInnerFilterGraph2->EnumFilters(ppEnumFilters);
1215        }
1216    STDMETHOD(FindFilterByName)(LPCWSTR pszName, IBaseFilter** ppFilter) override
1217        {
1218                _Z4(atlTraceCOM, 4, _T("this 0x%p, pszName \"%s\"\n"), this, CString(pszName));
1219                return m_pInnerFilterGraph2->FindFilterByName(pszName, ppFilter);
1220        }
1221    STDMETHOD(ConnectDirect)(IPin* pOutputPin, IPin* pInputPin, const AM_MEDIA_TYPE* pMediaType) override
1222        {
1223                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1224                if(pOutputPin && pInputPin)
1225                        _ATLTRY
1226                        {
1227                                _Z4(atlTraceGeneral, 4, _T("pOutputPin \"%ls\", pInputPin \"%ls\", pMediaType 0x%p\n"), _FilterGraphHelper::GetPinFullName(pOutputPin), _FilterGraphHelper::GetPinFullName(pInputPin), pMediaType);
1228                                if(pMediaType)
1229                                        _FilterGraphHelper::TraceMediaType(pMediaType);
1230                                #pragma region Log Filter
1231                                // NOTE: This inserts additional filter without graph owner's will, for troubleshooting purposes; CLogFilter logs streaming details
1232                                #if FALSE
1233                                        const CComPtr<IBaseFilter> pOutputBaseFilter = _FilterGraphHelper::GetPinFilter(pOutputPin);
1234                                        const CComPtr<IBaseFilter> pInputBaseFilter = _FilterGraphHelper::GetPinFilter(pInputPin);
1235                                        class __declspec(uuid("{09075D10-D7EC-420f-A8F9-940E1602A371}")) AudioSplitter;
1236                                        if(_FilterGraphHelper::GetFilterClassIdentifier(pOutputBaseFilter) == __uuidof(AudioSplitter) || _FilterGraphHelper::GetFilterClassIdentifier(pInputBaseFilter) == __uuidof(AudioSplitter))
1237                                                _ATLTRY
1238                                                {
1239                                                        _A(_FilterGraphHelper::GetPinDirection(pOutputPin) == PINDIR_OUTPUT);
1240                                                        CObjectPtr<CLogFilter> pLogFilter;
1241                                                        pLogFilter.Construct();
1242                                                        CString sName = AtlFormatString(_T("Log (%s; %s)"), _FilterGraphHelper::GetFilterName(pOutputBaseFilter), _FilterGraphHelper::GetFilterName(pInputBaseFilter));
1243                                                        __C(m_pInnerFilterGraph2->AddFilter(pLogFilter, CStringW(sName)));
1244                                                        _ATLTRY
1245                                                        {
1246                                                                __C(m_pInnerFilterGraph2->ConnectDirect(pOutputPin, pLogFilter->GetInputPin(), pMediaType));
1247                                                                __C(m_pInnerFilterGraph2->ConnectDirect(pLogFilter->GetOutputPin(), pInputPin, pMediaType));
1248                                                                _Z4(atlTraceGeneral, 4, _T("this 0x%p, pLogFilter->GetName() \"%ls\"\n"), this, pLogFilter->GetName());
1249                                                                return S_OK;
1250                                                        }
1251                                                        _ATLCATCHALL()
1252                                                        {
1253                                                                __C(m_pInnerFilterGraph2->RemoveFilter(pLogFilter));
1254                                                                _ATLRETHROW;
1255                                                        }
1256                                                }
1257                                                _ATLCATCHALL()
1258                                                {
1259                                                        _Z_EXCEPTION();
1260                                                }
1261                                #endif
1262                                #pragma endregion
1263                        }
1264                        _ATLCATCHALL()
1265                        {
1266                                _Z_EXCEPTION();
1267                        }
1268                HOOK_PROLOG(CFilterGraphConnectHookHost)
1269                        OnConnectDirect(pT, pOutputPin, pInputPin, (const BYTE*) pMediaType, &bDefault);
1270                HOOK_EPILOG()
1271                const HRESULT nConnectDirectResult = m_pInnerFilterGraph2->ConnectDirect(pOutputPin, pInputPin, pMediaType);
1272                _Z4(atlTraceGeneral, 4, _T("this 0x%p, nConnectDirectResult 0x%08X\n"), this, nConnectDirectResult);
1273                return nConnectDirectResult;
1274        }
1275    STDMETHOD(Reconnect)(IPin* pPin) override
1276        {
1277                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1278                HOOK_PROLOG(CFilterGraphConnectHookHost)
1279                        OnReconnect(pT, pPin, &bDefault);
1280                HOOK_EPILOG()
1281                return m_pInnerFilterGraph2->Reconnect(pPin);
1282        }
1283    STDMETHOD(Disconnect)(IPin* pPin) override
1284        {
1285                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1286                HOOK_PROLOG(CFilterGraphConnectHookHost)
1287                        OnDisconnect(pT, pPin, &bDefault);
1288                HOOK_EPILOG()
1289                return m_pInnerFilterGraph2->Disconnect(pPin);
1290        }
1291    STDMETHOD(SetDefaultSyncSource)() override
1292        {
1293                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1294                return m_pInnerFilterGraph2->SetDefaultSyncSource();
1295        }
1296
1297// IGraphBuilder
1298    STDMETHOD(Connect)(IPin* pOutputPin, IPin* pInputPin) override
1299        {
1300                _Z4(atlTraceCOM, 4, _T("this 0x%p, pOutputPin 0x%p, pInputPin 0x%p\n"), this, pOutputPin, pInputPin);
1301                if(pOutputPin && pInputPin)
1302                        _ATLTRY
1303                        {
1304                                _Z4(atlTraceGeneral, 4, _T("pOutputPin 0x%p \"%ls\" (filter 0x%p), pInputPin 0x%p \"%ls\" (filter 0x%p)\n"), 
1305                                        pOutputPin, _FilterGraphHelper::GetPinFullName(pOutputPin), _FilterGraphHelper::GetPinFilter(pOutputPin),
1306                                        pInputPin, _FilterGraphHelper::GetPinFullName(pInputPin), _FilterGraphHelper::GetPinFilter(pInputPin),
1307                                        0);
1308                        }
1309                        _ATLCATCHALL()
1310                        {
1311                                _Z_EXCEPTION();
1312                        }
1313                HOOK_PROLOG(CFilterGraphConnectHookHost)
1314                        OnConnect(pT, pOutputPin, pInputPin, &bDefault);
1315                HOOK_EPILOG()
1316                const HRESULT nConnectResult = m_pInnerFilterGraph2->Connect(pOutputPin, pInputPin);
1317                _Z4(atlTraceGeneral, 4, _T("this 0x%p, nConnectResult 0x%08X\n"), this, nConnectResult);
1318                return nConnectResult;
1319        }
1320    STDMETHOD(Render)(IPin* pOutputPin) override
1321        {
1322                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1323                return m_pInnerFilterGraph2->Render(pOutputPin);
1324        }
1325    STDMETHOD(RenderFile)(LPCWSTR pszFileName, LPCWSTR pszPlayListFileName) override
1326        {
1327                _Z4(atlTraceCOM, 4, _T("this 0x%p, pszFileName \"%s\", pszPlayListFileName \"%s\"\n"), this, CString(pszFileName), CString(pszPlayListFileName));
1328                return m_pInnerFilterGraph2->RenderFile(pszFileName, pszPlayListFileName);
1329        }
1330    STDMETHOD(AddSourceFilter)(LPCWSTR pszFileName, LPCWSTR pszFilterName, IBaseFilter** ppBaseFilter) override
1331        {
1332                _Z4(atlTraceCOM, 4, _T("this 0x%p, pszFileName \"%s\", pszFilterName \"%s\"\n"), this, CString(pszFileName), CString(pszFilterName));
1333                ReleaseTemporaryUnknown();
1334                HOOK_PROLOG(CFilterGraphAddRemoveHookHost)
1335                        OnAddSourceFilter(pT, pszFileName, pszFilterName, reinterpret_cast<IUnknown**>(ppBaseFilter), &bDefault);
1336                HOOK_EPILOG()
1337                return m_pInnerFilterGraph2->AddSourceFilter(pszFileName, pszFilterName, ppBaseFilter);
1338        }
1339        STDMETHOD(SetLogFile)(DWORD_PTR hFile) override
1340        {
1341                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1342                return m_pInnerFilterGraph2->SetLogFile(hFile);
1343        }
1344        STDMETHOD(Abort)() override
1345        {
1346                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1347                return m_pInnerFilterGraph2->Abort();
1348        }
1349        STDMETHOD(ShouldOperationContinue)() override
1350        {
1351                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1352                return m_pInnerFilterGraph2->ShouldOperationContinue();
1353        }
1354
1355// IFilterGraph2
1356        STDMETHOD(AddSourceFilterForMoniker)(IMoniker* pMoniker, IBindCtx* pBindCtx, LPCWSTR pszFilterName, IBaseFilter** ppBaseFilter) override
1357        {
1358                _Z4(atlTraceCOM, 4, _T("this 0x%p, pszFilterName \"%s\"\n"), this, CString(pszFilterName));
1359                ReleaseTemporaryUnknown();
1360                HOOK_PROLOG(CFilterGraphAddRemoveHookHost)
1361                        OnAddSourceFilterForMoniker(pT, pMoniker, pBindCtx, pszFilterName, reinterpret_cast<IUnknown**>(ppBaseFilter), &bDefault);
1362                HOOK_EPILOG()
1363                return m_pInnerFilterGraph2->AddSourceFilterForMoniker(pMoniker, pBindCtx, pszFilterName, ppBaseFilter);
1364        }
1365        STDMETHOD(ReconnectEx)(IPin* pPin, const AM_MEDIA_TYPE* pMediaType) override
1366        {
1367                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1368                HOOK_PROLOG(CFilterGraphConnectHookHost)
1369                        OnReconnectEx(pT, pPin, (const BYTE*) pMediaType, &bDefault);
1370                HOOK_EPILOG()
1371                return m_pInnerFilterGraph2->ReconnectEx(pPin, pMediaType);
1372        }
1373        STDMETHOD(RenderEx)(IPin* pOutputPin, DWORD nFlags, DWORD* pnContext) override
1374        {
1375                _Z4(atlTraceCOM, 4, _T("this 0x%p, nFlags 0x%X\n"), this, nFlags);
1376                return m_pInnerFilterGraph2->RenderEx(pOutputPin, nFlags, pnContext);
1377        }
1378
1379// IFilterGraph3
1380    STDMETHOD(SetSyncSourceEx)(IReferenceClock* pFilterGraphReferenceClock, IReferenceClock* pFilterReferenceClock, IBaseFilter* pBaseFilter) override
1381        {
1382                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1383                _A(m_pInnerFilterGraph3);
1384                return m_pInnerFilterGraph3->SetSyncSourceEx(pFilterGraphReferenceClock, pFilterReferenceClock, pBaseFilter);
1385        }
1386
1387// IMediaControl
1388        STDMETHOD(Run)() override
1389        {
1390                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1391                _ATLTRY
1392                {
1393                        OAFilterState State = (OAFilterState) -1;
1394                        if(SUCCEEDED(m_pInnerMediaControl->GetState(0, &State)) && State == State_Stopped)
1395                                _FilterGraphHelper::TraceGraphBuilder(this);
1396                }
1397                _ATLCATCHALL()
1398                {
1399                        _Z_EXCEPTION();
1400                }
1401                HOOK_PROLOG(CFilterGraphStateControlHookHost)
1402                        OnRun(pT, &bDefault);
1403                HOOK_EPILOG()
1404                const HRESULT nRunResult = m_pInnerMediaControl->Run();
1405                _Z4_DSHRESULT(nRunResult);
1406                return nRunResult;
1407        }
1408        STDMETHOD(Pause)() override
1409        {
1410                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1411                _ATLTRY
1412                {
1413                        OAFilterState State = (OAFilterState) -1;
1414                        if(SUCCEEDED(m_pInnerMediaControl->GetState(0, &State)) && State == State_Stopped)
1415                                _FilterGraphHelper::TraceGraphBuilder(this);
1416                }
1417                _ATLCATCHALL()
1418                {
1419                        _Z_EXCEPTION();
1420                }
1421                HOOK_PROLOG(CFilterGraphStateControlHookHost)
1422                        OnPause(pT, &bDefault);
1423                HOOK_EPILOG()
1424                return m_pInnerMediaControl->Pause();
1425        }
1426        STDMETHOD(Stop)() override
1427        {
1428                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1429                HOOK_PROLOG(CFilterGraphStateControlHookHost)
1430                        OnStop(pT, &bDefault);
1431                HOOK_EPILOG()
1432                return m_pInnerMediaControl->Stop();
1433        }
1434        STDMETHOD(GetState)(LONG nTimeout, OAFilterState* pState) override
1435        {
1436                _Z5(atlTraceCOM, 5, _T("this 0x%p, nTimeout %d\n"), this, nTimeout);
1437                return m_pInnerMediaControl->GetState(nTimeout, pState);
1438        }
1439        STDMETHOD(RenderFile)(BSTR sFileName) override
1440        {
1441                _Z4(atlTraceCOM, 4, _T("this 0x%p, sFileName \"%s\"\n"), this, CString(sFileName));
1442                return m_pInnerMediaControl->RenderFile(sFileName);
1443        }
1444    STDMETHOD(AddSourceFilter)(BSTR sFileName, IDispatch** ppDispatch) override
1445        {
1446                _Z4(atlTraceCOM, 4, _T("this 0x%p, sFileName \"%s\"\n"), this, CString(sFileName));
1447                ReleaseTemporaryUnknown();
1448                _ATLTRY
1449                {
1450                        CComPtr<IBaseFilter> pBaseFilter;
1451                        BOOL bDefault = TRUE;
1452                        const HRESULT nResult = HookMediaControlAddSourceFilter(sFileName, &pBaseFilter, &bDefault);
1453                        if(!bDefault)
1454                        {
1455                                __D(ppDispatch, E_POINTER);
1456                                *ppDispatch = NULL;
1457                                if(SUCCEEDED(nResult))
1458                                {
1459                                        CComQIPtr<IDispatch> pDispatch = pBaseFilter;
1460                                        __D(pDispatch, E_NOINTERFACE);
1461                                        *ppDispatch = pDispatch.Detach();
1462                                }
1463                                return nResult;
1464                        }
1465                }
1466                _ATLCATCH(Exception)
1467                {
1468                        _C(Exception);
1469                }
1470                return m_pInnerMediaControl->AddSourceFilter(sFileName, ppDispatch);
1471        }
1472        STDMETHOD(get_FilterCollection)(IDispatch** ppDispatch) override
1473        {
1474                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1475                ReleaseTemporaryUnknown();
1476                return m_pInnerMediaControl->get_FilterCollection(ppDispatch);
1477        }
1478        STDMETHOD(get_RegFilterCollection)(IDispatch** ppDispatch) override
1479        {
1480                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1481                ReleaseTemporaryUnknown();
1482                return m_pInnerMediaControl->get_RegFilterCollection(ppDispatch);
1483        }
1484        STDMETHOD(StopWhenReady)() override
1485        {
1486                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1487                return m_pInnerMediaControl->StopWhenReady();
1488        }
1489
1490// IMediaEventSink
1491    STDMETHOD(Notify)(LONG nEventCode, LONG_PTR nParameter1, LONG_PTR nParameter2) override
1492        {
1493                _Z4(atlTraceCOM, 4, _T("this 0x%p, nEventCode %s, nParameter1 0x%p, nParameter2 0x%p\n"), this, _FilterGraphHelper::FormatEventCode(nEventCode), nParameter1, nParameter2);
1494                #pragma region EC_COMPLETE
1495                if(nEventCode == EC_COMPLETE)
1496                        _ATLTRY
1497                        {
1498                                IBaseFilter* pBaseFilter = (IBaseFilter*) nParameter2;
1499                                if(pBaseFilter)
1500                                {
1501                                        const CStringW sName = _FilterGraphHelper::GetFilterName(pBaseFilter);
1502                                        _Z3(atlTraceCOM, 3, _T("Received EC_COMPLETE from filter 0x%p \"%ls\"\n"), pBaseFilter, sName);
1503                                }
1504                                //TCHAR pszComment[64];
1505                                //_stprintf_s(pszComment, _T("DirectShow-Complete-0x%08X"), (HRESULT) nParameter1);
1506                                //TryWriteMiniDump(pszComment);
1507                        }
1508                        _ATLCATCHALL()
1509                        {
1510                                _Z_EXCEPTION();
1511                        }
1512                #pragma endregion
1513                #pragma region EC_ERRORABORT, EC_ERRORABORTEX
1514                if(nEventCode == EC_ERRORABORT || nEventCode == EC_ERRORABORTEX)
1515                {
1516                        if(nEventCode == EC_ERRORABORTEX && nParameter2)
1517                                _Z4(atlTraceGeneral, 4, _T("nParameter2 \"%s\"\n"), CString((BSTR) nParameter2));
1518                        static CConstIntegerRegistryValue g_nErrorAbortMiniDumpMode(_T("ErrorAbort MiniDump Mode")); // 0 Default (=1), 1 Disabled, 2 Enabled
1519                        if((DWORD) g_nErrorAbortMiniDumpMode == 2) // Enabled
1520                        {
1521                                TCHAR pszComment[64];
1522                                _stprintf_s(pszComment, _T("DirectShow-ErrorAbort-0x%08X"), (HRESULT) nParameter1);
1523                                static LONG g_nCounter = 0;
1524                                TryWriteMiniDump(pszComment, &g_nCounter);
1525                        }
1526                }
1527                #pragma endregion
1528                if(!m_pInnerMediaEventSink)
1529                        return S_FALSE;
1530                return m_pInnerMediaEventSink->Notify(nEventCode, nParameter1, nParameter2);
1531        }
1532
1533// IMediaEvent
1534        STDMETHOD(GetEventHandle)(OAEVENT* pnEventHandle) override
1535        {
1536                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1537                return m_pInnerMediaEventEx->GetEventHandle(pnEventHandle);
1538        }
1539        STDMETHOD(GetEvent)(LONG* pnEventCode, LONG_PTR* pnParameter1, LONG_PTR* pnParameter2, LONG nTimeout) override
1540        {
1541                _Z4(atlTraceCOM, nTimeout ? 4 : 5, _T("this 0x%p, nTimeout %d\n"), this, nTimeout);
1542                const HRESULT nGetEventResult = m_pInnerMediaEventEx->GetEvent(pnEventCode, pnParameter1, pnParameter2, nTimeout);
1543                if(pnEventCode && pnParameter1 && pnParameter2)
1544                        _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);
1545                return nGetEventResult;
1546        }
1547        STDMETHOD(WaitForCompletion)(LONG nTimeout, LONG* pnEventCode) override
1548        {
1549                _Z4(atlTraceCOM, 4, _T("this 0x%p, nTimeout %d\n"), this, nTimeout);
1550                const HRESULT nWaitForCompletionResult = m_pInnerMediaEventEx->WaitForCompletion(nTimeout, pnEventCode);
1551                if(pnEventCode)
1552                        _Z4(atlTraceCOM, 4, _T("nWaitForCompletionResult 0x%08X, *pnEventCode %s\n"), nWaitForCompletionResult, _FilterGraphHelper::FormatEventCode(*pnEventCode));
1553                return nWaitForCompletionResult;
1554        }
1555        STDMETHOD(CancelDefaultHandling)(LONG nEventCode) override
1556        {
1557                _Z4(atlTraceCOM, 4, _T("this 0x%p, nEventCode %s\n"), this, _FilterGraphHelper::FormatEventCode(nEventCode));
1558                return m_pInnerMediaEventEx->CancelDefaultHandling(nEventCode);
1559        }
1560        STDMETHOD(RestoreDefaultHandling)(LONG nEventCode) override
1561        {
1562                _Z4(atlTraceCOM, 4, _T("this 0x%p, nEventCode %s\n"), this, _FilterGraphHelper::FormatEventCode(nEventCode));
1563                return m_pInnerMediaEventEx->RestoreDefaultHandling(nEventCode);
1564        }
1565        STDMETHOD(FreeEventParams)(LONG nEventCode, LONG_PTR nParameter1, LONG_PTR nParameter2) override
1566        {
1567                _Z4(atlTraceCOM, 4, _T("this 0x%p, nEventCode %s, nParameter1 0x%p, nParameter2 0x%p\n"), this, _FilterGraphHelper::FormatEventCode(nEventCode), nParameter1, nParameter2);
1568                return m_pInnerMediaEventEx->FreeEventParams(nEventCode, nParameter1, nParameter2);
1569        }
1570       
1571// IMediaEventEx
1572        STDMETHOD(SetNotifyWindow)(OAHWND nWindowHandle, LONG nMessage, LONG_PTR nParameter) override
1573        {
1574                _Z4(atlTraceCOM, 4, _T("this 0x%p, nWindowHandle 0x%08X, nMessage 0x%04x, nParameter %p\n"), this, nWindowHandle, nMessage, nParameter);
1575                return m_pInnerMediaEventEx->SetNotifyWindow(nWindowHandle, nMessage, nParameter);
1576        }
1577        STDMETHOD(SetNotifyFlags)(LONG nNotifyFlags) override
1578        {
1579                _Z4(atlTraceCOM, 4, _T("this 0x%p, nNotifyFlags 0x%X\n"), this, nNotifyFlags);
1580                return m_pInnerMediaEventEx->SetNotifyFlags(nNotifyFlags);
1581        }
1582        STDMETHOD(GetNotifyFlags)(LONG* pnNotifyFlags) override
1583        {
1584                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
1585                return m_pInnerMediaEventEx->GetNotifyFlags(pnNotifyFlags);
1586        }
1587
1588// IObjectWithSite
1589        STDMETHOD(SetSite)(IUnknown* pSite) override
1590        {
1591                _Z4(atlTraceCOM, 4, _T("this 0x%p, pSite 0x%p\n"), this, pSite);
1592                _ATLTRY
1593                {
1594                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1595                        m_pSite = pSite;
1596                }
1597                _ATLCATCH(Exception)
1598                {
1599                        _C(Exception);
1600                }
1601                return S_OK;
1602        }
1603    STDMETHOD(GetSite)(REFIID InterfaceIdentifier, VOID** ppvSite) override
1604        {
1605                _Z4(atlTraceCOM, 4, _T("this 0x%p, InterfaceIdentifier %ls\n"), this, _PersistHelper::StringFromInterfaceIdentifier(InterfaceIdentifier));
1606                _ATLTRY
1607                {
1608                        __D(ppvSite, E_POINTER);
1609                        *ppvSite = NULL;
1610                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1611                        _D(m_pSite, E_FAIL);
1612                        return m_pSite->QueryInterface(InterfaceIdentifier, ppvSite);
1613                }
1614                _ATLCATCH(Exception)
1615                {
1616                        _C(Exception);
1617                }
1618                return S_OK;
1619        }
1620};
1621
1622////////////////////////////////////////////////////////////
1623// CSpy
1624
1625class ATL_NO_VTABLE CSpy :
1626        public CSpyT<CSpy, &CLSID_FilterGraph>,
1627        public CComCoClass<CSpy, &CLSID_Spy>
1628{
1629public:
1630        enum { IDR = IDR_FILTERGRAPHSPY };
1631
1632private:
1633        static LPCTSTR g_pszClassName;
1634
1635public:
1636        //typedef CBlackListAwareComCreatorT<CComObjectCached<CSpy>, CSpy, &g_pszClassName> _ClassFactoryCreatorClass; // DECLARE_CLASSFACTORY override
1637        typedef CComCreator2<CBlackListAwareComCreatorT<CComObject<CSpy>, CSpy, &g_pszClassName>, CBlackListAwareComCreatorT<CComAggObject<CSpy>, CSpy, &g_pszClassName> > _CreatorClass; // DECLARE_AGGREGATABLE override
1638
1639public:
1640// CSpy
1641};
1642
1643__declspec(selectany) LPCTSTR CSpy::g_pszClassName = _T("CSpy");
1644
1645OBJECT_ENTRY_AUTO(__uuidof(Spy), CSpy)
1646
1647////////////////////////////////////////////////////////////
1648// CNoThreadSpy
1649
1650class ATL_NO_VTABLE CNoThreadSpy :
1651        public CSpyT<CNoThreadSpy, &CLSID_FilterGraphNoThread>,
1652        public CComCoClass<CNoThreadSpy, &CLSID_NoThreadSpy>
1653{
1654public:
1655        enum { IDR = IDR_NOTHREADFILTERGRAPHSPY };
1656
1657private:
1658        static LPCTSTR g_pszClassName;
1659
1660public:
1661        //typedef CBlackListAwareComCreatorT<CComObjectCached<CNoThreadSpy>, CNoThreadSpy, &g_pszClassName> _ClassFactoryCreatorClass; // DECLARE_CLASSFACTORY override
1662        typedef CComCreator2<CBlackListAwareComCreatorT<CComObject<CNoThreadSpy>, CNoThreadSpy, &g_pszClassName>, CBlackListAwareComCreatorT<CComAggObject<CNoThreadSpy>, CNoThreadSpy, &g_pszClassName> > _CreatorClass; // DECLARE_AGGREGATABLE override
1663
1664public:
1665// CNoThreadSpy
1666};
1667
1668__declspec(selectany) LPCTSTR CNoThreadSpy::g_pszClassName = _T("CNoThreadSpy");
1669
1670OBJECT_ENTRY_AUTO(__uuidof(NoThreadSpy), CNoThreadSpy)
1671
1672////////////////////////////////////////////////////////////
1673// CPrivateThreadSpy
1674
1675class ATL_NO_VTABLE CPrivateThreadSpy :
1676        public CSpyT<CPrivateThreadSpy, &CLSID_FilterGraphPrivateThread>,
1677        public CComCoClass<CPrivateThreadSpy, &CLSID_PrivateThreadSpy>
1678{
1679public:
1680        enum { IDR = IDR_PRIVATETHREADFILTERGRAPHSPY };
1681
1682private:
1683        static LPCTSTR g_pszClassName;
1684
1685public:
1686        //typedef CBlackListAwareComCreatorT<CComObjectCached<CPrivateThreadSpy>, CPrivateThreadSpy, &g_pszClassName> _ClassFactoryCreatorClass; // DECLARE_CLASSFACTORY override
1687        typedef CComCreator2<CBlackListAwareComCreatorT<CComObject<CPrivateThreadSpy>, CPrivateThreadSpy, &g_pszClassName>, CBlackListAwareComCreatorT<CComAggObject<CPrivateThreadSpy>, CPrivateThreadSpy, &g_pszClassName> > _CreatorClass; // DECLARE_AGGREGATABLE override
1688
1689public:
1690// CPrivateThreadSpy
1691};
1692
1693__declspec(selectany) LPCTSTR CPrivateThreadSpy::g_pszClassName = _T("CPrivateThreadSpy");
1694
1695OBJECT_ENTRY_AUTO(__uuidof(PrivateThreadSpy), CPrivateThreadSpy)
Note: See TracBrowser for help on using the repository browser.