source: trunk/DirectShowSpy/FilterGraphTable.h @ 795

Last change on this file since 795 was 545, checked in by roman, 8 years ago

Added previously not included hooks; added IFilterMapper3 hook suppors; template library related updates; added FGT to replace ROT (to access services in particular) - work in progress; fixed class enumeration hook

File size: 20.3 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
24class CFilterGraphTableBase
25{
26public:
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
343public:
344// CFilterGraphTableBase
345};
346
347__declspec(selectany) CFilterGraphTableBase::CActiveObject* CFilterGraphTableBase::CActiveObject::g_pInstance = NULL;
348
349////////////////////////////////////////////////////////////
350// CFilterGraphTableItem
351
352class 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{
359public:
360        enum { IDR = IDR_FILTERGRAPHTABLEITEM };
361
362//DECLARE_REGISTRY_RESOURCEID(IDR)
363
364DECLARE_PROTECT_FINAL_CONSTRUCT()
365
366BEGIN_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)
372END_COM_MAP()
373
374public:
375
376private:
377        mutable CRoCriticalSection m_DataCriticalSection;
378        CComPtr<IFilterGraph2> m_pFilterGraph;
379        CObjectPtr<CActiveObject> m_pActiveObject;
380        ULONGLONG m_nTime;
381
382public:
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
521OBJECT_ENTRY_AUTO(__uuidof(FilterGraphTableItem), CFilterGraphTableItem)
522
523////////////////////////////////////////////////////////////
524// CFilterGraphTable
525
526class 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{
533public:
534        enum { IDR = IDR_FILTERGRAPHTABLE };
535
536//DECLARE_REGISTRY_RESOURCEID(IDR)
537
538DECLARE_PROTECT_FINAL_CONSTRUCT()
539
540BEGIN_COM_MAP(CFilterGraphTable)
541        COM_INTERFACE_ENTRY(IFilterGraphTable)
542        COM_INTERFACE_ENTRY(IDispatch)
543        COM_INTERFACE_ENTRY(IProvideClassInfo2)
544        COM_INTERFACE_ENTRY(IProvideClassInfo)
545END_COM_MAP()
546
547public:
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
589private:
590        mutable CRoCriticalSection m_DataCriticalSection;
591        CItemArray m_ItemArray;
592
593public:
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
774OBJECT_ENTRY_AUTO(__uuidof(FilterGraphTable), CFilterGraphTable)
Note: See TracBrowser for help on using the repository browser.