/*++ Copyright (c) 1997 Microsoft Corporation Module Name: membag.h Abstract: This module contains the definition for the ISEODictionary object in memory. Author: Andy Jacobs (andyj@microsoft.com) Revision History: andyj 02/10/97 created andyj 02/12/97 Converted PropertyBag's to Dictonary's --*/ // MEMBAG.h : Declaration of the CSEOMemDictionary #include "tfdlist.h" #include "rwnew.h" enum DataType {Empty, DWord, String, Interface}; class DataItem { public: typedef DLIST_ENTRY* (*PFNDLIST)( class DataItem*); DataItem() { m_pszKey = NULL; eType = Empty; }; DataItem(DWORD d) { eType = DWord; dword = d; }; DataItem(LPCSTR s, int iSize = -1) { eType = String; iStringSize = ((iSize >= 0) ? iSize : (lstrlen(s) + 1)); pStr = (LPSTR) MyMalloc(iStringSize); if (pStr) { strncpy(pStr, s, iStringSize); } m_pszKey = NULL; }; DataItem(LPCWSTR s, int iSize = -1) { eType = String; iStringSize = sizeof(WCHAR) * ((iSize >= 0) ? iSize : (wcslen(s) + 1)); pStr = (LPSTR) MyMalloc(iStringSize); if (pStr) { ATLW2AHELPER(pStr, s, iStringSize); } m_pszKey = NULL; }; DataItem(IUnknown *p) { eType = Interface; pUnk = p; if(pUnk) pUnk->AddRef(); m_pszKey = NULL; } DataItem(const DataItem &diItem) { eType = diItem.eType; if(eType == DWord) dword = diItem.dword; else if(eType == String) { iStringSize = diItem.iStringSize; pStr = (LPSTR) MyMalloc(iStringSize); if (pStr) { strncpy(pStr, diItem.pStr, iStringSize); } } else if(eType == Interface) { pUnk = diItem.pUnk; if(pUnk) pUnk->AddRef(); } if (diItem.m_pszKey) { m_pszKey = (LPSTR) MyMalloc(lstrlen(diItem.m_pszKey) + 1); if (m_pszKey) { strcpy(m_pszKey, diItem.m_pszKey); } } else { m_pszKey = NULL; } }; DataItem &operator=(const DataItem &diItem) { eType = diItem.eType; if(eType == DWord) dword = diItem.dword; else if(eType == String) {iStringSize = diItem.iStringSize; pStr = (LPSTR) MyMalloc(iStringSize); if (pStr) { strncpy(pStr, diItem.pStr, iStringSize);} } else if(eType == Interface) {pUnk = diItem.pUnk; if(pUnk) pUnk->AddRef();} if (diItem.m_pszKey) { m_pszKey = (LPSTR) MyMalloc(lstrlen(diItem.m_pszKey) + 1); if (m_pszKey) { strcpy(m_pszKey, diItem.m_pszKey); } } else { m_pszKey = NULL; } return *this; }; DataItem(VARIANT *pVar); ~DataItem() { if(eType == String) MyFree(pStr); else if((eType == Interface) && pUnk) pUnk->Release(); eType = Empty; if (m_pszKey) { MyFree(m_pszKey); m_pszKey = NULL; } }; BOOL SetKey(LPCSTR pszKey) { if (m_pszKey) { MyFree(m_pszKey); m_pszKey = NULL; } m_pszKey = (LPSTR) MyMalloc(lstrlen(pszKey) + 1); if (!m_pszKey) return FALSE; strcpy(m_pszKey, pszKey); return TRUE; } BOOL IsEmpty() const {return (eType == Empty);}; BOOL IsDWORD() const {return (eType == DWord);}; BOOL IsString() const {return (eType == String);}; BOOL IsInterface() const {return (eType == Interface);}; operator DWORD() const {return (const) (IsDWORD() ? dword : 0);}; operator LPCSTR() const {return (IsString() ? pStr : NULL);}; LPCSTR GetString() const {return (IsString() ? pStr : NULL);}; operator LPUNKNOWN() const {return (IsInterface() ? pUnk : NULL);}; HRESULT AsVARIANT(VARIANT *pVar) const; int StringSize() const {return iStringSize;}; static DLIST_ENTRY *GetListEntry(DataItem *p) { return &p->m_listentry; } LPCSTR GetKey() { return m_pszKey; } private: DataType eType; int iStringSize; union { DWORD dword; LPSTR pStr; LPUNKNOWN pUnk; }; DLIST_ENTRY m_listentry; LPSTR m_pszKey; }; class ComparableString { public: ComparableString(LPCSTR p = NULL) : m_ptr(0), m_bAlloc(TRUE) { if(!p) return; m_ptr = (LPSTR) MyMalloc(lstrlen(p) + 1); if (m_ptr) { lstrcpy(m_ptr, p); } }; ComparableString(const ComparableString &csOther) : m_ptr(0) { LPCSTR p = csOther.m_ptr; m_ptr = (LPSTR) MyMalloc(lstrlen(p) + 1); if (m_ptr) { lstrcpy(m_ptr, p); } }; ~ComparableString() {if(m_bAlloc&&m_ptr) MyFree(m_ptr);}; LPCSTR Data() const {return m_ptr;}; bool operator<(const ComparableString &csOther) const { if (!m_ptr || !csOther.m_ptr) { if (csOther.m_ptr) { return (true); } return (false); } return (lstrcmpi(m_ptr, csOther.m_ptr) < 0);}; protected: LPSTR m_ptr; BOOL m_bAlloc; }; class ComparableStringRef : public ComparableString { public: ComparableStringRef(LPCSTR p) { m_ptr = (LPSTR) p; m_bAlloc = FALSE; }; }; typedef TDListHead OurList; class OurMap { public: class iterator : public TDListIterator { public: iterator(OurList *pHead) : TDListIterator(pHead) { m_fFound = FALSE; } // get the key for the current item LPCSTR GetKey() { return Current()->GetKey(); } // get the data for the current item DataItem *GetData() { return Current(); } void operator++() { Next(); } DataItem *operator*() { return Current(); } void SetList(OurMap *pMap) { ReBind(&(pMap->m_list)); } // point the iterator to a specific item in the list // arguments: // pszKey - key to find // iMatchType - -1 == point at first item with smaller key // 0 == point at item with key // 1 == point at first item with larger key // returns: // TRUE if a match was found, FALSE otherwise BOOL find(LPCSTR pszKey, DWORD iMatchType = 0) { if (strncmp(pszKey, "-1", 2) == 0) DebugBreak(); // reset the iterator Front(); // walk until we match the key while (!AtEnd()) { const char *pszCurrentKey = Current()->GetKey(); if (lstrcmpi(pszCurrentKey, pszKey) == iMatchType) { m_fFound = TRUE; return TRUE; } Next(); } m_fFound = FALSE; return FALSE; }; // did the last search succeed? BOOL Found() { return m_fFound; } private: BOOL m_fFound; }; friend iterator; OurMap() { m_cList = 0; } ~OurMap() { // remove all items from the list while (m_cList) { delete m_list.PopFront(); m_cList--; } _ASSERT(m_list.IsEmpty()); } void erase(iterator i) { m_cList--; delete i.RemoveItem(); } BOOL insert(LPCSTR pszKey, DataItem di) { char buf[255]; OurMap::iterator it(&m_list); DataItem *pDI = new DataItem(); if (pDI == NULL) return FALSE; // copy the data item to the one that we will insert into // our list *pDI = di; if (!pDI->SetKey(pszKey)) { delete pDI; return FALSE; } // find the first item with a larger key. if no such item was // found then insert at head of list if (it.find(pszKey, 1)) { it.InsertBefore(pDI); } else { m_list.PushFront(pDI); } m_cList++; return TRUE; } iterator find(LPCSTR pszKey) { OurMap::iterator it(&m_list); it.find(pszKey); return it; } iterator begin() { OurMap::iterator it(&m_list); return it; } long size() { return m_cList; } private: OurList m_list; long m_cList; }; ///////////////////////////////////////////////////////////////////////////// // CSEOMemDictionary class ATL_NO_VTABLE CSEOMemDictionary : public CComObjectRootEx, public CComCoClass, public IDispatchImpl, public IPropertyBag, public IDispatchImpl { friend class CSEOMemDictionaryEnum; // Helper class public: HRESULT FinalConstruct(); void FinalRelease(); DECLARE_PROTECT_FINAL_CONSTRUCT(); DECLARE_REGISTRY_RESOURCEID_EX(IDR_StdAfx, L"SEOMemDictionary Class", L"SEO.SEOMemDictionary.1", L"SEO.SEOMemDictionary"); BEGIN_COM_MAP(CSEOMemDictionary) COM_INTERFACE_ENTRY(ISEODictionary) COM_INTERFACE_ENTRY(IPropertyBag) COM_INTERFACE_ENTRY(IEventPropertyBag) COM_INTERFACE_ENTRY_IID(IID_IDispatch, IEventPropertyBag) COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pUnkMarshaler.p) END_COM_MAP() // ISEODictionary public: virtual /* [id][propget][helpstring] */ HRESULT STDMETHODCALLTYPE get_Item( /* [in] */ VARIANT __RPC_FAR *pvarName, /* [retval][out] */ VARIANT __RPC_FAR *pvarResult); virtual /* [propput][helpstring] */ HRESULT STDMETHODCALLTYPE put_Item( /* [in] */ VARIANT __RPC_FAR *pvarName, /* [in] */ VARIANT __RPC_FAR *pvarValue); virtual /* [hidden][id][propget][helpstring] */ HRESULT STDMETHODCALLTYPE get__NewEnum( /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunkResult); virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetVariantA( /* [in] */ LPCSTR pszName, /* [retval][out] */ VARIANT __RPC_FAR *pvarResult); virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetVariantW( /* [in] */ LPCWSTR pszName, /* [retval][out] */ VARIANT __RPC_FAR *pvarResult); virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetVariantA( /* [in] */ LPCSTR pszName, /* [in] */ VARIANT __RPC_FAR *pvarValue); virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetVariantW( /* [in] */ LPCWSTR pszName, /* [in] */ VARIANT __RPC_FAR *pvarValue); virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetStringA( /* [in] */ LPCSTR pszName, /* [out][in] */ DWORD __RPC_FAR *pchCount, /* [retval][size_is][out] */ LPSTR pszResult); virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetStringW( /* [in] */ LPCWSTR pszName, /* [out][in] */ DWORD __RPC_FAR *pchCount, /* [retval][size_is][out] */ LPWSTR pszResult); virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetStringA( /* [in] */ LPCSTR pszName, /* [in] */ DWORD chCount, /* [size_is][in] */ LPCSTR pszValue); virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetStringW( /* [in] */ LPCWSTR pszName, /* [in] */ DWORD chCount, /* [size_is][in] */ LPCWSTR pszValue); virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetDWordA( /* [in] */ LPCSTR pszName, /* [retval][out] */ DWORD __RPC_FAR *pdwResult); virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetDWordW( /* [in] */ LPCWSTR pszName, /* [retval][out] */ DWORD __RPC_FAR *pdwResult); virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetDWordA( /* [in] */ LPCSTR pszName, /* [in] */ DWORD dwValue); virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetDWordW( /* [in] */ LPCWSTR pszName, /* [in] */ DWORD dwValue); virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetInterfaceA( /* [in] */ LPCSTR pszName, /* [in] */ REFIID iidDesired, /* [retval][iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunkResult); virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetInterfaceW( /* [in] */ LPCWSTR pszName, /* [in] */ REFIID iidDesired, /* [retval][iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunkResult); virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetInterfaceA( /* [in] */ LPCSTR pszName, /* [in] */ IUnknown __RPC_FAR *punkValue); virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetInterfaceW( /* [in] */ LPCWSTR pszName, /* [in] */ IUnknown __RPC_FAR *punkValue); DECLARE_GET_CONTROLLING_UNKNOWN(); // IPropertyBag public: HRESULT STDMETHODCALLTYPE Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog); HRESULT STDMETHODCALLTYPE Write(LPCOLESTR pszPropName, VARIANT *pVar); // IEventPropertyBag public: HRESULT STDMETHODCALLTYPE Item(VARIANT *pvarPropDesired, VARIANT *pvarPropValue); HRESULT STDMETHODCALLTYPE Name(long lPropIndex, BSTR *pbstrPropName); HRESULT STDMETHODCALLTYPE Add(BSTR pszPropName, VARIANT *pvarPropValue); HRESULT STDMETHODCALLTYPE Remove(VARIANT *pvarPropDesired); HRESULT STDMETHODCALLTYPE get_Count(long *plCount); /* Just use the get__NewEnum from ISEODictionary HRESULT STDMETHODCALLTYPE get__NewEnum(IUnknown **ppUnkEnum); */ protected: HRESULT Insert(LPCSTR pszName, const DataItem &diItem); private: // Private data OurMap m_mData; CShareLockNH m_lock; CComPtr m_pUnkMarshaler; };