source: trunk/DirectShowSpy/Common.h @ 455

Last change on this file since 455 was 455, checked in by roman, 9 years ago

Cosmetic

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