home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Windows Gam…ming Gurus (2nd Edition)
/
Disc2.iso
/
vc98
/
mfc
/
src
/
olelink.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1998-06-16
|
22KB
|
847 lines
// 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
/////////////////////////////////////////////////////////////////////////////