source: trunk/DirectShowSpy/Common.h @ 468

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