source: trunk/DirectShowSpy/FilterGraphSpy.h @ 319

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

Memory allocator properties on text and on log; Cosmetic changes

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