windows-nt/Source/XPSP1/NT/shell/ext/docpropv3/propertycacheitem.cpp

1289 lines
23 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//
// Copyright 2001 - Microsoft Corporation
//
//
// Created By:
// Geoff Pease (GPease) 23-JAN-2001
//
// Maintained By:
// Geoff Pease (GPease) 23-JAN-2001
//
#include "pch.h"
#include "DocProp.h"
#include "DefProp.h"
#include "PropertyCacheItem.h"
#pragma hdrstop
// ***************************************************************************
//
// Class statics
//
// ***************************************************************************
WCHAR CPropertyCacheItem::_szMultipleString[ MAX_PATH ] = { 0 };
// ***************************************************************************
//
// Constructor / Destructor / Initialization
//
// ***************************************************************************
//
// CreateInstance
//
HRESULT
CPropertyCacheItem::CreateInstance(
CPropertyCacheItem ** ppItemOut
)
{
TraceFunc( "" );
HRESULT hr;
Assert( NULL != ppItemOut );
CPropertyCacheItem * pthis = new CPropertyCacheItem;
if ( NULL != pthis )
{
hr = THR( pthis->Init( ) );
if ( SUCCEEDED( hr ) )
{
*ppItemOut = pthis;
}
else
{
pthis->Destroy( );
}
}
else
{
hr = E_OUTOFMEMORY;
}
HRETURN( hr );
}
//
// Constructor
//
CPropertyCacheItem::CPropertyCacheItem( void )
{
TraceFunc( "" );
Assert( NULL == _pNext );
Assert( FALSE == _fReadOnly );
Assert( FALSE == _fDirty );
Assert( IsEqualIID( _fmtid, CLSID_NULL ) );
Assert( 0 == _propid );
Assert( VT_EMPTY == _vt );
Assert( 0 == _uCodePage );
Assert( VT_EMPTY == _propvar.vt );
Assert( 0 == _idxDefProp );
Assert( NULL == _ppui );
Assert( 0 == _wszTitle[ 0 ] );
Assert( 0 == _wszDesc[ 0 ] );
Assert( 0 == _wszValue[ 0 ] );
Assert( 0 == _wszHelpFile[ 0 ] );
Assert( NULL == _pDefVals );
TraceFuncExit( );
}
//
// Initialization
//
HRESULT
CPropertyCacheItem::Init( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
_idxDefProp = -1L;
HRETURN( hr );
}
//
// Destructor
//
CPropertyCacheItem::~CPropertyCacheItem( void )
{
TraceFunc( "" );
if ( NULL != _ppui )
{
_ppui->Release( );
}
if ( NULL != _pDefVals )
{
for ( ULONG idx = 0; NULL != _pDefVals[ idx ].pszName; idx ++ )
{
TraceFree( _pDefVals[ idx ].pszName );
}
TraceFree( _pDefVals );
}
TraceFuncExit( );
}
//
// Description:
// Attempts to destroy the property item.
//
// Return Values:
// S_OK
// Success!
//
HRESULT
CPropertyCacheItem::Destroy( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
delete this;
HRETURN( hr );
}
// ***************************************************************************
//
// Private Methods
//
// ***************************************************************************
//
// Description:
// Looks in our "default property list" for a matching fmtid/propid
// combination and sets _idxDefProp to that index.
//
// Return Values:
// S_OK
// Success!
//
// HRESULT_FROM_WIN32(ERROR_NOT_FOUND)
// Entry was not found. _idxDefProp is invalid.
//
HRESULT
CPropertyCacheItem::FindDefPropertyIndex( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
if ( -1L == _idxDefProp )
{
ULONG idx;
for ( idx = 0; NULL != g_rgDefPropertyItems[ idx ].pFmtID; idx ++ )
{
if ( IsEqualPFID( _fmtid, *g_rgDefPropertyItems[ idx ].pFmtID )
&& _propid == g_rgDefPropertyItems[ idx ].propID
)
{
_idxDefProp = idx;
break;
}
}
if ( -1L == _idxDefProp )
{
// don't wrap.
hr = HRESULT_FROM_WIN32( ERROR_NOT_FOUND );
}
}
HRETURN( hr );
}
//
// Description:
// Check the static member _szMultipleString to make sure it has been
// loaded.
//
void
CPropertyCacheItem::EnsureMultipleStringLoaded( void )
{
TraceFunc( "" );
if ( 0 == _szMultipleString[ 0 ] )
{
int iRet = LoadString( g_hInstance, IDS_COMPOSITE_MISMATCH, _szMultipleString, ARRAYSIZE(_szMultipleString) );
AssertMsg( 0 != iRet, "Missing string resource?" );
}
TraceFuncExit( );
}
// ***************************************************************************
//
// Public Methods
//
// ***************************************************************************
//
// Description:
// Stores a IPropetyUI interface to be used for translating the property
// "properties" into different forms.
//
// Return Values:
// S_OK
// Success!
//
HRESULT
CPropertyCacheItem::SetPropertyUIHelper(
IPropertyUI * ppuiIn
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
//
// If we have an existing helper, release it.
//
if ( NULL != _ppui )
{
_ppui->Release( );
}
_ppui = ppuiIn;
if ( NULL != _ppui )
{
_ppui->AddRef( );
}
HRETURN( hr );
}
//
// Description:
// Retrieves a copy (AddRef'ed) of the IPropertyUI interface that this
// property item is using.
//
// Return Values:
// S_OK
// Success! pppuiOut is valid.
//
// S_FALSE
// Success, but pppuiOut is NULL.
//
// E_POINTER
// pppuiOut is NULL.
//
// other HRESULTs.
//
HRESULT
CPropertyCacheItem::GetPropertyUIHelper(
IPropertyUI ** pppuiOut
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
if ( NULL == pppuiOut )
goto InvalidPointer;
//
// If we have an existing helper, release it.
//
if ( NULL == _ppui )
{
*pppuiOut = NULL;
hr = S_FALSE;
}
else
{
hr = THR( _ppui->TYPESAFEQI( *pppuiOut ) );
}
Cleanup:
HRETURN( hr );
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
}
//
// Description:
// Changes the _pNext member variable
//
// Return Values:
// S_OK
// Success!
//
HRESULT
CPropertyCacheItem::SetNextItem(
CPropertyCacheItem * pNextIn
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
_pNext = pNextIn;
HRETURN( hr );
}
//
// Description:
// Retrieves the _pNext member variable
//
// Return Values:
// S_OK
// Success!
//
// S_FALSE
//
//
// E_POINTER
// ppNextOut is NULL.
//
HRESULT
CPropertyCacheItem::GetNextItem(
CPropertyCacheItem ** ppNextOut
)
{
TraceFunc( "" );
HRESULT hr;
if ( NULL != ppNextOut )
{
*ppNextOut = _pNext;
if ( NULL == _pNext )
{
hr = S_FALSE;
}
else
{
hr = S_OK;
}
}
else
{
hr = THR( E_POINTER );
}
HRETURN( hr );
}
//
// Description:
// Sets the FMTID of the property.
//
// Return Values:
// S_OK
// Success!
//
HRESULT
CPropertyCacheItem::SetFmtId(
const FMTID * pFmtIdIn
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
_fmtid = *pFmtIdIn;
_idxDefProp = -1;
HRETURN( hr );
}
//
// Description:
// Retrieves the FMTID of the property.
//
// Return Values:
// S_OK
// Success!
//
// E_POINTER
// pfmtidOut is invalid.
//
HRESULT
CPropertyCacheItem::GetFmtId(
FMTID * pfmtidOut
)
{
TraceFunc( "" );
HRESULT hr;
if ( NULL != pfmtidOut )
{
*pfmtidOut = _fmtid;
hr = S_OK;
}
else
{
hr = THR( E_POINTER );
}
HRETURN( hr );
}
//
// Description:
// Sets the PROPID of the property.
//
// Return Values:
// S_OK
// Success!
//
HRESULT
CPropertyCacheItem::SetPropId(
PROPID propidIn
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
_propid = propidIn;
_idxDefProp = -1;
HRETURN( hr );
}
//
// Description:
// Retrieves the PROPID of the property.
//
// Return Values:
// S_OK
// Success!
//
// E_POINTER
// ppropidOut is invalid.
//
HRESULT
CPropertyCacheItem::GetPropId(
PROPID * ppropidOut
)
{
TraceFunc( "" );
HRESULT hr;
if ( NULL == ppropidOut )
goto InvalidPointer;
*ppropidOut = _propid;
hr = S_OK;
Cleanup:
HRETURN( hr );
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
}
//
// Description:
// Sets the VARTYPE of the property.
//
// Return Values:
// S_OK
// Success!
//
HRESULT
CPropertyCacheItem::SetDefaultVarType(
VARTYPE vtIn
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
_vt = vtIn;
HRETURN( hr );
}
//
// Description:
// Retrieves the VARTYPE of the property.
//
// Return Values:
// S_OK
// Success!
//
// E_POINTER
// pvtOut is invalid.
//
HRESULT
CPropertyCacheItem::GetDefaultVarType(
VARTYPE * pvtOut
)
{
TraceFunc( "" );
HRESULT hr;
if ( NULL != pvtOut )
{
switch ( _vt )
{
case VT_VECTOR | VT_VARIANT:
Assert( _propvar.capropvar.cElems == 2 );
*pvtOut = _propvar.capropvar.pElems[ 1 ].vt;
hr = S_OK;
break;
case VT_VECTOR | VT_LPSTR:
*pvtOut = VT_LPSTR;
hr = S_OK;
break;
case VT_VECTOR | VT_LPWSTR:
*pvtOut = VT_LPWSTR;
hr = S_OK;
break;
default:
*pvtOut = _vt;
hr = S_OK;
break;
}
}
else
{
hr = E_POINTER;
}
HRETURN( hr );
}
//
// Description:
// Stores the Code Page for the property value.
//
// Return Values:
// S_OK
// Success!
//
HRESULT
CPropertyCacheItem::SetCodePage(
UINT uCodePageIn
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
_uCodePage = uCodePageIn;
HRETURN( hr );
}
//
// Description:
// Retrieves the Code Page for the property value.
//
// Return Values:
// S_OK
// Success!
//
// E_POINTER
// puCodePageOut is NULL.
//
HRESULT
CPropertyCacheItem::GetCodePage(
UINT * puCodePageOut
)
{
TraceFunc( "" );
HRESULT hr;
if ( NULL != puCodePageOut )
{
*puCodePageOut = _uCodePage;
hr = S_OK;
}
else
{
hr = THR( E_POINTER );
}
HRETURN( hr );
}
//
// Description:
// Retrieves the property name for this property to be display in the UI.
// The pointer handed out does not need to be freed.
//
// Return Values:
// S_OK
// Success!
//
// E_POINTER
// ppwszOut is NULL.
//
// E_UNEXPECTED
// Need to call SetPropertyUIHelper( ) before calling this method.
//
// HRESULT_FROM_WIN32(ERROR_INTERNAL_ERROR)
// The resource string is malformed.
//
// other HRESULTs
//
HRESULT
CPropertyCacheItem::GetPropertyTitle(
LPCWSTR * ppwszOut
)
{
TraceFunc( "" );
HRESULT hr;
if ( NULL == ppwszOut )
goto InvalidPointer;
*ppwszOut = NULL;
if ( NULL == _ppui )
goto UnexpectedState;
hr = THR( _ppui->GetDisplayName( _fmtid, _propid, PUIFNF_DEFAULT, _wszTitle, ARRAYSIZE(_wszTitle) ) );
// Even if this fails, the buffer will still be valid and empty.
*ppwszOut = _wszTitle;
hr = S_OK;
Cleanup:
HRETURN( hr );
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
UnexpectedState:
hr = THR( E_UNEXPECTED );
goto Cleanup;
}
//
// Description:
// Retrieves the property name for this property to be display in the UI.
// The pointer handed out does not need to be freed.
//
// Return Values:
// S_OK
// Success!
//
// E_POINTER
// ppwszOut is NULL.
//
// E_UNEXPECTED
// Need to call SetPropertyUIHelper( ) before calling this method.
//
// HRESULT_FROM_WIN32(ERROR_INTERNAL_ERROR)
// The resource string is malformed.
//
// other HRESULTs
//
HRESULT
CPropertyCacheItem::GetPropertyDescription(
LPCWSTR * ppwszOut
)
{
TraceFunc( "" );
HRESULT hr;
if ( NULL == ppwszOut )
goto InvalidPointer;
*ppwszOut = NULL;
if ( NULL == _ppui )
goto UnexpectedState;
hr = THR( _ppui->GetPropertyDescription( _fmtid, _propid, _wszDesc, ARRAYSIZE(_wszDesc) ) );
// if it failed, the buffer will still be valid and empty.
*ppwszOut = _wszDesc;
hr = S_OK;
Cleanup:
HRETURN( hr );
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
UnexpectedState:
hr = THR( E_UNEXPECTED );
goto Cleanup;
}
//
// Description:
// Retrieves the help information about a property. The pointer handed
// out to the help file does not need to be freed.
//
// Return Values:
// S_OK
// Success!
//
// E_POINTER
// ppwszFileOut or puHelpIDOut is NULL.
//
// E_UNEXPECTED
// Need to call SetPropertyUIHelper( ) before calling this method.
//
// other HRESULTs
//
HRESULT
CPropertyCacheItem::GetPropertyHelpInfo(
LPCWSTR * ppwszFileOut
, UINT * puHelpIDOut
)
{
TraceFunc( "" );
HRESULT hr;
if (( NULL == ppwszFileOut ) || ( NULL == puHelpIDOut ))
goto InvalidPointer;
*ppwszFileOut = NULL;
*puHelpIDOut = 0;
if ( NULL == _ppui )
goto UnexpectedState;
hr = THR( _ppui->GetHelpInfo( _fmtid, _propid, _wszHelpFile, ARRAYSIZE(_wszHelpFile), puHelpIDOut ) );
if ( FAILED( hr ) )
goto Cleanup;
*ppwszFileOut = _wszHelpFile;
hr = S_OK;
Cleanup:
HRETURN( hr );
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
UnexpectedState:
hr = THR( E_UNEXPECTED );
goto Cleanup;
}
//
// Description:
// Retrieves a LPWSTR the to a buffer (own by the property) that can
// used to display the property as a string. The pointer handed out
// does not need to be freed.
//
// Return Values:
// S_OK
// Success!
//
// E_POINTER
// ppwszOut is NULL.
//
// E_UNEXPECTED
// Need to call SetPropertyUIHelper( ) before calling this method.
//
// other HRESULTs
//
HRESULT
CPropertyCacheItem::GetPropertyStringValue(
LPCWSTR * ppwszOut
)
{
TraceFunc( "" );
HRESULT hr;
if ( NULL == ppwszOut )
goto InvalidPointer;
*ppwszOut = NULL;
if ( NULL == _ppui )
goto UnexpectedState;
//
// If the property has been marked to indicate multiple values, then
// return the "< multiple values >" string.
//
if ( _fMultiple )
{
EnsureMultipleStringLoaded( );
*ppwszOut = _szMultipleString;
hr = S_OK;
goto Cleanup;
}
if ( ( VT_VECTOR | VT_VARIANT ) == _vt )
{
Assert( 2 == _propvar.capropvar.cElems );
hr = THR( _ppui->FormatForDisplay( _fmtid, _propid, &_propvar.capropvar.pElems[ 1 ], PUIFFDF_DEFAULT, _wszValue, ARRAYSIZE(_wszValue) ) );
if ( FAILED( hr ) )
goto Cleanup;
}
else
{
hr = THR( _ppui->FormatForDisplay( _fmtid, _propid, &_propvar, PUIFFDF_DEFAULT, _wszValue, ARRAYSIZE(_wszValue) ) );
if ( FAILED( hr ) )
goto Cleanup;
}
*ppwszOut = _wszValue;
hr = S_OK;
Cleanup:
HRETURN( hr );
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
UnexpectedState:
hr = THR( E_UNEXPECTED );
goto Cleanup;
}
//
// Description:
// Retrieves the Image Index for a property.
//
// Return Values:
// S_OK
// Success!
//
// E_POINTER
// piImageOut is NULL.
//
HRESULT
CPropertyCacheItem::GetImageIndex(
int * piImageOut
)
{
TraceFunc( "" );
HRESULT hr;
if ( NULL == piImageOut )
goto InvalidPointer;
// Initlize to read-only
*piImageOut = PTI_PROP_READONLY;
if ( !_fReadOnly )
{
// don't wrap - this can fail
hr = FindDefPropertyIndex( );
if ( S_OK == hr )
{
if ( !g_rgDefPropertyItems[ _idxDefProp ].fReadOnly )
{
*piImageOut = PTI_PROP_READWRITE;
}
}
}
hr = S_OK;
Cleanup:
HRETURN( hr );
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
}
//
// Description:
// Retrieves the Property Folder IDentifer (PFID) for this property.
//
// Return Values:
// S_OK
// Success!
//
// S_FALSE
// Call succeeded, but there isn't a PFID for this property.
//
// E_POINTER
// ppdifOut is NULL.
//
HRESULT
CPropertyCacheItem::GetPFID(
const PFID ** ppPFIDOut
)
{
TraceFunc( "" );
HRESULT hr;
if ( NULL == ppPFIDOut )
goto InvalidPointer;
*ppPFIDOut = NULL;
// don't wrap - this can fail.
hr = FindDefPropertyIndex( );
if ( S_OK == hr )
{
*ppPFIDOut = g_rgDefPropertyItems[ _idxDefProp ].ppfid;
}
if ( NULL == *ppPFIDOut )
{
hr = S_FALSE;
}
Cleanup:
HRETURN( hr );
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
}
//
// Description:
// Retrieves the CLSID of the control to CoCreate( ) to edit this property.
// The object must support the IEditVariantsInPlace interface. This method
// will return S_FALSE (pclsidOut will be CLSID_NULL) is the property is
// read-only.
//
// Return Values:
// S_OK
// Success!
//
// S_FALSE
// Success, but the CLSID is CLSID_NULL.
//
// E_POINTER
// pclsidOut is NULL.
//
// other HRESULTs
//
HRESULT
CPropertyCacheItem::GetControlCLSID(
CLSID * pclsidOut
)
{
TraceFunc( "" );
HRESULT hr;
if ( NULL == pclsidOut )
goto InvalidPointer;
// don't wrap - this can fail.
hr = FindDefPropertyIndex( );
if ( FAILED( hr ) )
goto Cleanup;
//
// If it is read-only, return S_FALSE and a CLSID of CLSID_NULL.
//
if ( g_rgDefPropertyItems[ _idxDefProp ].fReadOnly )
{
*pclsidOut = CLSID_NULL;
hr = S_FALSE;
goto Cleanup;
}
*pclsidOut = *g_rgDefPropertyItems[ _idxDefProp ].pclsidControl;
if ( CLSID_NULL == *pclsidOut )
{
hr = S_FALSE;
}
Cleanup:
HRETURN( hr );
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
}
//
// Description:
// Retrieve the current property value in the form on a variant. If the
// property is backed by multiple sources, then S_FALSE is returned and
// the variant is empty.
//
// Return Value:
// S_OK
// Success!
//
// S_FALSE
// Multiple value property. Variant is empty.
//
// E_POINTER
// ppvarOut is NULL.
//
// E_FAIL
// Property is READ-ONLY.
//
// other HRESULTs.
//
STDMETHODIMP
CPropertyCacheItem::GetPropertyValue(
PROPVARIANT ** ppvarOut
)
{
TraceFunc( "" );
HRESULT hr;
if ( NULL == ppvarOut )
goto InvalidPointer;
*ppvarOut = &_propvar;
hr = S_OK;
Cleanup:
HRETURN( hr );
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
}
//
// Description:
// Marks the property as being dirty.
//
// Return Values:
// S_OK
// Success!
//
// other HRESULTs.
//
STDMETHODIMP
CPropertyCacheItem::MarkDirty( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
_fDirty = TRUE;
_fMultiple = FALSE;
HRETURN( hr );
}
//
// Description:
// Checks to see if the property has been marked dirty.
//
// Return Values:
// S_OK
// Success and the property is dirty.
//
// S_FALSE
// Success and the proprety is clean.
//
STDMETHODIMP
CPropertyCacheItem::IsDirty( void )
{
TraceFunc( "" );
HRESULT hr;
if ( _fDirty )
{
hr = S_OK;
}
else
{
hr = S_FALSE;
}
HRETURN( hr );
}
//
// Description:
// Marks the property read-only.
//
// Return Values:
// S_OK
// Success!
//
STDMETHODIMP
CPropertyCacheItem::MarkReadOnly( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
_fReadOnly = TRUE;
HRETURN( hr );
}
//
// Description:
// Retrieves an array of pointer to an array of strings that are
// zero-indexed. This is used for properties that have well-known
// enumerated states that are indexed (such as "Status").
//
// Return Values:
// S_OK
// Success!
//
// S_FALSE
// Proprety doesn't support enumerated states.
//
// E_INVALIDARG
// ppDefValOut is NULL.
//
// other HRESULTs.
//
STDMETHODIMP
CPropertyCacheItem::GetStateStrings(
DEFVAL ** ppDefValOut
)
{
TraceFunc( "" );
HRESULT hr;
ULONG idx;
ULONG idxEnd;
//
// Check parameters.
//
if ( NULL == ppDefValOut )
goto InvalidPointer;
*ppDefValOut = NULL;
if ( NULL == _ppui )
goto UnexpectedState;
// don't wrap - this can fail.
hr = FindDefPropertyIndex( );
if ( FAILED( hr ) )
goto Cleanup;
if ( !g_rgDefPropertyItems[ _idxDefProp ].fEnumeratedValues )
{
hr = S_FALSE;
goto Cleanup;
}
if ( NULL != _pDefVals )
{
*ppDefValOut = _pDefVals;
hr = S_OK;
goto Cleanup;
}
AssertMsg( NULL != g_rgDefPropertyItems[ _idxDefProp ].pDefVals, "Why did one mark this property as ENUM, but provide no items?" );
//
// Since we moved all the string in SHELL32, we need to use our table
// enumerate the property values to retrieve all the strings. Since
// our table is read-only, we need to allocate a copy of the DEFVALs
// for this property and have PropertyUI fill in the blanks.
//
_pDefVals = (DEFVAL *) TraceAlloc( HEAP_ZERO_MEMORY, sizeof(DEFVAL) * g_rgDefPropertyItems[ _idxDefProp ].cDefVals );
if ( NULL == _pDefVals )
goto OutOfMemory;
CopyMemory( _pDefVals, g_rgDefPropertyItems[ _idxDefProp ].pDefVals, sizeof(DEFVAL) * g_rgDefPropertyItems[ _idxDefProp ].cDefVals );
idxEnd = g_rgDefPropertyItems[ _idxDefProp ].cDefVals - 1; // the last entry is always { 0, NULL }
for ( idx = 0; idx < idxEnd; idx ++ )
{
PROPVARIANT propvar;
propvar.vt = g_rgDefPropertyItems[ _idxDefProp ].vt;
propvar.ulVal = g_rgDefPropertyItems[ _idxDefProp ].pDefVals[ idx ].ulVal;
_pDefVals[ idx ].pszName = (LPTSTR) TraceAlloc( HEAP_ZERO_MEMORY, sizeof(_wszValue) );
if ( NULL == _pDefVals[ idx ].pszName )
goto OutOfMemory;
hr = THR( _ppui->FormatForDisplay( _fmtid, _propid, &propvar, PUIFFDF_DEFAULT, _pDefVals[ idx ].pszName, ARRAYSIZE(_wszValue) ) );
if ( FAILED( hr ) )
goto Cleanup;
}
*ppDefValOut = _pDefVals;
hr = S_OK;
Cleanup:
HRETURN( hr );
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
OutOfMemory:
hr = E_OUTOFMEMORY;
goto Cleanup;
UnexpectedState:
hr = THR( E_UNEXPECTED );
goto Cleanup;
}
//
// Description:
// Marks a property as having multiple values. This should only be called
// when multiple source documents have been selected and the values are
// all different.
//
// Return Value:
// S_OK
// Success!
//
HRESULT
CPropertyCacheItem::MarkMultiple( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
_fMultiple = TRUE;
PropVariantClear( &_propvar );
HRETURN( hr );
}