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