source: trunk/DirectShowSpy/Common.h @ 440

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

Added media sample trace API and UI

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