⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 olelink.cpp

📁 c语言编程软件vc6.0中文绿色版_vc6.0官方下载
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -