source: trunk/DirectShowSpy/FilterGraphSpy.h @ 545

Last change on this file since 545 was 545, checked in by roman, 8 years ago

Added previously not included hooks; added IFilterMapper3 hook suppors; template library related updates; added FGT to replace ROT (to access services in particular) - work in progress; fixed class enumeration hook

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