mirror of https://github.com/UMSKT/xpmgr.git
227 lines
8.2 KiB
C++
227 lines
8.2 KiB
C++
//****************************************************************************
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// File: UIRibbonPropertyHelpers.h
|
|
//
|
|
// Contents: Property helper functions for the Windows Ribbon Framework
|
|
//
|
|
//****************************************************************************
|
|
|
|
#pragma once
|
|
|
|
#include <propvarutil.h>
|
|
|
|
interface IUIImage;
|
|
|
|
#ifndef TUIPROPERTYKEYDEFINED
|
|
// A version of PROPERTYKEY whose VARTYPE can be tested at compile time.
|
|
#include <pshpack8.h>
|
|
template<VARTYPE T>
|
|
struct TUIPROPERTYKEY
|
|
{
|
|
GUID fmtid;
|
|
DWORD pid;
|
|
inline operator const PROPERTYKEY&() const { return reinterpret_cast<const PROPERTYKEY&>(*this); }
|
|
inline const PROPERTYKEY* operator&() const { return reinterpret_cast<const PROPERTYKEY*>(this); }
|
|
};
|
|
#include <poppack.h>
|
|
|
|
C_ASSERT(sizeof(TUIPROPERTYKEY<VT_BOOL>) == sizeof(PROPERTYKEY));
|
|
|
|
#define TUIPROPERTYKEYDEFINED
|
|
#endif // TUIPROPERTYKEYDEFINED
|
|
|
|
// UIBreakCheckType is being used to do both Compilation and Runtime checking of types on PROPVARIANTs
|
|
|
|
struct UIWrongType {};
|
|
|
|
template<class A, VARTYPE B>
|
|
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>, 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<class T>
|
|
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<T, VT_BOOL>::_Type valid = UIBreakCheckType<T, VT_BOOL>::Validate(propertyKey);
|
|
return valid ? InitPropVariantFromBoolean(fVal, pPropVar) : E_INVALIDARG;
|
|
}
|
|
|
|
template<class T>
|
|
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<T, VT_UI4>::_Type valid = UIBreakCheckType<T, VT_UI4>::Validate(propertyKey);
|
|
return valid ? InitPropVariantFromUInt32(ulVal, pPropVar) : E_INVALIDARG;
|
|
}
|
|
|
|
template<class T>
|
|
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<T, VT_LPWSTR>::_Type valid = UIBreakCheckType<T, VT_LPWSTR>::Validate(propertyKey);
|
|
return valid ? InitPropVariantFromString(psz, pPropVar) : E_INVALIDARG;
|
|
}
|
|
|
|
template<class T>
|
|
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<T, VT_DECIMAL>::_Type valid = UIBreakCheckType<T, VT_DECIMAL>::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<class T>
|
|
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<T, VT_UNKNOWN>::_Type valid = UIBreakCheckType<T, VT_UNKNOWN>::Validate(propertyKey);
|
|
if (valid)
|
|
{
|
|
pPropVar->vt = VT_UNKNOWN;
|
|
pPropVar->punkVal = pUnk;
|
|
if (pUnk)
|
|
{
|
|
pUnk->AddRef();
|
|
}
|
|
return S_OK;
|
|
}
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
template<class T>
|
|
HRESULT UIInitPropertyFromImage(const T& propertyKey, __in IUIImage* pImage, __out PROPVARIANT* pPropVar)
|
|
{
|
|
return UIInitPropertyFromInterface(propertyKey, pImage, pPropVar);
|
|
}
|
|
|
|
template<class T>
|
|
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<T, VT_ARRAY|VT_UNKNOWN>::_Type valid = UIBreakCheckType<T, VT_ARRAY|VT_UNKNOWN>::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<class T>
|
|
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<T, VT_BOOL>::_Type valid = UIBreakCheckType<T, VT_BOOL>::Validate(propertyKey);
|
|
return valid ? PropVariantToBoolean(propvarIn, pfRet) : E_INVALIDARG;
|
|
}
|
|
|
|
template<class T>
|
|
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<T, VT_UI4>::_Type valid = UIBreakCheckType<T, VT_UI4>::Validate(propertyKey);
|
|
return valid ? PropVariantToUInt32(propvarIn, pulVal) : E_INVALIDARG;
|
|
}
|
|
|
|
// Allocate a new string and return it in ppszOut
|
|
template<class T>
|
|
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<T, VT_LPWSTR>::_Type valid = UIBreakCheckType<T, VT_LPWSTR>::Validate(propertyKey);
|
|
return valid ? PropVariantToStringAlloc(propvarIn, ppszOut) : E_INVALIDARG;
|
|
}
|
|
|
|
template<class T>
|
|
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<T, VT_DECIMAL>::_Type valid = UIBreakCheckType<T, VT_DECIMAL>::Validate(propertyKey);
|
|
if (valid && propvarIn.vt == VT_DECIMAL)
|
|
{
|
|
*pDecValue = propvarIn.decVal;
|
|
return S_OK;
|
|
}
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
template<class T, class TInterface>
|
|
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<T, VT_UNKNOWN>::_Type valid = UIBreakCheckType<T, VT_UNKNOWN>::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<class T>
|
|
HRESULT UIPropertyToImage(const T& propertyKey, REFPROPVARIANT propvarIn, __deref_out IUIImage** ppImage)
|
|
{
|
|
return UIPropertyToInterface(propertyKey, propvarIn, ppImage);
|
|
}
|
|
|
|
template<class T>
|
|
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<T, VT_ARRAY|VT_UNKNOWN>::_Type valid = UIBreakCheckType<T, VT_ARRAY|VT_UNKNOWN>::Validate(propertyKey);
|
|
if (valid && propvarIn.vt == (VT_ARRAY|VT_UNKNOWN) )
|
|
{
|
|
return ::SafeArrayCopy(propvarIn.parray, ppsa);
|
|
}
|
|
return E_INVALIDARG;
|
|
}
|
|
|