| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846 |
- // 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_OLE3_SEG
- #pragma code_seg(AFX_OLE3_SEG)
- #endif
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- #define new DEBUG_NEW
- #define OLE_MAXNAMESIZE (256)
- /////////////////////////////////////////////////////////////////////////////
- // COleLinkingDoc - enables linking to embeddings (basis for server)
- COleLinkingDoc::COleLinkingDoc()
- {
- m_dwRegister = 0;
- m_pFactory = NULL;
- m_bVisibleLock = FALSE;
- m_bDeferErrors = FALSE;
- m_pLastException = NULL;
- m_lpMonikerROT = NULL;
- ASSERT_VALID(this);
- }
- COleLinkingDoc::~COleLinkingDoc()
- {
- ASSERT_VALID(this);
- ASSERT(!m_bVisibleLock);
- DisconnectViews();
- ASSERT(m_viewList.IsEmpty());
- Revoke(); // cleanup naming support
- ExternalDisconnect();
- }
- /////////////////////////////////////////////////////////////////////////////
- // COleLinkingDoc moniker handling
- LPMONIKER COleLinkingDoc::GetMoniker(OLEGETMONIKER nAssign)
- {
- USES_CONVERSION;
- ASSERT_VALID(this);
- // use base class implementation if no registered moniker
- if (m_strMoniker.IsEmpty())
- return COleDocument::GetMoniker(nAssign);
- // return file moniker based on current path name
- LPMONIKER lpMoniker;
- CreateFileMoniker(T2COLE(m_strMoniker), &lpMoniker);
- return lpMoniker;
- }
- BOOL COleLinkingDoc::Register(COleObjectFactory* pFactory, LPCTSTR lpszPathName)
- {
- USES_CONVERSION;
- ASSERT_VALID(this);
- ASSERT(pFactory == NULL ||
- AfxIsValidAddress(pFactory, sizeof(COleObjectFactory)));
- ASSERT(lpszPathName == NULL || AfxIsValidString(lpszPathName));
- ASSERT(m_dwRegister == 0);
- // attach the document to the server
- ASSERT(m_pFactory == NULL || m_pFactory == pFactory);
- m_pFactory = pFactory;
- BOOL bResult = TRUE;
- // create file moniker based on path name
- RELEASE(m_lpMonikerROT);
- m_strMoniker.Empty();
- if (lpszPathName != NULL)
- {
- if (CreateFileMoniker(T2COLE(lpszPathName), &m_lpMonikerROT) != S_OK)
- bResult = FALSE;
- }
- // register file moniker as running
- if (m_lpMonikerROT != NULL)
- {
- // see if the object is already running in the ROT
- LPRUNNINGOBJECTTABLE lpROT = NULL;
- VERIFY(GetRunningObjectTable(0, &lpROT) == S_OK);
- ASSERT(lpROT != NULL);
- LPUNKNOWN lpUnk;
- if (lpROT->GetObject(m_lpMonikerROT, &lpUnk) == S_OK)
- {
- // fatal error -- can't register same moniker twice!
- lpUnk->Release();
- RELEASE(m_lpMonikerROT);
- return FALSE;
- }
- // not already running -- so ok to attempt registration
- SCODE sc = lpROT->Register(NULL, (LPUNKNOWN)
- GetInterface(&IID_IUnknown), m_lpMonikerROT, &m_dwRegister);
- lpROT->Release();
- m_strMoniker = lpszPathName;
- if (sc != S_OK)
- bResult = FALSE;
- }
- // update all objects with new moniker
- POSITION pos = GetStartPosition();
- COleClientItem* pItem;
- while ((pItem = GetNextClientItem(pos)) != NULL)
- {
- if (pItem->m_bMoniker)
- {
- ASSERT(pItem->m_lpObject != NULL);
- pItem->m_lpObject->SetMoniker(OLEWHICHMK_CONTAINER,
- m_lpMonikerROT);
- }
- }
- return bResult;
- }
- void COleLinkingDoc::Revoke()
- {
- ASSERT_VALID(this);
- // revoke current registration
- if (m_dwRegister != 0)
- {
- LPRUNNINGOBJECTTABLE lpROT = NULL;
- GetRunningObjectTable(0, &lpROT);
- if (lpROT != NULL)
- {
- lpROT->Revoke(m_dwRegister);
- lpROT->Release();
- }
- m_dwRegister = 0;
- }
- RELEASE(m_lpMonikerROT);
- m_strMoniker = _T("");
- }
- BOOL COleLinkingDoc::OnNewDocument()
- {
- ASSERT_VALID(this);
- Revoke();
- RegisterIfServerAttached(NULL, TRUE);
- if (!COleDocument::OnNewDocument())
- return FALSE;
- AfxOleSetUserCtrl(TRUE);
- return TRUE;
- }
- BOOL COleLinkingDoc::OnOpenDocument(LPCTSTR lpszPathName)
- {
- ASSERT_VALID(this);
- // always register the document before opening it
- Revoke();
- if (!RegisterIfServerAttached(lpszPathName, FALSE))
- {
- // always output a trace (it is just an FYI -- not generally fatal)
- TRACE1("Warning: Unable to register moniker '%s' as running\n", lpszPathName);
- }
- if (!COleDocument::OnOpenDocument(lpszPathName))
- {
- Revoke();
- return FALSE;
- }
- // if the app was started only to print, don't set user control
- CWinApp* pApp = AfxGetApp();
- ASSERT(pApp != NULL);
- if (pApp->m_pCmdInfo == NULL ||
- (pApp->m_pCmdInfo->m_nShellCommand != CCommandLineInfo::FileDDE &&
- pApp->m_pCmdInfo->m_nShellCommand != CCommandLineInfo::FilePrint))
- {
- AfxOleSetUserCtrl(TRUE);
- }
- return TRUE;
- }
- BOOL COleLinkingDoc::OnSaveDocument(LPCTSTR lpszPathName)
- {
- ASSERT_VALID(this);
- BOOL bRemember = m_bRemember;
- if (!COleDocument::OnSaveDocument(lpszPathName))
- return FALSE;
- if (bRemember && (m_strMoniker != lpszPathName))
- {
- // update the moniker/registration since the name has changed
- Revoke();
- RegisterIfServerAttached(lpszPathName, TRUE);
- }
- return TRUE;
- }
- void COleLinkingDoc::OnCloseDocument()
- {
- InternalAddRef(); // protect document during shutdown
- // update lock count before sending notifications
- UpdateVisibleLock(FALSE, FALSE);
- Revoke(); // cleanup naming support
- // remove visible lock if present
- if (m_bVisibleLock)
- {
- m_bVisibleLock = FALSE;
- LockExternal(FALSE, FALSE);
- }
- // cleanup the document but don't delete yet
- BOOL bAutoDelete = m_bAutoDelete;
- m_bAutoDelete = FALSE;
- COleDocument::OnCloseDocument();
- ASSERT_VALID(this);
- // remove extra reference count and destroy
- InterlockedDecrement(&m_dwRef);
- if (bAutoDelete)
- delete this; // now safe to destroy document
- }
- void COleLinkingDoc::UpdateVisibleLock(BOOL bVisible, BOOL bRemoveRefs)
- {
- ASSERT_VALID(this);
- if (bVisible != m_bVisibleLock)
- {
- InternalAddRef(); // make sure document is stable
- m_bVisibleLock = bVisible;
- LockExternal(bVisible, bRemoveRefs);
- InternalRelease(); // may Release the document!
- }
- }
- void COleLinkingDoc::OnShowViews(BOOL bVisible)
- {
- if (bVisible)
- UpdateVisibleLock(bVisible, TRUE);
- }
- void COleLinkingDoc::SaveToStorage(CObject* pObject)
- {
- ASSERT_VALID(this);
- if (pObject != NULL)
- ASSERT_VALID(pObject);
- // write the classID of the application to the root storage
- if (m_pFactory != NULL)
- {
- ASSERT(m_lpRootStg != NULL);
- WriteClassStg(m_lpRootStg, m_pFactory->GetClassID());
- }
- COleDocument::SaveToStorage(pObject);
- }
- BOOL COleLinkingDoc::RegisterIfServerAttached(LPCTSTR lpszPathName, BOOL bMessage)
- {
- ASSERT_VALID(this);
- ASSERT(lpszPathName == NULL || AfxIsValidString(lpszPathName));
- CDocTemplate* pTemplate = GetDocTemplate();
- ASSERT_VALID(pTemplate);
- COleObjectFactory* pFactory =
- (COleObjectFactory*)pTemplate->m_pAttachedFactory;
- if (pFactory != NULL)
- {
- // always attach the document to the server at this time
- ASSERT_KINDOF(COleObjectFactory, pFactory);
- m_pFactory = pFactory;
- // register with OLE Server
- if (!Register(pFactory, lpszPathName))
- {
- if (bMessage)
- {
- // only report error when message box allowed
- ReportSaveLoadException(lpszPathName, NULL, FALSE,
- AFX_IDP_FAILED_TO_NOTIFY);
- }
- return FALSE;
- }
- }
- return TRUE;
- }
- LPOLEITEMCONTAINER COleLinkingDoc::GetContainer()
- {
- ASSERT_VALID(this);
- // get the IOleItemContainer interface via QueryInterface
- LPOLEITEMCONTAINER lpContainer;
- InternalQueryInterface(&IID_IOleItemContainer, (LPLP)&lpContainer);
- return lpContainer;
- }
- /////////////////////////////////////////////////////////////////////////////
- // COleLinkingDoc default implementation
- COleServerItem* COleLinkingDoc::OnGetLinkedItem(LPCTSTR /*lpszItemName*/)
- {
- ASSERT_VALID(this);
- // default implementation is in COleServerDoc
- return NULL;
- }
- COleClientItem* COleLinkingDoc::OnFindEmbeddedItem(LPCTSTR lpszItemName)
- {
- ASSERT_VALID(this);
- ASSERT(AfxIsValidString(lpszItemName));
- // default implementation walks list of client items looking for
- // a case sensitive match
- POSITION pos = GetStartPosition();
- COleClientItem* pItem;
- while ((pItem = GetNextClientItem(pos)) != NULL)
- {
- // a client item is running if there is a match in name
- // and the m_lpObject is also running.
- TCHAR szItemName[OLE_MAXITEMNAME];
- pItem->GetItemName(szItemName);
- if (lstrcmp(szItemName, lpszItemName) == 0)
- return pItem;
- }
- #ifdef _DEBUG
- if (afxTraceFlags & traceOle)
- {
- TRACE0("Warning: default COleLinkingDoc::OnFindEmbeddedItem\n");
- TRACE1("\timplementation failed to find item '%s'.\n", lpszItemName);
- }
- #endif
- return NULL; // no matching item found
- }
- void COleLinkingDoc::LockExternal(BOOL bLock, BOOL bRemoveRefs)
- {
- // when an item binding is successful, the original document
- // is released. To keep it alive and the RPC stubs that make
- // it available to the external world (via the running object
- // table), we need to place a lock on it.
- // a lock created with CoLockObjectExternal adds a reference
- // to the object itself (with IUnknown::AddRef) as well
- // as keeping the RPC stub alive.
- ::CoLockObjectExternal((LPUNKNOWN)GetInterface(&IID_IUnknown),
- bLock, bRemoveRefs);
- if (bLock)
- {
- // avoid "dead" objects in the running object table (ROT), by
- // re-registering this object in the ROT.
- if (!m_strPathName.IsEmpty())
- {
- Revoke();
- RegisterIfServerAttached(m_strPathName, FALSE);
- }
- }
- }
- void COleLinkingDoc::ReportSaveLoadException(LPCTSTR lpszPathName,
- CException* e, BOOL bSaving, UINT nIDPDefault)
- {
- // watch out for special mode
- if (m_bDeferErrors)
- {
- // Note: CException::Delete does not treat m_bAutoDelete as a
- // traditional BOOL. Only if it is greater than zero does it
- // take on a TRUE quality. (that is, all tests are for
- // m_bAutoDelete > 0). So, if m_bAutoDelete is already "true"
- // (1) this will make it false, and if it is already "false"
- // it is still considered "false". Valid values for
- // m_bAutoDelete are thus negative, 0, and 1. Values greater
- // than 1, although not explicitly asserted in CException,
- // would be invalid. In short, by using increment and
- // decrement operations, we enable this to work with both
- // self-deleting and non-self-deleting CException classes.
- --e->m_bAutoDelete;
- // save the exception for later
- m_pLastException = e;
- return;
- }
- // otherwise, just call base class
- COleDocument::ReportSaveLoadException(lpszPathName, e, bSaving,
- nIDPDefault);
- }
- SCODE COleLinkingDoc::EndDeferErrors(SCODE sc)
- {
- ASSERT(m_bDeferErrors != 0);
- --m_bDeferErrors;
- if (m_pLastException != NULL)
- {
- ASSERT_VALID(m_pLastException);
- if (sc == S_OK)
- sc = COleException::Process(m_pLastException);
- // Note: See note above in ReportSaveLoadException for
- // a comment regarding the special treatment of m_bAutoDelete.
- ++m_pLastException->m_bAutoDelete;
- // now get rid of the exception that we saved
- m_pLastException->Delete();
- m_pLastException = NULL;
- }
- return sc;
- }
- /////////////////////////////////////////////////////////////////////////////
- // COleLinkingDoc OLE interface implementation
- BEGIN_INTERFACE_MAP(COleLinkingDoc, COleDocument)
- INTERFACE_PART(COleLinkingDoc, IID_IPersist, PersistFile)
- INTERFACE_PART(COleLinkingDoc, IID_IPersistFile, PersistFile)
- INTERFACE_PART(COleLinkingDoc, IID_IParseDisplayName, OleItemContainer)
- INTERFACE_PART(COleLinkingDoc, IID_IOleContainer, OleItemContainer)
- INTERFACE_PART(COleLinkingDoc, IID_IOleItemContainer, OleItemContainer)
- END_INTERFACE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // COleLinkingDoc::XPersistFile implementation
- STDMETHODIMP_(ULONG) COleLinkingDoc::XPersistFile::AddRef()
- {
- METHOD_PROLOGUE_EX_(COleLinkingDoc, PersistFile)
- return pThis->ExternalAddRef();
- }
- STDMETHODIMP_(ULONG) COleLinkingDoc::XPersistFile::Release()
- {
- METHOD_PROLOGUE_EX_(COleLinkingDoc, PersistFile)
- return pThis->ExternalRelease();
- }
- STDMETHODIMP COleLinkingDoc::XPersistFile::QueryInterface(
- REFIID iid, LPVOID* ppvObj)
- {
- METHOD_PROLOGUE_EX_(COleLinkingDoc, PersistFile)
- return pThis->ExternalQueryInterface(&iid, ppvObj);
- }
- STDMETHODIMP COleLinkingDoc::XPersistFile::GetClassID(LPCLSID lpClassID)
- {
- METHOD_PROLOGUE_EX_(COleLinkingDoc, PersistFile)
- // this is sometimes called for documents not attached to servers!
- if (pThis->m_pFactory == NULL)
- {
- *lpClassID = CLSID_NULL;
- return E_FAIL;
- }
- // get the class ID from the connected server object
- ASSERT_VALID(pThis->m_pFactory);
- *lpClassID = pThis->m_pFactory->GetClassID();
- return S_OK;
- }
- STDMETHODIMP COleLinkingDoc::XPersistFile::IsDirty()
- {
- METHOD_PROLOGUE_EX(COleLinkingDoc, PersistFile)
- return pThis->IsModified() ? S_OK : S_FALSE;
- }
- STDMETHODIMP COleLinkingDoc::XPersistFile::Load(
- LPCOLESTR lpszFileName, DWORD /*dwMode*/)
- {
- METHOD_PROLOGUE_EX(COleLinkingDoc, PersistFile)
- ASSERT_VALID(pThis);
- USES_CONVERSION;
- CString strFileName;
- SCODE sc = E_FAIL;
- pThis->BeginDeferErrors();
- LPCTSTR lpszFileNameT = OLE2CT(lpszFileName);
- TRY
- {
- BOOL bUserCtrl = AfxOleGetUserCtrl();
- // delegate to file-based Open implementation
- if (!pThis->OnOpenDocument(lpszFileNameT))
- {
- AfxOleSetUserCtrl(bUserCtrl);
- return sc;
- }
- pThis->SendInitialUpdate();
- // set the path name, but don't add to MRU list
- pThis->SetPathName(lpszFileNameT, FALSE);
- AfxOleSetUserCtrl(bUserCtrl);
- sc = S_OK;
- }
- END_TRY
- sc = pThis->EndDeferErrors(sc);
- ASSERT_VALID(pThis);
- return sc;
- }
- STDMETHODIMP COleLinkingDoc::XPersistFile::Save(
- LPCOLESTR lpszFileName, BOOL fRemember)
- {
- METHOD_PROLOGUE_EX(COleLinkingDoc, PersistFile)
- ASSERT_VALID(pThis);
- USES_CONVERSION;
- CString strFileName;
- SCODE sc = E_FAIL;
- pThis->BeginDeferErrors();
- TRY
- {
- // delegate to file-based Save/Save As implementation
- ASSERT(pThis->m_bRemember);
- pThis->m_bRemember = fRemember;
- pThis->OnSaveDocument(OLE2CT(lpszFileName));
- sc = S_OK;
- }
- END_TRY
- sc = pThis->EndDeferErrors(sc);
- ASSERT_VALID(pThis);
- return sc;
- }
- STDMETHODIMP COleLinkingDoc::XPersistFile::SaveCompleted(LPCOLESTR lpszFileName)
- {
- METHOD_PROLOGUE_EX(COleLinkingDoc, PersistFile)
- ASSERT_VALID(pThis);
- USES_CONVERSION;
- TRY
- {
- // set the path name, but don't add to MRU list
- pThis->SetPathName(OLE2CT(lpszFileName), FALSE);
- }
- END_TRY
- ASSERT_VALID(pThis);
- return S_OK;
- }
- STDMETHODIMP COleLinkingDoc::XPersistFile::GetCurFile(LPOLESTR* lplpszFileName)
- {
- METHOD_PROLOGUE_EX_(COleLinkingDoc, PersistFile)
- *lplpszFileName = NULL;
- // use title if no document
- LPCTSTR lpszResult;
- if (pThis->m_strPathName.IsEmpty())
- lpszResult = pThis->m_strTitle;
- else
- lpszResult = pThis->m_strPathName;
- ASSERT(lpszResult != NULL);
- // allocate memory for the file name
- *lplpszFileName = AfxAllocTaskOleString(lpszResult);
- if (*lplpszFileName == NULL)
- return E_OUTOFMEMORY;
- ASSERT_VALID(pThis);
- return S_OK;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Implementation of IOleItemContainer
- // (supports linking to embeddings and linking to pseudo-objects)
- STDMETHODIMP_(ULONG) COleLinkingDoc::XOleItemContainer::AddRef()
- {
- METHOD_PROLOGUE_EX_(COleLinkingDoc, OleItemContainer)
- return pThis->ExternalAddRef();
- }
- STDMETHODIMP_(ULONG) COleLinkingDoc::XOleItemContainer::Release()
- {
- METHOD_PROLOGUE_EX_(COleLinkingDoc, OleItemContainer)
- return pThis->ExternalRelease();
- }
- STDMETHODIMP COleLinkingDoc::XOleItemContainer::QueryInterface(
- REFIID iid, LPVOID* ppvObj)
- {
- METHOD_PROLOGUE_EX_(COleLinkingDoc, OleItemContainer)
- return pThis->ExternalQueryInterface(&iid, ppvObj);
- }
- STDMETHODIMP COleLinkingDoc::XOleItemContainer::EnumObjects(
- DWORD /*grfFlags*/, LPENUMUNKNOWN* ppEnumUnknown)
- {
- *ppEnumUnknown = NULL;
- return E_NOTIMPL;
- }
- STDMETHODIMP COleLinkingDoc::XOleItemContainer::ParseDisplayName(LPBC lpbc,
- LPOLESTR lpszDisplayName, ULONG* cchEaten, LPMONIKER* ppMoniker)
- {
- METHOD_PROLOGUE_EX_(COleLinkingDoc, OleItemContainer)
- USES_CONVERSION;
- // reset all OUT parameters
- *ppMoniker = NULL;
- TCHAR szItemName[OLE_MAXNAMESIZE];
- LPTSTR lpszDest = szItemName;
- LPCTSTR lpszSrc = OLE2CT(lpszDisplayName);
- // skip leading delimiters
- int cEaten = 0;
- while (*lpszSrc != '\0' && (*lpszSrc == '\\' || *lpszSrc == '/' ||
- *lpszSrc == ':' || *lpszSrc == '!' || *lpszSrc == '['))
- {
- if (_istlead(*lpszSrc))
- ++lpszSrc, ++cEaten;
- ++lpszSrc;
- ++cEaten;
- }
- // parse next token in szItemName
- while (*lpszSrc != '\0' && *lpszSrc != '\\' && *lpszSrc != '/' &&
- *lpszSrc != ':' && *lpszSrc != '!' && *lpszSrc != '[' &&
- cEaten < OLE_MAXNAMESIZE-1)
- {
- if (_istlead(*lpszSrc))
- *lpszDest++ = *lpszSrc++, ++cEaten;
- *lpszDest++ = *lpszSrc++;
- ++cEaten;
- }
- *cchEaten = cEaten;
- *lpszDest = 0;
- // attempt to get the object
- LPUNKNOWN lpUnknown;
- SCODE sc = GetObject(T2OLE(szItemName), BINDSPEED_INDEFINITE, lpbc,
- IID_IUnknown, (LPLP)&lpUnknown);
- if (sc != S_OK)
- return sc;
- // item name found -- create item moniker for it
- lpUnknown->Release();
- return CreateItemMoniker(OLESTDDELIMOLE, T2COLE(szItemName), ppMoniker);
- }
- STDMETHODIMP COleLinkingDoc::XOleItemContainer::LockContainer(BOOL fLock)
- {
- METHOD_PROLOGUE_EX_(COleLinkingDoc, OleItemContainer)
- pThis->LockExternal(fLock, TRUE);
- return S_OK;
- }
- STDMETHODIMP COleLinkingDoc::XOleItemContainer::GetObject(
- LPOLESTR lpszItem, DWORD dwSpeedNeeded, LPBINDCTX /*pbc*/, REFIID riid,
- LPVOID* ppvObject)
- {
- METHOD_PROLOGUE_EX(COleLinkingDoc, OleItemContainer)
- ASSERT_VALID(pThis);
- USES_CONVERSION;
- *ppvObject = NULL;
- SCODE sc = MK_E_NOOBJECT;
- TRY
- {
- LPCTSTR lpszItemT = OLE2CT(lpszItem);
- // check for link to embedding
- COleClientItem* pClientItem = pThis->OnFindEmbeddedItem(lpszItemT);
- if (pClientItem != NULL)
- {
- ASSERT_VALID(pClientItem);
- sc = S_OK;
- // item found -- make sure it is running
- if (!::OleIsRunning(pClientItem->m_lpObject))
- {
- // should not run the object if bind-speed is immediate
- if (dwSpeedNeeded != BINDSPEED_INDEFINITE)
- sc = MK_E_EXCEEDEDDEADLINE;
- else
- {
- // bind speed is not immediate -- so run the object
- sc = OleRun(pClientItem->m_lpObject);
- }
- }
- if (sc == S_OK)
- {
- // return the object with appropriate interface
- sc = pClientItem->m_lpObject->QueryInterface(riid, ppvObject);
- }
- }
- else
- {
- // check for link to pseudo object
- COleServerItem* pServerItem = pThis->OnGetLinkedItem(lpszItemT);
- if (pServerItem != NULL)
- {
- if (!pServerItem->m_bNeedUnlock)
- {
- // when a link is bound, the document must be kept alive
- pThis->LockExternal(TRUE, FALSE);
- pServerItem->m_bNeedUnlock = TRUE;
- }
- // matching item found -- query for the requested interface
- sc = pServerItem->ExternalQueryInterface(&riid, ppvObject);
- }
- }
- }
- END_TRY
- return sc;
- }
- STDMETHODIMP COleLinkingDoc::XOleItemContainer::GetObjectStorage(
- LPOLESTR lpszItem, LPBINDCTX /*pbc*/, REFIID riid, LPVOID* ppvStorage)
- {
- METHOD_PROLOGUE_EX(COleLinkingDoc, OleItemContainer)
- ASSERT_VALID(pThis);
- USES_CONVERSION;
- *ppvStorage = NULL;
- // only IStorage is supported
- if (riid != IID_IStorage)
- return E_UNEXPECTED;
- // check for link to embedding
- COleClientItem* pClientItem = pThis->OnFindEmbeddedItem(OLE2CT(lpszItem));
- if (pClientItem != NULL)
- {
- ASSERT_VALID(pClientItem);
- // if object has no storage, can't return it!
- if (pClientItem->m_lpStorage != NULL)
- {
- // found matching item -- return the storage
- *ppvStorage = pClientItem->m_lpStorage;
- pClientItem->m_lpStorage->AddRef();
- return S_OK;
- }
- }
- return MK_E_NOSTORAGE;
- }
- STDMETHODIMP COleLinkingDoc::XOleItemContainer::IsRunning(LPOLESTR lpszItem)
- {
- METHOD_PROLOGUE_EX(COleLinkingDoc, OleItemContainer)
- ASSERT_VALID(pThis);
- USES_CONVERSION;
- // check for link to embedding
- LPCTSTR lpszItemT = OLE2CT(lpszItem);
- COleClientItem* pClientItem = pThis->OnFindEmbeddedItem(lpszItemT);
- if (pClientItem != NULL)
- {
- ASSERT_VALID(pClientItem);
- if (!::OleIsRunning(pClientItem->m_lpObject))
- return S_FALSE;
- return S_OK; // item is in document and is running
- }
- // check for link to pseudo object
- SCODE sc = MK_E_NOOBJECT;
- TRY
- {
- COleServerItem* pServerItem = pThis->OnGetLinkedItem(lpszItemT);
- if (pServerItem != NULL)
- sc = S_OK;
- }
- END_TRY
- return sc;
- }
- /////////////////////////////////////////////////////////////////////////////
- // COleLinkingDoc diagnostics
- #ifdef _DEBUG
- void COleLinkingDoc::AssertValid() const
- {
- COleDocument::AssertValid();
- if (m_pFactory != NULL)
- m_pFactory->AssertValid();
- }
- void COleLinkingDoc::Dump(CDumpContext& dc) const
- {
- COleDocument::Dump(dc);
- dc << "\nm_dwRegister = " << m_dwRegister;
- dc << "\nm_bVisibleLock = " << m_bVisibleLock;
- if (m_pFactory != NULL)
- dc << "\nwith factory: " << m_pFactory;
- else
- dc << "\nwith no factory";
- dc << "\n";
- }
- #endif //_DEBUG
- /////////////////////////////////////////////////////////////////////////////
|