source: trunk/DirectShowSpy/Common.h @ 432

Last change on this file since 432 was 432, checked in by roman, 7 years ago

VS2013 related updates; use of CSIDL_LOCAL_APPDATA instead of CSIDL_APPDATA for fallback log writes; added bitness and privilege indication in all captions

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