//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1994-2000. // // File: PLIST.HXX // // Contents: Property List class // // Classes: CPropertyList // CPropEntry // CPListException // // History: 17-May-94 t-jeffc Created. // //---------------------------------------------------------------------------- #pragma once const MAX_LINE_LENGTH = 512; const MAX_PROPNAME_LENGTH = 200; unsigned const PLIST_DEFAULT_WIDTH = 10; // forward decls class CQueryScanner; class CEmptyPropertyList; class CPropEntry; //+--------------------------------------------------------------------------- // // Class: CPropEntryIter // // Purpose: Iterates over CPropEntry items in a CPropertyList // // History: 28-Feb-96 dlee Created. // //---------------------------------------------------------------------------- class CPropEntryIter { public: CPropEntryIter( CEmptyPropertyList & list ); CPropEntry const * Next(); private: CEmptyPropertyList & _list; }; //+--------------------------------------------------------------------------- // // Class: CPropEntry // // Purpose: One entry in the 'friendly' to 'ugly' property name // mapping. A list of these is managed by CPropertyList. // // History: 17-May-94 t-jeffc Created. // //---------------------------------------------------------------------------- class CPropEntry { public: CPropEntry( XPtrST & wcsDisplayName, XPtrST & wcsName ) : _szFriendlyName( wcsName.Acquire() ), _szDisplayName( wcsDisplayName.Acquire() ), _ppentryNext( 0 ), _ptype(0), _uWidth(0), _fIsDisplayed( TRUE ), _fStaticStrings( FALSE ) { } CPropEntry( XPtrST & wcsName, DBTYPE dbType, const GUID & guid, PROPID propId ) : _szFriendlyName( wcsName.Acquire() ), _szDisplayName( 0 ), _ppentryNext( 0 ), _ptype(dbType), _uWidth(0), _fIsDisplayed( TRUE ), _fStaticStrings( FALSE ) { _prop.SetPropSet(guid); _prop.SetProperty(propId); } CPropEntry( XPtrST & wcsName, DBTYPE dbType, const GUID & guid, const WCHAR * wcsPropName ) : _szFriendlyName( wcsName.Acquire() ), _szDisplayName( 0 ), _ppentryNext( 0 ), _ptype(dbType), _uWidth(0), _fIsDisplayed( TRUE ), _fStaticStrings( FALSE ) { _prop.SetPropSet(guid); if ( !_prop.SetProperty(wcsPropName) ) THROW( CException(E_OUTOFMEMORY) ); } CPropEntry( XPtrST & wcsName, DBTYPE dbType, const DBID dbCol ) : _szFriendlyName( wcsName.Acquire() ), _szDisplayName( 0 ), _ppentryNext( 0 ), _ptype(dbType), _uWidth(0), _fIsDisplayed( TRUE ), _fStaticStrings( FALSE ), _prop( dbCol ) { } CPropEntry( LPWSTR wcsName, LPWSTR wcsDisplayName, DBTYPE dbType, const DBID dbCol ) : _szFriendlyName( wcsName ), _szDisplayName( wcsDisplayName ), _ppentryNext( 0 ), _ptype(dbType), _uWidth(0), _fIsDisplayed( TRUE ), _fStaticStrings( TRUE ), _prop( dbCol ) { } ~CPropEntry() { if (! _fStaticStrings) { delete _szFriendlyName; delete _szDisplayName; } } BOOL NameMatch( WCHAR const * wcsName ) const { return !wcscmp( wcsName, _szFriendlyName ); } BOOL DisplayNameMatch( WCHAR const * wcsName ) const { return !_wcsicmp( wcsName, _szDisplayName ); } // getters/setters CPropEntry * Next() const { return _ppentryNext; } void SetNext( CPropEntry * ppentry ) { _ppentryNext = ppentry; } DBTYPE GetPropType() const { return _ptype; } void SetPropType( DBTYPE ptype ) { _ptype = ptype; } unsigned int GetWidth() const { return _uWidth; } void SetWidth( unsigned int uWidth ) { _uWidth = uWidth; } CDbColId & PropSpec() { return _prop; } CDbColId const & PropSpec() const { return _prop; } WCHAR const * GetName() const { return _szFriendlyName; } WCHAR const * GetDisplayName() const { return _szDisplayName; } BOOL IsDisplayed() const { return _fIsDisplayed; } void SetDisplayed( BOOL fDisplayed ) { _fIsDisplayed = fDisplayed; } private: CPropEntry * _ppentryNext; WCHAR * _szFriendlyName; WCHAR * _szDisplayName; CDbColId _prop; unsigned int _uWidth; BOOL _fIsDisplayed; BOOL _fStaticStrings; DBTYPE _ptype; }; // Keep this in sync with CPropEntry. Can't use CPropEntry because // CDbColId can't be initialized with static initializer, and it's // too painful to use DBID in CPropEntry. struct SPropEntry { CPropEntry * _ppentryNext; WCHAR * _szFriendlyName; WCHAR * _szDisplayName; DBID _prop; unsigned int _uWidth; BOOL _fIsDisplayed; BOOL _fStaticStrings; DBTYPE _ptype; }; //+--------------------------------------------------------------------------- // // Class: CEmptyPropertyList // // Purpose: Base class implementing common functionality. // // History: 28-Aug-97 krishnan Created. // //---------------------------------------------------------------------------- class CEmptyPropertyList : public IColumnMapper { public: CEmptyPropertyList() : _cRefs( 1 ), _iLastEntryPos( 0 ), _pPropIterator( 0 ) { } static unsigned GetPropTypeCount(); static WCHAR const * GetPropTypeName( unsigned i ); static DBTYPE GetPropType( unsigned i ); BOOL GetPropInfo( WCHAR const * wcsPropName, CDbColId ** ppprop, DBTYPE * pproptype, unsigned int * puWidth ); BOOL GetPropInfo( CDbColId const & prop, WCHAR const ** pwcsName, DBTYPE * pproptype, unsigned int * puWidth ); // // This is the same for all property lists, since it only // itetarates through the list of entries using proplist // specific iterators. // CPropEntry const * Find( CDbColId const & prop ); // // These are only meaningful where there is a list. // virtual CPropEntry const * Find( WCHAR const * wcsName ) = 0; virtual void AddEntry( CPropEntry * ppentry, int iLine ) = 0; virtual CPropEntry const * Next() = 0; virtual void InitIterator() = 0; virtual ULONG GetCount() = 0; virtual SCODE GetAllEntries(CPropEntry **ppPropEntries, ULONG ulMaxCount) = 0; // // IUnknown methods. // STDMETHOD(QueryInterface) (THIS_ REFIID riid, void ** ppvObj); STDMETHOD_(ULONG, AddRef) (THIS); STDMETHOD_(ULONG, Release) (THIS); // // IColumnMapper methods // STDMETHOD(GetPropInfoFromName) ( const WCHAR *wcsPropName, DBID * *ppPropId, DBTYPE *pPropType, unsigned int *puiWidth); STDMETHOD(GetPropInfoFromId) ( const DBID *pPropId, WCHAR * *pwcsName, DBTYPE *pPropType, unsigned int *puiWidth); STDMETHOD(EnumPropInfo) ( ULONG iEntry, const WCHAR * *pwcsName, DBID * *ppPropId, DBTYPE *pPropType, unsigned int *puiWidth); STDMETHOD(IsMapUpToDate) () = 0; protected: // this should be virtual so the derived classes's destructor will always // be called. virtual ~CEmptyPropertyList() { delete _pPropIterator; } private: LONG _cRefs; // ref counting // Variables to support EnumPropInfo ULONG _iLastEntryPos; // last retrieved entry position. CPropEntryIter * _pPropIterator; // the enumerator }; //+--------------------------------------------------------------------------- // // Class: CStaticPropertyList // // Purpose: Static list of 'friendly' to 'ugly' property name mapping. // It also holds an array of "file" based property mapping, which // will be used only when file based entries are used to override // the static entries (as in CPropListFile) // // History: 17-May-94 t-jeffc Created. // 28-Aug-97 krishnan IColumnMapper replaces PPropertyList. // //---------------------------------------------------------------------------- class CStaticPropertyList : public CEmptyPropertyList { public: CStaticPropertyList(ULONG ulCodePage = CP_ACP) : CEmptyPropertyList(), _ulCodePage( ulCodePage ), _icur( 0 ), _pcur( 0 ) { } virtual void AddEntry( CPropEntry * ppentry, int iLine ) { Win4Assert(!"Should not have been called."); } virtual CPropEntry const * Find( WCHAR const * wcsName ); virtual CPropEntry const * Find( CDbColId const & prop ) { return CEmptyPropertyList::Find(prop); } virtual CPropEntry const * Next(); virtual void InitIterator(); STDMETHOD(IsMapUpToDate) () { // the static property list is always up to date. return S_OK; }; virtual ULONG GetCount() {return cStaticPropEntries;}; virtual SCODE GetAllEntries(CPropEntry **ppPropEntries, ULONG ulMaxCount); protected: enum { cStaticPropHash = 1311 }; // Static (system-defined) properties, like path and filename static const CPropEntry * _aStaticEntries[ cStaticPropHash ]; static const unsigned cStaticPropEntries; private: ULONG _ulCodePage; CPropEntry const * _pcur; unsigned _icur; }; //+--------------------------------------------------------------------------- // // Class: CPropertyList // // Purpose: Parses and manages a 'friendly' to 'ugly' property name // mapping. // // History: 17-May-94 t-jeffc Created. // 28-Aug-97 krishnan IColumnMapper replaces PPropertyList. // //---------------------------------------------------------------------------- class CPropertyList : public CEmptyPropertyList { public: CPropertyList(ULONG ulCodePage = CP_ACP) : CEmptyPropertyList(), _ulCodePage( ulCodePage ), _icur( 0 ), _pcur( 0 ), _ulCount( 0 ) { RtlZeroMemory( _aEntries, sizeof _aEntries ); } void ClearList(); virtual void AddEntry( CPropEntry * ppentry, int iLine ); virtual CPropEntry const * Find( WCHAR const * wcsName ); virtual CPropEntry const * Find( CDbColId const & prop ) { return CEmptyPropertyList::Find(prop); } virtual CPropEntry const * Next(); virtual void InitIterator(); virtual ULONG GetCount(); virtual SCODE GetAllEntries(CPropEntry **ppPropEntries, ULONG ulMaxCount); static void ParseOneLine( CQueryScanner & scan, int iLine, XPtr & propentry ); STDMETHOD(IsMapUpToDate) () { // // The local list is always considered up to date because it can't // go get new items even if it knew there were new ones. The // owner adds them. // return S_OK; }; ~CPropertyList(); private: CPropEntry * FindDynamic( WCHAR const * wcsName ); enum { cPropHash = 13}; // Dynamic (user-defined) properties CPropEntry * _aEntries[ cPropHash ]; ULONG _ulCodePage; CMutexSem _mtxList; CPropEntry const * _pcur; unsigned _icur; ULONG _ulCount; }; inline ULONG CPropertyList::GetCount() { return _ulCount; } //+--------------------------------------------------------------------------- // // Class: CPListException // // Purpose: Exception class for property list errors // // History: 17-May-94 t-jeffc Created. // //---------------------------------------------------------------------------- class CPListException : public CException { public: CPListException( SCODE ple, int iLine ) : CException( ple ), _iLine( iLine ) { } SCODE GetPListError() { return GetErrorCode(); } int GetLine() { return _iLine; } private: int _iLine; }; inline CPropEntryIter::CPropEntryIter( CEmptyPropertyList & list ) : _list( list ) { _list.InitIterator(); } inline CPropEntry const * CPropEntryIter::Next() { return _list.Next(); } ULONG HashFun( WCHAR const * pwcName );