1289 lines
23 KiB
C++
1289 lines
23 KiB
C++
|
//
|
||
|
// 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 );
|
||
|
}
|