//**************************************************************************** // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: UIRibbonPropertyHelpers.h // // Contents: Property helper functions for the Windows Ribbon Framework // //**************************************************************************** #pragma once #include interface IUIImage; #ifndef TUIPROPERTYKEYDEFINED // A version of PROPERTYKEY whose VARTYPE can be tested at compile time. #include template struct TUIPROPERTYKEY { GUID fmtid; DWORD pid; inline operator const PROPERTYKEY&() const { return reinterpret_cast(*this); } inline const PROPERTYKEY* operator&() const { return reinterpret_cast(this); } }; #include C_ASSERT(sizeof(TUIPROPERTYKEY) == sizeof(PROPERTYKEY)); #define TUIPROPERTYKEYDEFINED #endif // TUIPROPERTYKEYDEFINED // UIBreakCheckType is being used to do both Compilation and Runtime checking of types on PROPVARIANTs struct UIWrongType {}; template struct UIBreakCheckType { // If a PROPERTYKEY/type combination is invalid, compilation will break (it will try to cast a bool to UIWrongType) typedef UIWrongType _Type; static bool Validate(REFPROPERTYKEY key) { UNREFERENCED_PARAMETER(key); return false; } }; #define UI_REGISTER_TYPE( type ) \ template<> struct UIBreakCheckType< TUIPROPERTYKEY, type > \ { \ typedef bool _Type; \ static bool Validate(REFPROPERTYKEY key) { UNREFERENCED_PARAMETER(key); return true; } \ }; \ template<> struct UIBreakCheckType< PROPERTYKEY, type > \ { \ typedef bool _Type; \ /* we cannot catch at compilation time when PROPERTYKEYs are by reference, so check at runtime */ \ static bool Validate(REFPROPERTYKEY key) { return (type) == key.pid; }\ }; // Register known types UI_REGISTER_TYPE( VT_BOOL ) UI_REGISTER_TYPE( VT_UI4 ) UI_REGISTER_TYPE( VT_LPWSTR ) UI_REGISTER_TYPE( VT_DECIMAL ) UI_REGISTER_TYPE( VT_UNKNOWN ) UI_REGISTER_TYPE( VT_ARRAY|VT_UNKNOWN ) //====================================================================================== // PROPVARIANT initializer helpers template HRESULT UIInitPropertyFromBoolean(const T& propertyKey, BOOL fVal, __out PROPVARIANT* pPropVar) { // If this fails to compile, it means this property is not of type VT_BOOL UIBreakCheckType::_Type valid = UIBreakCheckType::Validate(propertyKey); return valid ? InitPropVariantFromBoolean(fVal, pPropVar) : E_INVALIDARG; } template HRESULT UIInitPropertyFromUInt32(const T& propertyKey, UINT ulVal, __out PROPVARIANT* pPropVar) { // If this fails to compile, it means this property is not of type VT_UI4 UIBreakCheckType::_Type valid = UIBreakCheckType::Validate(propertyKey); return valid ? InitPropVariantFromUInt32(ulVal, pPropVar) : E_INVALIDARG; } template HRESULT UIInitPropertyFromString(const T& propertyKey, __in PCWSTR psz, __out PROPVARIANT* pPropVar) { // If this fails to compile, it means this property is not of type VT_LPWSTR UIBreakCheckType::_Type valid = UIBreakCheckType::Validate(propertyKey); return valid ? InitPropVariantFromString(psz, pPropVar) : E_INVALIDARG; } template HRESULT UIInitPropertyFromDecimal(const T& propertyKey, const DECIMAL& decValue, __out PROPVARIANT* pPropVar) { // If this fails to compile, it means this property is not of type VT_DECIMAL UIBreakCheckType::_Type valid = UIBreakCheckType::Validate(propertyKey); if (valid) { // Must set decVal before vt because the two overlap. pPropVar->decVal = decValue; pPropVar->vt = VT_DECIMAL; return S_OK; } return E_INVALIDARG; } template HRESULT UIInitPropertyFromInterface(const T& propertyKey, __in IUnknown* pUnk, __out PROPVARIANT* pPropVar) { // If this fails to compile, it means this property is not of type VT_UNKNOWN UIBreakCheckType::_Type valid = UIBreakCheckType::Validate(propertyKey); if (valid) { pPropVar->vt = VT_UNKNOWN; pPropVar->punkVal = pUnk; if (pUnk) { pUnk->AddRef(); } return S_OK; } return E_INVALIDARG; } template HRESULT UIInitPropertyFromImage(const T& propertyKey, __in IUIImage* pImage, __out PROPVARIANT* pPropVar) { return UIInitPropertyFromInterface(propertyKey, pImage, pPropVar); } template HRESULT UIInitPropertyFromIUnknownArray(const T& propertyKey, __in SAFEARRAY* psa, __out PROPVARIANT* pPropVar) { // If this fails to compile, it means this property is not of type VT_ARRAY UIBreakCheckType::_Type valid = UIBreakCheckType::Validate(propertyKey); if (valid && (psa->fFeatures & FADF_UNKNOWN) ) { HRESULT hr = ::SafeArrayCopy(psa, &pPropVar->parray); if (SUCCEEDED(hr)) { pPropVar->vt = VT_ARRAY|VT_UNKNOWN; } return hr; } return E_INVALIDARG; } //====================================================================================== // Extract value from PROPVARIANT template HRESULT UIPropertyToBoolean(const T& propertyKey, REFPROPVARIANT propvarIn, __out BOOL *pfRet) { // If this fails to compile, it means this property is not of type VT_BOOL UIBreakCheckType::_Type valid = UIBreakCheckType::Validate(propertyKey); return valid ? PropVariantToBoolean(propvarIn, pfRet) : E_INVALIDARG; } template HRESULT UIPropertyToUInt32(const T& propertyKey, REFPROPVARIANT propvarIn, __out UINT *pulVal) { // If this fails to compile, it means this property is not of type VT_UI4 UIBreakCheckType::_Type valid = UIBreakCheckType::Validate(propertyKey); return valid ? PropVariantToUInt32(propvarIn, pulVal) : E_INVALIDARG; } // Allocate a new string and return it in ppszOut template HRESULT UIPropertyToStringAlloc(const T& propertyKey, REFPROPVARIANT propvarIn, __deref_out PWSTR *ppszOut) { // If this fails to compile, it means this property is not of type VT_LPWSTR UIBreakCheckType::_Type valid = UIBreakCheckType::Validate(propertyKey); return valid ? PropVariantToStringAlloc(propvarIn, ppszOut) : E_INVALIDARG; } template HRESULT UIPropertyToDecimal(const T& propertyKey, REFPROPVARIANT propvarIn, __out DECIMAL *pDecValue) { // If this fails to compile, it means this property is not of type VT_DECIMAL UIBreakCheckType::_Type valid = UIBreakCheckType::Validate(propertyKey); if (valid && propvarIn.vt == VT_DECIMAL) { *pDecValue = propvarIn.decVal; return S_OK; } return E_INVALIDARG; } template HRESULT UIPropertyToInterface(const T& propertyKey, REFPROPVARIANT propvarIn, __deref_out TInterface** ppObj) { *ppObj = NULL; // If this fails to compile, it means this property is not of type VT_UNKNOWN UIBreakCheckType::_Type valid = UIBreakCheckType::Validate(propertyKey); if (valid && propvarIn.vt == VT_UNKNOWN) { if (propvarIn.punkVal) { return propvarIn.punkVal->QueryInterface(__uuidof(TInterface), (void**)ppObj); } return S_OK; } return E_INVALIDARG; } template HRESULT UIPropertyToImage(const T& propertyKey, REFPROPVARIANT propvarIn, __deref_out IUIImage** ppImage) { return UIPropertyToInterface(propertyKey, propvarIn, ppImage); } template HRESULT UIPropertyToIUnknownArrayAlloc(const T& propertyKey, REFPROPVARIANT propvarIn, __deref_out SAFEARRAY** ppsa) { // If this fails to compile, it means this property is not of type VT_ARRAY UIBreakCheckType::_Type valid = UIBreakCheckType::Validate(propertyKey); if (valid && propvarIn.vt == (VT_ARRAY|VT_UNKNOWN) ) { return ::SafeArrayCopy(propvarIn.parray, ppsa); } return E_INVALIDARG; }