home *** CD-ROM | disk | FTP | other *** search
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #include "stdafx.h"
-
- #ifdef AFX_OLE_SEG
- #pragma code_seg(AFX_OLE_SEG)
- #endif
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- #define new DEBUG_NEW
-
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem - Container view of IOleObject and related interfaces
-
- COleClientItem::COleClientItem(COleDocument* pContainerDoc)
- {
- if (pContainerDoc != NULL)
- ASSERT_VALID(pContainerDoc);
-
- // initialize OLE client side view of IOleObject
- m_lpObject = NULL;
- m_lpViewObject = NULL;
- m_dwConnection = 0;
- m_lpStorage = NULL;
- m_lpLockBytes = NULL;
- m_scLast = S_OK;
- m_pView = NULL;
- m_pInPlaceFrame = NULL;
- m_pInPlaceDoc = NULL;
- m_nItemState = emptyState; // initially empty until OleLoad, OleCreate
- m_bMoniker = FALSE;
- m_nDrawAspect = DVASPECT_CONTENT; // default draw aspect
- m_dwItemNumber = 0;
- m_bLinkUnavail = FALSE; // set to TRUE on failed DoVerb, or in links dialog
- m_nItemType = OT_UNKNOWN; // type unknown so far
- m_hWndServer = NULL;
- m_bClosing = FALSE; // COleClientItem::Close in process
- m_bLocked = FALSE; // need CoLockObjectExternal(..., FALSE, ...)
-
- // initialize compound file support
- m_lpNewStorage = NULL;
- m_bNeedCommit = FALSE;
-
- if (pContainerDoc != NULL)
- pContainerDoc->AddItem(this);
-
- ASSERT(m_pDocument == pContainerDoc);
- ASSERT_VALID(this);
-
- AfxOleLockApp();
- }
-
- COleClientItem::~COleClientItem()
- {
- ASSERT_VALID(this);
-
- // release any references we may have to other objects
- Release();
-
- // only remove it from the associated document if it hasn't been detached
- // from the document already!
- if (m_pDocument != NULL)
- m_pDocument->RemoveItem(this);
-
- // make sure all outside connections are disconnected
- ExternalDisconnect();
- AfxOleUnlockApp();
- }
-
- void COleClientItem::Delete(BOOL bAutoDelete)
- {
- USES_CONVERSION;
- ASSERT_VALID(this);
-
- Release(); // first close it
-
- COleDocument* pDoc = GetDocument();
- if (pDoc != NULL && pDoc->m_bCompoundFile)
- {
- // cleanup docfile storage first
- COleDocument* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
-
- if (pDoc->m_lpRootStg != NULL)
- {
- // get item name
- TCHAR szItemName[OLE_MAXITEMNAME];
- GetItemName(szItemName);
-
- // attempt to remove it from the storage, ignore errors
- pDoc->m_lpRootStg->DestroyElement(T2COLE(szItemName));
- }
- }
-
- if (bAutoDelete)
- {
- // remove item from document
- if (pDoc != NULL)
- pDoc->RemoveItem(this);
-
- InternalRelease(); // remove the item from memory
- }
- }
-
- void COleClientItem::Release(OLECLOSE dwCloseOption)
- {
- ASSERT_VALID(this);
-
- m_scLast = S_OK;
-
- // cleanup view advise
- if (m_lpViewObject != NULL)
- {
- DWORD dwAspect;
- IAdviseSink* pAdviseSink;
-
- pAdviseSink = NULL;
- VERIFY(m_lpViewObject->GetAdvise(&dwAspect, NULL, &pAdviseSink) == S_OK);
- if( pAdviseSink != NULL )
- {
- RELEASE( pAdviseSink );
- }
- VERIFY(m_lpViewObject->SetAdvise(dwAspect, 0, NULL) == S_OK);
- RELEASE(m_lpViewObject);
- }
-
- // cleanup the OLE object itself
- if (m_lpObject != NULL)
- {
- // cleanup object advise
- if (m_dwConnection != 0)
- {
- VERIFY(m_lpObject->Unadvise(m_dwConnection) == S_OK);
- m_dwConnection = 0;
- }
-
- // close object and save (except now when called from destructor)
- // (NOTE: errors are _not_ reported as an exception)
- m_scLast = m_lpObject->Close(dwCloseOption);
- RELEASE(m_lpObject);
- }
-
- // cleanup storage related data
- RELEASE(m_lpStorage);
- RELEASE(m_lpLockBytes);
-
- // cleanup in-place editing data
- if (m_pInPlaceFrame != NULL)
- {
- m_pInPlaceFrame->InternalRelease();
- m_pInPlaceFrame = NULL;
- if (m_pInPlaceDoc != NULL)
- {
- m_pInPlaceDoc->InternalRelease();
- m_pInPlaceDoc = NULL;
- }
- }
- ASSERT(m_pInPlaceFrame == NULL);
- ASSERT(m_pInPlaceDoc == NULL);
- }
-
- void COleClientItem::Close(OLECLOSE dwCloseOption)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
-
- // gaurd against re-entry
- if (m_bClosing)
- return;
-
- m_bClosing = TRUE;
-
- // attempt to close the object
- m_scLast = m_lpObject->Close(dwCloseOption);
-
- // remove external lock placed on item during in-place activation
- if (m_bLocked)
- {
- OleLockRunning(m_lpObject, FALSE, TRUE);
- m_bLocked = FALSE;
- }
-
- // handle failure cases -- COleClientItem::Close can be used to
- // robustly handle a server crashing (ie. something unexpected happens,
- // we'll call COleClientItem::Close to attempt safe shutdown)
- if (GetItemState() != loadedState)
- {
- // We'll call COleClientItem::Close anywhere a catastrophe
- // happens inside of other portions of COleClientItem. We must
- // completely exit from any in-place/open state.
-
- // force transition from activeUIState to activeState
- if (GetItemState() == activeUIState)
- OnDeactivateUI(FALSE);
-
- // force transition from activeState to loadedState
- if (GetItemState() == activeState)
- OnDeactivate();
-
- if (m_nItemState != loadedState)
- {
- // in case of extreme failure, force loadedState
- OnChange(OLE_CHANGED_STATE, (DWORD)loadedState);
- m_nItemState = loadedState; // force it to loaded state
- }
- }
-
- m_bClosing = FALSE; // now safe for further close calls
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem name management
-
- DWORD COleClientItem::GetNewItemNumber()
- {
- ASSERT_VALID(this);
-
- COleDocument* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- DWORD dwNextItemNumber = pDoc->m_dwNextItemNumber;
-
- for (;;)
- {
- // make sure that m_dwNextItemNumber is not used in another item first
- POSITION pos = pDoc->GetStartPosition();
- COleClientItem* pItem;
- while ((pItem = pDoc->GetNextClientItem(pos)) != NULL)
- {
- if (pItem->m_dwItemNumber == dwNextItemNumber)
- break;
- }
- if (pItem == NULL)
- break; // no item using m_dwNextItemNumber
-
- // m_dwNextItemNumber is in use, bump to next one!
- ++dwNextItemNumber;
- }
-
- pDoc->m_dwNextItemNumber = dwNextItemNumber + 1;
- return dwNextItemNumber;
- }
-
- void COleClientItem::GetItemName(LPTSTR lpszItemName) const
- {
- ASSERT_VALID(this);
- ASSERT(lpszItemName != NULL);
-
- wsprintf(lpszItemName, _T("Embedding %lu"), m_dwItemNumber);
- ASSERT(lstrlen(lpszItemName) < OLE_MAXITEMNAME);
- }
-
- // extracts icon resource ID and path name from registry "file.exe,35" format
- static void AfxGetIconInfo(LPCTSTR lpszRegInfo, LPTSTR lpszImagePath,
- UINT& nIndex)
- {
- LPTSTR pstrTarget = lpszImagePath;
- LPCTSTR pstrSource = lpszRegInfo;
- while (*pstrSource != ',' && *pstrSource != '\0')
- {
- *pstrTarget = *pstrSource;
- pstrTarget = _tcsinc(pstrTarget);
- pstrSource = _tcsinc(pstrSource);
- }
- *pstrTarget = '\0';
-
- // extract the index
- if (*pstrSource != '\0')
- {
- LPTSTR pstrIndex = _tcsinc(pstrSource);
- nIndex = (UINT) _ttol(pstrIndex);
- }
- else
- nIndex = 0;
- }
-
- HICON COleClientItem::GetIconFromRegistry() const
- {
- CLSID clsid;
- GetClassID(&clsid);
- if (clsid == CLSID_NULL)
- return NULL;
-
- return GetIconFromRegistry(clsid);
- }
-
- HICON COleClientItem::GetIconFromRegistry(CLSID& clsid)
- {
- // This function will extract the icon registered as the DefaultIcon
- // for the server referred to by clsid. We get the ProgID for the server
- // and then extract \\hkcr\progid\DefaultIcon. If that doesn't exist, we
- // get a default icon from \\hkcr\DocShortcut\DefaultIcon and if that fails
- // we just return 0.
-
- USES_CONVERSION;
-
- HICON hIcon = NULL;
- HRESULT hr;
- OLECHAR *szCLSID;
- DWORD dwType = 0;
- TCHAR szName[MAX_PATH+1];
- TCHAR szPathName[MAX_PATH+1];
- HKEY hkeyObj;
- HKEY hkeyDefIcon;
- HKEY hkeyCLSID;
- UINT nIndex;
-
- hr = ::StringFromCLSID(clsid, &szCLSID);
- if (!SUCCEEDED(hr))
- return NULL;
-
- // first, try for the real icon
- if (RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("clsid"), 0, KEY_READ, &hkeyCLSID) == ERROR_SUCCESS)
- {
- if (RegOpenKeyEx(hkeyCLSID, OLE2T(szCLSID), 0, KEY_READ, &hkeyObj) == ERROR_SUCCESS)
- {
- if (RegOpenKeyEx(hkeyObj, _T("DefaultIcon"), 0, KEY_READ, &hkeyDefIcon) == ERROR_SUCCESS)
- {
- DWORD dwCount;
- dwCount = sizeof(szName);
- if (RegQueryValueEx(hkeyDefIcon, NULL, NULL, &dwType, (BYTE*) szName, &dwCount) == ERROR_SUCCESS)
- {
- AfxGetIconInfo(szName, szPathName, nIndex);
-
- // Load the icon
- hIcon = ::ExtractIcon(AfxGetApp()->m_hInstance, szPathName, nIndex);
-
- // ExtractIcon() failure case means NULL return
- if (int(hIcon) == 1)
- hIcon = NULL;
- }
- RegCloseKey(hkeyDefIcon);
- }
- RegCloseKey(hkeyObj);
- }
- RegCloseKey(hkeyCLSID);
- }
-
- // if we didn't get the real icon, try the default icon
- if (hIcon == NULL)
- {
- if (RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("DocShortcut"), 0, KEY_READ,&hkeyObj) == ERROR_SUCCESS)
- {
- if (RegOpenKeyEx(hkeyObj, _T("DefaultIcon"), 0, KEY_READ, &hkeyDefIcon) == ERROR_SUCCESS)
- {
- DWORD dwCount;
- dwCount = sizeof(szName);
- if (RegQueryValueEx(hkeyDefIcon, NULL, NULL, &dwType, (BYTE*) szName, &dwCount) == ERROR_SUCCESS)
- {
- AfxGetIconInfo(szName, szPathName, nIndex);
-
- // Load the icon
- hIcon = ::ExtractIcon(AfxGetApp()->m_hInstance, szPathName, nIndex);
-
- // ExtractIcon() failure case means NULL return
- if (int(hIcon) == 1)
- hIcon = NULL;
- }
- RegCloseKey(hkeyDefIcon);
- }
- RegCloseKey(hkeyObj);
- }
- }
-
- ::CoTaskMemFree(szCLSID);
- return hIcon;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem creation helpers
-
- void COleClientItem::UpdateItemType()
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
-
- // check for linked object
- LPOLELINK lpOleLink = QUERYINTERFACE(m_lpObject, IOleLink);
- if (lpOleLink != NULL)
- {
- lpOleLink->Release();
- m_nItemType = OT_LINK;
- return;
- }
-
- // check for static object
- DWORD dwStatus;
- if (m_lpObject->GetMiscStatus(DVASPECT_CONTENT, &dwStatus) == S_OK
- && (dwStatus & OLEMISC_STATIC) == 0)
- {
- m_nItemType = OT_EMBEDDED;
- return;
- }
-
- // not not link, not embedding -- must be static
- m_nItemType = OT_STATIC;
- }
-
- BOOL COleClientItem::FinishCreate(SCODE sc)
- {
- USES_CONVERSION;
-
- ASSERT_VALID(this);
- ASSERT(m_pView == NULL);
-
- TRY
- {
- // m_lpObject is currently an IUnknown, convert to IOleObject
- if (m_lpObject != NULL)
- {
- LPUNKNOWN lpUnk = m_lpObject;
- m_lpObject = QUERYINTERFACE(lpUnk, IOleObject);
- lpUnk->Release();
- if (m_lpObject == NULL)
- AfxThrowOleException(E_OUTOFMEMORY);
- }
-
- // check return code from create function
- CheckGeneral(sc);
-
- UpdateItemType();
-
- // cache the IViewObject interface
- m_lpViewObject = QUERYINTERFACE(m_lpObject, IViewObject2);
- if (m_lpViewObject == NULL)
- CheckGeneral(E_NOINTERFACE);
- ASSERT(m_lpViewObject != NULL);
-
- if (GetType() != OT_STATIC)
- {
- // setup for advises; we assume that OLE cleans them up properly
- LPADVISESINK lpAdviseSink =
- (LPADVISESINK)GetInterface(&IID_IAdviseSink);
- ASSERT(lpAdviseSink != NULL);
- CheckGeneral(m_lpObject->Advise(lpAdviseSink, &m_dwConnection));
- ASSERT(m_dwConnection != 0);
-
- // set up view advise
- VERIFY(m_lpViewObject->SetAdvise(DVASPECT_CONTENT, 0, lpAdviseSink)
- == S_OK);
-
- // the server shows these in its user-interface
- // (as document title and in File Exit menu)
- m_lpObject->SetHostNames(T2COLE(AfxGetAppName()),
- T2COLE(m_pDocument->GetTitle()));
- }
-
- // all items are "contained" -- this makes our reference to this object
- // weak -- which is needed for links to embedding silent update.
- OleSetContainedObject(m_lpObject, TRUE);
-
- // considered loaded at this point
- m_nItemState = loadedState;
- }
- CATCH_ALL(e)
- {
- Release(); // release the object just in case
- ASSERT_VALID(this);
- DELETE_EXCEPTION(e);
- return FALSE;
- }
- END_CATCH_ALL
-
- // set state to loaded
- ASSERT(m_nItemState != emptyState);
-
- // otherwise no errors, return success!
- ASSERT_VALID(this);
- return TRUE;
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // COleClientItem create API variants
-
- BOOL COleClientItem::CreateFromClipboard(
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
-
- // get clipboard contents
- COleDataObject dataObject;
- if (!dataObject.AttachClipboard())
- return FALSE;
-
- // create from IDataObject
- BOOL bResult = CreateFromData(&dataObject, render, cfFormat, lpFormatEtc);
-
- ASSERT_VALID(this);
- return bResult;
- }
-
- BOOL COleClientItem::CreateLinkFromClipboard(
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
-
- // get clipboard contents
- COleDataObject dataObject;
- if (!dataObject.AttachClipboard())
- return FALSE;
-
- // create from IDataObject
- BOOL bResult = CreateLinkFromData(&dataObject, render, cfFormat, lpFormatEtc);
- ASSERT_VALID(this);
-
- return bResult;
- }
-
- BOOL COleClientItem::CreateStaticFromClipboard(
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
-
- // get clipboard contents
- COleDataObject dataObject;
- if (!dataObject.AttachClipboard())
- return FALSE;
-
- // create from IDataObject
- BOOL bResult = CreateStaticFromData(&dataObject, render, cfFormat,
- lpFormatEtc);
-
- ASSERT_VALID(this);
- return bResult;
- }
-
- // Creation from IDataObject (used for drag-drop)
- BOOL COleClientItem::CreateFromData(COleDataObject* pDataObject,
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
-
- // get storage for the object via virtual function call
- m_dwItemNumber = GetNewItemNumber();
- GetItemStorage();
- ASSERT(m_lpStorage != NULL);
-
- // fill in FORMATETC struct
- FORMATETC formatEtc;
- lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
-
- // attempt to create the object
- LPOLECLIENTSITE lpClientSite = GetClientSite();
- LPDATAOBJECT lpDataObject = pDataObject->GetIDataObject(FALSE);
- SCODE sc = ::OleCreateFromData(lpDataObject, IID_IUnknown, render,
- lpFormatEtc, lpClientSite, m_lpStorage, (LPLP)&m_lpObject);
- BOOL bResult = FinishCreate(sc);
-
- ASSERT_VALID(this);
- return bResult;
- }
-
- BOOL COleClientItem::CreateLinkFromData(COleDataObject* pDataObject,
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
-
- // get storage for the object via virtual function call
- m_dwItemNumber = GetNewItemNumber();
- GetItemStorage();
- ASSERT(m_lpStorage != NULL);
-
- // fill in FORMATETC struct
- FORMATETC formatEtc;
- lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
-
- // attempt to create the link
- LPOLECLIENTSITE lpClientSite = GetClientSite();
- LPDATAOBJECT lpDataObject = pDataObject->GetIDataObject(FALSE);
- SCODE sc = ::OleCreateLinkFromData(lpDataObject, IID_IUnknown,
- render, lpFormatEtc, lpClientSite, m_lpStorage, (LPLP)&m_lpObject);
- BOOL bResult = FinishCreate(sc);
-
- ASSERT_VALID(this);
- return bResult;
- }
-
- BOOL COleClientItem::CreateStaticFromData(COleDataObject* pDataObject,
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
-
- // get storage for the object via virtual function call
- m_dwItemNumber = GetNewItemNumber();
- GetItemStorage();
- ASSERT(m_lpStorage != NULL);
-
- // fill in FORMATETC struct
- FORMATETC formatEtc;
- lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
-
- // attempt to create the link
- LPOLECLIENTSITE lpClientSite = GetClientSite();
- LPDATAOBJECT lpDataObject = pDataObject->GetIDataObject(FALSE);
- SCODE sc = ::OleCreateStaticFromData(lpDataObject, IID_IUnknown,
- render, lpFormatEtc, lpClientSite, m_lpStorage, (LPLP)&m_lpObject);
- BOOL bResult = FinishCreate(sc);
-
- ASSERT_VALID(this);
- return bResult;
- }
-
- // Creation from files (in OLE 1.0, the user did this through packager)
- BOOL COleClientItem::CreateFromFile(LPCTSTR lpszFileName, REFCLSID clsid,
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- USES_CONVERSION;
-
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
-
- // get storage for the object via virtual function call
- m_dwItemNumber = GetNewItemNumber();
- GetItemStorage();
- ASSERT(m_lpStorage != NULL);
-
- // fill in FORMATETC struct
- FORMATETC formatEtc;
- lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
-
- // attempt to create the object
- LPOLECLIENTSITE lpClientSite = GetClientSite();
- SCODE sc = ::OleCreateFromFile(clsid, T2COLE(lpszFileName),
- IID_IUnknown, render, lpFormatEtc, lpClientSite, m_lpStorage,
- (LPLP)&m_lpObject);
- BOOL bResult = FinishCreate(sc);
-
- ASSERT_VALID(this);
- return bResult;
- }
-
- BOOL COleClientItem::CreateLinkFromFile(LPCTSTR lpszFileName,
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- USES_CONVERSION;
-
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
-
- // get storage for the object via virtual function call
- m_dwItemNumber = GetNewItemNumber();
- GetItemStorage();
- ASSERT(m_lpStorage != NULL);
-
- // fill in FORMATETC struct
- FORMATETC formatEtc;
- lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
-
- // attempt to create the link
- LPOLECLIENTSITE lpClientSite = GetClientSite();
- SCODE sc = ::OleCreateLinkToFile(T2COLE(lpszFileName),
- IID_IUnknown, render, lpFormatEtc, lpClientSite, m_lpStorage,
- (LPLP)&m_lpObject);
- BOOL bResult = FinishCreate(sc);
-
- ASSERT_VALID(this);
- return bResult;
- }
-
- // create from class name (for insert item dialog)
- BOOL COleClientItem::CreateNewItem(REFCLSID clsid,
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
-
- // get storage for the object via virtual function call
- m_dwItemNumber = GetNewItemNumber();
- GetItemStorage();
- ASSERT(m_lpStorage != NULL);
-
- // fill in FORMATETC struct
- FORMATETC formatEtc;
- lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
-
- // attempt to create the object
- LPOLECLIENTSITE lpClientSite = GetClientSite();
- SCODE sc = ::OleCreate(clsid, IID_IUnknown,
- render, lpFormatEtc, lpClientSite, m_lpStorage, (LPLP)&m_lpObject);
- BOOL bResult = FinishCreate(sc);
-
- ASSERT_VALID(this);
- return bResult;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // More advanced creation
-
- BOOL COleClientItem::CreateCloneFrom(const COleClientItem* pSrcItem)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT_VALID(pSrcItem);
- ASSERT(m_pDocument != NULL);
-
- // create storage for the item
- m_dwItemNumber = GetNewItemNumber();
- GetItemStorage();
- ASSERT(m_lpStorage != NULL);
-
- // save the object first
- LPPERSISTSTORAGE lpPersistStorage =
- QUERYINTERFACE(pSrcItem->m_lpObject, IPersistStorage);
- ASSERT(lpPersistStorage != NULL);
- SCODE sc = ::OleSave(lpPersistStorage, m_lpStorage, FALSE);
- lpPersistStorage->SaveCompleted(NULL);
- lpPersistStorage->Release();
- if (sc != S_OK)
- {
- // failed the save, do not attempt to create clone
- m_scLast = sc;
- return FALSE;
- }
-
- // get information on the view advise type
- ASSERT(pSrcItem->m_lpViewObject != NULL);
- DWORD dwAspect;
- IAdviseSink* pAdviseSink;
- pAdviseSink = NULL;
- VERIFY(pSrcItem->m_lpViewObject->GetAdvise(&dwAspect, NULL, &pAdviseSink) ==
- S_OK);
- if( pAdviseSink != NULL )
- {
- RELEASE(pAdviseSink);
- }
-
- // then load the new object from the new storage
- LPOLECLIENTSITE lpClientSite = GetClientSite();
- sc = ::OleLoad(m_lpStorage, IID_IUnknown,
- lpClientSite, (LPLP)&m_lpObject);
- BOOL bResult = FinishCreate(sc);
-
- ASSERT_VALID(this);
- return bResult;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Storage for COleClientItem objects (memory and compound files)
-
- BOOL COleClientItem::IsModified() const
- {
- SCODE sc;
-
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
-
- // get IPersistStorage interface, and call IsDirty
- LPPERSISTSTORAGE lpPersistStorage =
- QUERYINTERFACE(m_lpObject, IPersistStorage);
- if( lpPersistStorage != NULL )
- {
- sc = lpPersistStorage->IsDirty();
- lpPersistStorage->Release();
- }
- else
- {
- LPPERSISTSTREAMINIT lpPersistStreamInit;
- lpPersistStreamInit = QUERYINTERFACE( m_lpObject, IPersistStreamInit );
- if( lpPersistStreamInit != NULL )
- {
- sc = lpPersistStreamInit->IsDirty();
- lpPersistStreamInit->Release();
- }
- else
- {
- LPPERSISTSTREAM lpPersistStream;
- lpPersistStream = QUERYINTERFACE( m_lpObject, IPersistStream );
- if( lpPersistStream != NULL )
- {
- sc = lpPersistStream->IsDirty();
- lpPersistStream->Release();
- }
- else
- {
- sc = E_NOINTERFACE;
- }
- }
- }
-
- // S_OK == S_TRUE, therefore object dirty!
- return sc == S_OK || FAILED(sc);
- }
-
- void COleClientItem::GetItemStorageFlat()
- {
- ASSERT_VALID(this);
- ASSERT(m_lpStorage == NULL);
- ASSERT(m_lpLockBytes == NULL);
-
- SCODE sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &m_lpLockBytes);
- if (sc != S_OK)
- AfxThrowOleException(sc);
- ASSERT(m_lpLockBytes != NULL);
-
- sc = ::StgCreateDocfileOnILockBytes(m_lpLockBytes,
- STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &m_lpStorage);
- if (sc != S_OK)
- {
- VERIFY(m_lpLockBytes->Release() == 0);
- m_lpLockBytes = NULL;
- AfxThrowOleException(sc);
- }
- ASSERT(m_lpStorage != NULL);
-
- ASSERT_VALID(this);
- }
-
- void COleClientItem::ReadItemFlat(CArchive& ar)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpStorage == NULL);
- ASSERT(m_lpLockBytes == NULL);
-
- // read number of bytes in the ILockBytes
- DWORD dwBytes;
- ar >> dwBytes;
-
- // allocate enough memory to read entire block
- HGLOBAL hStorage = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, dwBytes);
- if (hStorage == NULL)
- AfxThrowMemoryException();
-
- LPVOID lpBuf = ::GlobalLock(hStorage);
- ASSERT(lpBuf != NULL);
- DWORD dwBytesRead = ar.Read(lpBuf, dwBytes);
- ::GlobalUnlock(hStorage);
-
- // throw exception in case of partial object
- if (dwBytesRead != dwBytes)
- {
- ::GlobalFree(hStorage);
- AfxThrowArchiveException(CArchiveException::endOfFile);
- }
-
- SCODE sc = CreateILockBytesOnHGlobal(hStorage, TRUE, &m_lpLockBytes);
- if (sc != S_OK)
- {
- ::GlobalFree(hStorage);
- AfxThrowOleException(sc);
- }
- ASSERT(m_lpLockBytes != NULL);
- ASSERT(::StgIsStorageILockBytes(m_lpLockBytes) == S_OK);
-
- sc = ::StgOpenStorageOnILockBytes(m_lpLockBytes, NULL,
- STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &m_lpStorage);
- if (sc != S_OK)
- {
- VERIFY(m_lpLockBytes->Release() == 0);
- m_lpLockBytes = NULL;
- // ILockBytes::Release will GlobalFree the hStorage
- AfxThrowOleException(sc);
- }
-
- // attempt to load the object from the storage
- LPUNKNOWN lpUnk = NULL;
- sc = ::OleLoad(m_lpStorage, IID_IUnknown, GetClientSite(),
- (LPLP)&lpUnk);
- CheckGeneral(sc);
-
- ASSERT(lpUnk != NULL);
- m_lpObject = QUERYINTERFACE(lpUnk, IOleObject);
- lpUnk->Release();
- if (m_lpObject == NULL)
- AfxThrowOleException(E_OUTOFMEMORY);
-
- ASSERT_VALID(this);
- }
-
- void COleClientItem::WriteItemFlat(CArchive& ar)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpStorage != NULL);
- ASSERT(m_lpLockBytes != NULL);
-
- // save the OLE object to its storage first
- LPPERSISTSTORAGE lpPersistStorage =
- QUERYINTERFACE(m_lpObject, IPersistStorage);
- ASSERT(lpPersistStorage != NULL);
- SCODE sc;
- if (GetDocument()->m_bCompoundFile || lpPersistStorage->IsDirty() == S_OK)
- {
- sc = ::OleSave(lpPersistStorage, m_lpStorage,
- !GetDocument()->m_bCompoundFile);
- lpPersistStorage->SaveCompleted(NULL);
- }
- lpPersistStorage->Release();
- m_lpStorage->Commit(STGC_OVERWRITE);
- ASSERT(::StgIsStorageILockBytes(m_lpLockBytes) == S_OK);
-
- // attempt to get the handle to the global memory
- HGLOBAL hStorage;
- sc = ::GetHGlobalFromILockBytes(m_lpLockBytes, &hStorage);
- if (sc != S_OK)
- AfxThrowOleException(sc);
-
- // first write a byte count
- STATSTG statstg;
- sc = m_lpLockBytes->Stat(&statstg, STATFLAG_NONAME);
- if (sc != S_OK)
- AfxThrowOleException(sc);
- ASSERT(statstg.cbSize.HighPart == 0); // don't support >4GB objects
- DWORD dwBytes = statstg.cbSize.LowPart;
- ar << dwBytes;
-
- // write the contents of the block
- LPVOID lpBuf = GlobalLock(hStorage);
- ASSERT(lpBuf != NULL);
- ar.Write(lpBuf, (UINT)dwBytes);
- ::GlobalUnlock(hStorage);
- }
-
- void COleClientItem::GetItemStorageCompound()
- {
- USES_CONVERSION;
-
- COleDocument* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- ASSERT(pDoc->m_bCompoundFile);
- if (pDoc->m_lpRootStg == NULL)
- {
- ASSERT(pDoc->m_bEmbedded);
- pDoc->m_bEmbedded = FALSE;
- if (!pDoc->OnNewDocument())
- {
- TRACE0("Warning OnNewDocument failed during COleClientItem::CreateXXXX\n");
- AfxThrowMemoryException();
- }
- }
- ASSERT(pDoc->m_lpRootStg != NULL);
-
- // get item name
- TCHAR szItemName[OLE_MAXITEMNAME];
- GetItemName(szItemName);
-
- // create storage for this item
- LPSTORAGE lpStorage;
- SCODE sc = pDoc->m_lpRootStg->CreateStorage(T2COLE(szItemName),
- STGM_CREATE|STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE,
- 0, 0, &lpStorage);
- if (sc != S_OK)
- {
- TRACE1("Warning: unable to create child storage %s.\n", szItemName);
- // upon failure throw file exception (item will be cleaned up)
- AfxThrowOleException(sc);
- }
- ASSERT(lpStorage != NULL);
-
- // everything should have worked
- m_lpStorage = lpStorage;
- ASSERT(m_lpStorage != NULL);
- }
-
- void COleClientItem::ReadItemCompound(CArchive& ar)
- {
- USES_CONVERSION;
-
- COleDocument* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- ASSERT(pDoc->m_lpRootStg != NULL);
- ASSERT(pDoc->m_bCompoundFile);
- ASSERT(m_lpStorage == NULL);
- ASSERT(m_lpLockBytes == NULL);
-
- if (ar.m_bForceFlat)
- {
- ReadItemFlat(ar);
- RELEASE(m_lpStorage);
- RELEASE(m_lpLockBytes);
-
- // change the number to something definitely unique
- m_dwItemNumber = GetNewItemNumber();
-
- // create new storage
- GetItemStorageCompound();
- LPPERSISTSTORAGE lpPersistStorage =
- QUERYINTERFACE(m_lpObject, IPersistStorage);
- ASSERT(lpPersistStorage != NULL);
- SCODE sc = ::OleSave(lpPersistStorage, m_lpStorage, FALSE);
- if (FAILED(sc))
- {
- lpPersistStorage->Release();
- CheckGeneral(sc);
- }
- VERIFY(lpPersistStorage->SaveCompleted(m_lpStorage) == S_OK);
- lpPersistStorage->Release();
- }
- else
- {
- // get item name
- TCHAR szItemName[OLE_MAXITEMNAME];
- GetItemName(szItemName);
-
- // open storage for this item
- LPSTORAGE lpStorage;
- SCODE sc = pDoc->m_lpRootStg->OpenStorage(T2COLE(szItemName), NULL,
- STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE,
- 0, 0, &lpStorage);
- if (sc != S_OK)
- {
- TRACE1("Warning: unable to open child storage %s.\n", szItemName);
- // upon failure throw file exception (item will be cleaned up)
- AfxThrowOleException(sc);
- }
- ASSERT(lpStorage != NULL);
-
- // remember the storage
- m_lpStorage = lpStorage;
- ASSERT(m_lpStorage != NULL);
-
- // attempt to load the object from the storage
- LPUNKNOWN lpUnk = NULL;
- sc = ::OleLoad(m_lpStorage, IID_IUnknown, GetClientSite(),
- (LPLP)&lpUnk);
- CheckGeneral(sc);
-
- // get IOleObject interface for the newly loaded object
- ASSERT(lpUnk != NULL);
- m_lpObject = QUERYINTERFACE(lpUnk, IOleObject);
- lpUnk->Release();
- if (m_lpObject == NULL)
- AfxThrowOleException(E_OUTOFMEMORY);
- }
- }
-
- void COleClientItem::WriteItemCompound(CArchive& ar)
- {
- USES_CONVERSION;
-
- COleDocument* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- ASSERT(pDoc->m_lpRootStg != NULL);
- ASSERT(pDoc->m_bCompoundFile);
- ASSERT(m_lpNewStorage == NULL);
-
- if (ar.m_bForceFlat)
- {
- LPSTORAGE pTempStorage = m_lpStorage;
- LPLOCKBYTES pTempLockBytes = m_lpLockBytes;
- m_lpStorage = NULL;
- m_lpLockBytes = NULL;
- GetItemStorageFlat();
- WriteItemFlat(ar);
- RELEASE(m_lpStorage);
- RELEASE(m_lpLockBytes);
- m_lpStorage = pTempStorage;
- m_lpLockBytes = pTempLockBytes;
- return;
- }
-
- // get item name
- TCHAR szItemName[OLE_MAXITEMNAME];
- GetItemName(szItemName);
-
- // determine destination storage
- ASSERT(m_lpStorage != NULL);
- LPSTORAGE lpStorage = m_lpStorage;
- if (!pDoc->m_bSameAsLoad)
- {
- // need to create new storage for this item
- SCODE sc = pDoc->m_lpRootStg->CreateStorage(T2COLE(szItemName),
- STGM_CREATE|STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE,
- 0, 0, &lpStorage);
- if (sc != S_OK)
- {
- TRACE1("Warning: unable to create child storage %s.\n",
- szItemName);
- AfxThrowOleException(sc);
- }
- // remember the storage for CommitItem stage
- m_lpNewStorage = lpStorage;
- m_bNeedCommit = TRUE;
- }
- ASSERT(lpStorage != NULL);
-
- // save dirty object
- LPPERSISTSTORAGE lpPersistStorage =
- QUERYINTERFACE(m_lpObject, IPersistStorage);
- ASSERT(lpPersistStorage != NULL);
- SCODE sc = S_OK;
- if (!pDoc->m_bSameAsLoad || lpPersistStorage->IsDirty() == S_OK)
- {
- // call OleSave now and IPersistStorage::SaveCompleted later
- sc = ::OleSave(lpPersistStorage, lpStorage, pDoc->m_bSameAsLoad);
- }
- lpPersistStorage->Release();
-
- // if it fails, abort the save
- if (FAILED(sc))
- AfxThrowOleException(sc);
-
- // now will need to call CommitItem for this item
- m_bNeedCommit = TRUE;
- lpStorage->Commit(STGC_ONLYIFCURRENT);
- }
-
- void COleClientItem::GetItemStorage()
- {
- if (GetDocument()->m_bCompoundFile)
- GetItemStorageCompound();
- else
- GetItemStorageFlat();
- }
-
- void COleClientItem::ReadItem(CArchive& ar)
- {
- if (GetDocument()->m_bCompoundFile)
- ReadItemCompound(ar);
- else
- ReadItemFlat(ar);
- }
-
- void COleClientItem::WriteItem(CArchive& ar)
- {
- if (GetDocument()->m_bCompoundFile)
- WriteItemCompound(ar);
- else
- WriteItemFlat(ar);
- }
-
- void COleClientItem::CommitItem(BOOL bSuccess)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
-
- if (!m_bNeedCommit)
- return;
-
- LPPERSISTSTORAGE lpPersistStorage =
- QUERYINTERFACE(m_lpObject, IPersistStorage);
- ASSERT(lpPersistStorage != NULL);
-
- // forget about new storage if save failed along the way...
- if (m_lpNewStorage != NULL && !bSuccess)
- RELEASE(m_lpNewStorage);
-
- // let the object remember the new storage
- VERIFY(lpPersistStorage->SaveCompleted(m_lpNewStorage) == S_OK);
- lpPersistStorage->Release();
-
- // determine/remember new storage
- if (m_lpNewStorage != NULL)
- {
- m_lpStorage->Release();
- m_lpStorage = m_lpNewStorage;
- m_lpNewStorage = NULL;
- }
-
- m_bNeedCommit = FALSE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem serialization
-
- void COleClientItem::Serialize(CArchive& ar)
- {
- ASSERT_VALID(this);
-
- CDocItem::Serialize(ar);
- ASSERT(m_pDocument != NULL); // must 'SetDocument' first
-
- if (ar.IsStoring())
- {
- ASSERT(m_lpObject != NULL);
-
- // first, save the type flag (this is used for versioning)
- ar << (DWORD)OT_OLE2;
-
- ar << m_dwItemNumber; // save the item number
-
- // write the view advise type to storage
- ASSERT(m_lpViewObject != NULL);
- DWORD dwAspect;
- IAdviseSink* pAdviseSink;
- pAdviseSink = NULL;
- VERIFY(m_lpViewObject->GetAdvise(&dwAspect, NULL, &pAdviseSink) == S_OK);
- if( pAdviseSink != NULL )
- {
- RELEASE(pAdviseSink);
- }
- ar << dwAspect; // save the display aspect
-
- // write flag indicating whether to create moniker upon load
- ar << (WORD)m_bMoniker;
-
- // save current default display aspect
- ar << (DWORD)m_nDrawAspect;
-
- // save object to storage (calls OleSave)
- WriteItem(ar);
- }
- else
- {
- ASSERT(m_lpObject == NULL);
-
- // first, get the type flag (for OLE 1.0 compatible reading)
- DWORD dwType;
- ar >> dwType;
- if (dwType != OT_OLE2)
- AfxThrowArchiveException(CArchiveException::generic);
-
- ar >> m_dwItemNumber; // get the item number
-
- DWORD dwAspect; // read the display aspect (aspects that are cached)
- ar >> dwAspect;
-
- WORD bMoniker; // see if we should create & set the moniker
- ar >> bMoniker;
-
- DWORD nDrawAspect; // read the default display aspect
- ar >> nDrawAspect;
- m_nDrawAspect = (DVASPECT)nDrawAspect;
-
- // read the OLE object from storage (calls OleLoad)
- ReadItem(ar);
-
- // finish OLE object creation process, setup advises, etc.
- if (!FinishCreate(S_OK))
- AfxThrowArchiveException(CArchiveException::generic);
-
- if (bMoniker)
- {
- // force moniker creation by calling GetMoniker
- LPMONIKER lpMoniker;
- if (GetClientSite()->GetMoniker(OLEGETMONIKER_FORCEASSIGN,
- OLEWHICHMK_OBJREL, &lpMoniker) == S_OK)
- {
- ASSERT(lpMoniker != NULL);
- lpMoniker->Release();
- ASSERT(m_bMoniker); // moniker should have been assigned
- }
- }
-
- // fix up the document's m_dwNextItemNumber
- if (m_dwItemNumber >= GetDocument()->m_dwNextItemNumber)
- GetDocument()->m_dwNextItemNumber = m_dwItemNumber + 1;
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // default callback implementation
-
- void COleClientItem::OnChange(OLE_NOTIFICATION nCode, DWORD /*dwParam*/)
- {
- ASSERT_VALID(this);
-
- switch (nCode)
- {
- case OLE_CLOSED:
- break; // no default implementation
-
- case OLE_CHANGED:
- case OLE_SAVED:
- ASSERT(m_pDocument != NULL);
- m_pDocument->SetModifiedFlag();
- break;
-
- case OLE_CHANGED_STATE:
- case OLE_CHANGED_ASPECT:
- break; // no default implementation
-
- default:
- ASSERT(FALSE);
- }
-
- ASSERT_VALID(this);
- }
-
- void COleClientItem::OnDataChange(
- LPFORMATETC /*lpFormatEtc*/, LPSTGMEDIUM /*lpStgMedium*/)
- {
- ASSERT(FALSE); // derivative must override -- must not call base class
- }
-
- void COleClientItem::OnGetItemPosition(CRect& /*rPosition*/)
- {
- // default does nothing
- }
-
- void COleClientItem::OnGetClipRect(CRect& rClipRect)
- {
- ASSERT_VALID(this);
- ASSERT(AfxIsValidAddress(&rClipRect, sizeof(RECT)));
-
- // default clips rectClip to client area of the active view
- ASSERT_VALID(m_pView);
- m_pView->GetClientRect(&rClipRect);
- }
-
- void COleClientItem::OnShowItem()
- {
- ASSERT_VALID(this);
-
- CDocument* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
-
- // attempt to use m_pView set during activation
- CView* pView = m_pView;
- if (pView == NULL)
- {
- // otherwise, find the first view of this document
- POSITION pos = pDoc->GetFirstViewPosition();
- if (pos == NULL || (pView = pDoc->GetNextView(pos)) == NULL)
- return;
- }
-
- CFrameWnd* pFrameWnd = pView->GetParentFrame();
- if (pFrameWnd != NULL)
- {
- // activate frame holding view
- pFrameWnd->ActivateFrame();
- pFrameWnd->OnUpdateFrameTitle(TRUE);
-
- // activate app frame if necessary
- pFrameWnd = pFrameWnd->GetParentFrame();
- if (pFrameWnd != NULL)
- {
- ASSERT_KINDOF(CFrameWnd, pFrameWnd);
- pFrameWnd->ActivateFrame();
- pFrameWnd->OnUpdateFrameTitle(TRUE);
- }
- }
-
- if (!pDoc->GetPathName().IsEmpty())
- {
- // user is also in control of the application, when a file-based
- // document becomes visible.
- AfxOleSetUserCtrl(TRUE);
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem - attributes
-
- void COleClientItem::GetClassID(CLSID* pClassID) const
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
- ASSERT(AfxIsValidAddress(pClassID, sizeof(CLSID)));
-
- if (m_lpObject->GetUserClassID(pClassID) != S_OK)
- *pClassID = CLSID_NULL;
- }
-
- BOOL COleClientItem::GetExtent(LPSIZE lpSize, DVASPECT nDrawAspect)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
- ASSERT(AfxIsValidAddress(lpSize, sizeof(CSize)));
-
- // use current default aspect if specific one not specified
- if (nDrawAspect == -1)
- nDrawAspect = m_nDrawAspect;
-
- // get the extent
- m_scLast = m_lpObject->GetExtent(nDrawAspect, lpSize);
- return m_scLast == S_OK;
- }
-
- BOOL COleClientItem::GetCachedExtent(LPSIZE lpSize, DVASPECT nDrawAspect)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpViewObject != NULL);
- ASSERT(AfxIsValidAddress(lpSize, sizeof(CSize)));
-
- // use current default aspect if specific one not specified
- if (nDrawAspect == -1)
- nDrawAspect = m_nDrawAspect;
-
- COleDocument* pDoc = (COleDocument*)GetDocument();
- ASSERT_VALID(pDoc);
-
- // get the extent
- m_scLast = m_lpViewObject->GetExtent(nDrawAspect, -1, pDoc->m_ptd, lpSize);
- return m_scLast == S_OK;
- }
-
- BOOL COleClientItem::SetIconicMetafile(HGLOBAL hMetaPict)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
-
- // get IOleCache interface
- LPOLECACHE lpOleCache = QUERYINTERFACE(m_lpObject, IOleCache);
- if (lpOleCache == NULL)
- {
- TRACE0("Warning: object does not support IOleCache interface.\n");
- return FALSE;
- }
- ASSERT(lpOleCache != NULL);
-
- // new cache is for CF_METAFILEPICT, DVASPECT_ICON
- FORMATETC formatEtc;
- formatEtc.cfFormat = CF_METAFILEPICT;
- formatEtc.ptd = NULL;
- formatEtc.dwAspect = DVASPECT_ICON;
- formatEtc.lindex = -1;
- formatEtc.tymed = TYMED_MFPICT;
-
- // setup the cache so iconic aspect is now included
- DWORD dwConnection;
- SCODE sc = lpOleCache->Cache(&formatEtc,
- ADVF_NODATA|ADVF_PRIMEFIRST|ADVF_ONLYONCE, &dwConnection);
- if (FAILED(sc))
- {
- lpOleCache->Release();
- return FALSE;
- }
-
- // set data if iconic image provided
- if (hMetaPict != NULL)
- {
- STGMEDIUM stgMedium;
- stgMedium.tymed = TYMED_MFPICT;
- stgMedium.hGlobal = hMetaPict;
- stgMedium.pUnkForRelease = NULL;
-
- sc = lpOleCache->SetData(&formatEtc, &stgMedium, FALSE);
- if (FAILED(sc))
- {
- lpOleCache->Release();
- return FALSE;
- }
- }
- lpOleCache->Release();
-
- return TRUE;
- }
-
- HGLOBAL COleClientItem::GetIconicMetafile()
- {
- USES_CONVERSION;
-
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
-
- // get IDataObject interface
- LPDATAOBJECT lpDataObject = QUERYINTERFACE(m_lpObject, IDataObject);
- ASSERT(lpDataObject != NULL);
-
- // cache is for CF_METAFILEPICT, DVASPECT_ICON
- FORMATETC formatEtc;
- formatEtc.cfFormat = CF_METAFILEPICT;
- formatEtc.ptd = NULL;
- formatEtc.dwAspect = DVASPECT_ICON;
- formatEtc.lindex = -1;
- formatEtc.tymed = TYMED_MFPICT;
-
- // attempt to get the icon picture
- STGMEDIUM stgMedium;
- if (lpDataObject->GetData(&formatEtc, &stgMedium) != S_OK)
- {
- lpDataObject->Release();
-
- // no current picture, attempt to get from class ID
- CLSID clsid;
- if (m_lpObject->GetUserClassID(&clsid) != S_OK)
- return NULL;
-
- TCHAR szTemp[_MAX_PATH];
- LPTSTR lpszLabel = NULL;
- if (GetType() == OT_LINK)
- {
- // it is a link, attempt to get link name
- LPOLELINK lpOleLink = QUERYINTERFACE(m_lpObject, IOleLink);
- if (lpOleLink != NULL)
- {
- LPOLESTR lpszDisplayName = NULL;
- lpOleLink->GetSourceDisplayName(&lpszDisplayName);
- if (lpszDisplayName != NULL)
- {
- szTemp[0] = 0;
- AfxGetFileTitle(OLE2CT(lpszDisplayName), szTemp, _countof(szTemp));
- if (szTemp[0] != '\0')
- lpszLabel = szTemp;
- CoTaskMemFree(lpszDisplayName);
- }
- lpOleLink->Release();
- }
- }
-
- HGLOBAL hMetaPict = OleGetIconOfClass(clsid, T2OLE(lpszLabel), lpszLabel == NULL);
- if (hMetaPict != NULL)
- {
- // cache it for later GetData (or drawing)
- SetIconicMetafile(hMetaPict);
- return hMetaPict;
- }
- return NULL;
- }
- lpDataObject->Release();
-
- // can't handle data where punkForRelease is set
- if (stgMedium.pUnkForRelease != NULL)
- {
- ::ReleaseStgMedium(&stgMedium);
- return NULL;
- }
- ASSERT(stgMedium.tymed == TYMED_MFPICT);
- ASSERT(stgMedium.hGlobal != NULL);
-
- return stgMedium.hGlobal; // return HGLOBAL to METAFILEPICT
- }
-
- void COleClientItem::SetDrawAspect(DVASPECT nDrawAspect)
- {
- ASSERT_VALID(this);
-
- // prime iconic cache (in case object has never displayed iconic)
- if (nDrawAspect == DVASPECT_ICON)
- {
- SetIconicMetafile(NULL); // allow object to provide own icon
- HGLOBAL hMetaPict = GetIconicMetafile();
- _AfxDeleteMetafilePict(hMetaPict);
- }
-
- // Note: the aspect you are setting may be uncached and therefore blank.
- // To make sure it is cached use SetIconPicture or use IOleCache to
- // set the cache yourself.
- m_nDrawAspect = nDrawAspect;
-
- // mark document as dirty (m_nDrawAspect is part of persistent state)
- ASSERT_VALID(m_pDocument);
- m_pDocument->SetModifiedFlag();
- }
-
- // Helper used to get the DVTARGETDEVICE pointer for the first printer.
- BOOL COleClientItem::GetPrintDeviceInfo(
- LPOLECACHE* plpOleCache, DVTARGETDEVICE** pptd, DWORD* pdwConnection)
- {
- *plpOleCache = NULL;
- *pptd = NULL;
-
- // get IOleCache interface
- LPOLECACHE lpOleCache = QUERYINTERFACE(m_lpObject, IOleCache);
- if (lpOleCache == NULL)
- {
- TRACE0("Warning: object does not support IOleCache interface.\n");
- return FALSE; // no cache -- no possible print device
- }
- ASSERT(lpOleCache != NULL);
-
- // get enumerator for the cache
- LPENUMSTATDATA lpEnumSTATDATA;
- if (lpOleCache->EnumCache(&lpEnumSTATDATA) != S_OK || lpEnumSTATDATA == NULL)
- {
- lpOleCache->Release();
- return FALSE;
- }
- // enumerate entries in the cache (look for one with ptd != NULL)
- STATDATA statData;
- while (lpEnumSTATDATA->Next(1, &statData, NULL) == S_OK)
- {
- ASSERT(statData.pAdvSink == NULL);
-
- // return first non-NULL ptd (we assume this is a printer cache)
- if (statData.formatetc.ptd != NULL)
- {
- if (pdwConnection != NULL)
- *pdwConnection = statData.dwConnection;
- *pptd = statData.formatetc.ptd;
- lpEnumSTATDATA->Release();
-
- *plpOleCache = lpOleCache;
- return TRUE; // Note: lpOleCache pointer is still alive
- }
- }
- // release interfaces
- lpEnumSTATDATA->Release();
- lpOleCache->Release();
- return FALSE; // data not found
- }
-
- void COleClientItem::AttachDataObject(COleDataObject& rDataObject) const
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
-
- // get the IDataObject interface for the item
- LPDATAOBJECT lpDataObject = QUERYINTERFACE(m_lpObject, IDataObject);
- ASSERT(lpDataObject != NULL);
-
- // return it by attaching it
- rDataObject.Attach(lpDataObject, TRUE);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem - general operations
-
- BOOL COleClientItem::Draw(CDC* pDC, LPCRECT lpBounds, DVASPECT nDrawAspect)
- {
- ASSERT_VALID(this);
- ASSERT(AfxIsValidAddress(lpBounds, sizeof(RECT), FALSE));
- ASSERT_VALID(pDC);
-
- if (m_lpObject == NULL || m_lpViewObject == NULL)
- return FALSE; // partially created COleClientItem object
-
- // use current draw aspect if aspect is -1 (default)
- if (nDrawAspect == -1)
- nDrawAspect = m_nDrawAspect;
-
- // convert RECT lpBounds to RECTL rclBounds
- RECTL rclBounds;
- rclBounds.left = lpBounds->left;
- rclBounds.top = lpBounds->top;
- rclBounds.right = lpBounds->right;
- rclBounds.bottom = lpBounds->bottom;
-
- // get RECTL describing window extents and origin
- RECTL rclWBounds;
- CPoint ptOrg = pDC->GetWindowOrg();
- CSize sizeExt = pDC->GetWindowExt();
- rclWBounds.left = ptOrg.x;
- rclWBounds.top = ptOrg.y;
- rclWBounds.right = sizeExt.cx;
- rclWBounds.bottom = sizeExt.cy;
-
- // get target device to use for draw
- COleDocument* pDoc = GetDocument();
- const DVTARGETDEVICE* ptd = NULL;
- HDC hdcTarget = NULL;
- if (pDC->IsPrinting() && pDoc->m_ptd != NULL)
- {
- ptd = pDoc->m_ptd;
- hdcTarget = pDC->m_hAttribDC;
- }
-
- // attempt draw with target device
- SCODE sc = m_lpViewObject->Draw(nDrawAspect, -1, NULL,
- (DVTARGETDEVICE*)ptd, hdcTarget, pDC->m_hDC,
- &rclBounds, &rclWBounds, NULL, 0);
- if (ptd != NULL && sc == OLE_E_BLANK)
- {
- // attempt draw without target device
- sc = m_lpViewObject->Draw(nDrawAspect, -1, NULL,
- NULL, NULL, pDC->m_hDC,
- &rclBounds, &rclWBounds, NULL, 0);
- }
-
- if (sc != S_OK && sc == OLE_E_BLANK)
- return FALSE; // return FALSE if the object is blank
-
- CheckGeneral(sc); // otherwise, may throw exception on error
- return TRUE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem clipboard helpers
-
- void COleClientItem::GetEmbeddedItemData(LPSTGMEDIUM lpStgMedium)
- {
- ASSERT_VALID(this);
- ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
-
- LPLOCKBYTES lpLockBytes;
- SCODE sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);
- if (sc != S_OK)
- AfxThrowOleException(sc);
- ASSERT(lpLockBytes != NULL);
-
- LPSTORAGE lpStorage;
- sc = ::StgCreateDocfileOnILockBytes(lpLockBytes,
- STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &lpStorage);
- if (sc != S_OK)
- {
- VERIFY(lpLockBytes->Release() == 0);
- AfxThrowOleException(sc);
- }
- ASSERT(lpStorage != NULL);
- lpLockBytes->Release();
-
- // save the object into the storage
- LPPERSISTSTORAGE lpPersistStorage =
- QUERYINTERFACE(m_lpObject, IPersistStorage);
- ASSERT(lpPersistStorage != NULL);
- sc = ::OleSave(lpPersistStorage, lpStorage, FALSE);
- lpPersistStorage->SaveCompleted(NULL);
- lpPersistStorage->Release();
- if (sc != S_OK)
- {
- VERIFY(lpStorage->Release() == 0);
- AfxThrowOleException(sc);
- }
-
- // add it to the data source
- lpStgMedium->tymed = TYMED_ISTORAGE;
- lpStgMedium->pstg = lpStorage;
- lpStgMedium->pUnkForRelease = NULL;
- }
-
- void COleClientItem::AddCachedData(COleDataSource* pDataSource)
- {
- ASSERT_VALID(this);
- ASSERT_VALID(pDataSource);
-
- // get IOleCache interface
- LPOLECACHE lpOleCache = QUERYINTERFACE(m_lpObject, IOleCache);
- if (lpOleCache == NULL)
- {
- TRACE0("Warning: object does not support IOleCache interface.\n");
- return;
- }
- ASSERT(lpOleCache != NULL);
-
- // Get IEnumSTATDATA interface for IOleCache
- LPENUMSTATDATA lpEnumSTATDATA;
- if (lpOleCache->EnumCache(&lpEnumSTATDATA) != S_OK || lpEnumSTATDATA == NULL)
- {
- lpOleCache->Release();
- return;
- }
-
- // get IDataObject interface
- LPDATAOBJECT lpDataObject = QUERYINTERFACE(m_lpObject, IDataObject);
- ASSERT(lpDataObject != NULL);
-
- // enumerate all of the cached formats
- STATDATA statData;
- while (lpEnumSTATDATA->Next(1, &statData, NULL) == S_OK)
- {
- ASSERT(statData.pAdvSink == NULL);
-
- // for each format supported, attempt to get copy of the data
- STGMEDIUM stgMedium;
- if (lpDataObject->GetData(&statData.formatetc, &stgMedium) != S_OK)
- {
- // data is not available
- CoTaskMemFree(statData.formatetc.ptd);
- }
- else if (stgMedium.pUnkForRelease != NULL)
- {
- // don't cache data with pUnkForRelease != NULL
- ::ReleaseStgMedium(&stgMedium);
- CoTaskMemFree(statData.formatetc.ptd);
- }
- else
- {
- // format was acceptable -- add it to the clipboard
- pDataSource->CacheData(0, &stgMedium, &statData.formatetc);
- }
- }
-
- // release interfaces
- lpEnumSTATDATA->Release();
- lpDataObject->Release();
- lpOleCache->Release();
- }
-
- BOOL COleClientItem::GetLinkSourceData(LPSTGMEDIUM lpStgMedium)
- {
- ASSERT_VALID(this);
- ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
-
- LPMONIKER lpMoniker = NULL;
- LPOLELINK lpOleLink = QUERYINTERFACE(m_lpObject, IOleLink);
- if (lpOleLink == NULL)
- {
- // get moniker from client site
- LPOLECLIENTSITE lpClientSite = GetClientSite();
- ASSERT(lpClientSite != NULL);
- SCODE sc = lpClientSite->GetMoniker(OLEGETMONIKER_TEMPFORUSER,
- OLEWHICHMK_OBJFULL, &lpMoniker);
- if (sc != S_OK)
- {
- TRACE0("Warning: unable to get moniker from client site.\n");
- return FALSE;
- }
- ASSERT(lpMoniker != NULL);
- }
- else
- {
- // get moniker from the link object itself
- SCODE sc = lpOleLink->GetSourceMoniker(&lpMoniker);
- lpOleLink->Release();
- if (sc != S_OK)
- {
- TRACE0("Warning: unable to get moniker from link source.\n");
- return FALSE;
- }
- ASSERT(lpMoniker != NULL);
- }
-
- // create a memory based stream to write the moniker to
- LPSTREAM lpStream;
- if (::CreateStreamOnHGlobal(NULL, TRUE, &lpStream) != S_OK)
- {
- lpMoniker->Release();
- AfxThrowMemoryException();
- }
- ASSERT(lpStream != NULL);
-
- // write the moniker to the stream, and add it to the clipboard
- SCODE sc = ::OleSaveToStream(lpMoniker, lpStream);
- lpMoniker->Release();
- if (sc != S_OK)
- {
- lpStream->Release();
- AfxThrowOleException(sc);
- }
-
- // write the class ID of the document to the stream as well
- CLSID clsid;
- sc = m_lpObject->GetUserClassID(&clsid);
- if (sc != S_OK)
- {
- lpStream->Release();
- AfxThrowOleException(sc);
- }
- sc = WriteClassStm(lpStream, clsid);
- if (sc != S_OK)
- {
- lpStream->Release();
- AfxThrowOleException(sc);
- }
-
- // add it to the data source
- lpStgMedium->tymed = TYMED_ISTREAM;
- lpStgMedium->pstm = lpStream;
- lpStgMedium->pUnkForRelease = NULL;
- return TRUE;
- }
-
- void COleClientItem::GetObjectDescriptorData(
- LPPOINT lpOffset, LPSIZE lpSize, LPSTGMEDIUM lpStgMedium)
- {
- USES_CONVERSION;
-
- ASSERT_VALID(this);
- ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
- ASSERT(lpOffset == NULL ||
- AfxIsValidAddress(lpOffset, sizeof(CPoint), FALSE));
-
- POINTL pointT;
- if (lpOffset != NULL)
- {
- pointT.x = lpOffset->x;
- pointT.y = lpOffset->y;
- ((CDC*)NULL)->DPtoHIMETRIC((SIZE*)&pointT);
- }
- else
- {
- pointT.x = 0;
- pointT.y = 0;
- }
-
- SIZE sizeT;
- if (lpSize != NULL)
- {
- sizeT.cx = lpSize->cx;
- sizeT.cy = lpSize->cy;
- ((CDC*)NULL)->DPtoHIMETRIC(&sizeT);
- }
- else
- {
- sizeT.cx = 0;
- sizeT.cy = 0;
- }
-
- COleDocument* pDoc = GetDocument();
-
- // get the object descriptor for the IOleObject
- InterlockedIncrement(&m_dwRef);
- HGLOBAL hGlobal = _AfxOleGetObjectDescriptorData(
- m_lpObject, T2COLE(pDoc->GetPathName()), m_nDrawAspect, pointT, &sizeT);
- InterlockedDecrement(&m_dwRef);
-
- if (hGlobal == NULL)
- AfxThrowMemoryException();
-
- // setup the STGMEDIUM
- lpStgMedium->tymed = TYMED_HGLOBAL;
- lpStgMedium->hGlobal = hGlobal;
- lpStgMedium->pUnkForRelease = NULL;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Embedded COleClientItem operations
-
- void COleClientItem::SetHostNames(LPCTSTR lpszHost, LPCTSTR lpszHostObj)
- {
- USES_CONVERSION;
-
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
- ASSERT(AfxIsValidString(lpszHost));
-
- ASSERT(AfxIsValidString(lpszHostObj));
- CheckGeneral(m_lpObject->SetHostNames(T2COLE(lpszHost),
- T2COLE(lpszHostObj)));
- }
-
- void COleClientItem::SetExtent(const CSize& size, DVASPECT nDrawAspect)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
-
- CheckGeneral(m_lpObject->SetExtent(nDrawAspect, (SIZE*)&size));
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem OLE interface implementation
-
- BEGIN_INTERFACE_MAP(COleClientItem, CDocItem)
- INTERFACE_PART(COleClientItem, IID_IOleClientSite, OleClientSite)
- INTERFACE_PART(COleClientItem, IID_IAdviseSink, AdviseSink)
- INTERFACE_PART(COleClientItem, IID_IOleWindow, OleIPSite)
- INTERFACE_PART(COleClientItem, IID_IOleInPlaceSite, OleIPSite)
- END_INTERFACE_MAP()
-
- /////////////////////////////////////////////////////////////////////////////
- // Implementation of IOleClientSite
-
- STDMETHODIMP_(ULONG) COleClientItem::XOleClientSite::AddRef()
- {
- METHOD_PROLOGUE_EX_(COleClientItem, OleClientSite)
- return pThis->ExternalAddRef();
- }
-
- STDMETHODIMP_(ULONG) COleClientItem::XOleClientSite::Release()
- {
- METHOD_PROLOGUE_EX_(COleClientItem, OleClientSite)
- return pThis->ExternalRelease();
- }
-
- STDMETHODIMP COleClientItem::XOleClientSite::QueryInterface(
- REFIID iid, LPVOID* ppvObj)
- {
- METHOD_PROLOGUE_EX_(COleClientItem, OleClientSite)
- return pThis->ExternalQueryInterface(&iid, ppvObj);
- }
-
- STDMETHODIMP COleClientItem::XOleClientSite::SaveObject()
- {
- METHOD_PROLOGUE_EX(COleClientItem, OleClientSite)
- ASSERT_VALID(pThis);
-
- LPPERSISTSTORAGE lpPersistStorage =
- QUERYINTERFACE(pThis->m_lpObject, IPersistStorage);
- ASSERT(lpPersistStorage != NULL);
- SCODE sc = S_OK;
- if (lpPersistStorage->IsDirty() == S_OK)
- {
- // S_OK == S_TRUE != S_FALSE, therefore object is dirty!
- sc = ::OleSave(lpPersistStorage, pThis->m_lpStorage, TRUE);
- if (sc == S_OK)
- sc = lpPersistStorage->SaveCompleted(NULL);
-
- // mark the document as dirty, if save sucessful.
- pThis->m_pDocument->SetModifiedFlag();
- }
- lpPersistStorage->Release();
- return sc;
- }
-
- STDMETHODIMP COleClientItem::XOleClientSite::GetMoniker(
- DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER* ppMoniker)
- {
- METHOD_PROLOGUE_EX(COleClientItem, OleClientSite)
- ASSERT_VALID(pThis);
-
- USES_CONVERSION;
-
- COleDocument* pDoc = pThis->GetDocument();
- ASSERT_VALID(pDoc);
- ASSERT(ppMoniker != NULL);
- *ppMoniker = NULL;
-
- switch (dwWhichMoniker)
- {
- case OLEWHICHMK_CONTAINER:
- // return the current moniker for the document
- *ppMoniker = pDoc->GetMoniker((OLEGETMONIKER)dwAssign);
- break;
-
- case OLEWHICHMK_OBJREL:
- {
- if (!pDoc->IsKindOf(RUNTIME_CLASS(COleLinkingDoc)))
- break;
-
- // don't return relative moniker if no document moniker
- LPMONIKER lpMoniker = pDoc->GetMoniker((OLEGETMONIKER)dwAssign);
- if (lpMoniker == NULL)
- break;
- lpMoniker->Release();
-
- // relative monikers have to handle assignment correctly
- switch (dwAssign)
- {
- case OLEGETMONIKER_ONLYIFTHERE:
- if (!pThis->m_bMoniker)
- break; // no moniker assigned, don't return one
- // fall through...
-
- case OLEGETMONIKER_TEMPFORUSER:
- case OLEGETMONIKER_FORCEASSIGN:
- {
- // create item moniker from item name
- TCHAR szItemName[OLE_MAXITEMNAME];
- pThis->GetItemName(szItemName);
- CreateItemMoniker(OLESTDDELIMOLE, T2COLE(szItemName),
- ppMoniker);
-
- // notify the object of the assignment
- if (dwAssign != OLEGETMONIKER_TEMPFORUSER &&
- *ppMoniker != NULL && !pThis->m_bMoniker)
- {
- pThis->m_bMoniker = TRUE;
- VERIFY(pThis->m_lpObject->SetMoniker(
- OLEWHICHMK_OBJREL, *ppMoniker) == S_OK);
- ASSERT_VALID(pThis->m_pDocument);
- pThis->m_pDocument->SetModifiedFlag();
- }
- }
- break;
-
- case OLEGETMONIKER_UNASSIGN:
- pThis->m_bMoniker = FALSE;
- break;
- }
- }
- break;
-
- case OLEWHICHMK_OBJFULL:
- {
- // get each sub-moniker: item & document
- LPMONIKER lpMoniker1, lpMoniker2;
- GetMoniker(dwAssign, OLEWHICHMK_CONTAINER, &lpMoniker1);
- GetMoniker(dwAssign, OLEWHICHMK_OBJREL, &lpMoniker2);
-
- // create composite moniker
- if (lpMoniker1 != NULL && lpMoniker2 != NULL)
- ::CreateGenericComposite(lpMoniker1, lpMoniker2, ppMoniker);
-
- // release sub-monikers
- RELEASE(lpMoniker1);
- RELEASE(lpMoniker2);
- }
- break;
- }
-
- return *ppMoniker != NULL ? S_OK : E_FAIL;
- }
-
- STDMETHODIMP COleClientItem::XOleClientSite::GetContainer(
- LPOLECONTAINER* ppContainer)
- {
- #ifdef _DEBUG
- METHOD_PROLOGUE_EX(COleClientItem, OleClientSite)
- #else
- METHOD_PROLOGUE_EX_(COleClientItem, OleClientSite)
- #endif
-
- // return the IOleItemContainer interface in the document
- COleDocument* pDoc = pThis->GetDocument();
- ASSERT_VALID(pDoc);
- *ppContainer = pDoc->GetContainer();
-
- return *ppContainer != NULL ? S_OK : E_NOINTERFACE;
- }
-
- STDMETHODIMP COleClientItem::XOleClientSite::ShowObject()
- {
- METHOD_PROLOGUE_EX(COleClientItem, OleClientSite)
- ASSERT_VALID(pThis);
-
- TRY
- {
- pThis->OnShowItem();
- }
- END_TRY
-
- return S_OK;
- }
-
- STDMETHODIMP COleClientItem::XOleClientSite::OnShowWindow(BOOL fShow)
- {
- METHOD_PROLOGUE_EX(COleClientItem, OleClientSite)
- ASSERT_VALID(pThis);
-
- // ignore this if the item is already in-place
- if (pThis->IsInPlaceActive())
- return S_OK;
-
- TRY
- {
- // store new state of object -- determines how object may be drawn
- COleClientItem::ItemState uNewState;
- uNewState = fShow ? COleClientItem::openState :
- COleClientItem::loadedState;
- if (uNewState != pThis->m_nItemState)
- {
- pThis->OnChange(OLE_CHANGED_STATE, (DWORD)uNewState);
- pThis->m_nItemState = uNewState;
- }
- }
- END_TRY
-
- return S_OK;
- }
-
- STDMETHODIMP COleClientItem::XOleClientSite::RequestNewObjectLayout()
- {
- return E_NOTIMPL;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Implementation of IAdviseSink
-
- STDMETHODIMP_(ULONG) COleClientItem::XAdviseSink::AddRef()
- {
- METHOD_PROLOGUE_EX_(COleClientItem, AdviseSink)
- return pThis->ExternalAddRef();
- }
-
- STDMETHODIMP_(ULONG) COleClientItem::XAdviseSink::Release()
- {
- METHOD_PROLOGUE_EX_(COleClientItem, AdviseSink)
- return pThis->ExternalRelease();
- }
-
- STDMETHODIMP COleClientItem::XAdviseSink::QueryInterface(
- REFIID iid, LPVOID* ppvObj)
- {
- METHOD_PROLOGUE_EX_(COleClientItem, AdviseSink)
- return pThis->ExternalQueryInterface(&iid, ppvObj);
- }
-
- STDMETHODIMP_(void) COleClientItem::XAdviseSink::OnDataChange(
- LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
- {
- METHOD_PROLOGUE_EX(COleClientItem, AdviseSink)
- ASSERT_VALID(pThis);
-
- // Only interesting for advanced containers. Forward it such that
- // containers do not have to implement the entire interface.
- pThis->OnDataChange(lpFormatEtc, lpStgMedium);
- }
-
- STDMETHODIMP_(void) COleClientItem::XAdviseSink::OnViewChange(
- DWORD aspects, LONG /*lindex*/)
- {
- METHOD_PROLOGUE_EX(COleClientItem, AdviseSink)
- ASSERT_VALID(pThis);
-
- pThis->OnChange(OLE_CHANGED, (DVASPECT)aspects);
- }
-
- STDMETHODIMP_(void) COleClientItem::XAdviseSink::OnRename(
- LPMONIKER /*lpMoniker*/)
- {
- // only interesting to the OLE link object. Containers ignore this.
- }
-
- STDMETHODIMP_(void) COleClientItem::XAdviseSink::OnSave()
- {
- METHOD_PROLOGUE_EX(COleClientItem, AdviseSink)
- ASSERT_VALID(pThis);
-
- pThis->OnChange(OLE_SAVED, (DVASPECT)0);
- }
-
- STDMETHODIMP_(void) COleClientItem::XAdviseSink::OnClose()
- {
- METHOD_PROLOGUE_EX(COleClientItem, AdviseSink)
- ASSERT_VALID(pThis);
-
- pThis->OnChange(OLE_CLOSED, (DVASPECT)0);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem diagnostics
-
- #ifdef _DEBUG
- void COleClientItem::AssertValid() const
- {
- CDocItem::AssertValid();
- if (m_lpNewStorage != NULL)
- ASSERT(m_bNeedCommit);
- if (m_pView != NULL)
- m_pView->AssertValid();
- if (m_pInPlaceFrame != NULL)
- m_pInPlaceFrame->AssertValid();
- if (m_pInPlaceDoc != NULL)
- m_pInPlaceDoc->AssertValid();
- }
-
- void COleClientItem::Dump(CDumpContext& dc) const
- {
- CDocItem::Dump(dc);
-
- // shallow dump
- dc << "m_lpObject = " << (void*)m_lpObject;
- dc << "\nm_dwItemNumber = " << m_dwItemNumber;
- dc << "\nm_nDrawAspect = " << (int)m_nDrawAspect;
- dc << "\nm_scLast = " << m_scLast;
- dc << "\nm_lpStorage = " << m_lpStorage;
- dc << "\nm_lpLockBytes = " << m_lpLockBytes;
- dc << "\nm_dwConnection = " << m_dwConnection;
- dc << "\nm_bLinkUnavail = " << m_bLinkUnavail;
- dc << "\nm_bMoniker = " << m_bMoniker;
- dc << "\nm_lpNewStorage = " << m_lpNewStorage;
- dc << "\nm_bNeedCommit = " << m_bNeedCommit;
- dc << "\nm_nItemState = " << (int)m_nItemState;
- dc << "\nm_pView = " << (void*)m_pView;
- dc << "\nm_dwContainerStyle = " << m_dwContainerStyle;
- dc << "\nm_pInPlaceFrame = " << (void*)m_pInPlaceFrame;
- dc << "\nm_hWndServer = " << m_hWndServer;
- }
- #endif //_DEBUG
-
- /////////////////////////////////////////////////////////////////////////////
- // Inline function declarations expanded out-of-line
-
- #ifndef _AFX_ENABLE_INLINES
-
- // expand inlines for OLE client APIs
- static char _szAfxOleInl[] = "afxole.inl";
- #undef THIS_FILE
- #define THIS_FILE _szAfxOleInl
- #define _AFXOLECLI_INLINE
- #define _AFXOLEDOBJ_INLINE
- #include "afxole.inl"
-
- #endif //!_AFX_ENABLE_INLINES
-
- #ifdef AFX_INIT_SEG
- #pragma code_seg(AFX_INIT_SEG)
- #endif
-
- // IMPLEMENT_DYNAMIC for COleLinkingDoc here for better .OBJ granularity
- IMPLEMENT_DYNAMIC(COleLinkingDoc, COleDocument)
-
- /////////////////////////////////////////////////////////////////////////////
-