source: trunk/DirectShowSpy/Common.h @ 937

Last change on this file since 937 was 641, checked in by roman, 5 years ago
  • Property svn:keywords set to Id
File size: 21.5 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#if defined(DIRECTSHOWSPY)
19        #include "AboutDialog.h"
20        namespace EmailTools
21        {
22                #include "Module_i.h"
23                #undef __Module_i_h__
24                #include "..\..\Repository-Private\Utilities\EmailTools\Module_i.h"
25                #include "..\..\Repository-Private\Utilities\EmailTools\Message.h"
26        }
27        using namespace EmailTools;
28        #define  BZ_NO_STDIO
29        #include "..\..\Repository-Private\Utilities\DeflateTools\Bzip2Item.h"
30#endif // defined(DIRECTSHOWSPY)
31
32////////////////////////////////////////////////////////////
33// CProcessTokenPrivileges
34
35class CProcessTokenPrivileges
36{
37public:
38        CAccessToken m_ProcessToken;
39        CTokenPrivileges m_OriginalProcessTokenPrivileges;
40        BOOL m_bTakeOwnershipPrivilegeEnabled;
41        BOOL m_bRestorePrivilegeEnabled;
42
43public:
44// CProcessTokenPrivileges
45        CProcessTokenPrivileges() :
46                m_bTakeOwnershipPrivilegeEnabled(FALSE),
47                m_bRestorePrivilegeEnabled(FALSE)
48        {
49        }
50        ~CProcessTokenPrivileges()
51        {
52                if(m_bTakeOwnershipPrivilegeEnabled)
53                {
54                        __E(m_ProcessToken.EnableDisablePrivileges(m_OriginalProcessTokenPrivileges));
55                        m_bRestorePrivilegeEnabled = FALSE;
56                        m_bTakeOwnershipPrivilegeEnabled = FALSE;
57                }
58        }
59        VOID Adjust()
60        {
61                _A(!m_ProcessToken.GetHandle());
62                // NOTE: Enable SE_TAKE_OWNERSHIP_NAME and SE_RESTORE_NAME privileges in order to be able to access registry key permissions
63                __E(m_ProcessToken.GetProcessToken(TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES));
64                __E(m_ProcessToken.EnablePrivilege(SE_TAKE_OWNERSHIP_NAME, &m_OriginalProcessTokenPrivileges));
65                m_bTakeOwnershipPrivilegeEnabled = TRUE;
66                __E(m_ProcessToken.EnablePrivilege(SE_RESTORE_NAME));
67                m_bRestorePrivilegeEnabled = TRUE;
68        }
69        BOOL IsTakeOwnershipPrivilegeEnabled() const
70        {
71                return m_bTakeOwnershipPrivilegeEnabled;
72        }
73        BOOL IsRestorePrivilegeEnabled() const
74        {
75                return m_bRestorePrivilegeEnabled;
76        }
77};
78
79////////////////////////////////////////////////////////////
80// CClassIdentifierRegKeySecurity
81
82class CClassIdentifierRegKeySecurity
83{
84public:
85        CLSID m_ClassIdentifier;
86        CRegKey m_Key;
87        CSecurityDesc m_OriginalSecurityDescriptor;
88
89public:
90// CClassIdentifierRegKeySecurity
91        static VOID GetRegKeySecurityDescriptor(CRegKey& Key, SECURITY_INFORMATION SecurityInformation, CSecurityDesc& SecurityDescriptor)
92        {
93                DWORD nSecurityDescriptorSize = 0;
94                Key.GetKeySecurity(SecurityInformation, NULL, &nSecurityDescriptorSize);
95                CTempBuffer<SECURITY_DESCRIPTOR> pSecurityDescriptor;
96                _W(pSecurityDescriptor.AllocateBytes(nSecurityDescriptorSize));
97                __C(HRESULT_FROM_WIN32(Key.GetKeySecurity(SecurityInformation, pSecurityDescriptor, &nSecurityDescriptorSize)));
98                SecurityDescriptor = *pSecurityDescriptor;
99        }
100        static CString StringFromSecurityDescriptor(CSecurityDesc& SecurityDescriptor)
101        {
102                CString sSecurityDescriptorString;
103                __E(SecurityDescriptor.ToString(&sSecurityDescriptorString));
104                return sSecurityDescriptorString;
105        }
106        static CString StringFromRegKeySecurityDescriptor(CRegKey& Key, SECURITY_INFORMATION SecurityInformation)
107        {
108                CSecurityDesc SecurityDescriptor;
109                GetRegKeySecurityDescriptor(Key, SecurityInformation, SecurityDescriptor);
110                return StringFromSecurityDescriptor(SecurityDescriptor);
111        }
112        CClassIdentifierRegKeySecurity(const CLSID& ClassIdentifier) throw() :
113                m_ClassIdentifier(ClassIdentifier)
114        {
115        }
116        ~CClassIdentifierRegKeySecurity()
117        {
118                if(m_Key)
119                {
120                        // QUES: Would it be more reliable to leave ownership and revert DACL only in absence of Restore privilege?
121                        __C(HRESULT_FROM_WIN32(m_Key.SetKeySecurity(OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, const_cast<SECURITY_DESCRIPTOR*>((const SECURITY_DESCRIPTOR*) m_OriginalSecurityDescriptor))));
122                        _Z4(atlTraceGeneral, 4, _T("Owner & DACL: %s\n"), StringFromRegKeySecurityDescriptor(m_Key, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION));
123                        __C(HRESULT_FROM_WIN32(m_Key.Close()));
124                }
125        }
126        BOOL Adjust()
127        {
128                if(m_Key)
129                        return FALSE;
130                const CString sKeyName = AtlFormatString(_T("CLSID\\%ls"), _PersistHelper::StringFromIdentifier(m_ClassIdentifier));
131                __C(HRESULT_FROM_WIN32(m_Key.Open(HKEY_CLASSES_ROOT, sKeyName, READ_CONTROL | WRITE_OWNER)));
132                GetRegKeySecurityDescriptor(m_Key, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, m_OriginalSecurityDescriptor);
133                // NOTE:
134                //   Windows 5.1: CLSID {E436EBB2-524F-11CE-9F53-0020AF0BA770} Key Owner: O:AB (Administrators)
135                //   Windows 6.0: CLSID {E436EBB2-524F-11CE-9F53-0020AF0BA770} Key Owner: O:S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464 (TrustedInstaller)
136                _Z4(atlTraceGeneral, 4, _T("ClassIdentifier %ls, m_OriginalSecurityDescriptor %s\n"), _PersistHelper::StringFromIdentifier(m_ClassIdentifier), StringFromSecurityDescriptor(m_OriginalSecurityDescriptor));
137                // NOTE: Take ownership of the key to Administrators in order to be able to update key DACL
138                // QUES: Would it be more reliable to take ownership to self in absence of Restore privilege?
139                CSecurityDesc AdministratorsOwnerSecurityDescriptor;
140                AdministratorsOwnerSecurityDescriptor.SetOwner(Sids::Admins());
141                __C(HRESULT_FROM_WIN32(m_Key.SetKeySecurity(OWNER_SECURITY_INFORMATION, const_cast<SECURITY_DESCRIPTOR*>((const SECURITY_DESCRIPTOR*) AdministratorsOwnerSecurityDescriptor))));
142                _Z4(atlTraceGeneral, 4, _T("Owner: %s\n"), StringFromRegKeySecurityDescriptor(m_Key, OWNER_SECURITY_INFORMATION));
143                // NOTE: Reopen the key to obtain given privileges
144                __C(HRESULT_FROM_WIN32(m_Key.Close()));
145                __C(HRESULT_FROM_WIN32(m_Key.Open(HKEY_CLASSES_ROOT, sKeyName, READ_CONTROL | WRITE_DAC | WRITE_OWNER)));
146                // NOTE: Adjust key DACL in order to make the key writable
147                CSecurityDesc AccessListSecurityDescriptor = m_OriginalSecurityDescriptor;
148                CDacl AccessList;
149                __E(AccessListSecurityDescriptor.GetDacl(&AccessList));
150                _W(AccessList.AddAllowedAce(Sids::Admins(), GENERIC_ALL, CONTAINER_INHERIT_ACE));
151                AccessListSecurityDescriptor.SetDacl(AccessList);
152                __C(HRESULT_FROM_WIN32(m_Key.SetKeySecurity(DACL_SECURITY_INFORMATION, const_cast<SECURITY_DESCRIPTOR*>((const SECURITY_DESCRIPTOR*) AccessListSecurityDescriptor))));
153                _Z4(atlTraceGeneral, 4, _T("DACL: %s\n"), StringFromRegKeySecurityDescriptor(m_Key, DACL_SECURITY_INFORMATION));
154                return TRUE;
155        }
156};
157
158////////////////////////////////////////////////////////////
159// TreatAsUpdateRegistryFromResource
160
161template <typename T>
162inline VOID TreatAsUpdateRegistryFromResource(const CLSID& TreatAsClassIdentifier, BOOL bRegister)
163{
164        _Z2(atlTraceRegistrar, 2, _T("TreatAsClassIdentifier %ls, bRegister %d\n"), _PersistHelper::StringFromIdentifier(TreatAsClassIdentifier), bRegister);
165        // NOTE: Registration is more sophisticated starting Vista operating system
166        const BOOL bAdjustProcessTokenPrivileges = IsWindowsVistaOrGreater();
167        _Z4(atlTraceRegistrar, 4, _T("bAdjustProcessTokenPrivileges %d\n"), bAdjustProcessTokenPrivileges);
168        CProcessTokenPrivileges ProcessTokenPrivileges;
169        if(bAdjustProcessTokenPrivileges)
170                _ATLTRY
171                {
172                        ProcessTokenPrivileges.Adjust();
173                }
174                _ATLCATCHALL()
175                {
176                        _Z_EXCEPTION();
177                }
178        CLSID CurrentTreatAsClassIdentifier = CLSID_NULL;
179        const HRESULT nCoGetTreatAsClassResult = CoGetTreatAsClass(TreatAsClassIdentifier, &CurrentTreatAsClassIdentifier);
180        __C(nCoGetTreatAsClassResult);
181        _Z4(atlTraceRegistrar, 4, _T("bRegister %d, nCoGetTreatAsClassResult 0x%08X, CurrentTreatAsClassIdentifier %ls\n"), bRegister, nCoGetTreatAsClassResult, _PersistHelper::StringFromIdentifier(CurrentTreatAsClassIdentifier));
182        __D(!bRegister || nCoGetTreatAsClassResult != S_OK || CurrentTreatAsClassIdentifier == T::GetObjectCLSID(), E_UNNAMED);
183        CClassIdentifierRegKeySecurity ClassIdentifierRegKeySecurity(TreatAsClassIdentifier);
184        if(!bRegister && nCoGetTreatAsClassResult == S_OK)
185        {
186                if(bAdjustProcessTokenPrivileges)
187                        ClassIdentifierRegKeySecurity.Adjust();
188                __C(CoTreatAsClass(TreatAsClassIdentifier, CLSID_NULL));
189        }
190        _A(_pAtlModule);
191        UpdateRegistryFromResource<T>(bRegister);
192        if(bRegister)
193        {
194                if(bAdjustProcessTokenPrivileges)
195                        ClassIdentifierRegKeySecurity.Adjust();
196                #if _DEVELOPMENT
197                        const HRESULT nCoTreatAsClassResult = CoTreatAsClass(TreatAsClassIdentifier, T::GetObjectCLSID());
198                        _Z2(atlTraceRegistrar, SUCCEEDED(nCoTreatAsClassResult) ? 4 : 2, _T("nCoTreatAsClassResult 0x%08X\n"), nCoTreatAsClassResult);
199                        __C(nCoTreatAsClassResult);
200                        const HRESULT nCoGetTreatAsClassResult = CoGetTreatAsClass(TreatAsClassIdentifier, &CurrentTreatAsClassIdentifier);
201                        _Z4(atlTraceRegistrar, 4, _T("nCoGetTreatAsClassResult 0x%08X, CurrentTreatAsClassIdentifier %ls\n"), nCoGetTreatAsClassResult, _PersistHelper::StringFromIdentifier(CurrentTreatAsClassIdentifier));
202                        _A(CurrentTreatAsClassIdentifier == T::GetObjectCLSID());
203                #else
204                        __C(CoTreatAsClass(TreatAsClassIdentifier, T::GetObjectCLSID()));
205                #endif // _DEVELOPMENT
206        }
207}
208
209////////////////////////////////////////////////////////////
210// CBlackListAwareComCreatorT
211
212template <typename T, const CLSID* t_pClassIdentifier>
213class ATL_NO_VTABLE CTransparentCoClassT
214{
215public:
216// CTransparentCoClassT
217        static HINSTANCE CoLoadOriginalLibrary()
218        {
219                const HINSTANCE hModule = CoLoadLibrary(const_cast<LPOLESTR>((LPCOLESTR) CT2COLE(T::GetOriginalLibraryName())), TRUE);
220                __E(hModule);
221                return hModule;
222        }
223        static CComPtr<IUnknown> CoCreateOriginalInstance(HINSTANCE hModule, IUnknown* pControllingUnknown = NULL)
224        {
225                typedef HRESULT (WINAPI *DLLGETCLASSOBJECT)(REFCLSID, REFIID, VOID**);
226                DLLGETCLASSOBJECT DllGetClassObject = (DLLGETCLASSOBJECT) GetProcAddress(hModule, "DllGetClassObject");
227                __E(DllGetClassObject);
228                CComPtr<IClassFactory> pClassFactory;
229                __C(DllGetClassObject(*t_pClassIdentifier, __uuidof(IClassFactory), (VOID**) &pClassFactory));
230                _A(pClassFactory);
231                CComPtr<IUnknown> pUnknown;
232                __C(pClassFactory->CreateInstance(pControllingUnknown, __uuidof(IUnknown), (VOID**) &pUnknown));
233                return pUnknown;
234        }
235        static CComPtr<IUnknown> CoCreateOriginalInstance(IUnknown* pControllingUnknown = NULL)
236        {
237                CComPtr<IUnknown> pUnknown;
238                const HINSTANCE hModule = CoLoadOriginalLibrary();
239                _ATLTRY
240                {
241                        pUnknown = CoCreateOriginalInstance(hModule, pControllingUnknown);
242                }
243                _ATLCATCHALL()
244                {
245                        CoFreeLibrary(hModule);
246                        _ATLRETHROW;
247                }
248                CoFreeLibrary(hModule);
249                return pUnknown;
250        }
251};
252
253////////////////////////////////////////////////////////////
254// CBlackListAwareComCreatorT
255
256template <typename _ObjectClass, typename _Class, LPCTSTR* t_ppszName>
257class CBlackListAwareComCreatorT :
258        public CComCreator<_ObjectClass>
259{
260public:
261// CBlackListAwareComCreatorT
262        static HRESULT WINAPI CreateInstance(VOID* pvControllingUnknown, REFIID InterfaceIdentifier, VOID** ppvObject) throw()
263        {
264                _A(ppvObject);
265                *ppvObject = NULL;
266                #pragma region Check Black List
267                static INT g_nBlackListed = 0; // 0 Unknown, 1 No, 2 Yes
268                {
269                        _A(_pAtlModule);
270                        CComCritSecLock<CComCriticalSection> Lock(_pAtlModule->m_csStaticDataInitAndTypeInfo);
271                        if(!g_nBlackListed)
272                        {
273                                TCHAR pszPath[MAX_PATH] = { 0 };
274                                _W(GetModuleFileName(NULL, pszPath, DIM(pszPath)));
275                                LPTSTR pszFileName = FindFileName(pszPath);
276                                _A(pszFileName);
277                                RemoveExtension(pszFileName);
278                                const CString sBlackList = _RegKeyHelper::QueryStringValue(HKEY_LOCAL_MACHINE, REGISTRY_ROOT, AtlFormatString(_T("%s Black List"), *t_ppszName));
279                                CRoArrayT<CString> BlackListArray;
280                                _StringHelper::GetCommaSeparatedItems(sBlackList, BlackListArray);
281                                BOOL bFound = FALSE;
282                                for(SIZE_T nIndex = 0; nIndex < BlackListArray.GetCount(); nIndex++)
283                                {
284                                        CPath sFileName = (LPCTSTR) BlackListArray[nIndex];
285                                        sFileName.RemoveExtension();
286                                        if(_tcsicmp(sFileName, pszFileName) == 0)
287                                        {
288                                                _Z2(atlTraceCOM, 2, _T("Will instantiate original COM class, sFileName \"%s\"\n"), sFileName);
289                                                bFound = TRUE;
290                                                break;
291                                        }
292                                }
293                                g_nBlackListed = bFound ? 2 : 1;
294                        }
295                }
296                #pragma endregion
297                if(g_nBlackListed == 2)
298                        #pragma region CoCreateInstance Original Class
299                        _ATLTRY
300                        {
301                                _A(_pAtlModule);
302                                const LONG nLockResult = _pAtlModule->Lock();
303                                _ATLTRY
304                                {
305                                        CComPtr<IUnknown> pUnknown = _Class::CoCreateOriginalInstance((IUnknown*) pvControllingUnknown);
306                                        if(InterfaceIdentifier == __uuidof(IUnknown))
307                                                *ppvObject = pUnknown.Detach();
308                                        else
309                                                __C(pUnknown->QueryInterface(InterfaceIdentifier, ppvObject));
310                                }
311                                _ATLCATCHALL()
312                                {
313                                        _pAtlModule->Unlock();
314                                        _ATLRETHROW;
315                                }
316                                const LONG nUnlockResult = _pAtlModule->Unlock();
317                                _Z6(atlTraceGeneral, 6, _T("nLockResult %d, nUnlockResult %d\n"), nLockResult, nUnlockResult);
318                                return S_OK;
319                        }
320                        _ATLCATCH(Exception)
321                        {
322                                _A(FAILED(Exception));
323                                _C(Exception);
324                        }
325                        #pragma endregion
326                return __super::CreateInstance(pvControllingUnknown, InterfaceIdentifier, ppvObject);
327        }
328};
329
330////////////////////////////////////////////////////////////
331// CHookHostT
332
333template <typename T, typename IHook, LPCTSTR* t_ppszHookName>
334class CHookHostT
335{
336public:
337
338        ////////////////////////////////////////////////////////
339        // CHookArray
340
341        class CHookArray :
342                public CRoArrayT<CComPtr<IHook> >
343        {
344        public:
345        // CHookArray
346        };
347
348private:
349        mutable CRoCriticalSection m_HookCriticalSection;
350        BOOL m_bHookArrayInitialized;
351        CHookArray m_HookArray;
352
353        VOID InitializeHookArray()
354        {
355                _A(m_HookArray.IsEmpty());
356                CRoListT<CLSID> ClassIdentifierList;
357                static const HKEY g_phParentKeys[] = { HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER };
358                static const LPCTSTR g_ppszKeyNameFormats[] = { _T("SOFTWARE\\Classes\\"), _T("Software\\Classes\\") };
359                for(SIZE_T nKeyIndex = 0; nKeyIndex < DIM(g_phParentKeys); nKeyIndex++)
360                {
361                        const CString sKeyName = AtlFormatString(_T("%sCLSID\\%ls\\Hooks\\%s"), g_ppszKeyNameFormats[nKeyIndex], _PersistHelper::StringFromIdentifier(T::GetObjectCLSID()), *t_ppszHookName);
362                        CRegKey Key;
363                        if(FAILED(HRESULT_FROM_WIN32(Key.Open(g_phParentKeys[nKeyIndex], sKeyName, KEY_READ))))
364                                continue;
365                        for(DWORD nIndex = 0; ; nIndex++)
366                        {
367                                DWORD nNameLength = 0;
368                                RegEnumKeyEx(Key, nIndex, NULL, &nNameLength, NULL, NULL, NULL, NULL);
369                                nNameLength = max(2 * nNameLength, 256);
370                                CTempBuffer<TCHAR, 4096> pszName(nNameLength);
371                                const HRESULT nRegEnumKeyResult = HRESULT_FROM_WIN32(RegEnumKeyEx(Key, nIndex, pszName, &nNameLength, NULL, NULL, NULL, NULL));
372                                if(FAILED(nRegEnumKeyResult))
373                                {
374                                        __D(nRegEnumKeyResult == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS), nRegEnumKeyResult);
375                                        break;
376                                }
377                                _ATLTRY
378                                {
379                                        const CLSID ClassIdentifier = _PersistHelper::ClassIdentifierFromString(CT2CW(pszName));
380                                        _Z4(atlTraceGeneral, 4, _T("ClassIdentifier %ls\n"), _PersistHelper::StringFromIdentifier(ClassIdentifier));
381                                        __D(ClassIdentifier != CLSID_NULL, E_UNNAMED);
382                                        if(ClassIdentifierList.Find(ClassIdentifier))
383                                                continue;
384                                        _W(ClassIdentifierList.AddTail(ClassIdentifier));
385                                        CComPtr<IHook> pHook;
386                                        __C(pHook.CoCreateInstance(ClassIdentifier));
387                                        _W(m_HookArray.Add(pHook) >= 0);
388                                }
389                                _ATLCATCHALL()
390                                {
391                                        _Z_EXCEPTION();
392                                }
393                        }
394                }
395        }
396
397public:
398// CHookHostT
399        CHookHostT() throw() :
400                m_bHookArrayInitialized(FALSE)
401        {
402        }
403        SIZE_T GetHookArray(CHookArray& HookArray)
404        {
405                _A(HookArray.IsEmpty());
406                CRoCriticalSectionLock HookLock(m_HookCriticalSection);
407                if(!m_bHookArrayInitialized)
408                        _ATLTRY
409                        {
410                                m_bHookArrayInitialized = TRUE;
411                                InitializeHookArray();
412                        }
413                        _ATLCATCHALL()
414                        {
415                                _Z_EXCEPTION();
416                        }
417                HookArray.Append(m_HookArray);
418                return HookArray.GetCount();
419        }
420};
421
422#define HOOK_PROLOG(Base) \
423        _ATLTRY \
424        { \
425                Base::CHookArray HookArray; \
426                if(Base::GetHookArray(HookArray)) \
427                { \
428                        T* pT = static_cast<T*>(this); \
429                        for(SIZE_T nIndex = 0; nIndex < HookArray.GetCount(); nIndex++) \
430                        { \
431                                BOOL bDefault = TRUE; \
432                                const HRESULT nResult = HookArray[nIndex]->
433                                               
434#define HOOK_EPILOG() \
435                                if(!bDefault) \
436                                        return nResult; \
437                                _A(SUCCEEDED(nResult)); \
438                        } \
439                } \
440        } \
441        _ATLCATCHALL() \
442        { \
443                _Z_EXCEPTION(); \
444        }
445
446////////////////////////////////////////////////////////////
447// COptions
448
449class COptions
450{
451public:
452
453        ////////////////////////////////////////////////////////
454        // CNameValue
455
456        class CNameValue
457        {
458        public:
459                CString m_sName;
460                CComVariantArray m_vValue;
461
462        public:
463        // CNameValue
464        };
465
466private:
467        mutable CRoCriticalSection m_DataCriticalSection;
468        CRoMapT<CString, CNameValue, CStringElementTraitsI<CString>> m_ValueMap;
469
470public:
471// COptions
472        CComVariantArray GetVariant() const
473        {
474                CComVariantArray vValues;
475                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
476                CRoArrayT<CComVariantArray> Array;
477                for(auto&& NameValue: m_ValueMap.GetValues())
478                {
479                        CComVariantArray vValue;
480                        Array.Add(vValue.FromElements(2, CComVariant(NameValue.m_sName), NameValue.m_vValue));
481                }
482                return vValues.FromElementArray(Array);
483        }
484        VOID SetVariant(CComVariantArray& vValue)
485        {
486                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
487                m_ValueMap.RemoveAll();
488                if(vValue.vt > VT_NULL)
489                {
490                        __D(vValue.IsPlainVariantArray(), E_INVALIDARG);
491                        CRoArrayT<CComVariantArray> ElementArray;
492                        vValue.ToElementArray(ElementArray);
493                        for(auto&& vItem: ElementArray)
494                        {
495                                __D(vItem.IsPlainVariantArray(), E_INVALIDARG);
496                                CRoArrayT<CComVariantArray> ValueArray;
497                                __D(vItem.ToElementArray(ValueArray) >= 2, E_INVALIDARG);
498                                __C(ValueArray[0].ChangeType(VT_BSTR));
499                                CString sName(ValueArray[0].bstrVal);
500                                CNameValue NameValue;
501                                NameValue.m_sName = sName;
502                                NameValue.m_vValue = ValueArray[1];
503                                _W(m_ValueMap.SetAt(sName, NameValue));
504                        }
505                }
506        }
507        VOID SetVariant(VARIANT vValue)
508        {
509                SetVariant(reinterpret_cast<CComVariantArray&>(vValue));
510        }
511        COptions& operator = (const COptions& Value)
512        {
513                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
514                CRoCriticalSectionLock ValueDataLock(Value.m_DataCriticalSection);
515                m_ValueMap.RemoveAll();
516                for(auto&& NameValue: Value.m_ValueMap.GetValues())
517                        _W(m_ValueMap.SetAt(NameValue.m_sName, NameValue));
518                return *this;
519        }
520        BOOL TryGetLongValue(const LPCTSTR pszName, LONG& nValue) //const
521        {
522                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
523                const POSITION Position = m_ValueMap.Lookup(pszName);
524                if(!Position)
525                        return FALSE; // No Value
526                CComVariant vLongValue;
527                if(FAILED(vLongValue.ChangeType(VT_I4, &m_ValueMap.GetValueAt(Position).m_vValue)))
528                        return FALSE; // Wrong Value Type
529                nValue = vLongValue.lVal;
530                return TRUE;
531        }
532        BOOL TryGetBoolValue(const LPCTSTR pszName, BOOL& bValue) //const
533        {
534                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
535                const POSITION Position = m_ValueMap.Lookup(pszName);
536                if(!Position)
537                        return FALSE; // No Value
538                CComVariant vBoolValue;
539                if(FAILED(vBoolValue.ChangeType(VT_BOOL, &m_ValueMap.GetValueAt(Position).m_vValue)))
540                        return FALSE; // Wrong Value Type
541                bValue = vBoolValue.boolVal != ATL_VARIANT_FALSE;
542                return TRUE;
543        }
544};
545
546#if defined(DIRECTSHOWSPY)
547
548        ////////////////////////////////////////////////////////////
549        // CModuleVersionInformationT
550
551        template <typename T>
552        class ATL_NO_VTABLE CModuleVersionInformationT :
553                public IDispatchImpl<IModuleVersionInformation>
554        {
555        public:
556        // CModuleVersionInformationT
557
558        // IModuleVersionInformation
559                STDMETHOD(get_Path)(BSTR* psPath) override
560                {
561                        _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), static_cast<T*>(this));
562                        _ATLTRY
563                        {
564                                __D(psPath, E_POINTER);
565                                *psPath = CComBSTR(_VersionInfoHelper::GetModulePath()).Detach();
566                        }
567                        _ATLCATCH(Exception)
568                        {
569                                _C(Exception);
570                        }
571                        return S_OK;
572                }
573                STDMETHOD(get_FileVersion)(LONGLONG* pnFileVersion) override
574                {
575                        _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), static_cast<T*>(this));
576                        _ATLTRY
577                        {
578                                __D(pnFileVersion, E_POINTER);
579                                *pnFileVersion = (LONGLONG) _VersionInfoHelper::GetFileVersion(_VersionInfoHelper::GetModulePath());
580                        }
581                        _ATLCATCH(Exception)
582                        {
583                                _C(Exception);
584                        }
585                        return S_OK;
586                }
587                STDMETHOD(get_FileVersionString)(BSTR* psFileVersionString) override
588                {
589                        _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), static_cast<T*>(this));
590                        _ATLTRY
591                        {
592                                __D(psFileVersionString, E_POINTER);
593                                *psFileVersionString = CComBSTR(_VersionInfoHelper::GetVersionString(_VersionInfoHelper::GetFileVersion(_VersionInfoHelper::GetModulePath()))).Detach();
594                        }
595                        _ATLCATCH(Exception)
596                        {
597                                _C(Exception);
598                        }
599                        return S_OK;
600                }
601        };
602
603#endif // defined(DIRECTSHOWSPY)
604
605////////////////////////////////////////////////////////////
606// DIRECTSHOWSPY_NAMESPACE_PREFIX
607
608#if !defined(DIRECTSHOWSPY_NAMESPACE_PREFIX)
609        #if defined(DIRECTSHOWSPY)
610                #define DIRECTSHOWSPY_NAMESPACE_PREFIX
611        #else
612                #define DIRECTSHOWSPY_NAMESPACE_PREFIX AlaxInfoDirectShowSpy::
613        #endif // DIRECTSHOWSPY
614#endif // !defined(DIRECTSHOWSPY_NAMESPACE_PREFIX)
Note: See TracBrowser for help on using the repository browser.