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