source: trunk/DirectShowSpy/FilterMapperSpy.h @ 455

Last change on this file since 455 was 376, checked in by roman, 9 years ago

Changed year to 2015; Added Copy and Save As links in graph text, RunTime? property pages

  • Property svn:keywords set to Id
File size: 14.3 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2008-2015
3// Created by Roman Ryltsov roman@alax.info, http://alax.info
4//
5// This source code is published to complement DirectShowSpy developer powertoy
6// and demonstrate the internal use of APIs and tricks powering the tool. It is
7// allowed to freely re-use the portions of the code in other projects, commercial
8// or otherwise (provided that you don’t pretend that you wrote the original tool).
9//
10// Please keep in mind that DirectShowSpy is a developer tool, it is strongly recommended
11// that it is not shipped with release grade software. It is allowed to distribute
12// DirectShowSpy if only it is not registered with Windows by default and either
13// used privately, or registered on specific throubleshooting request. The advice applies
14// to hooking methods used by DirectShowSpy in general as well.
15
16#pragma once
17
18#include "rodshow.h"
19#include <..\Samples\multimedia\directshow\misc\mapper\fil_data.h>
20#include "Module_i.h"
21#include "Common.h"
22
23////////////////////////////////////////////////////////////
24// CFilterMapperSpyT
25
26template <typename T, const CLSID* t_pFilterMapperClassIdentifier>
27class ATL_NO_VTABLE CFilterMapperSpyT :
28        public CComObjectRootEx<CComMultiThreadModel>,
29        //public CComCoClass<CFilterMapperSpyT, &CLSID_FilterMapperSpy>,
30        public CTransparentCoClassT<T, t_pFilterMapperClassIdentifier>,
31        public IDispatchImpl<IFilterMapperSpy>,
32        public IAMFilterData,
33        public IFilterMapper2
34{
35        typedef CFilterMapperSpyT<T, t_pFilterMapperClassIdentifier> CFilterMapperSpy;
36
37public:
38        //enum { IDR = IDR_FILTERMAPPERSPY };
39
40//DECLARE_REGISTRY_RESOURCEID(IDR)
41
42DECLARE_PROTECT_FINAL_CONSTRUCT()
43
44DECLARE_GET_CONTROLLING_UNKNOWN()
45
46DECLARE_QI_TRACE(CFilterMapperSpy)
47
48BEGIN_COM_MAP(CFilterMapperSpy)
49        COM_INTERFACE_ENTRY(IFilterMapperSpy)
50        COM_INTERFACE_ENTRY(IAMFilterData)
51        COM_INTERFACE_ENTRY(IFilterMapper2)
52        COM_INTERFACE_ENTRY_AGGREGATE_BLIND(m_pInnerUnknown)
53        //COM_INTERFACE_ENTRY(IDispatch)
54END_COM_MAP()
55
56private:
57        BOOL m_bIsAggregated;
58        HINSTANCE m_hQuartzModule;
59        CComPtr<IUnknown> m_pInnerUnknown;
60        CComPtr<IFilterMapper2> m_pFilterMapper2;
61        CComPtr<IAMFilterData> m_pAmFilterData;
62
63        static VOID Trace(const REGFILTER2* pFilterInformation)
64        {
65                _A(pFilterInformation);
66                _Z4(atlTraceCOM, 4, _T("pFilterInformation { dwVersion %d, dwMerit 0x%08x, cPins2 %d }\n"), pFilterInformation->dwVersion, pFilterInformation->dwMerit, pFilterInformation->cPins2);
67                if(pFilterInformation->dwVersion == 2)
68                        for(ULONG nPinIndex = 0; nPinIndex < pFilterInformation->cPins2; nPinIndex++)
69                        {
70                                const REGFILTERPINS2& Pin = pFilterInformation->rgPins2[nPinIndex];
71                                _Z4(atlTraceCOM, 4, _T("pFilterInformation->rgPins2[%d] { dwFlags 0x%x, cInstances %d, nMediaTypes %d, nMediums %d }\n"), nPinIndex, Pin.dwFlags, Pin.cInstances, Pin.nMediaTypes, Pin.nMediums, Pin.clsPinCategory ? (LPCWSTR) _PersistHelper::StringFromIdentifier(*Pin.clsPinCategory) : L"NULL");
72                                for(UINT nIndex = 0; nIndex < Pin.nMediaTypes; nIndex++)
73                                {
74                                        const REGPINTYPES& Type = Pin.lpMediaType[nIndex];
75                                        _Z4(atlTraceCOM, 4, _T("pFilterInformation->rgPins2[...].lpMediaType[%d] { clsMajorType %ls, clsMinorType %ls }\n"), nIndex, Type.clsMajorType ? (LPCWSTR) _PersistHelper::StringFromIdentifier(*Type.clsMajorType) : L"NULL", Type.clsMinorType ? (LPCWSTR) _PersistHelper::StringFromIdentifier(*Type.clsMinorType) : L"NULL");
76                                }
77                                for(UINT nIndex = 0; nIndex < Pin.nMediums; nIndex++)
78                                {
79                                        const REGPINMEDIUM& Medium = Pin.lpMedium[nIndex];
80                                        _Z4(atlTraceCOM, 4, _T("pFilterInformation->rgPins2[...].lpMedium[%d] { clsMedium %ls, dw1 0x%x, dw2 0x%x }\n"), nIndex, _PersistHelper::StringFromIdentifier(Medium.clsMedium), Medium.dw1, Medium.dw2);
81                                }
82                        }
83        }
84        BOOL IsAggregated() const throw()
85        {
86                return (ULONG) m_dwRef >= 0x00001000;
87        }
88
89public:
90// CFilterMapperSpyT
91        static LPCTSTR GetOriginalLibraryName() throw()
92        {
93                return _T("quartz.dll");
94        }
95        static CString GetObjectFriendlyName()
96        {
97                return _StringHelper::GetLine(T::IDR, 2);
98        }
99        static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()
100        {
101                _Z2(atlTraceRegistrar, 2, _T("bRegister %d\n"), bRegister);
102                _ATLTRY
103                {
104                        TreatAsUpdateRegistryFromResource<T>(*t_pFilterMapperClassIdentifier, bRegister);
105                }
106                _ATLCATCH(Exception)
107                {
108                        _C(Exception);
109                }
110                return S_OK;
111        }
112        CFilterMapperSpyT() throw() :
113                m_hQuartzModule(NULL)
114        {
115                _Z4_THIS();
116        }
117        ~CFilterMapperSpyT() throw()
118        {
119                _Z4_THIS();
120        }
121        HRESULT FinalConstruct() throw()
122        {
123                _ATLTRY
124                {
125                        m_bIsAggregated = IsAggregated();
126                        TCHAR pszPath[MAX_PATH] = { 0 };
127                        _W(GetModuleFileName(NULL, pszPath, DIM(pszPath)));
128                        _Z4(atlTraceRefcount, 4, _T("pszPath \"%s\", this 0x%08x, m_dwRef %d, m_bIsAggregated %d\n"), pszPath, this, m_dwRef, m_bIsAggregated);
129                        const HINSTANCE hModule = CoLoadLibrary(const_cast<LPOLESTR>((LPCOLESTR) CT2COLE(GetOriginalLibraryName())), TRUE);
130                        _ATLTRY
131                        {
132                                typedef HRESULT (WINAPI *DLLGETCLASSOBJECT)(REFCLSID, REFIID, VOID**);
133                                DLLGETCLASSOBJECT DllGetClassObject = (DLLGETCLASSOBJECT) GetProcAddress(hModule, "DllGetClassObject");
134                                __E(DllGetClassObject);
135                                CComPtr<IClassFactory> pClassFactory;
136                                __C(DllGetClassObject(*t_pFilterMapperClassIdentifier, __uuidof(IClassFactory), (VOID**) &pClassFactory));
137                                _A(pClassFactory);
138                                const CComPtr<IUnknown> pControllingUnknown = GetControllingUnknown();
139                                {
140                                        CComPtr<IUnknown> pUnknown;
141                                        __C(pClassFactory->CreateInstance(pControllingUnknown, __uuidof(IUnknown), (VOID**) &pUnknown));
142                                        const CComQIPtr<IFilterMapper2> pFilterMapper2 = pUnknown;
143                                        __D(pFilterMapper2, E_NOINTERFACE);
144                                        pFilterMapper2.p->Release();
145                                        const CComQIPtr<IAMFilterData> pAmFilterData = pUnknown;
146                                        __D(pAmFilterData, E_NOINTERFACE);
147                                        pAmFilterData.p->Release();
148                                        m_pInnerUnknown = pUnknown;
149                                        m_pFilterMapper2 = pFilterMapper2;
150                                        m_pAmFilterData = pAmFilterData;
151                                }
152                        }
153                        _ATLCATCHALL()
154                        {
155                                CoFreeLibrary(hModule);
156                                _ATLRETHROW;
157                        }
158                        _A(!m_hQuartzModule);
159                        m_hQuartzModule = hModule;
160                }
161                _ATLCATCH(Exception)
162                {
163                        _C(Exception);
164                }
165                return S_OK;
166        }
167        VOID FinalRelease() throw()
168        {
169                _Z5(atlTraceRefcount, 5, _T("m_dwRef 0x%x\n"), m_dwRef);
170                CComPtr<IUnknown> pControllingUnknown = GetControllingUnknown();
171                if(m_pFilterMapper2)
172                {
173                        pControllingUnknown.p->AddRef();
174                        m_pFilterMapper2 = NULL;
175                }
176                if(m_pAmFilterData)
177                {
178                        pControllingUnknown.p->AddRef();
179                        m_pAmFilterData = NULL;
180                }
181                _ATLTRY
182                {
183                        m_pInnerUnknown = NULL;
184                }
185                _ATLCATCHALL()
186                {
187                        _Z_EXCEPTION();
188                        // NOTE: For some unidentified reason Quartz's FilterGraph may crash during final release, to smooth the effect the exception is silently caught
189                        m_pInnerUnknown.p = NULL;
190                }
191                if(m_hQuartzModule)
192                {
193                        CoFreeLibrary(m_hQuartzModule);
194                        m_hQuartzModule = NULL;
195                }
196        }
197
198// IFilterMapperSpy
199
200// IAMFilterData
201        STDMETHOD(ParseFilterData)(BYTE* pnFilterData, ULONG nFilterDataSize, BYTE** ppFilterInformation) throw()
202        {
203                _Z4(atlTraceCOM, 4, _T("nFilterDataSize %d\n"), nFilterDataSize);
204                const HRESULT nResult = m_pAmFilterData->ParseFilterData(pnFilterData, nFilterDataSize, ppFilterInformation);
205                if(SUCCEEDED(nResult) && ppFilterInformation && *ppFilterInformation && *((BYTE**) *ppFilterInformation))
206                        _ATLTRY
207                        {
208                                Trace((REGFILTER2*) *((BYTE**) *ppFilterInformation));
209                        }
210                        _ATLCATCHALL()
211                        {
212                                _Z_EXCEPTION();
213                        }
214                return nResult;
215        }
216        STDMETHOD(CreateFilterData)(REGFILTER2* pFilterInformation, BYTE** ppnFilterData, ULONG* pnFilterDataSize) throw()
217        {
218                _Z4(atlTraceCOM, 4, _T("...\n"));
219                if(pFilterInformation)
220                        _ATLTRY
221                        {
222                                Trace(pFilterInformation);
223                        }
224                        _ATLCATCHALL()
225                        {
226                                _Z_EXCEPTION();
227                        }
228                return m_pAmFilterData->CreateFilterData(pFilterInformation, ppnFilterData, pnFilterDataSize);
229        }
230
231// IFilterMapper2
232        STDMETHOD(CreateCategory)(REFCLSID CategoryIdentifier, DWORD nMerit, LPCWSTR pszDescription) throw()
233        {
234                _Z4(atlTraceCOM, 4, _T("CategoryIdentifier %ls, nMerit 0x%08x, pszDescription \"%s\"\n"), _PersistHelper::StringFromIdentifier(CategoryIdentifier), nMerit, CString(pszDescription));
235                return m_pFilterMapper2->CreateCategory(CategoryIdentifier, nMerit, pszDescription);
236        }
237        STDMETHOD(UnregisterFilter)(const CLSID* pCategoryIdentifier, LPCOLESTR pszInstance, REFCLSID FilterClassIdentifier) throw()
238        {
239                _Z4(atlTraceCOM, 4, _T("pCategoryIdentifier %ls, pszInstance %s, FilterClassIdentifier %ls\n"), pCategoryIdentifier ? (LPCWSTR) _PersistHelper::StringFromIdentifier(*pCategoryIdentifier) : L"NULL", pszInstance ? (LPCTSTR) AtlFormatString(_T("\"%s\""), CString(pszInstance)) : _T("NULL"), _PersistHelper::StringFromIdentifier(FilterClassIdentifier));
240                return m_pFilterMapper2->UnregisterFilter(pCategoryIdentifier, pszInstance, FilterClassIdentifier);
241        }
242        STDMETHOD(RegisterFilter)(REFCLSID FilterClassIdentifier, LPCWSTR pszName, IMoniker** ppMoniker, const CLSID* pCategoryIdentifier, LPCOLESTR pszInstance, const REGFILTER2* pFilterInformation) throw()
243        {
244                _Z4(atlTraceCOM, 4, _T("FilterClassIdentifier %ls, pszName \"%s\", pCategoryIdentifier %ls, pszInstance %s\n"), _PersistHelper::StringFromIdentifier(FilterClassIdentifier), CString(pszName), pCategoryIdentifier ? (LPCWSTR) _PersistHelper::StringFromIdentifier(*pCategoryIdentifier) : L"NULL", pszInstance ? (LPCTSTR) AtlFormatString(_T("\"%s\""), CString(pszInstance)) : _T("NULL"));
245                if(pFilterInformation)
246                        _ATLTRY
247                        {
248                                Trace(pFilterInformation);
249                        }
250                        _ATLCATCHALL()
251                        {
252                                _Z_EXCEPTION();
253                        }
254                return m_pFilterMapper2->RegisterFilter(FilterClassIdentifier, pszName, ppMoniker, pCategoryIdentifier, pszInstance, pFilterInformation);
255        }
256        STDMETHOD(EnumMatchingFilters)(IEnumMoniker** ppEnumMoniker, DWORD nFlags, BOOL bExactMatch, DWORD nMinimalMerit, BOOL bInputNeeded, DWORD nInputTypeCount, const GUID* pInputTypes, const REGPINMEDIUM* pInputMedium, const CLSID* pInputPinCategory, BOOL bRender, BOOL bOutputNeeded, DWORD nOutputTypeCount, const GUID* pOutputTypes, const REGPINMEDIUM* pOutputMedium, const CLSID* pOutputPinCategory) throw()
257        {
258                _Z4(atlTraceCOM, 4, _T("nFlags 0x%x, bExactMatch %d, nMinimalMerit 0x%08x, bInputNeeded %d, nInputTypeCount %d, pInputPinCategory %ls, bRender %d, bOutputNeeded %d, nOutputTypeCount %d, pOutputPinCategory %ls\n"), nFlags, bExactMatch, nMinimalMerit, bInputNeeded, nInputTypeCount, pInputPinCategory ? (LPCWSTR) _PersistHelper::StringFromIdentifier(*pInputPinCategory) : L"NULL", bRender, bOutputNeeded, nOutputTypeCount, pOutputPinCategory ? (LPCWSTR) _PersistHelper::StringFromIdentifier(*pOutputPinCategory) : L"NULL");
259                for(DWORD nInputTypeIndex = 0; nInputTypeIndex < nInputTypeCount; nInputTypeIndex++)
260                {
261                        const GUID& MajorType = pInputTypes[2 * nInputTypeIndex + 0];
262                        const GUID& Subtype = pInputTypes[2 * nInputTypeIndex + 1];
263                        _Z4(atlTraceCOM, 4, _T("nInputTypeIndex %d, MajorType %ls, Subtype %ls\n"), nInputTypeIndex, _PersistHelper::StringFromIdentifier(MajorType), _PersistHelper::StringFromIdentifier(Subtype));
264                }
265                if(pInputMedium)
266                        _Z4(atlTraceCOM, 4, _T("pInputMedium { clsMedium %ls, dw1 0x%x, dw2 0x%x }\n"), _PersistHelper::StringFromIdentifier(pInputMedium->clsMedium), pInputMedium->dw1, pInputMedium->dw2);
267                for(DWORD nOutputTypeIndex = 0; nOutputTypeIndex < nOutputTypeCount; nOutputTypeIndex++)
268                {
269                        const GUID& MajorType = pOutputTypes[2 * nOutputTypeIndex + 0];
270                        const GUID& Subtype = pOutputTypes[2 * nOutputTypeIndex + 1];
271                        _Z4(atlTraceCOM, 4, _T("nOutputTypeIndex %d, MajorType %ls, Subtype %ls\n"), nOutputTypeIndex, _PersistHelper::StringFromIdentifier(MajorType), _PersistHelper::StringFromIdentifier(Subtype));
272                }
273                if(pOutputMedium)
274                        _Z4(atlTraceCOM, 4, _T("pOutputMedium { clsMedium %ls, dw1 0x%x, dw2 0x%x }\n"), _PersistHelper::StringFromIdentifier(pOutputMedium->clsMedium), pOutputMedium->dw1, pOutputMedium->dw2);
275                const HRESULT nResult = m_pFilterMapper2->EnumMatchingFilters(ppEnumMoniker, nFlags, bExactMatch, nMinimalMerit, bInputNeeded, nInputTypeCount, pInputTypes, pInputMedium, pInputPinCategory, bRender, bOutputNeeded, nOutputTypeCount, pOutputTypes, pOutputMedium, pOutputPinCategory);
276                if(SUCCEEDED(nResult))
277                        _ATLTRY
278                        {
279                                const CComPtr<IEnumMoniker>& pEnumMoniker = reinterpret_cast<const CComPtr<IEnumMoniker>&>(*ppEnumMoniker);
280                                __C(pEnumMoniker->Reset());
281                                CComPtr<IMoniker> pMoniker;
282                                while(pEnumMoniker->Next(1, &pMoniker, NULL) == S_OK)
283                                {
284                                        _Z4(atlTraceCOM, 4, _T("pMoniker %ls\n"), _FilterGraphHelper::GetMonikerDisplayName(pMoniker));
285                                        CComPtr<IBindCtx> pBindCtx;
286                                        __C(CreateBindCtx(0, &pBindCtx));
287                                        CComPtr<IPropertyBag> pPropertyBag;
288                                        __C(pMoniker->BindToStorage(pBindCtx, NULL, __uuidof(IPropertyBag), (VOID**) &pPropertyBag));
289                                        const CStringW sFriendlyName = _FilterGraphHelper::ReadPropertyBagString(pPropertyBag, OLESTR("FriendlyName"));
290                                        const CStringW sDescription = _FilterGraphHelper::ReadPropertyBagString(pPropertyBag, OLESTR("Description"));
291                                        const CStringW sDevicePath = _FilterGraphHelper::ReadPropertyBagString(pPropertyBag, OLESTR("DevicePath"));
292                                        _Z4(atlTraceCOM, 4, _T("sFriendlyName \"%ls\", sDescription \"%ls\", sDevicePath \"%ls\"\n"), sFriendlyName, sDescription, sDevicePath);
293                                        pMoniker.Release();
294                                }
295                                __C(pEnumMoniker->Reset());
296                        }
297                        _ATLCATCHALL()
298                        {
299                                _Z_EXCEPTION();
300                        }
301                return nResult;
302        }
303};
304
305////////////////////////////////////////////////////////////
306// CFilterMapperSpy
307
308class ATL_NO_VTABLE CFilterMapperSpy :
309        public CFilterMapperSpyT<CFilterMapperSpy, &CLSID_FilterMapper2>,
310        public CComCoClass<CFilterMapperSpy, &CLSID_FilterMapperSpy>
311{
312public:
313        enum { IDR = IDR_FILTERMAPPERSPY };
314
315private:
316        static LPCTSTR g_pszClassName;
317
318public:
319        //typedef CBlackListAwareComCreatorT<CComObjectCached<CFilterMapperSpy>, CFilterMapperSpy, &g_pszClassName> _ClassFactoryCreatorClass; // DECLARE_CLASSFACTORY override
320        typedef CComCreator2<CBlackListAwareComCreatorT<CComObject<CFilterMapperSpy>, CFilterMapperSpy, &g_pszClassName>, CBlackListAwareComCreatorT<CComAggObject<CFilterMapperSpy>, CFilterMapperSpy, &g_pszClassName> > _CreatorClass; // DECLARE_AGGREGATABLE override
321
322public:
323// CFilterMapperSpy
324};
325
326__declspec(selectany) LPCTSTR CFilterMapperSpy::g_pszClassName = _T("CFilterMapperSpy");
327
328OBJECT_ENTRY_AUTO(__uuidof(FilterMapperSpy), CFilterMapperSpy)
329
Note: See TracBrowser for help on using the repository browser.