source: trunk/DirectShowSpy/FilterGraphSpy.h @ 448

Last change on this file since 448 was 441, checked in by roman, 9 years ago

Added filtering in media sample trace UI; fixed thread safety problem; fixed file mapping initialization issue; removed media sample leak feature (to extend file mapping lifetime) and replaced with file mapping ownership transfer to UI process; added menu item to jump right to filter graph

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