source: trunk/DirectShowSpy/FilterGraphSpy.h @ 276

Last change on this file since 276 was 276, checked in by roman, 10 years ago

Updated header (on use, applicability, redistribution)

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