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 dont 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 "Module_i.h" |
---|
19 | #include "Common.h" |
---|
20 | |
---|
21 | //////////////////////////////////////////////////////////// |
---|
22 | // CFilterGraphTableBase |
---|
23 | |
---|
24 | // NOTE: Exclude from legacy Windows XP toolset builds |
---|
25 | |
---|
26 | #if NTDDI_VERSION > 0x06010000 // NTDDI_WIN7 |
---|
27 | |
---|
28 | #define AVAILABILITY_FILTERGRAPHTABLE |
---|
29 | |
---|
30 | class CFilterGraphTableBase |
---|
31 | { |
---|
32 | public: |
---|
33 | |
---|
34 | //////////////////////////////////////////////////////// |
---|
35 | // Structure |
---|
36 | |
---|
37 | #pragma pack(push) |
---|
38 | #pragma pack(push, 16) |
---|
39 | |
---|
40 | enum |
---|
41 | { |
---|
42 | ITEMFLAGS_NONE = 0, |
---|
43 | ITEMFLAG_ACTIVE = 0x01, |
---|
44 | ITEMFLAGS_DEFAULT = ITEMFLAGS_NONE, |
---|
45 | }; |
---|
46 | |
---|
47 | typedef struct _ITEM |
---|
48 | { |
---|
49 | UINT32 nFlags; |
---|
50 | UINT32 nProcessIdentifier; |
---|
51 | GUID ActiveObjectClassIdentifier; |
---|
52 | } ITEM; |
---|
53 | |
---|
54 | typedef struct _HEADER |
---|
55 | { |
---|
56 | UINT64 nCapacity; |
---|
57 | UINT64 nSpinValue; |
---|
58 | UINT32 nItemCount; |
---|
59 | ITEM pItems[1]; |
---|
60 | |
---|
61 | CInterlockedLongLong& GetSpinValue() |
---|
62 | { |
---|
63 | return reinterpret_cast<CInterlockedLongLong&>(nSpinValue); |
---|
64 | } |
---|
65 | VOID Lock() |
---|
66 | { |
---|
67 | CInterlockedLongLong& nSpinValue = GetSpinValue(); |
---|
68 | for(; ; ) |
---|
69 | { |
---|
70 | if(nSpinValue.Increment() == 0) |
---|
71 | break; |
---|
72 | nSpinValue.Decrement(); |
---|
73 | SwitchToThread(); |
---|
74 | } |
---|
75 | } |
---|
76 | VOID Unlock() |
---|
77 | { |
---|
78 | CInterlockedLongLong& nSpinValue = GetSpinValue(); |
---|
79 | nSpinValue.Decrement(); |
---|
80 | } |
---|
81 | } HEADER; |
---|
82 | |
---|
83 | #pragma pack(pop) |
---|
84 | |
---|
85 | //////////////////////////////////////////////////////// |
---|
86 | // CActiveObjectFileMapping |
---|
87 | |
---|
88 | class CActiveObjectFileMapping : |
---|
89 | public CAtlFileMapping<HEADER> |
---|
90 | { |
---|
91 | public: |
---|
92 | // CActiveObjectFileMapping |
---|
93 | static CString GetName() |
---|
94 | { |
---|
95 | // NOTE: Kernel object namespaces |
---|
96 | return _T("Global\\") _T("AlaxInfoDirectShowSpy.ActiveObjectFileMapping"); |
---|
97 | } |
---|
98 | static SIZE_T GetCapacity() |
---|
99 | { |
---|
100 | return 1 << 20; // 1 MB |
---|
101 | } |
---|
102 | VOID Create() |
---|
103 | { |
---|
104 | _A(!GetHandle()); |
---|
105 | const SIZE_T nCapacity = GetCapacity(); |
---|
106 | // TODO: Security |
---|
107 | BOOL bExist; |
---|
108 | const HRESULT nResult = __super::MapSharedMem(nCapacity, GetName(), &bExist); |
---|
109 | if(!bExist) |
---|
110 | { |
---|
111 | #pragma region Security |
---|
112 | CDacl AccessControlList; |
---|
113 | __E(AtlGetDacl(GetHandle(), SE_KERNEL_OBJECT, &AccessControlList)); |
---|
114 | //AccessControlList.AddAllowedAce(Sids::Admins(), FILE_MAP_ALL_ACCESS, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE); |
---|
115 | //AccessControlList.AddAllowedAce(Sids::Interactive(), FILE_MAP_READ, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE); |
---|
116 | AccessControlList.AddAllowedAce(Sids::World(), FILE_MAP_ALL_ACCESS, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE); |
---|
117 | __E(AtlSetDacl(GetHandle(), SE_KERNEL_OBJECT, AccessControlList)); |
---|
118 | #pragma endregion |
---|
119 | HEADER* pHeader = *this; |
---|
120 | pHeader->nCapacity = (UINT32) nCapacity; |
---|
121 | _A(!pHeader->nItemCount); |
---|
122 | pHeader->GetSpinValue().Decrement(); |
---|
123 | } |
---|
124 | } |
---|
125 | BOOL Open() |
---|
126 | { |
---|
127 | _A(!GetHandle()); |
---|
128 | const HRESULT nResult = __super::OpenMapping(GetName(), GetCapacity()); |
---|
129 | return SUCCEEDED(nResult); |
---|
130 | } |
---|
131 | }; |
---|
132 | |
---|
133 | //////////////////////////////////////////////////////// |
---|
134 | // CActiveObject |
---|
135 | |
---|
136 | class ATL_NO_VTABLE CActiveObject : |
---|
137 | public CComObjectRootEx<CComMultiThreadModelNoCS>, |
---|
138 | public IExternalConnectionImpl<CActiveObject>, |
---|
139 | public IDispatchImpl<IFilterGraphTableActiveObject> |
---|
140 | { |
---|
141 | DECLARE_NO_REGISTRY() |
---|
142 | |
---|
143 | DECLARE_QI_TRACE(CActiveObject) |
---|
144 | |
---|
145 | BEGIN_COM_MAP(CActiveObject) |
---|
146 | COM_INTERFACE_ENTRY(IExternalConnection) |
---|
147 | COM_INTERFACE_ENTRY(IFilterGraphTableActiveObject) |
---|
148 | COM_INTERFACE_ENTRY(IDispatch) |
---|
149 | END_COM_MAP() |
---|
150 | |
---|
151 | public: |
---|
152 | |
---|
153 | private: |
---|
154 | static CActiveObject* g_pInstance; |
---|
155 | mutable CRoCriticalSection m_DataCriticalSection; |
---|
156 | CRoArrayT<CComPtr<IFilterGraphTableItem>> m_ItemList; |
---|
157 | GUID m_ClassIdentifier; |
---|
158 | ::CActiveObject m_ActiveObject; |
---|
159 | //::CActiveObjectT<CDefaultActiveObjectHandler> m_ActiveObject; |
---|
160 | CActiveObjectFileMapping m_FileMapping; |
---|
161 | UINT32 m_nItemIndex; |
---|
162 | |
---|
163 | public: |
---|
164 | // CActiveObject |
---|
165 | CActiveObject() : |
---|
166 | m_ClassIdentifier(CLSID_NULL) |
---|
167 | { |
---|
168 | _Z4_THIS(); |
---|
169 | } |
---|
170 | ~CActiveObject() |
---|
171 | { |
---|
172 | _Z4_THIS(); |
---|
173 | } |
---|
174 | VOID Register() |
---|
175 | { |
---|
176 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
177 | if(m_ActiveObject.IsRegistered()) |
---|
178 | return; |
---|
179 | if(m_ClassIdentifier == CLSID_NULL) |
---|
180 | __C(CoCreateGuid(&m_ClassIdentifier)); |
---|
181 | // TODO: Handle CO_E_WRONG_SERVER_IDENTITY |
---|
182 | m_ActiveObject.Register((IFilterGraphTableActiveObject*) this, m_ClassIdentifier); |
---|
183 | _ATLTRY |
---|
184 | { |
---|
185 | if(!m_FileMapping.GetHandle()) |
---|
186 | m_FileMapping.Create(); |
---|
187 | HEADER* pHeader = m_FileMapping; |
---|
188 | _A(pHeader); |
---|
189 | pHeader->Lock(); |
---|
190 | _ATLTRY |
---|
191 | { |
---|
192 | #pragma region File Mapping Item |
---|
193 | UINT32 nItemIndex; |
---|
194 | for(nItemIndex = 0; nItemIndex < pHeader->nItemCount; nItemIndex++) |
---|
195 | if(!(pHeader->pItems[nItemIndex].nFlags & ITEMFLAG_ACTIVE)) |
---|
196 | break; |
---|
197 | if(nItemIndex >= pHeader->nItemCount) |
---|
198 | { |
---|
199 | // TODO: Compact items |
---|
200 | __D((SIZE_T) ((BYTE*) &pHeader->pItems[nItemIndex + 1] - (BYTE*) pHeader) <= pHeader->nCapacity, HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW)); |
---|
201 | ITEM& Item = pHeader->pItems[nItemIndex]; |
---|
202 | ZeroMemory(&Item, sizeof Item); |
---|
203 | pHeader->nItemCount++; |
---|
204 | } |
---|
205 | ITEM& Item = pHeader->pItems[nItemIndex]; |
---|
206 | Item.nFlags = ITEMFLAG_ACTIVE; |
---|
207 | Item.nProcessIdentifier = GetCurrentProcessId(); |
---|
208 | Item.ActiveObjectClassIdentifier = m_ClassIdentifier; |
---|
209 | m_nItemIndex = nItemIndex; |
---|
210 | #pragma endregion |
---|
211 | } |
---|
212 | _ATLCATCHALL() |
---|
213 | { |
---|
214 | pHeader->Unlock(); |
---|
215 | _ATLRETHROW; |
---|
216 | } |
---|
217 | pHeader->Unlock(); |
---|
218 | } |
---|
219 | _ATLCATCHALL() |
---|
220 | { |
---|
221 | m_ActiveObject.Unregister(); |
---|
222 | _ATLRETHROW; |
---|
223 | } |
---|
224 | } |
---|
225 | VOID Revoke() |
---|
226 | { |
---|
227 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
228 | if(!m_ActiveObject.IsRegistered()) |
---|
229 | return; |
---|
230 | _A(m_ClassIdentifier != CLSID_NULL); |
---|
231 | _A(m_FileMapping); |
---|
232 | #pragma region File Mapping Item |
---|
233 | HEADER* pHeader = m_FileMapping; |
---|
234 | pHeader->Lock(); |
---|
235 | _A(m_nItemIndex < pHeader->nItemCount); |
---|
236 | ITEM& Item = pHeader->pItems[m_nItemIndex]; |
---|
237 | Item.nFlags = 0; |
---|
238 | while(pHeader->nItemCount && !(pHeader->pItems[pHeader->nItemCount - 1].nFlags & ITEMFLAG_ACTIVE)) |
---|
239 | pHeader->nItemCount--; |
---|
240 | pHeader->Unlock(); |
---|
241 | #pragma endregion |
---|
242 | m_ActiveObject.Unregister(); |
---|
243 | } |
---|
244 | static CObjectPtr<CActiveObject> GetInstance() |
---|
245 | { |
---|
246 | _A(_pAtlModule); |
---|
247 | CComCritSecLock<CComCriticalSection> Lock(_pAtlModule->m_csStaticDataInitAndTypeInfo); |
---|
248 | if(!g_pInstance) |
---|
249 | { |
---|
250 | CObjectPtr<CActiveObject> pInstance; |
---|
251 | pInstance.Construct(); |
---|
252 | reinterpret_cast<CObjectPtr<CActiveObject>&>(g_pInstance) = pInstance; |
---|
253 | return pInstance; |
---|
254 | } |
---|
255 | return g_pInstance; |
---|
256 | } |
---|
257 | VOID Add(IFilterGraphTableItem* pItem) |
---|
258 | { |
---|
259 | _A(pItem); |
---|
260 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
261 | _A(!m_ItemList.FindFirst(pItem)); |
---|
262 | m_ItemList.Add(pItem); |
---|
263 | if(m_ItemList.GetCount() == 1) |
---|
264 | Register(); |
---|
265 | } |
---|
266 | VOID Remove(IFilterGraphTableItem* pItem) |
---|
267 | { |
---|
268 | _A(pItem); |
---|
269 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
270 | SIZE_T nIndex; |
---|
271 | if(!m_ItemList.FindFirst(pItem, &nIndex)) |
---|
272 | return; |
---|
273 | m_ItemList.RemoveAt(nIndex); |
---|
274 | if(m_ItemList.IsEmpty()) |
---|
275 | Revoke(); |
---|
276 | } |
---|
277 | |
---|
278 | // CComObjectRootEx |
---|
279 | ULONG InternalRelease() |
---|
280 | { |
---|
281 | ULONG nReferenceCount = __super::InternalRelease(); |
---|
282 | if(nReferenceCount == 1) |
---|
283 | { |
---|
284 | _A(_pAtlModule); |
---|
285 | CComCritSecLock<CComCriticalSection> Lock(_pAtlModule->m_csStaticDataInitAndTypeInfo); |
---|
286 | _Z4(atlTraceRefcount, 4, _T("this 0x%p, nReferenceCount %d, g_pInstance 0x%p\n"), this, nReferenceCount, g_pInstance); |
---|
287 | if(g_pInstance) |
---|
288 | { |
---|
289 | if(m_dwRef == 1) |
---|
290 | { |
---|
291 | g_pInstance = NULL; |
---|
292 | _W(__super::InternalRelease() == 0); |
---|
293 | nReferenceCount = 0; |
---|
294 | } |
---|
295 | } |
---|
296 | } |
---|
297 | return nReferenceCount; |
---|
298 | } |
---|
299 | |
---|
300 | // IFilterGraphTableActiveObject |
---|
301 | STDMETHOD(GetFilterGraphs)(LONG* pnProcessIdentifier, VARIANT* pvArray) override |
---|
302 | { |
---|
303 | _Z4(atlTraceCOM, 4, _T("...\n")); |
---|
304 | _ATLTRY |
---|
305 | { |
---|
306 | __D(pnProcessIdentifier && pvArray, E_POINTER); |
---|
307 | VariantInit(pvArray); |
---|
308 | const DWORD nProcessIdentifier = GetCurrentProcessId(); |
---|
309 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
310 | *pnProcessIdentifier = (LONG) nProcessIdentifier; |
---|
311 | CRoArrayT<CComVariantArray> Array; |
---|
312 | for(auto&& pFilterGraphTableItem: m_ItemList) |
---|
313 | { |
---|
314 | _ATLTRY |
---|
315 | { |
---|
316 | CComPtr<IUnknown> pFilterGraphUnknown; |
---|
317 | __C(pFilterGraphTableItem->get_FilterGraph(&pFilterGraphUnknown)); |
---|
318 | if(pFilterGraphUnknown) |
---|
319 | { |
---|
320 | DATE fTime; |
---|
321 | __C(pFilterGraphTableItem->get_Time(&fTime)); |
---|
322 | CComVariantArray vItemValue; |
---|
323 | vItemValue.FromElements(4, |
---|
324 | CComVariant((LONG) nProcessIdentifier), |
---|
325 | CComVariant((LONGLONG) (LONG_PTR) (IUnknown*) pFilterGraphUnknown), |
---|
326 | CComVariant((IUnknown*) pFilterGraphUnknown), |
---|
327 | CComVariant(fTime, VT_DATE), |
---|
328 | 0); |
---|
329 | Array.Add(vItemValue); |
---|
330 | } |
---|
331 | } |
---|
332 | _ATLCATCHALL() |
---|
333 | { |
---|
334 | _Z_EXCEPTION(); |
---|
335 | } |
---|
336 | } |
---|
337 | CComVariantArray vValue; |
---|
338 | vValue.FromElementArray(Array); |
---|
339 | _V(vValue.Detach(pvArray)); |
---|
340 | } |
---|
341 | _ATLCATCH(Exception) |
---|
342 | { |
---|
343 | _C(Exception); |
---|
344 | } |
---|
345 | return S_OK; |
---|
346 | } |
---|
347 | }; |
---|
348 | |
---|
349 | public: |
---|
350 | // CFilterGraphTableBase |
---|
351 | }; |
---|
352 | |
---|
353 | __declspec(selectany) CFilterGraphTableBase::CActiveObject* CFilterGraphTableBase::CActiveObject::g_pInstance = NULL; |
---|
354 | |
---|
355 | //////////////////////////////////////////////////////////// |
---|
356 | // CFilterGraphTableItem |
---|
357 | |
---|
358 | class ATL_NO_VTABLE CFilterGraphTableItem : |
---|
359 | public CComObjectRootEx<CComMultiThreadModelNoCS>, |
---|
360 | public CComCoClass<CFilterGraphTableItem, &__uuidof(FilterGraphTableItem)>, |
---|
361 | public IProvideClassInfo2Impl<&__uuidof(FilterGraphTableItem), &IID_NULL>, |
---|
362 | public IDispatchImpl<IFilterGraphTableItem>, |
---|
363 | public CFilterGraphTableBase |
---|
364 | { |
---|
365 | public: |
---|
366 | enum { IDR = IDR_FILTERGRAPHTABLEITEM }; |
---|
367 | |
---|
368 | //DECLARE_REGISTRY_RESOURCEID(IDR) |
---|
369 | |
---|
370 | DECLARE_PROTECT_FINAL_CONSTRUCT() |
---|
371 | |
---|
372 | BEGIN_COM_MAP(CFilterGraphTableItem) |
---|
373 | COM_INTERFACE_ENTRY(IFilterGraphTableItem) |
---|
374 | COM_INTERFACE_ENTRY(IDispatch) |
---|
375 | COM_INTERFACE_ENTRY(IProvideClassInfo2) |
---|
376 | COM_INTERFACE_ENTRY(IProvideClassInfo) |
---|
377 | COM_INTERFACE_ENTRY_IID(__uuidof(FilterGraphTableItem), CFilterGraphTableItem) |
---|
378 | END_COM_MAP() |
---|
379 | |
---|
380 | public: |
---|
381 | |
---|
382 | private: |
---|
383 | mutable CRoCriticalSection m_DataCriticalSection; |
---|
384 | CComPtr<IFilterGraph2> m_pFilterGraph; |
---|
385 | CObjectPtr<CActiveObject> m_pActiveObject; |
---|
386 | ULONGLONG m_nTime; |
---|
387 | |
---|
388 | public: |
---|
389 | // CFilterGraphTableItem |
---|
390 | static HRESULT WINAPI UpdateRegistry(BOOL bRegister) |
---|
391 | { |
---|
392 | _Z2(atlTraceRegistrar, 2, _T("bRegister %d\n"), bRegister); |
---|
393 | _ATLTRY |
---|
394 | { |
---|
395 | UpdateRegistryFromResource<CFilterGraphTableItem>(bRegister); |
---|
396 | } |
---|
397 | _ATLCATCH(Exception) |
---|
398 | { |
---|
399 | _C(Exception); |
---|
400 | } |
---|
401 | return S_OK; |
---|
402 | } |
---|
403 | CFilterGraphTableItem() : |
---|
404 | m_nTime(0) |
---|
405 | { |
---|
406 | _Z4_THIS(); |
---|
407 | } |
---|
408 | ~CFilterGraphTableItem() |
---|
409 | { |
---|
410 | _Z4_THIS(); |
---|
411 | } |
---|
412 | HRESULT FinalConstruct() |
---|
413 | { |
---|
414 | return S_OK; |
---|
415 | } |
---|
416 | VOID FinalRelease() |
---|
417 | { |
---|
418 | if(m_pActiveObject) |
---|
419 | { |
---|
420 | m_pActiveObject->Remove(this); |
---|
421 | m_pActiveObject.Release(); |
---|
422 | } |
---|
423 | } |
---|
424 | CComPtr<IFilterGraph2> GetFilterGraph() const |
---|
425 | { |
---|
426 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
427 | return m_pFilterGraph; |
---|
428 | } |
---|
429 | BOOL IsFilterGraphAvailable() const |
---|
430 | { |
---|
431 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
432 | return m_pFilterGraph != NULL; |
---|
433 | } |
---|
434 | BOOL SetFilterGraph(IFilterGraph2* pFilterGraph) |
---|
435 | { |
---|
436 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
437 | if(m_pFilterGraph == pFilterGraph) |
---|
438 | return FALSE; |
---|
439 | if(m_pFilterGraph) |
---|
440 | _ATLTRY |
---|
441 | { |
---|
442 | _A(m_pActiveObject); |
---|
443 | if(m_pActiveObject) |
---|
444 | m_pActiveObject->Remove(this); |
---|
445 | } |
---|
446 | _ATLCATCHALL() |
---|
447 | { |
---|
448 | _Z_EXCEPTION(); |
---|
449 | } |
---|
450 | if(pFilterGraph) |
---|
451 | { |
---|
452 | m_pFilterGraph = pFilterGraph; |
---|
453 | _ATLTRY |
---|
454 | { |
---|
455 | if(!m_pActiveObject) |
---|
456 | m_pActiveObject = CActiveObject::GetInstance(); |
---|
457 | m_pActiveObject->Add(this); |
---|
458 | } |
---|
459 | _ATLCATCHALL() |
---|
460 | { |
---|
461 | _Z_EXCEPTION(); |
---|
462 | m_pFilterGraph.Release(); |
---|
463 | _ATLRETHROW; |
---|
464 | } |
---|
465 | } else |
---|
466 | m_pFilterGraph.Release(); |
---|
467 | m_nTime = CMsAccurateFileTime::GetTime(); |
---|
468 | return TRUE; |
---|
469 | } |
---|
470 | |
---|
471 | // IFilterGraphTableItem |
---|
472 | STDMETHOD(get_FilterGraph)(IUnknown** ppFilterGraphUnknown) |
---|
473 | { |
---|
474 | _Z4(atlTraceCOM, 4, _T("...\n")); |
---|
475 | _ATLTRY |
---|
476 | { |
---|
477 | __D(ppFilterGraphUnknown, E_POINTER); |
---|
478 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
479 | *ppFilterGraphUnknown = CComPtr<IFilterGraph2>(m_pFilterGraph).Detach(); |
---|
480 | } |
---|
481 | _ATLCATCH(Exception) |
---|
482 | { |
---|
483 | _C(Exception); |
---|
484 | } |
---|
485 | return S_OK; |
---|
486 | } |
---|
487 | STDMETHOD(put_FilterGraph)(IUnknown* pFilterGraphUnknown) |
---|
488 | { |
---|
489 | _Z4(atlTraceCOM, 4, _T("pFilterGraphUnknown 0x%p\n"), pFilterGraphUnknown); |
---|
490 | _ATLTRY |
---|
491 | { |
---|
492 | const CComQIPtr<IFilterGraph2> pFilterGraph = pFilterGraphUnknown; |
---|
493 | __D(pFilterGraph || !pFilterGraphUnknown, E_INVALIDARG); |
---|
494 | if(!SetFilterGraph(pFilterGraph)) |
---|
495 | return S_FALSE; |
---|
496 | } |
---|
497 | _ATLCATCH(Exception) |
---|
498 | { |
---|
499 | _C(Exception); |
---|
500 | } |
---|
501 | return S_OK; |
---|
502 | } |
---|
503 | STDMETHOD(get_Time)(DATE* pfTime) |
---|
504 | { |
---|
505 | _Z4(atlTraceCOM, 4, _T("...\n")); |
---|
506 | _ATLTRY |
---|
507 | { |
---|
508 | __D(pfTime, E_POINTER); |
---|
509 | DATE fTime = 0; |
---|
510 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
511 | if(m_nTime) |
---|
512 | { |
---|
513 | SYSTEMTIME Time; |
---|
514 | _W(FileTimeToSystemTime(&reinterpret_cast<const FILETIME&>(m_nTime), &Time)); |
---|
515 | _W(SystemTimeToVariantTime(&Time, &fTime)); |
---|
516 | } |
---|
517 | *pfTime = fTime; |
---|
518 | } |
---|
519 | _ATLCATCH(Exception) |
---|
520 | { |
---|
521 | _C(Exception); |
---|
522 | } |
---|
523 | return S_OK; |
---|
524 | } |
---|
525 | }; |
---|
526 | |
---|
527 | OBJECT_ENTRY_AUTO(__uuidof(FilterGraphTableItem), CFilterGraphTableItem) |
---|
528 | |
---|
529 | //////////////////////////////////////////////////////////// |
---|
530 | // CFilterGraphTable |
---|
531 | |
---|
532 | class ATL_NO_VTABLE CFilterGraphTable : |
---|
533 | public CComObjectRootEx<CComMultiThreadModelNoCS>, |
---|
534 | public CComCoClass<CFilterGraphTable, &__uuidof(FilterGraphTable)>, |
---|
535 | public IProvideClassInfo2Impl<&__uuidof(FilterGraphTable), &IID_NULL>, |
---|
536 | public IDispatchImpl<IFilterGraphTable>, |
---|
537 | public CFilterGraphTableBase |
---|
538 | { |
---|
539 | public: |
---|
540 | enum { IDR = IDR_FILTERGRAPHTABLE }; |
---|
541 | |
---|
542 | //DECLARE_REGISTRY_RESOURCEID(IDR) |
---|
543 | |
---|
544 | DECLARE_PROTECT_FINAL_CONSTRUCT() |
---|
545 | |
---|
546 | BEGIN_COM_MAP(CFilterGraphTable) |
---|
547 | COM_INTERFACE_ENTRY(IFilterGraphTable) |
---|
548 | COM_INTERFACE_ENTRY(IDispatch) |
---|
549 | COM_INTERFACE_ENTRY(IProvideClassInfo2) |
---|
550 | COM_INTERFACE_ENTRY(IProvideClassInfo) |
---|
551 | END_COM_MAP() |
---|
552 | |
---|
553 | public: |
---|
554 | |
---|
555 | //////////////////////////////////////////////////////// |
---|
556 | // CItem |
---|
557 | |
---|
558 | class CItem |
---|
559 | { |
---|
560 | public: |
---|
561 | DWORD m_nProcessIdentifier; |
---|
562 | UINT64 m_nInstance; |
---|
563 | ULONGLONG m_nTime; |
---|
564 | CComPtr<IFilterGraph2> m_pFilterGraph; |
---|
565 | |
---|
566 | public: |
---|
567 | // CItem |
---|
568 | CComVariantArray GetAsVariant() const |
---|
569 | { |
---|
570 | SYSTEMTIME Time; |
---|
571 | _W(FileTimeToSystemTime(&reinterpret_cast<const FILETIME&>(m_nTime), &Time)); |
---|
572 | DATE fTime; |
---|
573 | _W(SystemTimeToVariantTime(&Time, &fTime)); |
---|
574 | CComVariantArray vValue; |
---|
575 | vValue.FromElements(4, |
---|
576 | CComVariant((LONG) m_nProcessIdentifier), |
---|
577 | CComVariant((LONGLONG) m_nInstance), |
---|
578 | CComVariant((IUnknown*) m_pFilterGraph), |
---|
579 | CComVariant(fTime, VT_DATE), |
---|
580 | 0); |
---|
581 | return vValue; |
---|
582 | } |
---|
583 | }; |
---|
584 | |
---|
585 | //////////////////////////////////////////////////////// |
---|
586 | // CItemArray |
---|
587 | |
---|
588 | class CItemArray : |
---|
589 | public CRoArrayT<CItem> |
---|
590 | { |
---|
591 | public: |
---|
592 | // CItemArray |
---|
593 | }; |
---|
594 | |
---|
595 | private: |
---|
596 | mutable CRoCriticalSection m_DataCriticalSection; |
---|
597 | CItemArray m_ItemArray; |
---|
598 | |
---|
599 | public: |
---|
600 | // CFilterGraphTable |
---|
601 | static HRESULT WINAPI UpdateRegistry(BOOL bRegister) |
---|
602 | { |
---|
603 | _Z2(atlTraceRegistrar, 2, _T("bRegister %d\n"), bRegister); |
---|
604 | _ATLTRY |
---|
605 | { |
---|
606 | UpdateRegistryFromResource<CFilterGraphTable>(bRegister); |
---|
607 | } |
---|
608 | _ATLCATCH(Exception) |
---|
609 | { |
---|
610 | _C(Exception); |
---|
611 | } |
---|
612 | return S_OK; |
---|
613 | } |
---|
614 | CFilterGraphTable() |
---|
615 | { |
---|
616 | _Z4_THIS(); |
---|
617 | } |
---|
618 | ~CFilterGraphTable() |
---|
619 | { |
---|
620 | _Z4_THIS(); |
---|
621 | } |
---|
622 | HRESULT FinalConstruct() |
---|
623 | { |
---|
624 | _ATLTRY |
---|
625 | { |
---|
626 | Initialize(); |
---|
627 | } |
---|
628 | _ATLCATCH(Exception) |
---|
629 | { |
---|
630 | _C(Exception); |
---|
631 | } |
---|
632 | return S_OK; |
---|
633 | } |
---|
634 | VOID FinalRelease() |
---|
635 | { |
---|
636 | } |
---|
637 | VOID Initialize() |
---|
638 | { |
---|
639 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
640 | _ATLTRY |
---|
641 | { |
---|
642 | CActiveObjectFileMapping FileMapping; |
---|
643 | if(FileMapping.Open()) |
---|
644 | { |
---|
645 | CRoArrayT<CLSID> ClassIdentifierArray; |
---|
646 | HEADER* pHeader = FileMapping; |
---|
647 | pHeader->Lock(); |
---|
648 | _ATLTRY |
---|
649 | { |
---|
650 | ClassIdentifierArray.SetCount(0, (INT) pHeader->nItemCount); |
---|
651 | for(UINT32 nItemIndex = 0; nItemIndex < pHeader->nItemCount; nItemIndex++) |
---|
652 | { |
---|
653 | const ITEM& Item = pHeader->pItems[nItemIndex]; |
---|
654 | if(Item.nFlags & ITEMFLAG_ACTIVE) |
---|
655 | ClassIdentifierArray.Add(Item.ActiveObjectClassIdentifier); |
---|
656 | } |
---|
657 | } |
---|
658 | _ATLCATCHALL() |
---|
659 | { |
---|
660 | pHeader->Unlock(); |
---|
661 | _ATLRETHROW; |
---|
662 | } |
---|
663 | pHeader->Unlock(); |
---|
664 | for(auto&& ClassIdentifier: ClassIdentifierArray) |
---|
665 | { |
---|
666 | CComPtr<IUnknown> pUnknown; |
---|
667 | const HRESULT nResult = GetActiveObject(ClassIdentifier, NULL, &pUnknown); |
---|
668 | if(FAILED(nResult)) |
---|
669 | continue; |
---|
670 | _A(pUnknown); |
---|
671 | _ATLTRY |
---|
672 | { |
---|
673 | const CComQIPtr<IFilterGraphTableActiveObject> pFilterGraphTableActiveObject = pUnknown; |
---|
674 | __D(pFilterGraphTableActiveObject, E_NOINTERFACE); |
---|
675 | LONG nProcessIdentifier; |
---|
676 | CComVariantArray vFilterGraphs; |
---|
677 | __C(pFilterGraphTableActiveObject->GetFilterGraphs(&nProcessIdentifier, &vFilterGraphs)); |
---|
678 | _Z4(atlTraceGeneral, 4, _T("nProcessIdentifier %d, vFilterGraphs.vt 0x%X\n"), nProcessIdentifier, vFilterGraphs.vt); |
---|
679 | if(vFilterGraphs.vt > VT_NULL) |
---|
680 | { |
---|
681 | CRoArrayT<CComVariantArray> Array; |
---|
682 | vFilterGraphs.ToElementArray(Array); |
---|
683 | for(auto&& Item: Array) |
---|
684 | { |
---|
685 | CRoArrayT<CComVariantArray> Array; |
---|
686 | Item.ToElementArray(Array); |
---|
687 | __D(Array.GetCount() >= 4, E_UNNAMED); |
---|
688 | CItem Item; |
---|
689 | Item.m_nProcessIdentifier = (DWORD) Array[0].GetAsType(VT_I4).lVal; |
---|
690 | Item.m_nInstance = (UINT64) Array[1].GetAsType(VT_I8).llVal; |
---|
691 | const DATE fTime = Array[3].GetAsType(VT_DATE).date; |
---|
692 | _A(fTime > 0); |
---|
693 | SYSTEMTIME Time; |
---|
694 | _W(VariantTimeToSystemTime(fTime, &Time)); |
---|
695 | _W(SystemTimeToFileTime(&Time, &reinterpret_cast<FILETIME&>(Item.m_nTime))); |
---|
696 | Item.m_pFilterGraph = CComQIPtr<IFilterGraph2>(Array[2].GetAsType(VT_UNKNOWN).punkVal); |
---|
697 | m_ItemArray.Add(Item); |
---|
698 | } |
---|
699 | } |
---|
700 | } |
---|
701 | _ATLCATCHALL() |
---|
702 | { |
---|
703 | _Z_EXCEPTION(); |
---|
704 | } |
---|
705 | } |
---|
706 | } |
---|
707 | } |
---|
708 | _ATLCATCHALL() |
---|
709 | { |
---|
710 | _Z_EXCEPTION(); |
---|
711 | } |
---|
712 | } |
---|
713 | SIZE_T GetItems(CItemArray& ItemArray) const |
---|
714 | { |
---|
715 | _A(ItemArray.IsEmpty()); |
---|
716 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
717 | ItemArray.Append(m_ItemArray); |
---|
718 | return ItemArray.GetCount(); |
---|
719 | } |
---|
720 | |
---|
721 | // IFilterGraphTable |
---|
722 | STDMETHOD(get__NewEnum)(IUnknown** ppEnum) |
---|
723 | { |
---|
724 | _Z4(atlTraceCOM, 4, _T("...\n")); |
---|
725 | _ATLTRY |
---|
726 | { |
---|
727 | __D(ppEnum, E_POINTER); |
---|
728 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
729 | CRoArrayT<CComVariant> VariantArray; |
---|
730 | VariantArray.SetCount(0, (INT) m_ItemArray.GetCount()); |
---|
731 | for(auto&& Item: m_ItemArray) |
---|
732 | VariantArray.Add(Item.GetAsVariant()); |
---|
733 | typedef CComEnum<IEnumVARIANT, &__uuidof(IEnumVARIANT), VARIANT, _Copy<VARIANT> > CEnumVariant; |
---|
734 | CObjectPtr<CEnumVariant> pEnumVariant; |
---|
735 | __C(pEnumVariant.Construct()->Init(VariantArray.GetData(), VariantArray.GetData() + VariantArray.GetCount(), (IFilterGraphTable*) this, AtlFlagCopy)); |
---|
736 | *ppEnum = pEnumVariant.Detach(); |
---|
737 | } |
---|
738 | _ATLCATCH(Exception) |
---|
739 | { |
---|
740 | _C(Exception); |
---|
741 | } |
---|
742 | return S_OK; |
---|
743 | } |
---|
744 | STDMETHOD(get_Item)(VARIANT vIndex, VARIANT* pvItem) |
---|
745 | { |
---|
746 | _Z4(atlTraceCOM, 4, _T("vIndex.vt 0x%x, .lVal %d\n"), vIndex.vt, vIndex.lVal); |
---|
747 | _ATLTRY |
---|
748 | { |
---|
749 | __D(pvItem, E_POINTER); |
---|
750 | VariantInit(pvItem); |
---|
751 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
752 | CComVariant vLongIndex; |
---|
753 | __C(vLongIndex.ChangeType(VT_I4, &vIndex)); |
---|
754 | __D((SIZE_T) vLongIndex.lVal < m_ItemArray.GetCount(), E_INVALIDARG); |
---|
755 | _V(m_ItemArray[(SIZE_T) vLongIndex.lVal].GetAsVariant().Detach(pvItem)); |
---|
756 | } |
---|
757 | _ATLCATCH(Exception) |
---|
758 | { |
---|
759 | _C(Exception); |
---|
760 | } |
---|
761 | return S_OK; |
---|
762 | } |
---|
763 | STDMETHOD(get_Count)(LONG* pnCount) |
---|
764 | { |
---|
765 | _Z4(atlTraceCOM, 4, _T("...\n")); |
---|
766 | _ATLTRY |
---|
767 | { |
---|
768 | __D(pnCount, E_POINTER); |
---|
769 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
770 | *pnCount = (LONG) m_ItemArray.GetCount(); |
---|
771 | } |
---|
772 | _ATLCATCH(Exception) |
---|
773 | { |
---|
774 | _C(Exception); |
---|
775 | } |
---|
776 | return S_OK; |
---|
777 | } |
---|
778 | }; |
---|
779 | |
---|
780 | OBJECT_ENTRY_AUTO(__uuidof(FilterGraphTable), CFilterGraphTable) |
---|
781 | |
---|
782 | #endif // NTDDI_VERSION |
---|