source: trunk/DirectShowSpy/FilterGraphTable.h @ 937

Last change on this file since 937 was 831, checked in by roman, 4 years ago

Upgrade to VS2017; removed exception filter (hook); improved tracing

File size: 20.4 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2008-2015
3// Created by Roman Ryltsov roman@alax.info, http://alax.info
4//
5// This source code is published to complement DirectShowSpy developer powertoy
6// and demonstrate the internal use of APIs and tricks powering the tool. It is
7// allowed to freely re-use the portions of the code in other projects, commercial
8// or otherwise (provided that you don’t pretend that you wrote the original tool).
9//
10// Please keep in mind that DirectShowSpy is a developer tool, it is strongly recommended
11// that it is not shipped with release grade software. It is allowed to distribute
12// DirectShowSpy if only it is not registered with Windows by default and either
13// used privately, or registered on specific throubleshooting request. The advice applies
14// to hooking methods used by DirectShowSpy in general as well.
15
16#pragma once
17
18#include "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
30class CFilterGraphTableBase
31{
32public:
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
349public:
350// CFilterGraphTableBase
351};
352
353__declspec(selectany) CFilterGraphTableBase::CActiveObject* CFilterGraphTableBase::CActiveObject::g_pInstance = NULL;
354
355////////////////////////////////////////////////////////////
356// CFilterGraphTableItem
357
358class 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{
365public:
366        enum { IDR = IDR_FILTERGRAPHTABLEITEM };
367
368//DECLARE_REGISTRY_RESOURCEID(IDR)
369
370DECLARE_PROTECT_FINAL_CONSTRUCT()
371
372BEGIN_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)
378END_COM_MAP()
379
380public:
381
382private:
383        mutable CRoCriticalSection m_DataCriticalSection;
384        CComPtr<IFilterGraph2> m_pFilterGraph;
385        CObjectPtr<CActiveObject> m_pActiveObject;
386        ULONGLONG m_nTime;
387
388public:
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
527OBJECT_ENTRY_AUTO(__uuidof(FilterGraphTableItem), CFilterGraphTableItem)
528
529////////////////////////////////////////////////////////////
530// CFilterGraphTable
531
532class 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{
539public:
540        enum { IDR = IDR_FILTERGRAPHTABLE };
541
542//DECLARE_REGISTRY_RESOURCEID(IDR)
543
544DECLARE_PROTECT_FINAL_CONSTRUCT()
545
546BEGIN_COM_MAP(CFilterGraphTable)
547        COM_INTERFACE_ENTRY(IFilterGraphTable)
548        COM_INTERFACE_ENTRY(IDispatch)
549        COM_INTERFACE_ENTRY(IProvideClassInfo2)
550        COM_INTERFACE_ENTRY(IProvideClassInfo)
551END_COM_MAP()
552
553public:
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
595private:
596        mutable CRoCriticalSection m_DataCriticalSection;
597        CItemArray m_ItemArray;
598
599public:
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
780OBJECT_ENTRY_AUTO(__uuidof(FilterGraphTable), CFilterGraphTable)
781
782#endif // NTDDI_VERSION
Note: See TracBrowser for help on using the repository browser.