home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-01-02 | 17.2 KB | 663 lines | [TEXT/dosa] |
- //
- // CPropBag.CPP
- //
- // Copyright (C) Microsoft Corporation, 1996
- //
-
- #include "headers.h"
-
-
- #define PBCONTENTS "%%pbcontents%%"
-
- //======================================================================
- //
- CPropertyBag::CPropertyBag()
- : m_cRef(1), m_pPropertiesTail(NULL),
- m_pPropertiesHead(NULL), m_cProperties(0), m_pbContents(0)
- {
- // This is a standalone COM object...
- // increase the ref count on the DLL so the DLL knows not to unload
- // until the last object has been destroyed
-
- DLLAddRef();
-
- }
-
- //======================================================================
- //
- CPropertyBag::~CPropertyBag()
- {
- DLLRelease();
- deletePropertyList();
-
- //
- // BUGBUG: davidna 5/7/96: Beta1 Hack.
- //
- // m_pbContents exists only if the OC knows of the %%PBCONTENTS%% name
- // and reads it.
- // Hopefully this just means the JavaOC
- //
- if(m_pbContents)
- {
- ULONG x =0, y = 2 * m_cProperties;
-
- char far * *pContents = (char **) ((ULONG)m_pbContents + sizeof(ULONG));
-
- // The storage for m_pbContents goes like this:
- // We have pointers to the name/value pairs following the
- // the count (ULONG) of items (or pairs)
- // we allocated storage for all the values so we must now set them free
-
-
- // pContents[0] is the first item name and
- // pContents[1] is the first item value
- // so bump past the name
- pContents++;
-
- for(x = 0; x < y; x+=2)
- {
- if(pContents[x])
- GTR_FREE(pContents[x]); // free the allocation for the value
- }
- GTR_FREE(m_pbContents);
- }
-
- }
- /*******************************************************************
-
- NAME: CPropertyBag::AddRef
-
- SYNOPSIS: Standard implementation of IUnknown::AddRef.
-
- ********************************************************************/
- STDMETHODIMP_(ULONG) CPropertyBag::AddRef(void)
- {
- return ++m_cRef;
- }
-
-
- /*******************************************************************
-
- NAME: CPropertyBag::Release
-
- SYNOPSIS: Standard implementation of IUnknown::Release
-
- ********************************************************************/
- STDMETHODIMP_(ULONG) CPropertyBag::Release(void)
- {
-
- if (--m_cRef == 0)
- {
- delete this;
- return 0;
- }
- return m_cRef;
- }
- /*******************************************************************
-
- NAME: CPropertyBag::QueryInterface
-
- SYNOPSIS: Standard implementation of IUnknown::QueryInterface.
-
- NOTES:
-
- ********************************************************************/
- STDMETHODIMP CPropertyBag::QueryInterface(REFIID riid, LPVOID *ppvObj)
- {
- // ppvObj must not be NULL
- ASSERT(ppvObj != NULL);
-
- if (ppvObj == NULL)
- return E_INVALIDARG;
-
- *ppvObj = NULL;
-
- if (riid == IID_IUnknown)
- *ppvObj = this;
- else
- if (riid == IID_IPropertyBag)
- *ppvObj = this;
- else
- return E_NOINTERFACE; // Otherwise, don't delegate to HTMLObj!!
-
- if (*ppvObj != NULL) // Should always be non-NULL at this point, but just to be safe...
- ((LPUNKNOWN)*ppvObj)->AddRef();
-
- return S_OK;
- }
-
- //======================================================================
- //
- // Asks the property bag to read the property named with pwcPropName
- // into the caller-initialized VARIANT in pVar.
- //
- //
- STDMETHODIMP_(HRESULT) CPropertyBag::Read
- (
- LPCOLESTR pszPropName,
- VARIANT *pVar,
- IErrorLog *pErrorLog
- )
- {
- #pragma unused (pErrorLog)
-
- if(NULL == m_pPropertiesHead)
- return E_INVALIDARG;
-
- ASSERT(NULL != pszPropName);
- if(NULL == pszPropName)
- return E_POINTER;
-
- ASSERT(NULL != pVar);
- if(NULL == pVar)
- return E_POINTER;
-
- HRESULT hr;
- PROPERTYLIST *pCurProp = m_pPropertiesHead;
-
- #if 0
- if(0 == strcmp(pszPropName, PBCONTENTS))
- {
- hr = GetPropertyBagContents(pVar,pErrorLog);
- return hr;
- }
- #endif
-
- while(pCurProp != NULL)
- {
- // Paranoia
- ASSERT((NULL != pCurProp->pProperty) && (NULL != pCurProp->pProperty->pszName));
- if(((NULL != pCurProp->pProperty) && (NULL != pCurProp->pProperty->pszName)))
- {
- if(0 == strcmp(pszPropName, pCurProp->pProperty->pszName) )
- {
- // Caller didn't specify
- if(pVar->vt == VT_EMPTY)
- pVar->vt = VT_I4; // assume long?
-
- hr = VariantChangeType(pVar, pCurProp->pProperty->pvarValue, 0, pVar->vt);
-
- break;
- }
- }
- pCurProp = (PROPERTYLIST *)pCurProp->pNext;
- }
-
- // at the end of the list?
- if(NULL == pCurProp)
- return E_INVALIDARG;
-
- if(SUCCEEDED(hr))
- return S_OK;
- else
- return E_FAIL; // didn't find it
- }
-
- //======================================================================
- //
- // Asks the property bag to read the property named with pszPropName
- // into the caller-initialized VARIANT in pVar.
- //
- //
- BOOL CPropertyBag::find
- (
- const char *pszPropName,
- PROPERTY * *ppProp
- )
- {
- if(NULL == m_pPropertiesHead)
- return FALSE;
-
- ASSERT(NULL != pszPropName);
- if(NULL == pszPropName)
- return FALSE;
-
-
- PROPERTYLIST *pCurProp = m_pPropertiesHead;
-
- while(pCurProp != NULL)
- {
- // Paranoia
- ASSERT((NULL != pCurProp->pProperty) && (NULL != pCurProp->pProperty->pszName));
- if(((NULL != pCurProp->pProperty) && (NULL != pCurProp->pProperty->pszName)))
- {
- if(0 == strcmp(pszPropName, pCurProp->pProperty->pszName) )
- {
-
- *ppProp = pCurProp->pProperty;
- return TRUE;
- }
- }
- pCurProp = (PROPERTYLIST *)pCurProp->pNext;
- }
- return FALSE; // didn't find it
- }
-
- //======================================================================
- //
- // Asks the property bag to save the property named with
- // pszPropName using the type and value in the
- // caller-initialized VARIANT in pVar.
- //
- STDMETHODIMP_(HRESULT) CPropertyBag::Write
- (
- LPCOLESTR pwcPropName,
- VARIANT *pVar
- )
- {
- PROPERTY *pProperty = new(PROPERTY);
- pProperty->pvarValue = new(VARIANT);
-
- VariantInit(pProperty->pvarValue);
-
- // make a copy
- VariantCopy(pProperty->pvarValue, pVar);
-
- pProperty->pszName = (char*)GTR_MALLOC((strlen(pwcPropName) + 1)*sizeof(char));
- strcpy(pProperty->pszName, pwcPropName);
-
- addToPropertyList(pProperty);
-
- return S_OK;
- }
-
- //======================================================================
- //
- BOOL CPropertyBag::addToPropertyList(PROPERTY *pProperty)
- {
- PROPERTYLIST * pNewProp = new(PROPERTYLIST);
-
- if(NULL == m_pPropertiesHead)
- {
- m_pPropertiesHead = pNewProp;
- m_pPropertiesHead->pPrev = NULL;
- m_pPropertiesHead->pNext = NULL;
- m_pPropertiesTail = m_pPropertiesHead;
- }
- else
- m_pPropertiesTail->pNext = pNewProp;
-
- // add it to the list
- pNewProp->pProperty = pProperty;
- pNewProp->pPrev = m_pPropertiesTail;
- pNewProp->pNext = NULL;
- m_pPropertiesTail = pNewProp;
-
- m_cProperties++;
- return TRUE;
- }
-
- //======================================================================
- //
- BOOL CPropertyBag::deletePropertyList()
- {
- if(NULL == m_pPropertiesHead)
- return TRUE;
-
- PROPERTYLIST *pCurProp = m_pPropertiesHead;
-
- while(pCurProp->pNext != NULL)
- {
- if(pCurProp->pProperty->pvarValue->vt == VT_BSTR &&
- pCurProp->pProperty->pvarValue->bstrVal)
- CoTaskMemFree(pCurProp->pProperty->pvarValue->bstrVal);
- SAFEDELETE( pCurProp->pProperty->pvarValue );
- if(pCurProp->pProperty->pszName)
- CoTaskMemFree( pCurProp->pProperty->pszName );
- SAFEDELETE( pCurProp->pProperty );
-
- pCurProp = (PROPERTYLIST *)pCurProp->pNext;
-
- SAFEDELETE( pCurProp->pPrev );
- }
-
- // remove the last one
- if(pCurProp->pProperty->pvarValue->vt == VT_BSTR &&
- pCurProp->pProperty->pvarValue->bstrVal)
- CoTaskMemFree(pCurProp->pProperty->pvarValue->bstrVal);
- SAFEDELETE( pCurProp->pProperty->pvarValue );
- if(pCurProp->pProperty->pszName)
- CoTaskMemFree( pCurProp->pProperty->pszName );
- SAFEDELETE( pCurProp->pProperty );
- SAFEDELETE( pCurProp );
-
- m_pPropertiesHead = NULL;
- m_pPropertiesTail = NULL;
- return TRUE;
- }
-
-
- void CPropertyBag::AddParam(const char *name, const char *value )
- {
- int length;
-
- // Add the param to the property bag
- VARIANT *pVar = new(VARIANT);
-
- // Fill in the VARIANT structure
- //
- VariantInit(pVar);
-
- length = strlen((char *) value);
-
- // VARIANT:BSTR's must be allocated with SysAllocString
- // (Copy 2)
- pVar->vt = VT_BSTR;
- // A BSTR is a VB counted string where the first DWORD is the
- // length of the string, not including the null terminator,
- // followed by a null-terminated string.
- pVar->bstrVal = (char*) CoTaskMemAlloc(sizeof(DWORD) + length + 1);
- *((LPDWORD) pVar->bstrVal) = (DWORD) length;
- memcpy(pVar->bstrVal + sizeof(DWORD), value, length + 1);
-
- ASSERT(NULL != pVar->bstrVal);
- if(NULL == pVar->bstrVal)
- return;
-
- // This is a wrapper that handles the CString
- // to OLE string conversion
- this->Write(name, pVar);
-
- CoTaskMemFree(pVar->bstrVal);
- // pPropertyBag->Write() made a copy (3 copies all told, a bit excessive I think, necessary?)
- // so SAFEDELETE() this now
- SAFEDELETE( pVar );
-
- return;
- }
-
- #if 0
- //======================================================================
- //
- // set the ExtentX & ExtentY values for the property bag
- // ulWidth & ulHeight are given in pixels.
- //
- void CPropertyBag::setExtents(ULONG ulWidth, ULONG ulHeight)
- {
- ASSERT(pSite != NULL);
- if(NULL == pSite)
- return;
-
- PROPERTY * pProp;
-
- BSTR pBstr[2] = {NULL,NULL};
- char szVal[20];
-
- CPropertyBag *pPropertyBag = NULL;
-
- // See if this CSite already has a Property Bag
- pPropertyBag = pSite->GetPropertyBag();
-
- // If not create a new one and set it to the CSite
- // The CSite method will addRef it in either case
- //
- if (NULL == pPropertyBag)
- {
- // Create a brand new property bag
- pPropertyBag = new( CPropertyBag());
- ASSERT(NULL != pPropertyBag);
- if(NULL == pPropertyBag)
- return;
- pSite->SetPropertyBag(pPropertyBag);
- }
- else
- {
- // Do these exist already?
- if(pPropertyBag->find("_extentX", &pProp)
- && pPropertyBag->find("_extentY", &pProp))
- return;
- }
-
- VARIANT *pVar[] = {new(VARIANT), new(VARIANT) };
-
- ASSERT((NULL != pVar[0]) && (NULL != pVar[1]));
- if ((NULL == pVar[0]) || (NULL == pVar[1]))
- {
- if(pVar[0])
- SAFEDELETE(pVar[0]);
- if(pVar[1])
- SAFEDELETE(pVar[1]);
- return;
- }
-
- VariantInit(pVar[0]);
- VariantInit(pVar[1]);
-
- pVar[0]->vt = VT_BSTR;
- pVar[1]->vt = VT_BSTR;
-
- SIZEL szPix={ulWidth,ulHeight}, szHim={0,0};
- XformSizeInPixelsToHimetric(NULL, &szPix, &szHim);
-
- // allocates pBstr
- Ansi2Unicode(_ultoa( szHim.cx, szVal, 10 ), &pBstr[0]);
- Ansi2Unicode(_ultoa( szHim.cy, szVal, 10 ), &pBstr[1]);
-
- ASSERT((NULL != pBstr[0]) && (NULL != pBstr[1]));
- if ((NULL == pBstr[0]) || (NULL == pBstr[1]))
- return;
-
- // VARIANT:BSTR's must be allocated with SysAllocString
- pVar[0]->bstrVal = SysAllocString(pBstr[0]);
- pVar[1]->bstrVal = SysAllocString(pBstr[1]);
-
-
- ASSERT((NULL != pVar[0]->bstrVal) && (NULL != pVar[1]->bstrVal));
- if ((NULL == pVar[0]->bstrVal) || (NULL == pVar[1]->bstrVal))
- {
- if(pVar[0]->bstrVal)
- SAFEDELETE(pVar[0]->bstrVal);
- if(pVar[1])
- SAFEDELETE(pVar[1]->bstrVal);
-
- if(pVar[0])
- SAFEDELETE(pVar[0]);
- if(pVar[1])
- SAFEDELETE(pVar[1]);
- return;
- }
-
- // This is a wrapper that handles the CString
- // to OLE string conversion
- pPropertyBag->lpstrWrite("_extentX", pVar[0]);
- pPropertyBag->lpstrWrite("_extentY", pVar[1]);
-
- // SAFEDELETE() these now
- SAFEDELETE( pVar[0]);
- SAFEDELETE( pVar[1]);
-
- // Don't need these any longer
- if(pBstr[0])
- GTR_FREE(pBstr[0]);
-
- if(pBstr[1])
- GTR_FREE(pBstr[1]);
- }
-
- //======================================================================
- //
- // Note: BUGBUG only name & value are used in this interim implementation
- //
- //
- //
- void HText_addParamToPropertyBag(HText *text, const char *name, const char *type,
- const char *value,const char *valueRef,
- const char *attr, const int iInsertTagElement )
- {
- if(NULL == name)
- return;
-
- if(NULL == value)
- return;
-
- // Find the object we're associated with, using iInsertTagElement
- if (iInsertTagElement <= -1) // we don't have an association
- return; // </INSERT> with no <INSERT>
-
- // Get a pointer to the Objects Element
- ELEMENT *pElement = &(text->w3doc->aElements[iInsertTagElement]);
- ASSERT(pElement != NULL);
- if(NULL == pElement)
- return;
-
- // Get the Object
- CInsertableObject *pObj = (CInsertableObject *)pElement->pInsert;
- if ( NULL == pObj)
- return;
-
- // Get the objects CSite
- CSite *pSite = NULL;
- CPropertyBag *pPropertyBag = NULL;
-
- HRESULT hr = pObj->GetSite(&pSite);
- ASSERT(SUCCEEDED(hr) && pSite != NULL);
- if (!SUCCEEDED(hr) || NULL == pSite)
- return;
-
- // See if this CSite already has a Property Bag
- pPropertyBag = pSite->GetPropertyBag();
-
- // If not create a new one and set it to the CSite
- // The CSite method will addRef it in either case
- //
- if (NULL == pPropertyBag)
- {
- // Create a brand new property bag
- pPropertyBag = new (CPropertyBag());
- hr = pSite->SetPropertyBag(pPropertyBag);
-
- }
-
- // Add the param to the property bag
- VARIANT *pVar = new(VARIANT);
- BSTR pBstr = NULL;
-
- // Fill in the VARIANT structure
- //
- VariantInit(pVar);
-
- // Convert ANSI to Unicode (copy 1)
- hr = Ansi2Unicode(value, &pBstr);
-
- ASSERT(NULL != pBstr);
- if(NULL == pBstr)
- return;
-
- // VARIANT:BSTR's must be allocated with SysAllocString
- // (Copy 2)
- pVar->vt = VT_BSTR;
- pVar->bstrVal = SysAllocString(pBstr);
-
- // Don't need this copy any longer
- GTR_FREE(pBstr);
-
- ASSERT(NULL != pVar->bstrVal);
- if(NULL == pVar->bstrVal)
- return;
-
- // This is a wrapper that handles the CString
- // to OLE string conversion
- pPropertyBag->lpstrWrite(name, pVar);
-
- // pPropertyBag->Write() made a copy (3 copies all told, a bit excessive I think, necessary?)
- // so SAFEDELETE() this now
- SAFEDELETE( pVar );
-
- return;
- }
-
- //======================================================================
- //
- // BUGBUG:HACKHACK davidna 5/7/96 Beta1 Hack
- //
- // Called when PropertyBag::read() is called with the Property name set
- // to "%%pbcontents%%"
- //
- // Put the contents in a block of memory as name & value pairs.
- // Stored as char FAR * 's
- // Return this in the callers Variant
- //
- // The storage goes like this:
- // We have pointers to the name/value pairs following the
- // the count (ULONG) of items (or pairs) in m_pbContents
- //
- // we allocate storage for all the values so we must them free later
- //
- //
- HRESULT CPropertyBag::GetPropertyBagContents
- (
- VARIANT *pVar,
- IErrorLog *pErrorLog
- )
- {
-
- PROPERTYLIST *pCurProp = m_pPropertiesHead;
- char far * *pContents;
-
- ASSERT(NULL != pVar);
- if(NULL == pVar)
- return E_POINTER;
-
- // Must be this type for this HACK!
- if(pVar->vt != (VT_BYREF|VT_UI1) )
- return E_INVALIDARG;
-
- if(NULL == m_pPropertiesHead)
- return E_FAIL;
-
- // only allowed to do this once
- //
- ASSERT(NULL == m_pbContents);
- if(NULL != m_pbContents)
- return E_FAIL;
-
- // allocate storage for the count (ULONG/number of items)
- // plus each of the items or name/value pairs
- //
- m_pbContents = (LPSTR *) GTR_MALLOC(sizeof(ULONG) + (sizeof(char far *) * m_cProperties)*2);
-
- ULONG *pcItems = (ULONG *)m_pbContents;
- *(ULONG *)m_pbContents = m_cProperties; // first ULONG is count of items
-
- // Bump the pointer past the length
- pContents = (char * *) ((ULONG)m_pbContents + sizeof(ULONG));
-
- // Fill in the blanks
- while(pCurProp != NULL)
- {
- ASSERT((NULL != pCurProp->pProperty) && (NULL != pCurProp->pProperty->pszName));
- if(((NULL != pCurProp->pProperty) && (NULL != pCurProp->pProperty->pszName)))
- {
- // store a pointer to the name
- //
- *pContents = pCurProp->pProperty->pszName;
- pContents++;
-
- // Now store a pointer to the value
- // Convert to ansi 'cause Java Applets probably won't like BSTR's
- // and they're our only users of this
- //
- // Ansi2Unicode allocates the memory so we need to remember
- // to deallocate this later
- //
- if(FAILED(Unicode2Ansi((pCurProp->pProperty->pvarValue->bstrVal), pContents)) )
- {
- GTR_FREE(*pContents);
- GTR_FREE(m_pbContents);
- m_pbContents = NULL;
- return E_FAIL;
- }
- else
- pContents++;
- }
- pCurProp = (PROPERTYLIST *)pCurProp->pNext;
- }
-
- // put in variant
- pVar->pbVal = (unsigned char *)m_pbContents;
-
- return S_OK;
- }
-
- #endif
-