//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1994 - 1999. // // File: propbase.hxx // // Contents: Headers for common property handling routines // // Classes: CUtlPropInfo, // CUtlProps // // History: 10-28-97 danleg Created from monarch uprops.hpp // //---------------------------------------------------------------------------- #pragma once // // Constants and Static Struct // #define DEFAULT_MACHINE L"." const ULONG DWORDSNEEDEDPERSET = 2; const ULONG DWORDSNEEDEDTOTAL = DWORDSNEEDEDPERSET * 5; // // Macros // #define INRANGE(z,zmin,zmax) ( (zmin) <= (z) && (z) <= (zmax) ) // // Utility functions // // Bit array routines. // Two versions: one for a single DWORD, one for arrays. // Note that you pass in not a bit mask, but the bit number. // i.e. dwBit = 0,1,2,3,4...31 instead of 1,2,4,8,0x10,0x20... inline void SETBIT( DWORD &dwFlags, DWORD dwBit ) { dwFlags |= 1 << dwBit; } inline void CLEARBIT( DWORD &dwFlags, DWORD dwBit ) { dwFlags &= ~ (1<> 5) // dw / 32 = dw / (sizeof(DWORD)*8) #define ModDword(dw) (dw & (32-1)) // dw % 32 #define DwordSizeofBits(nBits) (nBits/32+1) // Use in array declarations inline void SETBIT( DWORD rgdwFlags[], const DWORD dwBit ) { rgdwFlags[DivDword(dwBit)] |= 1 << ModDword(dwBit); } inline void CLEARBIT( DWORD rgdwFlags[], const DWORD dwBit ) { rgdwFlags[DivDword(dwBit)] &= ~( 1 << ModDword(dwBit) ); } #define CLEARBITARRAY( rgdwFlags ) RtlZeroMemory( rgdwFlags, sizeof(rgdwFlags) ) inline DWORD TESTBIT( const DWORD rgdwFlags[], const DWORD dwBit ) { //old//Note: Not {0,1}, but from {0...2^32-1}. // Note: Now returns {0,1}. return ( rgdwFlags[DivDword(dwBit)] & ( 1 << ModDword(dwBit) ) ) != 0; } #undef DivDWord #undef ModDWord // // Forward Declarations // class CColumnIds; // // Constants and Static Struct // // leave plenty of space for localization. const ULONG CCH_GETPROPERTYINFO_DESCRIP_BUFFER_SIZE = 256; const DWORD GETPROPINFO_ALLPROPIDS = 0x0001; const DWORD GETPROPINFO_NOTSUPPORTED = 0x0002; const DWORD GETPROPINFO_ERRORSOCCURRED = 0x0004; const DWORD GETPROPINFO_VALIDPROP = 0x0008; const DWORD GETPROP_ALLPROPIDS = 0x0001; const DWORD GETPROP_NOTSUPPORTED = 0x0002; const DWORD GETPROP_ERRORSOCCURRED = 0x0004; const DWORD GETPROP_VALIDPROP = 0x0008; const DWORD GETPROP_PROPSINERROR = 0x0010; const DWORD SETPROP_BADOPTION = 0x0001; const DWORD SETPROP_NOTSUPPORTED = 0x0002; const DWORD SETPROP_VALIDPROP = 0x0004; const DWORD SETPROP_ERRORS = 0x0008; const DWORD SETPROP_COLUMN_LEVEL = 0x0010; const DWORD DBINTERNFLAGS_NOCHANGE = 0x00000000; const DWORD DBINTERNFLAGS_CHANGED = 0x00000001; const DWORD DBINTERNFLAGS_CHEAPTOREQ = 0x00000002; const DWORD DBINTERNFLAGS_INERROR = 0x00000004; const DWORD DBINTERNFLAGS_INERRORSAVED = 0x00000008; const DWORD DBINTERNFLAGS_TOTRUE = 0x80000000; // Additional Property Flags needed internally const DWORD DBPROPFLAGS_CHANGE = 0x80000000; // Flags for controlling UPROPSETS const DWORD UPROPSET_HIDDEN = 0x00000001; const DWORD UPROPSET_PASSTHROUGH = 0x00000002; // Rules for GetPropertiesArgChk const DWORD ARGCHK_PROPERTIESINERROR = 0x00000001; // // STRUCTURE DEFINITIONS // typedef struct tagPropColId* PPROPCOLID; typedef struct tagUPROPVAL { DBPROPOPTIONS dwOption; DWORD dwFlags; VARIANT vValue; } UPROPVAL; typedef struct tagUPROPINFO { DBPROPID dwPropId; LPCWSTR pwszDesc; VARTYPE VarType; DBPROPFLAGS dwFlags; } UPROPINFO; typedef struct tagUPROP { ULONG cPropIds; UPROPINFO** rgpUPropInfo; UPROPVAL* pUPropVal; } UPROP; typedef struct tagUPROPSET { const GUID* pPropSet; ULONG cUPropInfo; const UPROPINFO* pUPropInfo; DWORD dwFlags; } UPROPSET; //+------------------------------------------------------------------------- // // Class: CUtlPropInfo // // Purpose: Base class for property storage // // History: 11-12-97 danleg Created from Monarch // //-------------------------------------------------------------------------- class CUtlPropInfo { public: // // Ctor / Dtor // CUtlPropInfo(); virtual ~CUtlPropInfo() { }; SCODE GetPropertyInfo ( ULONG cPropertySets, const DBPROPIDSET rgPropertySets[], ULONG * pcPropertyInfoSets, DBPROPINFOSET ** prgPropertyInfoSets, WCHAR ** ppDescBuffer ); // // Get the count of propsets. // ULONG GetUPropSetCount() { return _cUPropSet; } // // Reset the count of propsets. // void SetUPropSetCount( ULONG c ) { _cUPropSet = c; } // // Pure Virtual // virtual SCODE InitAvailUPropSets( ULONG * pcUPropSet, UPROPSET ** ppUPropSet, ULONG * pcElemPerSupported )=0; virtual SCODE InitUPropSetsSupported( DWORD * rgdwSupported )=0; // // Load a localized description // virtual ULONG LoadDescription ( LPCWSTR pwszDesc, PWSTR pwszBuff, ULONG cchBuff )=0; protected: // // Initialization routine called called from constructors of derived // classes. // void FInit(); private: // // Count of UPropSet items // ULONG _cUPropSet; // // Pointer to UPropset items // UPROPSET * _pUPropSet; // // Count of UPropSet Indexes // ULONG _cPropSetDex; // // Pointer to Array of UPropSet Index values // XArray _xaiPropSetDex; // // Number of DWORDS per UPropSet to indicate supported UPropIds // ULONG _cElemPerSupported; // // Pointer to array of DWORDs indicating supported UPropIds // XArray _xadwSupported; // // Member functions // // Retrieve the property id pointer SCODE GetUPropInfoPtr ( ULONG iPropSetDex, DBPROPID dwPropertyId, UPROPINFO ** ppUPropInfo ); // Retrieve the property set indexes that match this property set. SCODE GetPropertySetIndex( const GUID * pPropertySet ); // Determine the number of description buffers needed ULONG CalcDescripBuffers( ULONG cPropInfoSet, DBPROPINFOSET* pPropInfoSet ); }; //+------------------------------------------------------------------------- // // Class: CUtlProps // // Purpose: Base class for property storage // // History: 11-12-97 danleg Created from Monarch // //-------------------------------------------------------------------------- class CUtlProps { public: // // Ctor / Dtor // CUtlProps( DWORD dwFlags = 0 ); virtual ~CUtlProps(); // // Fill default values again. // SCODE FillDefaultValues(ULONG ulPropSetTarget = ULONG_MAX); // // Check the arguments for Retrieve Properties // void GetPropertiesArgChk( const ULONG cPropertySets, const DBPROPIDSET rgPropertySets[], ULONG * pcProperties, DBPROPSET ** prgProperties ); // // Check the arguments for Set Properties // static void SetPropertiesArgChk( const ULONG cPropertySets, const DBPROPSET rgPropertySets[] ); // // Retrieve Properties // SCODE GetProperties ( const ULONG cPropertySets, const DBPROPIDSET rgPropertySets[], ULONG * pcProperties, DBPROPSET ** prgProperties ); // // Set Properties // SCODE SetProperties ( const ULONG cPropertySets, const DBPROPSET rgPropertySets[] ); inline void SetPropertyInError( const ULONG iPropSet, const ULONG iPropId ); inline void ClearPropertyInError( ) ; BOOL IsPropSet ( const GUID * pguidPropSet, DBPROPID dwPropId ); SCODE GetPropValue ( const GUID * pguidPropSet, DBPROPID dwPropId, VARIANT * pvValue ); SCODE SetPropValue ( const GUID * pguidPropSet, DBPROPID dwPropId, VARIANT * pvValue ); SCODE CopyUPropVal ( ULONG iPropSet, UPROPVAL * rgUPropVal ); // // Virtuals functions // virtual SCODE GetIndexofPropSet( const GUID * pPropSet, ULONG * pulCurSet ); virtual SCODE GetIndexofPropIdinPropSet( ULONG iCurSet, DBPROPID dwPropertyId, ULONG * piCurPropId ); // // Pure Virtuals // virtual SCODE InitAvailUPropSets( ULONG * pcUPropSet, UPROPSET ** ppUPropSet, ULONG * pcElemPerSupported )=0; virtual SCODE GetDefaultValue ( ULONG iPropSet, DBPROPID dwPropId, DWORD * dwOption, VARIANT * pVar )=0; virtual SCODE IsValidValue ( ULONG iCurSet, DBPROP * pDBProp )=0; virtual SCODE InitUPropSetsSupported( DWORD * rgdwSupported) = 0; // // Inlined functions // inline ULONG GetUPropSetCount() { return _cUPropSet; } inline void SetUPropSetCount( ULONG c ) { _cUPropSet = c; } // // NOTE: The following functions depend on all prior properties in the // array being writable. This is because the UPROP array contains only // writable elements, and the UPROPINFO array contains writable and // read-only elements. If this is a problem, we would need to define // which one it came from and add the appropriate asserts... // // Get DBPROPOPTIONS_xx inline DWORD GetPropOption ( ULONG iPropSet, ULONG iProp ); // Set DBPROPOPTIONS_xx inline void SetPropOption ( ULONG iPropSet, ULONG iProp, DWORD dwOption ); // // Determine if property is required and variant_true // inline BOOL IsRequiredTrue ( ULONG iPropSet, ULONG iProp ); inline DWORD GetInternalFlags( ULONG iPropSet, ULONG iProp ); inline void AddInternalFlags( ULONG iPropSet, ULONG iProp, DWORD dwFlag ); inline void RemoveInternalFlags ( ULONG iPropSet, ULONG iProp, DWORD dwFlag ); inline VARIANT * GetVariant ( ULONG iPropSet, ULONG iProp ); inline SCODE SetVariant ( ULONG iPropSet, ULONG iProp, VARIANT * pv ); inline void SetValEmpty ( ULONG iPropSet, ULONG iProp ); inline BOOL IsEmpty ( ULONG iPropSet, ULONG iProp ); inline void SetValBool ( ULONG iPropSet, ULONG iProp, VARIANT_BOOL bVal ); inline VARIANT_BOOL GetValBool ( ULONG iPropSet, ULONG iProp ); inline void SetValShort ( ULONG iPropSet, ULONG iProp, SHORT iVal ); inline SHORT GetValShort ( ULONG iPropSet, ULONG iProp ); inline void SetValLong ( ULONG iPropSet, ULONG iProp, LONG lVal ); inline LONG GetValLong ( ULONG iPropSet, ULONG iProp ); inline SCODE SetValString ( ULONG iPropSet, ULONG iProp, const WCHAR * pwsz ); inline const WCHAR * GetValString( ULONG iPropSet, ULONG iProp ); inline const GUID * GetGuid ( ULONG iPropSet); inline DWORD GetPropID ( ULONG iPropSet, ULONG iProp ); inline VARTYPE GetExpectedVarType( ULONG iPropSet, ULONG iProp ); // Inline Methods inline void CopyAvailUPropSets( ULONG * pcUPropSet, UPROPSET ** ppUPropSet, ULONG * pcElemPerSupported ); inline void CopyUPropSetsSupported( XArray & xadwSupported ); inline void CopyUPropInfo ( ULONG iPropSet, XArray & xapUPropInfo ); protected: // // Number of DWORDS per UPropSet to indicate supported UPropIds // ULONG _cElemPerSupported; // // Pointer to array of DWORDs indicating supported UPropIds // XArray _xadwSupported; // // Pointer to array of DWORDs indicating if property is in error // XArray _xadwPropsInError; // // Initialization Method // virtual void FInit ( CUtlProps * pCopyMe = NULL ); private: // // Count of UPropSet items // ULONG _cUPropSet; // //Pointer to UPropset items // UPROPSET * _pUPropSet; XArray _xaUProp; // // Count of Hidden items // ULONG _cUPropSetHidden; // // Configuration flags // DWORD _dwFlags; // // Count of UPropSet Indexes // ULONG _cPropSetDex; // // Pointer to Array of UPropSet Index values // XArray _xaiPropSetDex; void FreeMemory ( ); ULONG GetCountofWritablePropsInPropSet( ULONG iPropSet ); ULONG GetUPropValIndex( ULONG iCurset, DBPROPID dwPropId); SCODE SetProperty ( ULONG iCurSet, ULONG iCurProp, DBPROP * pDBProp); // // Retrieve the property set indexes that // match this property set. // SCODE GetPropertySetIndex( GUID * pPropertySet ); }; // -------------------------------------------------------------------------- // -------------------- I N L I N E F U N C T I O N S ---------------------- // -------------------------------------------------------------------------- inline void CUtlProps::CopyAvailUPropSets ( ULONG* pcUPropSet, UPROPSET** ppUPropSet, ULONG* pcElemPerSupported ) { Win4Assert( pcUPropSet && ppUPropSet && pcElemPerSupported ); *pcUPropSet = _cUPropSet; *ppUPropSet = _pUPropSet; *pcElemPerSupported = _cElemPerSupported; } inline void CUtlProps::CopyUPropSetsSupported ( XArray & xadwSupported ) { // if the passed in array already has elements, we will leak Win4Assert( xadwSupported.IsNull() ); xadwSupported.Init( _xadwSupported ); //RtlCopyMemory( xadwSupported.GetPointer(), // _xadwSupported.GetPointer(), // _cUPropSet * _cElemPerSupported * sizeof(DWORD) ); } inline void CUtlProps::CopyUPropInfo ( ULONG iPropSet, XArray & xapUPropInfo ) { Win4Assert( xapUPropInfo.IsNull() ); Win4Assert( iPropSet < _cUPropSet ); xapUPropInfo.Init( _xaUProp[iPropSet].cPropIds ); RtlCopyMemory( xapUPropInfo.GetPointer(), _xaUProp[iPropSet].rgpUPropInfo, xapUPropInfo.SizeOf() ); } inline void CUtlProps::ClearPropertyInError() { Win4Assert( !_xadwPropsInError.IsNull() ); RtlZeroMemory( _xadwPropsInError.GetPointer(), _cUPropSet * _cElemPerSupported * sizeof(DWORD) ); }; // Save a few lines by defining a common set of asserts. #define is_proper_range \ ( (iPropSet < _cUPropSet) \ && (iProp < _pUPropSet[iPropSet].cUPropInfo) \ && (iProp < _xaUProp[iPropSet].cPropIds) ) // Set Property Ids that should be in Error inline void CUtlProps::SetPropertyInError ( const ULONG iPropSet, const ULONG iProp ) { SETBIT(&(_xadwPropsInError[iPropSet * _cElemPerSupported]), iProp); }; // determine if the property is Required and VARIANT_TRUE inline BOOL CUtlProps::IsRequiredTrue(ULONG iPropSet, ULONG iProp) { Win4Assert( is_proper_range ); Win4Assert(_xaUProp[iPropSet].pUPropVal[iProp].vValue.vt == VT_BOOL); Win4Assert(V_BOOL(&_xaUProp[iPropSet].pUPropVal[iProp].vValue) == VARIANT_TRUE || V_BOOL(&_xaUProp[iPropSet].pUPropVal[iProp].vValue) == VARIANT_FALSE); return( !(_xaUProp[iPropSet].pUPropVal[iProp].dwFlags & DBINTERNFLAGS_INERROR) && (_xaUProp[iPropSet].pUPropVal[iProp].dwOption == DBPROPOPTIONS_REQUIRED) && (V_BOOL(&_xaUProp[iPropSet].pUPropVal[iProp].vValue) == VARIANT_TRUE) ); }; // Get DBPROPOPTIONS_xx inline DWORD CUtlProps::GetPropOption(ULONG iPropSet, ULONG iProp) { Win4Assert( is_proper_range ); return _xaUProp[iPropSet].pUPropVal[iProp].dwOption; } inline void CUtlProps::SetPropOption(ULONG iPropSet, ULONG iProp, DWORD dwOption) { Win4Assert( is_proper_range ); _xaUProp[iPropSet].pUPropVal[iProp].dwOption = dwOption; } inline DWORD CUtlProps::GetInternalFlags(ULONG iPropSet, ULONG iProp) { Win4Assert( is_proper_range ); return _xaUProp[iPropSet].pUPropVal[iProp].dwFlags; } inline void CUtlProps::AddInternalFlags(ULONG iPropSet, ULONG iProp, DWORD dwFlags) { Win4Assert( is_proper_range ); _xaUProp[iPropSet].pUPropVal[iProp].dwFlags |= dwFlags; } inline void CUtlProps::RemoveInternalFlags(ULONG iPropSet, ULONG iProp, DWORD dwFlags) { Win4Assert( is_proper_range ); _xaUProp[iPropSet].pUPropVal[iProp].dwFlags &= ~dwFlags; } inline VARIANT * CUtlProps::GetVariant(ULONG iPropSet, ULONG iProp) { Win4Assert( is_proper_range ); return & _xaUProp[iPropSet].pUPropVal[iProp].vValue; } inline SCODE CUtlProps::SetVariant(ULONG iPropSet, ULONG iProp, VARIANT *pv ) { Win4Assert( is_proper_range ); // Does VariantClear first. return VariantCopy( &_xaUProp[iPropSet].pUPropVal[iProp].vValue, pv ); } inline void CUtlProps::SetValEmpty(ULONG iPropSet, ULONG iProp) { Win4Assert( is_proper_range ); VariantClear( &_xaUProp[iPropSet].pUPropVal[iProp].vValue ); } inline BOOL CUtlProps::IsEmpty(ULONG iPropSet, ULONG iProp) { Win4Assert( is_proper_range ); return ( _xaUProp[iPropSet].pUPropVal[iProp].vValue.vt == VT_EMPTY); } inline void CUtlProps::SetValBool(ULONG iPropSet, ULONG iProp, VARIANT_BOOL bVal ) { Win4Assert( is_proper_range ); // Note that we accept any "true" value. VariantClear(&_xaUProp[iPropSet].pUPropVal[iProp].vValue); _xaUProp[iPropSet].pUPropVal[iProp].vValue.vt = VT_BOOL; V_BOOL(&_xaUProp[iPropSet].pUPropVal[iProp].vValue) = (bVal ? VARIANT_TRUE : VARIANT_FALSE); } inline VARIANT_BOOL CUtlProps::GetValBool(ULONG iPropSet, ULONG iProp) { Win4Assert( is_proper_range ); Win4Assert(_xaUProp[iPropSet].pUPropVal[iProp].vValue.vt == VT_BOOL); return V_BOOL(&_xaUProp[iPropSet].pUPropVal[iProp].vValue); } inline void CUtlProps::SetValShort(ULONG iPropSet, ULONG iProp, SHORT iVal ) { Win4Assert( is_proper_range ); VariantClear(&_xaUProp[iPropSet].pUPropVal[iProp].vValue); _xaUProp[iPropSet].pUPropVal[iProp].vValue.vt = VT_I2; _xaUProp[iPropSet].pUPropVal[iProp].vValue.iVal = iVal; } inline SHORT CUtlProps::GetValShort(ULONG iPropSet, ULONG iProp) { Win4Assert( is_proper_range ); Win4Assert(_xaUProp[iPropSet].pUPropVal[iProp].vValue.vt == VT_I2); return _xaUProp[iPropSet].pUPropVal[iProp].vValue.iVal; } inline void CUtlProps::SetValLong(ULONG iPropSet, ULONG iProp, LONG lVal ) { Win4Assert( is_proper_range ); VariantClear(&_xaUProp[iPropSet].pUPropVal[iProp].vValue); _xaUProp[iPropSet].pUPropVal[iProp].vValue.vt = VT_I4; _xaUProp[iPropSet].pUPropVal[iProp].vValue.lVal = lVal; } // Get value as long inline LONG CUtlProps::GetValLong(ULONG iPropSet, ULONG iProp) { Win4Assert( is_proper_range ); Win4Assert(_xaUProp[iPropSet].pUPropVal[iProp].vValue.vt == VT_I4); return _xaUProp[iPropSet].pUPropVal[iProp].vValue.lVal; } // Set value as string inline SCODE CUtlProps::SetValString(ULONG iPropSet, ULONG iProp, const WCHAR *pwsz ) { Win4Assert( is_proper_range ); VARIANT *pv = &_xaUProp[iPropSet].pUPropVal[iProp].vValue; VariantClear(pv); pv->bstrVal = SysAllocString(pwsz); if ( pv->bstrVal ) pv->vt = VT_BSTR; else return E_FAIL; // See if this was used for non-string type. // Typically this is an easy way to pass integer as a string. if ( GetExpectedVarType(iPropSet,iProp) == VT_BSTR ) return NOERROR; if ( pwsz[0] != L'\0' ) return VariantChangeType( pv, pv, 0, GetExpectedVarType(iPropSet,iProp) ); // Set to "", which for non-string means empty. SysFreeString(pv->bstrVal); pv->vt = VT_EMPTY; return NOERROR; } inline const WCHAR * CUtlProps::GetValString(ULONG iPropSet, ULONG iProp) { Win4Assert( is_proper_range ); Win4Assert(_xaUProp[iPropSet].pUPropVal[iProp].vValue.vt == VT_BSTR); return _xaUProp[iPropSet].pUPropVal[iProp].vValue.bstrVal; } inline const GUID * CUtlProps::GetGuid(ULONG iPropSet) { Win4Assert(iPropSet < _cUPropSet); return _pUPropSet[iPropSet].pPropSet; } inline DWORD CUtlProps::GetPropID(ULONG iPropSet, ULONG iProp) { Win4Assert( is_proper_range ); return _pUPropSet[iPropSet].pUPropInfo[iProp].dwPropId; } inline VARTYPE CUtlProps::GetExpectedVarType(ULONG iPropSet, ULONG iProp) { Win4Assert( is_proper_range ); return _pUPropSet[iPropSet].pUPropInfo[iProp].VarType; } #undef is_proper_range