source: trunk/DirectShowSpy/FilterMapperSpy.h @ 267

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

Updated source code/copyright notice

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