source: trunk/DirectShowSpy/SystemDeviceEnumeratorSpy.h @ 937

Last change on this file since 937 was 627, checked in by roman, 6 years ago

Fixed problem with early unload on devenum.dll (64-bit?) when SystemDeviceEnumerator? is released before monikers

  • Property svn:keywords set to Id
File size: 25.2 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 <mmdeviceapi.h>
19#include "rodshow.h"
20#include "romf.h"
21#include "Module_i.h"
22#include "Common.h"
23
24////////////////////////////////////////////////////////////
25// CSystemDeviceEnumeratorSpyT
26
27// NOTE: Original CLSID_SystemDeviceEnum does not support aggregation
28
29template <typename T, const CLSID* t_pSystemDeviceEnumeratorClassIdentifier>
30class ATL_NO_VTABLE CSystemDeviceEnumeratorSpyT :
31        public CComObjectRootEx<CComMultiThreadModel>,
32        //public CComCoClass<CSystemDeviceEnumeratorSpyT, &CLSID_SystemDeviceEnumeratorSpy>,
33        public CTransparentCoClassT<T, t_pSystemDeviceEnumeratorClassIdentifier>,
34        public IDispatchImpl<ISystemDeviceEnumeratorSpy>,
35        public ICreateDevEnum,
36        public IMMDeviceActivator
37{
38        typedef CSystemDeviceEnumeratorSpyT<T, t_pSystemDeviceEnumeratorClassIdentifier> CSystemDeviceEnumeratorSpy;
39
40public:
41        //enum { IDR = IDR_SYSTEMDEVICEENUMERATORSPY };
42
43//DECLARE_REGISTRY_RESOURCEID(IDR)
44
45DECLARE_PROTECT_FINAL_CONSTRUCT()
46
47DECLARE_GET_CONTROLLING_UNKNOWN()
48
49DECLARE_QI_TRACE(CSystemDeviceEnumeratorSpyT)
50
51BEGIN_COM_MAP(CSystemDeviceEnumeratorSpyT)
52        COM_INTERFACE_ENTRY(ISystemDeviceEnumeratorSpy)
53        COM_INTERFACE_ENTRY(ICreateDevEnum)
54        COM_INTERFACE_ENTRY(IMMDeviceActivator)
55        COM_INTERFACE_ENTRY_FUNC(CLSID_SystemDeviceEnum, 0, QuerySystemDeviceEnumInterface)
56        COM_INTERFACE_ENTRY_AGGREGATE_BLIND(m_pSystemDeviceEnum.p)
57        //COM_INTERFACE_ENTRY(IDispatch)
58END_COM_MAP()
59
60public:
61
62        ////////////////////////////////////////////////////////
63        // CPropertyBag
64
65        class ATL_NO_VTABLE CPropertyBag :
66                public CComObjectRootEx<CComMultiThreadModelNoCS>,
67                public IPropertyBag,
68                public IPropertyBag2
69        {
70        public:
71
72        DECLARE_QI_TRACE(CPropertyBag)
73
74        BEGIN_COM_MAP(CPropertyBag)
75                COM_INTERFACE_ENTRY(IPropertyBag2)
76                COM_INTERFACE_ENTRY(IPropertyBag)
77        END_COM_MAP()
78
79        private:
80                CComPtr<IPropertyBag> m_pPropertyBag;
81                CComPtr<IPropertyBag2> m_pPropertyBag2;
82
83        public:
84        // CPropertyBag
85                CPropertyBag()
86                {
87                        _Z4_THIS();
88                }
89                ~CPropertyBag()
90                {
91                        _Z4_THIS();
92                }
93                VOID Initialize(IPropertyBag* pPropertyBag)
94                {
95                        _A(pPropertyBag);
96                        _A(!m_pPropertyBag);
97                        m_pPropertyBag = pPropertyBag;
98                        m_pPropertyBag2 = CComQIPtr<IPropertyBag2>(pPropertyBag);
99                }
100
101        // IPropertyBag
102                STDMETHOD(Read)(LPCOLESTR pszPropertyName, VARIANT* pvValue, IErrorLog* pErrorLog) override
103                {
104                        _Z4(atlTraceCOM, 4, _T("pszPropertyName %s\n"), CString(pszPropertyName));
105                        _ATLTRY
106                        {
107                                HRESULT nResult = m_pPropertyBag->Read(pszPropertyName, pvValue, pErrorLog);
108                                #pragma region DevicePath Fix for Skype 6.0.0.126
109                                //if(nResult == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) && pszPropertyName && _wcsicmp(pszPropertyName, L"DevicePath") == 0 && pvValue)
110                                //{
111                                //      _Z4(atlTraceGeneral, 4, _T("nResult 0x%08X\n"), nResult);
112                                //      CComVariant vValue = L"\\\\?\\fake";
113                                //      _V(vValue.Detach(pvValue));
114                                //      nResult = S_OK;
115                                //}
116                                #pragma endregion
117                                if(SUCCEEDED(nResult))
118                                {
119                                        CString sValue = _T("???");
120                                        CComVariant vStringValue;
121                                        if(SUCCEEDED(vStringValue.ChangeType(VT_BSTR, pvValue)))
122                                                sValue = CString(vStringValue.bstrVal);
123                                        _Z4(atlTraceGeneral, 4, _T("nResult 0x%08X, pvValue->vt 0x%X, %s\n"), nResult, pvValue->vt, sValue);
124                                } else
125                                {
126                                        _Z4(atlTraceGeneral, 4, _T("nResult 0x%08X\n"), nResult);
127                                }
128                                return nResult;
129                        }
130                        _ATLCATCH(Exception)
131                        {
132                                _C(Exception);
133                        }
134                        return S_OK;
135                }
136                STDMETHOD(Write)(LPCOLESTR pszPropertyName, VARIANT* pvValue) override
137                {
138                        _Z4(atlTraceCOM, 4, _T("pszPropertyName %s, pvValue->vt 0x%X\n"), CString(pszPropertyName), pvValue->vt);
139                        _ATLTRY
140                        {
141                                const HRESULT nResult = m_pPropertyBag->Write(pszPropertyName, pvValue);
142                                _Z4(atlTraceGeneral, 4, _T("nResult 0x%08X\n"), nResult);
143                                return nResult;
144                        }
145                        _ATLCATCH(Exception)
146                        {
147                                _C(Exception);
148                        }
149                        return S_OK;
150                }
151
152        // IPropertyBag2
153                STDMETHOD(Read)(ULONG cProperties, PROPBAG2 *pPropBag, IErrorLog *pErrLog, VARIANT *pvarValue, HRESULT *phrError) override
154                {
155                        _Z4(atlTraceCOM, 4, _T("...\n"));
156                        _ATLTRY
157                        {
158                                const HRESULT nResult = m_pPropertyBag2->Read(cProperties, pPropBag, pErrLog, pvarValue, phrError);
159                                _Z4(atlTraceGeneral, 4, _T("nResult 0x%08X\n"), nResult);
160                                return nResult;
161                        }
162                        _ATLCATCH(Exception)
163                        {
164                                _C(Exception);
165                        }
166                        return S_OK;
167                }
168                STDMETHOD(Write)(ULONG cProperties, PROPBAG2 *pPropBag, VARIANT *pvarValue) override
169                {
170                        _Z4(atlTraceCOM, 4, _T("...\n"));
171                        _ATLTRY
172                        {
173                                const HRESULT nResult = m_pPropertyBag2->Write(cProperties, pPropBag, pvarValue);
174                                _Z4(atlTraceGeneral, 4, _T("nResult 0x%08X\n"), nResult);
175                                return nResult;
176                        }
177                        _ATLCATCH(Exception)
178                        {
179                                _C(Exception);
180                        }
181                        return S_OK;
182                }
183                STDMETHOD(CountProperties)(ULONG *pcProperties) override
184                {
185                        _Z4(atlTraceCOM, 4, _T("...\n"));
186                        _ATLTRY
187                        {
188                                const HRESULT nResult = m_pPropertyBag2->CountProperties(pcProperties);
189                                _Z4(atlTraceGeneral, 4, _T("nResult 0x%08X\n"), nResult);
190                                return nResult;
191                        }
192                        _ATLCATCH(Exception)
193                        {
194                                _C(Exception);
195                        }
196                        return S_OK;
197                }
198                STDMETHOD(GetPropertyInfo)(ULONG iProperty, ULONG cProperties, PROPBAG2* pPropBag, ULONG *pcProperties) override
199                {
200                        _Z4(atlTraceCOM, 4, _T("...\n"));
201                        _ATLTRY
202                        {
203                                const HRESULT nResult = m_pPropertyBag2->GetPropertyInfo(iProperty, cProperties, pPropBag, pcProperties);
204                                _Z4(atlTraceGeneral, 4, _T("nResult 0x%08X\n"), nResult);
205                                return nResult;
206                        }
207                        _ATLCATCH(Exception)
208                        {
209                                _C(Exception);
210                        }
211                        return S_OK;
212                }
213                STDMETHOD(LoadObject)(LPCOLESTR pstrName, DWORD dwHint, IUnknown *pUnkObject, IErrorLog *pErrLog) override
214                {
215                        _Z4(atlTraceCOM, 4, _T("...\n"));
216                        _ATLTRY
217                        {
218                                const HRESULT nResult = m_pPropertyBag2->LoadObject(pstrName, dwHint, pUnkObject, pErrLog);
219                                _Z4(atlTraceGeneral, 4, _T("nResult 0x%08X\n"), nResult);
220                                return nResult;
221                        }
222                        _ATLCATCH(Exception)
223                        {
224                                _C(Exception);
225                        }
226                        return S_OK;
227                }
228        };
229
230        ////////////////////////////////////////////////////////
231        // CMoniker
232
233        class ATL_NO_VTABLE CMoniker :
234                public CComObjectRootEx<CComMultiThreadModelNoCS>,
235                public IMoniker
236        {
237        public:
238
239        DECLARE_QI_TRACE(CMoniker)
240
241        BEGIN_COM_MAP(CMoniker)
242                COM_INTERFACE_ENTRY(IMoniker)
243                COM_INTERFACE_ENTRY(IPersistStream)
244                COM_INTERFACE_ENTRY(IPersist)
245        END_COM_MAP()
246
247        private:
248                CObjectPtr<T> m_pT;
249                CComPtr<IMoniker> m_pMoniker;
250
251        public:
252        // CMoniker
253                CMoniker()
254                {
255                        _Z4_THIS();
256                }
257                ~CMoniker()
258                {
259                        _Z4_THIS();
260                }
261                VOID Initialize(T* pT, IMoniker* pMoniker)
262                {
263                        _A(pT && pMoniker);
264                        _A(!m_pT && !m_pMoniker);
265                        m_pT = pT;
266                        m_pMoniker = pMoniker;
267                }
268
269        // IPersist
270                STDMETHOD(GetClassID)(CLSID* pClassIdentifier) override
271                {
272                        _Z4(atlTraceCOM, 4, _T("...\n"));
273                        return m_pMoniker->GetClassID(pClassIdentifier);
274                }
275
276    // IPersistStream
277                STDMETHOD(IsDirty)() override
278                {
279                        _Z4(atlTraceCOM, 4, _T("...\n"));
280                        return m_pMoniker->IsDirty();
281                }
282                STDMETHOD(Load)(IStream* pStream) override
283                {
284                        _Z4(atlTraceCOM, 4, _T("...\n"));
285                        return m_pMoniker->Load(pStream);
286                }
287                STDMETHOD(Save)(IStream* pStream, BOOL bClearDirty) override
288                {
289                        _Z4(atlTraceCOM, 4, _T("...\n"));
290                        return m_pMoniker->Save(pStream, bClearDirty);
291                }
292                STDMETHOD(GetSizeMax)(ULARGE_INTEGER* pnMaximalSize) override
293                {
294                        _Z4(atlTraceCOM, 4, _T("...\n"));
295                        return m_pMoniker->GetSizeMax(pnMaximalSize);
296                }
297
298        // IMoniker
299                STDMETHOD(BindToObject)(IBindCtx* pBindCtx, IMoniker* pLeftMoniker, REFIID InterfaceIdentifier, VOID** ppvObject) override
300                {
301                        _Z4(atlTraceCOM, 4, _T("pBindCtx 0x%p, pLeftMoniker 0x%p, InterfaceIdentifier %ls\n"), pBindCtx, pLeftMoniker, _PersistHelper::StringFromInterfaceIdentifier(InterfaceIdentifier));
302                        _ATLTRY
303                        {
304                                return m_pMoniker->BindToObject(pBindCtx, pLeftMoniker, InterfaceIdentifier, ppvObject);
305                        }
306                        _ATLCATCH(Exception)
307                        {
308                                _C(Exception);
309                        }
310                        return S_OK;
311                }
312                STDMETHOD(BindToStorage)(IBindCtx* pBindCtx, IMoniker* pLeftMoniker, REFIID InterfaceIdentifier, VOID** ppvObject) override
313                {
314                        _Z4(atlTraceCOM, 4, _T("pBindCtx 0x%p, pLeftMoniker 0x%p, InterfaceIdentifier %ls\n"), pBindCtx, pLeftMoniker, _PersistHelper::StringFromInterfaceIdentifier(InterfaceIdentifier));
315                        _ATLTRY
316                        {
317                                const HRESULT nResult = m_pMoniker->BindToStorage(pBindCtx, pLeftMoniker, InterfaceIdentifier, ppvObject);
318                                if(SUCCEEDED(nResult) && *ppvObject)
319                                {
320                                        if(InterfaceIdentifier == __uuidof(IPropertyBag) || InterfaceIdentifier == __uuidof(IPropertyBag2))
321                                        {
322                                                CComPtr<IPropertyBag>& pPropertyBag = reinterpret_cast<CComPtr<IPropertyBag>&>(*ppvObject);
323                                                CObjectPtr<CPropertyBag> pPropertyBagWrapper;
324                                                pPropertyBagWrapper.Construct()->Initialize(pPropertyBag);
325                                                pPropertyBag = pPropertyBagWrapper;
326                                        }
327                                }
328                                return nResult;
329                        }
330                        _ATLCATCH(Exception)
331                        {
332                                _C(Exception);
333                        }
334                        return S_OK;
335                }
336                STDMETHOD(Reduce)(IBindCtx* pBindCtx, DWORD nDepth, IMoniker** ppLeftMoniker, IMoniker** ppReducedMoniker) override
337                {
338                        _Z4(atlTraceCOM, 4, _T("...\n"));
339                        _ATLTRY
340                        {
341                                return m_pMoniker->Reduce(pBindCtx, nDepth, ppLeftMoniker, ppReducedMoniker);
342                        }
343                        _ATLCATCH(Exception)
344                        {
345                                _C(Exception);
346                        }
347                        return S_OK;
348                }
349                STDMETHOD(ComposeWith)(IMoniker* pRightMoniker, BOOL bOnlyIfNotGeneric, IMoniker** ppCompositeMoniker) override
350                {
351                        _Z4(atlTraceCOM, 4, _T("...\n"));
352                        _ATLTRY
353                        {
354                                return m_pMoniker->ComposeWith(pRightMoniker, bOnlyIfNotGeneric, ppCompositeMoniker);
355                        }
356                        _ATLCATCH(Exception)
357                        {
358                                _C(Exception);
359                        }
360                        return S_OK;
361                }
362                STDMETHOD(Enum)(BOOL bForward, IEnumMoniker** ppEnumMoniker) override
363                {
364                        _Z4(atlTraceCOM, 4, _T("bForward %d\n"), bForward);
365                        _ATLTRY
366                        {
367                                return m_pMoniker->Enum(bForward, ppEnumMoniker);
368                        }
369                        _ATLCATCH(Exception)
370                        {
371                                _C(Exception);
372                        }
373                        return S_OK;
374                }
375                STDMETHOD(IsEqual)(IMoniker* pMoniker) override
376                {
377                        _Z4(atlTraceCOM, 4, _T("...\n"));
378                        _ATLTRY
379                        {
380                                return m_pMoniker->IsEqual(pMoniker);
381                        }
382                        _ATLCATCH(Exception)
383                        {
384                                _C(Exception);
385                        }
386                        return S_OK;
387                }
388                STDMETHOD(Hash)(DWORD* pnHashValue) override
389                {
390                        _Z4(atlTraceCOM, 4, _T("...\n"));
391                        _ATLTRY
392                        {
393                                return m_pMoniker->Hash(pnHashValue);
394                        }
395                        _ATLCATCH(Exception)
396                        {
397                                _C(Exception);
398                        }
399                        return S_OK;
400                }
401                STDMETHOD(IsRunning)(IBindCtx* pBindCtx, IMoniker* pLeftMoniker, IMoniker* pNewlyRunning) override
402                {
403                        _Z4(atlTraceCOM, 4, _T("...\n"));
404                        _ATLTRY
405                        {
406                                return m_pMoniker->IsRunning(pBindCtx, pLeftMoniker, pNewlyRunning);
407                        }
408                        _ATLCATCH(Exception)
409                        {
410                                _C(Exception);
411                        }
412                        return S_OK;
413                }
414                STDMETHOD(GetTimeOfLastChange)(IBindCtx* pBindCtx, IMoniker* pLeftMoniker, FILETIME* pFileTime) override
415                {
416                        _Z4(atlTraceCOM, 4, _T("...\n"));
417                        _ATLTRY
418                        {
419                                return m_pMoniker->GetTimeOfLastChange(pBindCtx, pLeftMoniker, pFileTime);
420                        }
421                        _ATLCATCH(Exception)
422                        {
423                                _C(Exception);
424                        }
425                        return S_OK;
426                }
427                STDMETHOD(Inverse)(IMoniker** ppMoniker) override
428                {
429                        _Z4(atlTraceCOM, 4, _T("...\n"));
430                        _ATLTRY
431                        {
432                                return m_pMoniker->Inverse(ppMoniker);
433                        }
434                        _ATLCATCH(Exception)
435                        {
436                                _C(Exception);
437                        }
438                        return S_OK;
439                }
440                STDMETHOD(CommonPrefixWith)(IMoniker* pMoniker, IMoniker** ppPrefixMoniker) override
441                {
442                        _Z4(atlTraceCOM, 4, _T("...\n"));
443                        _ATLTRY
444                        {
445                                return m_pMoniker->CommonPrefixWith(pMoniker, ppPrefixMoniker);
446                        }
447                        _ATLCATCH(Exception)
448                        {
449                                _C(Exception);
450                        }
451                        return S_OK;
452                }
453                STDMETHOD(RelativePathTo)(IMoniker* pMoniker, IMoniker** ppRelativeMoniker) override
454                {
455                        _Z4(atlTraceCOM, 4, _T("...\n"));
456                        _ATLTRY
457                        {
458                                return m_pMoniker->RelativePathTo(pMoniker, ppRelativeMoniker);
459                        }
460                        _ATLCATCH(Exception)
461                        {
462                                _C(Exception);
463                        }
464                        return S_OK;
465                }
466                STDMETHOD(GetDisplayName)(IBindCtx* pBindCtx, IMoniker* pLeftMoniker, LPOLESTR* ppszDisplayName) override
467                {
468                        _Z4(atlTraceCOM, 4, _T("pBindCtx 0x%p, pLeftMoniker 0x%p\n"), pBindCtx, pLeftMoniker);
469                        _ATLTRY
470                        {
471                                const HRESULT nResult = m_pMoniker->GetDisplayName(pBindCtx, pLeftMoniker, ppszDisplayName);
472                                if(SUCCEEDED(nResult))
473                                        _Z4(atlTraceGeneral, 4, _T("nResult 0x%08X, *ppszDisplayName %s\n"), nResult, CString(*ppszDisplayName));
474                                else
475                                        _Z4(atlTraceGeneral, 4, _T("nResult 0x%08X\n"), nResult);
476                                return nResult;
477                        }
478                        _ATLCATCH(Exception)
479                        {
480                                _C(Exception);
481                        }
482                        return S_OK;
483                }
484                STDMETHOD(ParseDisplayName)(IBindCtx* pBindCtx, IMoniker* pLeftMoniker, LPOLESTR pszDisplayName, ULONG* pnEatenLength, IMoniker** ppOutputMoniker) override
485                {
486                        _Z4(atlTraceCOM, 4, _T("pBindCtx 0x%p, pLeftMoniker 0x%p, pszDisplayName %s\n"), pBindCtx, pLeftMoniker, CString(pszDisplayName));
487                        _ATLTRY
488                        {
489                                return m_pMoniker->ParseDisplayName(pBindCtx, pLeftMoniker, pszDisplayName, pnEatenLength, ppOutputMoniker);
490                        }
491                        _ATLCATCH(Exception)
492                        {
493                                _C(Exception);
494                        }
495                        return S_OK;
496                }
497                STDMETHOD(IsSystemMoniker)(DWORD* pnSystemMonikerType) override
498                {
499                        _Z4(atlTraceCOM, 4, _T("...\n"));
500                        _ATLTRY
501                        {
502                                return m_pMoniker->IsSystemMoniker(pnSystemMonikerType);
503                        }
504                        _ATLCATCH(Exception)
505                        {
506                                _C(Exception);
507                        }
508                        return S_OK;
509                }
510        };
511
512        ////////////////////////////////////////////////////////
513        // CEnumMoniker
514
515        class ATL_NO_VTABLE CEnumMoniker :
516                public CComObjectRootEx<CComMultiThreadModelNoCS>,
517                public IEnumMoniker
518        {
519        public:
520
521        DECLARE_QI_TRACE(CEnumMoniker)
522
523        BEGIN_COM_MAP(CEnumMoniker)
524                COM_INTERFACE_ENTRY(IEnumMoniker)
525        END_COM_MAP()
526
527        private:
528                CObjectPtr<T> m_pT;
529                CComPtr<IEnumMoniker> m_pEnumMoniker;
530
531        public:
532        // CEnumMoniker
533                CEnumMoniker()
534                {
535                        _Z4_THIS();
536                }
537                ~CEnumMoniker()
538                {
539                        _Z4_THIS();
540                }
541                VOID Initialize(T* pT, IEnumMoniker* pEnumMoniker)
542                {
543                        _A(pT && pEnumMoniker);
544                        _A(!m_pT && !m_pEnumMoniker);
545                        // NOTE: T is references to make sure that m_hDevEnumModule is not unloaded too early (esp. after ~CSystemDeviceEnumeratorSpyT
546                        //       but before ~CEnumMoniker)
547                        m_pT = pT;
548                        m_pEnumMoniker = pEnumMoniker;
549                }
550
551        // IEnumMoniker
552                STDMETHOD(Next)(ULONG nElementCount, IMoniker** ppMoniker, ULONG* pnFetchElementCount) override
553                {
554                        _Z4(atlTraceCOM, 4, _T("this 0x%p, nElementCount %d\n"), this, nElementCount);
555                        _ATLTRY
556                        {
557                                const HRESULT nNextResult = m_pEnumMoniker->Next(nElementCount, ppMoniker, pnFetchElementCount);
558                                CRoArrayT<CString> Array;
559                                if(pnFetchElementCount)
560                                        Array.Add(AtlFormatString(_T("*pnFetchElementCount %d"), *pnFetchElementCount));
561                                _Z4(atlTraceGeneral, 4, _T("nNextResult 0x%08X, %s\n"), nNextResult, _StringHelper::Join(Array, _T(", ")));
562                                if(SUCCEEDED(nNextResult))
563                                {
564                                        ULONG nFetchedElementCount = nElementCount;
565                                        if(nNextResult != S_OK && pnFetchElementCount)
566                                                nFetchedElementCount = *pnFetchElementCount;
567                                        for(ULONG nIndex = 0; nIndex < nFetchedElementCount; nIndex++)
568                                        {
569                                                CComPtr<IMoniker>& pMoniker = reinterpret_cast<CComPtr<IMoniker>&>(ppMoniker[nIndex]);
570                                                if(!pMoniker)
571                                                        break;
572                                                CObjectPtr<CMoniker> pMonikerWrapper;
573                                                pMonikerWrapper.Construct()->Initialize(m_pT, pMoniker);
574                                                pMoniker = pMonikerWrapper;
575                                        }
576                                }
577                                return nNextResult;
578                        }
579                        _ATLCATCH(Exception)
580                        {
581                                _C(Exception);
582                        }
583                        return S_OK;
584                }
585                STDMETHOD(Skip)(ULONG nElementCount) override
586                {
587                        _Z4(atlTraceCOM, 4, _T("this 0x%p, nElementCount %d\n"), this, nElementCount);
588                        _ATLTRY
589                        {
590                                return m_pEnumMoniker->Skip(nElementCount);
591                        }
592                        _ATLCATCH(Exception)
593                        {
594                                _C(Exception);
595                        }
596                        return S_OK;
597                }
598                STDMETHOD(Reset)() override
599                {
600                        _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
601                        _ATLTRY
602                        {
603                                return m_pEnumMoniker->Reset();
604                        }
605                        _ATLCATCH(Exception)
606                        {
607                                _C(Exception);
608                        }
609                        return S_OK;
610                }
611                STDMETHOD(Clone)(IEnumMoniker** ppEnumMoniker) override
612                {
613                        _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
614                        _ATLTRY
615                        {
616                                __C(m_pEnumMoniker->Clone(ppEnumMoniker));
617                                CComPtr<IEnumMoniker>& pEnumMoniker = reinterpret_cast<CComPtr<IEnumMoniker>&>(*ppEnumMoniker);
618                                _A(pEnumMoniker);
619                                CObjectPtr<CEnumMoniker> pEnumMonikerWrapper;
620                                pEnumMonikerWrapper.Construct()->Initialize(m_pT, pEnumMoniker);
621                                pEnumMoniker = pEnumMonikerWrapper;
622                        }
623                        _ATLCATCH(Exception)
624                        {
625                                _C(Exception);
626                        }
627                        return S_OK;
628                }
629        };
630
631private:
632        HINSTANCE m_hDevEnumModule;
633        CComPtr<IUnknown> m_pSystemDeviceEnum;
634        CComPtr<ICreateDevEnum> m_pCreateDevEnum;
635        CComPtr<IMMDeviceActivator> m_pMmDeviceActivator;
636
637        HRESULT QuerySystemDeviceEnumInterface(REFIID InterfaceIdentifier, VOID** ppvObject)
638        {
639                _A(InterfaceIdentifier == CLSID_SystemDeviceEnum);
640                _A(ppvObject);
641                *ppvObject = CComPtr<IUnknown>(m_pSystemDeviceEnum).Detach();
642                return S_OK;
643        }
644        static HRESULT WINAPI QuerySystemDeviceEnumInterface(VOID* pvInstance, REFIID InterfaceIdentifier, VOID** ppvObject, DWORD_PTR)
645        {
646                return ((CSystemDeviceEnumeratorSpy*) pvInstance)->QuerySystemDeviceEnumInterface(InterfaceIdentifier, ppvObject);
647        }
648
649public:
650// CSystemDeviceEnumeratorSpyT
651        static LPCTSTR GetOriginalLibraryName()
652        {
653                return _T("devenum.dll");
654        }
655        static CString GetObjectFriendlyName()
656        {
657                return _StringHelper::GetLine(T::IDR, 2);
658        }
659        static HRESULT WINAPI UpdateRegistry(BOOL bRegister)
660        {
661                _Z2(atlTraceRegistrar, 2, _T("bRegister %d\n"), bRegister);
662                _ATLTRY
663                {
664                        TreatAsUpdateRegistryFromResource<T>(*t_pSystemDeviceEnumeratorClassIdentifier, bRegister);
665                }
666                _ATLCATCH(Exception)
667                {
668                        _C(Exception);
669                }
670                return S_OK;
671        }
672        CSystemDeviceEnumeratorSpyT() :
673                m_hDevEnumModule(NULL)
674        {
675                _Z4_THIS();
676        }
677        ~CSystemDeviceEnumeratorSpyT()
678        {
679                _Z4_THIS();
680        }
681        HRESULT FinalConstruct()
682        {
683                _ATLTRY
684                {
685                        TCHAR pszPath[MAX_PATH] = { 0 };
686                        _W(GetModuleFileName(NULL, pszPath, DIM(pszPath)));
687                        _Z4(atlTraceRefcount, 4, _T("pszPath \"%s\", this 0x%p, m_dwRef %d\n"), pszPath, this, m_dwRef);
688                        const HINSTANCE hModule = CoLoadLibrary(const_cast<LPOLESTR>((LPCOLESTR) CT2COLE(GetOriginalLibraryName())), TRUE);
689                        _ATLTRY
690                        {
691                                typedef HRESULT (WINAPI *DLLGETCLASSOBJECT)(REFCLSID, REFIID, VOID**);
692                                DLLGETCLASSOBJECT DllGetClassObject = (DLLGETCLASSOBJECT) GetProcAddress(hModule, "DllGetClassObject");
693                                __E(DllGetClassObject);
694                                CComPtr<IClassFactory> pClassFactory;
695                                __C(DllGetClassObject(*t_pSystemDeviceEnumeratorClassIdentifier, __uuidof(IClassFactory), (VOID**) &pClassFactory));
696                                _A(pClassFactory);
697                                CComPtr<IUnknown> pUnknown;
698                                __C(pClassFactory->CreateInstance(NULL, __uuidof(IUnknown), (VOID**) &pUnknown));
699                                __D(pUnknown, E_NOINTERFACE);
700                                CComPtr<IUnknown> pSystemDeviceEnum;
701                                __C(pUnknown->QueryInterface(CLSID_SystemDeviceEnum, (VOID**) &pSystemDeviceEnum));
702                                const CComQIPtr<ICreateDevEnum> pCreateDevEnum = pUnknown;
703                                const CComQIPtr<IMMDeviceActivator> pMmDeviceActivator = pUnknown;
704                                __D(pCreateDevEnum, E_NOINTERFACE);
705                                m_pSystemDeviceEnum = pSystemDeviceEnum;
706                                m_pCreateDevEnum = pCreateDevEnum;
707                                m_pMmDeviceActivator = pMmDeviceActivator;
708                        }
709                        _ATLCATCHALL()
710                        {
711                                CoFreeLibrary(hModule);
712                                _ATLRETHROW;
713                        }
714                        _A(!m_hDevEnumModule);
715                        m_hDevEnumModule = hModule;
716                }
717                _ATLCATCH(Exception)
718                {
719                        _C(Exception);
720                }
721                return S_OK;
722        }
723        VOID FinalRelease()
724        {
725                _Z5(atlTraceRefcount, 5, _T("m_dwRef 0x%X\n"), m_dwRef);
726                m_pSystemDeviceEnum.Release();
727                m_pCreateDevEnum.Release();
728                m_pMmDeviceActivator.Release();
729                if(m_hDevEnumModule)
730                {
731                        CoFreeLibrary(m_hDevEnumModule);
732                        m_hDevEnumModule = NULL;
733                }
734        }
735        static CString FormatDeviceCategory(const GUID& DeviceCategory)
736        {
737                static const struct 
738                { 
739                        const GUID* pIdentifier; 
740                        LPCSTR pszName; 
741                } g_pMap[] = 
742                {
743                        #define A(x) { &x, #x },
744                        A(CLSID_VideoInputDeviceCategory)
745                        A(CLSID_LegacyAmFilterCategory)
746                        A(CLSID_VideoCompressorCategory)
747                        A(CLSID_AudioCompressorCategory)
748                        A(CLSID_AudioInputDeviceCategory)
749                        A(CLSID_AudioRendererCategory)
750                        A(CLSID_MidiRendererCategory)
751                        A(CLSID_TransmitCategory)
752                        A(CLSID_DeviceControlCategory)
753                        A(CLSID_ActiveMovieCategories)
754                        A(CLSID_DVDHWDecodersCategory)
755                        A(CLSID_MediaEncoderCategory)
756                        A(CLSID_MediaMultiplexerCategory)
757                        #undef A
758                };
759                for(auto&& Item: g_pMap)
760                        if(*Item.pIdentifier == DeviceCategory)
761                                return CString(Item.pszName);
762                return CString(_PersistHelper::StringFromIdentifier(DeviceCategory));
763        }
764
765// ISystemDeviceEnumeratorSpy
766
767// ICreateDevEnum
768        STDMETHOD(CreateClassEnumerator)(REFCLSID DeviceCategory, IEnumMoniker** ppEnumMoniker, DWORD nFlags) override
769        {
770                _Z4(atlTraceCOM, 4, _T("this 0x%p, DeviceCategory %s, nFlags 0x%X\n"), this, FormatDeviceCategory(DeviceCategory), nFlags);
771                _ATLTRY
772                {
773                        const HRESULT nCreateClassEnumeratorResult = m_pCreateDevEnum->CreateClassEnumerator(DeviceCategory, ppEnumMoniker, nFlags);
774                        __C(nCreateClassEnumeratorResult);
775                        _D(nCreateClassEnumeratorResult == S_OK, nCreateClassEnumeratorResult);
776                        CComPtr<IEnumMoniker>& pEnumMoniker = reinterpret_cast<CComPtr<IEnumMoniker>&>(*ppEnumMoniker);
777                        if(pEnumMoniker)
778                        {
779                                #pragma region Trace Moniker
780                                __C(pEnumMoniker->Reset());
781                                for(; ; )
782                                {
783                                        CComPtr<IMoniker> pMoniker;
784                                        ULONG nElementCount;
785                                        if(pEnumMoniker->Next(1, &pMoniker, &nElementCount) != S_OK)
786                                                break;
787                                        _Z4(atlTraceGeneral, 4, _T("pMoniker %ls\n"), _FilterGraphHelper::GetMonikerDisplayName(pMoniker));
788                                        CComPtr<IBindCtx> pBindCtx;
789                                        __C(CreateBindCtx(0, &pBindCtx));
790                                        CComPtr<IPropertyBag> pPropertyBag;
791                                        __C(pMoniker->BindToStorage(pBindCtx, NULL, __uuidof(IPropertyBag), (VOID**) &pPropertyBag));
792                                        const CStringW sFriendlyName = _FilterGraphHelper::ReadPropertyBagString(pPropertyBag, OLESTR("FriendlyName"));
793                                        const CStringW sDescription = _FilterGraphHelper::ReadPropertyBagString(pPropertyBag, OLESTR("Description"));
794                                        const CStringW sDevicePath = _FilterGraphHelper::ReadPropertyBagString(pPropertyBag, OLESTR("DevicePath"));
795                                        _Z4(atlTraceCOM, 4, _T("sFriendlyName \"%ls\", sDescription \"%ls\", sDevicePath \"%ls\"\n"), sFriendlyName, sDescription, sDevicePath);
796                                }
797                                __C(pEnumMoniker->Reset());
798                                #pragma endregion
799                                CObjectPtr<CEnumMoniker> pEnumMonikerWrapper;
800                                pEnumMonikerWrapper.Construct()->Initialize(static_cast<T*>(this), pEnumMoniker);
801                                pEnumMoniker = pEnumMonikerWrapper;
802                        }
803                }
804                _ATLCATCH(Exception)
805                {
806                        _C(Exception);
807                }
808                return S_OK;
809        }
810
811// IMMDeviceActivator
812    STDMETHOD(Activate)(REFIID InterfaceIdentifier, IMMDevice* pMmDevice, PROPVARIANT* pvActivationParameters, VOID** ppObject) override
813        {
814                _Z4(atlTraceCOM, 4, _T("this 0x%p, InterfaceIdentifier %s, pMmDevice 0x%p\n"), this, _FilterGraphHelper::StringFromIdentifier(InterfaceIdentifier), pMmDevice);
815                _ATLTRY
816                {
817                        if(pvActivationParameters)
818                                _Z4(atlTraceCOM, 4, _T("*pvActivationParameters %s\n"), reinterpret_cast<MF::CPropVariant&>(*pvActivationParameters).Format());
819                        __D(m_pMmDeviceActivator, E_NOINTERFACE);
820                        const HRESULT nActivateResult = m_pMmDeviceActivator->Activate(InterfaceIdentifier, pMmDevice, pvActivationParameters, ppObject);
821                        _Z4_DSHRESULT(nActivateResult);
822                        return nActivateResult;
823                }
824                _ATLCATCH(Exception)
825                {
826                        _C(Exception);
827                }
828                return S_OK;
829        }
830};
831
832////////////////////////////////////////////////////////////
833// CSystemDeviceEnumeratorSpy
834
835class ATL_NO_VTABLE CSystemDeviceEnumeratorSpy :
836        public CSystemDeviceEnumeratorSpyT<CSystemDeviceEnumeratorSpy, &CLSID_SystemDeviceEnum>,
837        public CComCoClass<CSystemDeviceEnumeratorSpy, &CLSID_SystemDeviceEnumeratorSpy>
838{
839public:
840        enum { IDR = IDR_SYSTEMDEVICEENUMERATORSPY };
841
842private:
843        static LPCTSTR g_pszClassName;
844
845public:
846        //typedef CBlackListAwareComCreatorT<CComObjectCached<CSystemDeviceEnumeratorSpy>, CSystemDeviceEnumeratorSpy, &g_pszClassName> _ClassFactoryCreatorClass; // DECLARE_CLASSFACTORY override
847        typedef CComCreator2<CBlackListAwareComCreatorT<CComObject<CSystemDeviceEnumeratorSpy>, CSystemDeviceEnumeratorSpy, &g_pszClassName>, CBlackListAwareComCreatorT<CComAggObject<CSystemDeviceEnumeratorSpy>, CSystemDeviceEnumeratorSpy, &g_pszClassName> > _CreatorClass; // DECLARE_AGGREGATABLE override
848
849public:
850// CSystemDeviceEnumeratorSpy
851};
852
853__declspec(selectany) LPCTSTR CSystemDeviceEnumeratorSpy::g_pszClassName = _T("CSystemDeviceEnumeratorSpy");
854
855OBJECT_ENTRY_AUTO(__uuidof(SystemDeviceEnumeratorSpy), CSystemDeviceEnumeratorSpy)
Note: See TracBrowser for help on using the repository browser.