| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879 | 
							- // 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
 
- /////////////////////////////////////////////////////////////////////////////
 
- // COleDocument - enables both server and client
 
- COleDocument::COleDocument()
 
- {
 
- 	ASSERT(m_viewList.IsEmpty());
 
- 	ASSERT(m_docItemList.IsEmpty());
 
- #ifdef _DEBUG
 
- 	// check for common mistake of not initializing OLE libraries before
 
- 	//  creating an OLE document.
 
- 	LPMALLOC lpMalloc = NULL;
 
- 	if (::CoGetMalloc(MEMCTX_TASK, &lpMalloc) != S_OK)
 
- 	{
 
- 		TRACE0("Warning: CoGetMalloc(MEMCTX_TASK, ...) failed --\n");
 
- 		TRACE0("\tperhaps AfxOleInit() has not been called.\n");
 
- 	}
 
- 	RELEASE(lpMalloc);
 
- #endif
 
- 	m_dwNextItemNumber = 1; // item number for first item in document
 
- 	m_bLastVisible = FALSE;
 
- 	m_bRemember = TRUE;
 
- 	m_bSameAsLoad = TRUE;
 
- 	m_lpRootStg = NULL;
 
- 	m_ptd = NULL;       // default to screen target device
 
- 	m_bCompoundFile = FALSE;
 
- 	AfxOleLockApp();
 
- }
 
- COleDocument::~COleDocument()
 
- {
 
- 	ASSERT_VALID(this);
 
- #ifdef _DEBUG
 
- 	if (!m_docItemList.IsEmpty())
 
- 		TRACE1("Warning: destroying COleDocument with %d doc items.\n",
 
- 			m_docItemList.GetCount());
 
- #endif
 
- 	// remove all doc-items from the list before shutting down the storage
 
- 	POSITION pos = GetStartPosition();
 
- 	while (pos != NULL)
 
- 	{
 
- 		CDocItem* pItem = GetNextItem(pos);
 
- 		ASSERT(pItem != NULL);
 
- 		delete pItem;
 
- 	}
 
- 	// release the hold on the document storage
 
- 	RELEASE(m_lpRootStg);
 
- 	CoTaskMemFree(m_ptd);
 
- 	AfxOleUnlockApp();
 
- }
 
- /////////////////////////////////////////////////////////////////////////////
 
- // DocItem management
 
- void COleDocument::AddItem(CDocItem* pItem)
 
- {
 
- 	// don't do an ASSERT_VALID until after we've added it !
 
- 	ASSERT_KINDOF(CDocItem, pItem);
 
- 	ASSERT(pItem->m_pDocument == NULL);     // not yet initialized
 
- 	m_docItemList.AddTail(pItem);
 
- 	pItem->m_pDocument = this;
 
- 	ASSERT_VALID(pItem);    // now it must be valid
 
- }
 
- void COleDocument::RemoveItem(CDocItem* pItem)
 
- {
 
- 	ASSERT_VALID(pItem);    // must be valid before detach
 
- 	ASSERT_KINDOF(CDocItem, pItem);
 
- 	ASSERT(pItem->m_pDocument == this);     // formerly attached
 
- 	ASSERT(m_docItemList.Find(pItem) != NULL);  // must be in list
 
- 	m_docItemList.RemoveAt(m_docItemList.Find(pItem));
 
- 	ASSERT(m_docItemList.Find(pItem) == NULL);  // must not be in list now
 
- 	pItem->m_pDocument = NULL;
 
- }
 
- POSITION COleDocument::GetStartPosition() const
 
- {
 
- 	ASSERT_VALID(this);
 
- 	return m_docItemList.GetHeadPosition();
 
- }
 
- CDocItem* COleDocument::GetNextItem(POSITION& pos) const
 
- {
 
- 	// handle special case of !pos -- makes enumeration code smaller
 
- 	if (pos == NULL)
 
- 		return NULL;
 
- 	// otherwise get next item from list
 
- 	ASSERT_VALID(this);
 
- 	CDocItem* pItem = (CDocItem*)m_docItemList.GetNext(pos);
 
- 	ASSERT(pItem != NULL);
 
- 	ASSERT_KINDOF(CDocItem, pItem);
 
- 	ASSERT(pItem->m_pDocument == this);     // must be ours
 
- 	return pItem;
 
- }
 
- CDocItem*
 
- COleDocument::GetNextItemOfKind(POSITION& pos, CRuntimeClass* pClass) const
 
- {
 
- 	while (pos != NULL)
 
- 	{
 
- 		CDocItem* pItem = GetNextItem(pos);
 
- 		ASSERT_VALID(pItem);
 
- 		if (pItem->IsKindOf(pClass))
 
- 			return pItem;
 
- 	}
 
- 	return NULL;    // no suitable item found
 
- }
 
- COleClientItem* COleDocument::GetNextClientItem(POSITION& pos) const
 
- {
 
- 	COleClientItem *pItem =
 
- 		(COleClientItem*)GetNextItemOfKind(pos, RUNTIME_CLASS(COleClientItem));
 
- 	return pItem;
 
- }
 
- COleServerItem* COleDocument::GetNextServerItem(POSITION& pos) const
 
- {
 
- 	COleServerItem *pItem =
 
- 		(COleServerItem*)GetNextItemOfKind(pos, RUNTIME_CLASS(COleServerItem));
 
- 	return pItem;
 
- }
 
- void COleDocument::DeleteContents()
 
- {
 
- 	// deletes all COleClientItem objects in the doc item list
 
- 	//  (Note: doesn't touch server items or other docitems)
 
- 	POSITION pos = GetStartPosition();
 
- 	COleClientItem* pItem;
 
- 	while ((pItem = GetNextClientItem(pos)) != NULL)
 
- 	{
 
- 		if (pItem->m_lpObject != NULL)
 
- 		{
 
- 			pItem->Release(OLECLOSE_NOSAVE);    // release OLE object
 
- 			RemoveItem(pItem);  // disconnect from document
 
- 			pItem->InternalRelease();   // may 'delete pItem'
 
- 		}
 
- 	}
 
- }
 
- void COleDocument::SetPathName(LPCTSTR lpszPathName, BOOL bAddToMRU)
 
- {
 
- 	USES_CONVERSION;
 
- 	CDocument::SetPathName(lpszPathName, bAddToMRU);
 
- 	// update all of the objects' host names
 
- 	POSITION pos = GetStartPosition();
 
- 	COleClientItem* pItem;
 
- 	while ((pItem = GetNextClientItem(pos)) != NULL)
 
- 	{
 
- 		// update that item's host names
 
- 		pItem->m_lpObject->SetHostNames(T2COLE(AfxGetAppName()),
 
- 			T2COLE(m_strTitle));
 
- 	}
 
- }
 
- void COleDocument::Serialize(CArchive& ar)
 
- {
 
- 	ASSERT_VALID(this);
 
- 	// serialize all items in the doc item list
 
- 	if (ar.IsStoring())
 
- 	{
 
- 		DWORD dwCount = 0;
 
- 		POSITION pos = GetStartPosition();
 
- 		while (pos != NULL)
 
- 		{
 
- 			CDocItem* pDocItem = GetNextItem(pos);
 
- 			ASSERT_VALID(pDocItem);
 
- 			// only count non-blank ones
 
- 			if (!pDocItem->IsBlank())
 
- 				++dwCount;
 
- 		}
 
- 		ar << dwCount;  // write count of objects
 
- 		// serialize all the items in the list
 
- 		pos = GetStartPosition();
 
- 		while (pos != NULL)
 
- 		{
 
- 			CDocItem* pDocItem = GetNextItem(pos);
 
- 			ASSERT_VALID(pDocItem);
 
- 			// only write non-blank ones
 
- 			if (!pDocItem->IsBlank())
 
- 				ar << pDocItem;
 
- 		}
 
- 	}
 
- 	else
 
- 	{
 
- 		// read number of items in the file
 
- 		DWORD dwCount;
 
- 		ar >> dwCount;
 
- 		// read all of them into the list
 
- 		while (dwCount--)
 
- 		{
 
- 			CDocItem* pDocItem;
 
- 			ar >> pDocItem;     // as they are serialized, they are added!
 
- 		}
 
- 	}
 
- }
 
- void COleDocument::CommitItems(BOOL bSuccess)
 
- {
 
- 	// special 'Commit' phase for COleClientItem items
 
- 	POSITION pos = GetStartPosition();
 
- 	COleClientItem* pItem;
 
- 	while ((pItem = GetNextClientItem(pos)) != NULL)
 
- 	{
 
- 		// calling CommitItem with FALSE causes the object to revert
 
- 		//  to the original storage.  Calling CommitItem TRUE causes
 
- 		//  the item to adopt the new storage created in the Serialize
 
- 		//  function.
 
- 		pItem->CommitItem(bSuccess);
 
- 	}
 
- }
 
- BOOL COleDocument::HasBlankItems() const
 
- {
 
- 	ASSERT_VALID(this);
 
- 	POSITION pos = GetStartPosition();
 
- 	while (pos != NULL)
 
- 	{
 
- 		CDocItem* pDocItem = GetNextItem(pos);
 
- 		ASSERT_VALID(pDocItem);
 
- 		if (pDocItem->IsBlank())
 
- 			return TRUE;    // blank item found
 
- 	}
 
- 	return FALSE;   // no items found that were blank
 
- }
 
- void COleDocument::UpdateModifiedFlag()
 
- {
 
- 	ASSERT_VALID(this);
 
- 	POSITION pos = GetStartPosition();
 
- 	COleClientItem* pItem;
 
- 	while ((pItem = GetNextClientItem(pos)) != NULL)
 
- 	{
 
- 		if (pItem->IsModified())
 
- 		{
 
- 			SetModifiedFlag();
 
- 			break;
 
- 		}
 
- 	}
 
- }
 
- void COleDocument::PreCloseFrame(CFrameWnd* pFrameArg)
 
- {
 
- 	ASSERT_VALID(this);
 
- 	ASSERT_VALID(pFrameArg);
 
- 	// turn off redraw so the user doesn't see the deactivation happening
 
- 	BOOL bSetRedraw = FALSE;
 
- 	if (pFrameArg->GetStyle() & WS_VISIBLE)
 
- 	{
 
- 		pFrameArg->SendMessage(WM_SETREDRAW, (WPARAM)FALSE);
 
- 		bSetRedraw = TRUE;
 
- 	}
 
- 	// deactivate any inplace active items on this frame
 
- 	COleClientItem* pItem = GetInPlaceActiveItem(pFrameArg);
 
- 	if (pItem != NULL)
 
- 	{
 
- 		pItem->Deactivate();
 
- 		pItem->Close(OLECLOSE_NOSAVE);
 
- 	}
 
- 	// turn redraw back on
 
- 	if (bSetRedraw)
 
- 		pFrameArg->SendMessage(WM_SETREDRAW, (WPARAM)TRUE);
 
- 	// should not have any inplace active items
 
- 	ASSERT(GetInPlaceActiveItem(pFrameArg) == NULL);
 
- }
 
- BOOL COleDocument::SaveModified()
 
- {
 
- 	// determine if necessary to discard changes
 
- 	if (::InSendMessage())
 
- 	{
 
- 		POSITION pos = GetStartPosition();
 
- 		COleClientItem* pItem;
 
- 		while ((pItem = GetNextClientItem(pos)) != NULL)
 
- 		{
 
- 			ASSERT(pItem->m_lpObject != NULL);
 
- 			SCODE sc = pItem->m_lpObject->IsUpToDate();
 
- 			if (sc != OLE_E_NOTRUNNING && FAILED(sc))
 
- 			{
 
- 				// inside inter-app SendMessage limits the user's choices
 
- 				CString name = m_strPathName;
 
- 				if (name.IsEmpty())
 
- 					VERIFY(name.LoadString(AFX_IDS_UNTITLED));
 
- 				CString prompt;
 
- 				AfxFormatString1(prompt, AFX_IDP_ASK_TO_DISCARD, name);
 
- 				return AfxMessageBox(prompt, MB_OKCANCEL|MB_DEFBUTTON2,
 
- 					AFX_IDP_ASK_TO_DISCARD) == IDOK;
 
- 			}
 
- 		}
 
- 	}
 
- 	// sometimes items change without a notification, so we have to
 
- 	//  update the document's modified flag before calling
 
- 	//  CDocument::SaveModified.
 
- 	UpdateModifiedFlag();
 
- 	return CDocument::SaveModified();
 
- }
 
- void COleDocument::OnShowViews(BOOL /*bVisible*/)
 
- {
 
- 	// no default implementation
 
- }
 
- void COleDocument::OnIdle()
 
- {
 
- 	ASSERT_VALID(this);
 
- 	// determine if any visible views are on this document
 
- 	BOOL bVisible = FALSE;
 
- 	POSITION pos = GetFirstViewPosition();
 
- 	while (pos != NULL)
 
- 	{
 
- 		CView* pView = GetNextView(pos);
 
- 		ASSERT_VALID(pView);
 
- 		CFrameWnd* pFrameWnd = pView->GetParentFrame();
 
- 		ASSERT_VALID(pFrameWnd);
 
- 		if (pFrameWnd->GetStyle() & WS_VISIBLE)
 
- 		{
 
- 			bVisible = TRUE;
 
- 			break;
 
- 		}
 
- 	}
 
- 	// when state has changed, call OnShowViews
 
- 	if (bVisible != m_bLastVisible)
 
- 	{
 
- 		OnShowViews(bVisible);
 
- 		m_bLastVisible = bVisible;
 
- 	}
 
- }
 
- /////////////////////////////////////////////////////////////////////////////
 
- // COleDocument -> window mapping
 
- CFrameWnd* COleDocument::GetFirstFrame()
 
- {
 
- 	ASSERT_VALID(this);
 
- 	// get position of first view in the document
 
- 	POSITION pos = GetFirstViewPosition();
 
- 	// get view at that position
 
- 	CView* pView = GetNextView(pos);
 
- 	if (pView == NULL)
 
- 		return NULL;
 
- 	ASSERT_VALID(pView);
 
- 	// return the first frame window that is a parent of that view
 
- 	CFrameWnd* pFrameWnd = (CFrameWnd*)pView->GetParentFrame();
 
- 	ASSERT_VALID(pFrameWnd);
 
- 	ASSERT_KINDOF(CFrameWnd, pFrameWnd);
 
- 	return pFrameWnd;
 
- }
 
- /////////////////////////////////////////////////////////////////////////////
 
- // COleDocument helpers
 
- LPMONIKER COleDocument::GetMoniker(OLEGETMONIKER /*nAssign*/)
 
- {
 
- 	USES_CONVERSION;
 
- 	ASSERT_VALID(this);
 
- 	// no moniker for untitled documents
 
- 	if (m_strPathName.IsEmpty())
 
- 		return NULL;
 
- 	// return file moniker based on current path name
 
- 	LPMONIKER lpMoniker;
 
- 	CreateFileMoniker(T2COLE(m_strPathName), &lpMoniker);
 
- 	return lpMoniker;
 
- }
 
- LPOLEITEMCONTAINER COleDocument::GetContainer()
 
- {
 
- 	// COleDocument doesn't support IOleClientSite::GetContainer
 
- 	return NULL;
 
- }
 
- /////////////////////////////////////////////////////////////////////////////
 
- // 'Compound File' enabling in COleDocument
 
- BOOL COleDocument::OnNewDocument()
 
- {
 
- 	// call base class, which destroys all items
 
- 	if (!CDocument::OnNewDocument())
 
- 		return FALSE;
 
- 	// for file-based compound files, need to create temporary file
 
- 	if (m_bCompoundFile && !m_bEmbedded)
 
- 	{
 
- 		// abort changes to the current docfile
 
- 		RELEASE(m_lpRootStg);
 
- 		// create new temporary docfile
 
- 		LPSTORAGE lpStorage;
 
- 		SCODE sc = ::StgCreateDocfile(NULL, STGM_DELETEONRELEASE|
 
- 			STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_CREATE,
 
- 			0, &lpStorage);
 
- 		if (sc != S_OK)
 
- 			return FALSE;
 
- 		ASSERT(lpStorage != NULL);
 
- 		m_lpRootStg = lpStorage;
 
- 	}
 
- 	return TRUE;
 
- }
 
- BOOL COleDocument::OnOpenDocument(LPCTSTR lpszPathName)
 
- {
 
- 	USES_CONVERSION;
 
- 	ASSERT(lpszPathName == NULL || AfxIsValidString(lpszPathName));
 
- 	// just use default implementation if 'docfile' not enabled
 
- 	if (!m_bCompoundFile && m_lpRootStg == NULL)
 
- 	{
 
- 		ASSERT(lpszPathName != NULL);
 
- 		return CDocument::OnOpenDocument(lpszPathName);
 
- 	}
 
- 	if (IsModified())
 
- 		TRACE0("Warning: OnOpenDocument replaces an unsaved document.\n");
 
- 	// abort changes to current docfile
 
- 	if (lpszPathName != NULL)
 
- 	{
 
- 		DeleteContents();
 
- 		RELEASE(m_lpRootStg);
 
- 	}
 
- 	SetModifiedFlag();  // dirty during de-serialize
 
- 	BOOL bResult = FALSE;
 
- 	TRY
 
- 	{
 
- 		if (m_lpRootStg == NULL)
 
- 		{
 
- 			LPCOLESTR lpsz = T2COLE(lpszPathName);
 
- 			// use STGM_CONVERT if necessary
 
- 			SCODE sc;
 
- 			LPSTORAGE lpStorage = NULL;
 
- 			if (StgIsStorageFile(lpsz) == S_FALSE)
 
- 			{
 
- 				// convert existing storage file
 
- 				sc = StgCreateDocfile(lpsz, STGM_READWRITE|
 
- 					STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_CONVERT,
 
- 					0, &lpStorage);
 
- 				if (FAILED(sc) || lpStorage == NULL)
 
- 					sc = StgCreateDocfile(lpsz, STGM_READ|
 
- 						STGM_TRANSACTED|STGM_CONVERT, 0, &lpStorage);
 
- 			}
 
- 			else
 
- 			{
 
- 				// open new storage file
 
- 				sc = StgOpenStorage(lpsz, NULL,
 
- 					STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_DENY_WRITE,
 
- 					0, 0, &lpStorage);
 
- 				if (FAILED(sc) || lpStorage == NULL)
 
- 					sc = StgOpenStorage(lpsz, NULL,
 
- 						STGM_READ|STGM_TRANSACTED, 0, 0, &lpStorage);
 
- 			}
 
- 			if (FAILED(sc))
 
- 				AfxThrowOleException(sc);
 
- 			ASSERT(lpStorage != NULL);
 
- 			m_lpRootStg = lpStorage;
 
- 		}
 
- 		// use helper to read document from storage
 
- 		LoadFromStorage();
 
- 		SetModifiedFlag(FALSE); // start off with unmodified
 
- 		bResult = TRUE;
 
- 	}
 
- 	CATCH_ALL(e)
 
- 	{
 
- 		DeleteContents();   // removed failed contents
 
- 		RELEASE(m_lpRootStg);
 
- 		// if not file-based load, return exceptions to the caller
 
- 		if (lpszPathName == NULL)
 
- 		{
 
- 			THROW_LAST();
 
- 			ASSERT(FALSE);  // not reached
 
- 		}
 
- 		TRY
 
- 		{
 
- 			ReportSaveLoadException(lpszPathName, e,
 
- 				FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);
 
- 		}
 
- 		END_TRY
 
- 		DELETE_EXCEPTION(e);
 
- 	}
 
- 	END_CATCH_ALL
 
- 	return bResult;
 
- }
 
- BOOL COleDocument::OnSaveDocument(LPCTSTR lpszPathName)
 
- 	// lpszPathName must be fully qualified
 
- {
 
- 	USES_CONVERSION;
 
- 	ASSERT(lpszPathName == NULL || AfxIsValidString(lpszPathName));
 
- 	// use default implementation if 'docfile' not enabled
 
- 	if (!m_bCompoundFile && m_lpRootStg == NULL)
 
- 	{
 
- 		ASSERT(lpszPathName != NULL);
 
- 		return CDocument::OnSaveDocument(lpszPathName);
 
- 	}
 
- 	LPSTORAGE lpOrigStg = NULL;
 
- 	if (lpszPathName != NULL)
 
- 		m_bSameAsLoad = AfxComparePath(m_strPathName, lpszPathName);
 
- 	BOOL bResult = FALSE;
 
- 	TRY
 
- 	{
 
- 		// open new root storage if necessary
 
- 		if (lpszPathName != NULL && !m_bSameAsLoad)
 
- 		{
 
- 			// temporarily detach current storage
 
- 			lpOrigStg = m_lpRootStg;
 
- 			m_lpRootStg = NULL;
 
- 			LPSTORAGE lpStorage;
 
- 			SCODE sc = ::StgCreateDocfile(T2COLE(lpszPathName),
 
- 				STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_CREATE,
 
- 				0, &lpStorage);
 
- 			if (sc != S_OK)
 
- 				AfxThrowOleException(sc);
 
- 			ASSERT(lpStorage != NULL);
 
- 			m_lpRootStg = lpStorage;
 
- 		}
 
- 		ASSERT(m_lpRootStg != NULL);
 
- 		// use helper to save to root storage
 
- 		SaveToStorage();
 
- 		if (lpszPathName != NULL)
 
- 		{
 
- 			// commit each of the items
 
- 			CommitItems(m_bRemember && !m_bSameAsLoad);
 
- 			// mark document as clean if remembering the storage
 
- 			if (m_bRemember)
 
- 				SetModifiedFlag(FALSE);
 
- 			// remember correct storage or release save copy as storage
 
- 			if (!m_bSameAsLoad)
 
- 			{
 
- 				if (m_bRemember)
 
- 				{
 
- 					// Save As case -- m_stgRoot is new storage, forget old storage
 
- 					lpOrigStg->Release();
 
- 				}
 
- 				else
 
- 				{
 
- 					// Save Copy As case -- m_stgRoot should hook up to m_stgOrig.
 
- 					m_lpRootStg->Release();
 
- 					m_lpRootStg = lpOrigStg;
 
- 				}
 
- 			}
 
- 		}
 
- 		bResult = TRUE;
 
- 	}
 
- 	CATCH_ALL(e)
 
- 	{
 
- 		if (lpOrigStg != NULL)
 
- 		{
 
- 			// save as failed: abort new storage, and re-attach original
 
- 			RELEASE(m_lpRootStg);
 
- 			m_lpRootStg = lpOrigStg;
 
- 		}
 
- 		if (lpszPathName == NULL)
 
- 		{
 
- 			THROW_LAST();
 
- 			ASSERT(FALSE);  // not reached
 
- 		}
 
- 		TRY
 
- 		{
 
- 			ReportSaveLoadException(lpszPathName, e,
 
- 				TRUE, AFX_IDP_FAILED_TO_SAVE_DOC);
 
- 		}
 
- 		END_TRY
 
- 		DELETE_EXCEPTION(e);
 
- 	}
 
- 	END_CATCH_ALL
 
- 	// cleanup
 
- 	m_bSameAsLoad = TRUE;
 
- 	m_bRemember = TRUE;
 
- 	return bResult;
 
- }
 
- void COleDocument::OnCloseDocument()
 
- {
 
- 	// close the document without deleting the memory
 
- 	BOOL bAutoDelete = m_bAutoDelete;
 
- 	m_bAutoDelete = FALSE;
 
- 	CDocument::OnCloseDocument();
 
- 	// release storage since document has been closed
 
- 	RELEASE(m_lpRootStg);
 
- 	// delete the document if necessary
 
- 	if (bAutoDelete)
 
- 		delete this;
 
- }
 
- /////////////////////////////////////////////////////////////////////////////
 
- // Helpers for saving to IStorage based files
 
- //  (these are used in the 'docfile' implementation as well as for servers)
 
- void COleDocument::SaveToStorage(CObject* pObject)
 
- {
 
- 	ASSERT(m_lpRootStg != NULL);
 
- 	// create Contents stream
 
- 	COleStreamFile file;
 
- 	CFileException fe;
 
- 	if (!file.CreateStream(m_lpRootStg, _T("Contents"),
 
- 			CFile::modeReadWrite|CFile::shareExclusive|CFile::modeCreate, &fe))
 
- 	{
 
- 		if (fe.m_cause == CFileException::fileNotFound)
 
- 			AfxThrowArchiveException(CArchiveException::badSchema);
 
- 		else
 
- 			AfxThrowFileException(fe.m_cause, fe.m_lOsError);
 
- 	}
 
- 	// save to Contents stream
 
- 	CArchive saveArchive(&file, CArchive::store | CArchive::bNoFlushOnDelete);
 
- 	saveArchive.m_pDocument = this;
 
- 	saveArchive.m_bForceFlat = FALSE;
 
- 	TRY
 
- 	{
 
- 		// save the contents
 
- 		if (pObject != NULL)
 
- 			pObject->Serialize(saveArchive);
 
- 		else
 
- 			Serialize(saveArchive);
 
- 		saveArchive.Close();
 
- 		file.Close();
 
- 		// commit the root storage
 
- 		SCODE sc = m_lpRootStg->Commit(STGC_ONLYIFCURRENT);
 
- 		if (sc != S_OK)
 
- 			AfxThrowOleException(sc);
 
- 	}
 
- 	CATCH_ALL(e)
 
- 	{
 
- 		file.Abort();   // will not throw an exception
 
- 		CommitItems(FALSE); // abort save in progress
 
- 		NO_CPP_EXCEPTION(saveArchive.Abort());
 
- 		THROW_LAST();
 
- 	}
 
- 	END_CATCH_ALL
 
- }
 
- void COleDocument::LoadFromStorage()
 
- {
 
- 	ASSERT(m_lpRootStg != NULL);
 
- 	// open Contents stream
 
- 	COleStreamFile file;
 
- 	CFileException fe;
 
- 	if (!file.OpenStream(m_lpRootStg, _T("Contents"),
 
- 			CFile::modeRead|CFile::shareExclusive, &fe) &&
 
- 		!file.CreateStream(m_lpRootStg, _T("Contents"),
 
- 			CFile::modeRead|CFile::shareExclusive|CFile::modeCreate, &fe))
 
- 	{
 
- 		if (fe.m_cause == CFileException::fileNotFound)
 
- 			AfxThrowArchiveException(CArchiveException::badSchema);
 
- 		else
 
- 			AfxThrowFileException(fe.m_cause, fe.m_lOsError);
 
- 	}
 
- 	// load it with CArchive (loads from Contents stream)
 
- 	CArchive loadArchive(&file, CArchive::load | CArchive::bNoFlushOnDelete);
 
- 	loadArchive.m_pDocument = this;
 
- 	loadArchive.m_bForceFlat = FALSE;
 
- 	TRY
 
- 	{
 
- 		if (file.GetLength() != 0)
 
- 			Serialize(loadArchive);     // load main contents
 
- 		loadArchive.Close();
 
- 		file.Close();
 
- 	}
 
- 	CATCH_ALL(e)
 
- 	{
 
- 		file.Abort();   // will not throw an exception
 
- 		DeleteContents();   // removed failed contents
 
- 		NO_CPP_EXCEPTION(loadArchive.Abort());
 
- 		THROW_LAST();
 
- 	}
 
- 	END_CATCH_ALL
 
- }
 
- /////////////////////////////////////////////////////////////////////////////
 
- // COleDocument diagnostics
 
- #ifdef _DEBUG
 
- void COleDocument::AssertValid() const
 
- {
 
- 	CDocument::AssertValid();
 
- 	ASSERT(m_ptd == NULL || AfxIsValidAddress(m_ptd, (size_t)m_ptd->tdSize, FALSE));
 
- 	ASSERT_VALID(&m_docItemList);
 
- 	ASSERT(!m_bEmbedded || m_strPathName.IsEmpty());
 
- }
 
- void COleDocument::Dump(CDumpContext& dc) const
 
- {
 
- 	CDocument::Dump(dc);
 
- 	dc << "with " << m_docItemList.GetCount() << " doc items";
 
- 	dc << "\nm_dwNextItemNumber = " << m_dwNextItemNumber;
 
- 	dc << "\nm_bLastVisible = " << m_bLastVisible;
 
- 	dc << "\nm_bEmbedded = " << m_bEmbedded;
 
- 	dc << "\nm_lpRootStg = " << m_lpRootStg;
 
- 	dc << "\nm_bSameAsLoad = " << m_bSameAsLoad;
 
- 	dc << "\nm_bRemember = " << m_bRemember;
 
- 	dc << "\nm_ptd = " << m_ptd;
 
- 	dc << "\n";
 
- }
 
- #endif //_DEBUG
 
- /////////////////////////////////////////////////////////////////////////////
 
- // CDocItem
 
- CDocItem::CDocItem()
 
- {
 
- 	m_pDocument = NULL;
 
- }
 
- CDocItem::~CDocItem()
 
- {
 
- 	ASSERT(m_pDocument == NULL);    // must be detached from document
 
- }
 
- void CDocItem::Serialize(CArchive& ar)
 
- {
 
- 	if (ar.IsStoring())
 
- 	{
 
- 		ASSERT_VALID(m_pDocument);
 
- 		// nothing to do, there is no data
 
- 	}
 
- 	else
 
- 	{
 
- 		// if no document connected yet, attach it from the archive
 
- 		if (m_pDocument == NULL)
 
- 		{
 
- 			COleDocument* pContainerDoc = (COleDocument*)ar.m_pDocument;
 
- 			ASSERT_VALID(pContainerDoc);
 
- 			ASSERT_KINDOF(COleDocument, pContainerDoc);
 
- 			pContainerDoc->AddItem(this);
 
- 			ASSERT(pContainerDoc == m_pDocument);
 
- 		}
 
- 	}
 
- 	// perform ASSERT_VALID at the end because COleServerItem::AssertValid
 
- 	// checks the validity of the m_pDocument pointer
 
- 	ASSERT_VALID(this);
 
- }
 
- BOOL CDocItem::IsBlank() const
 
- {
 
- 	// by default, a CDocItem is not blank. COleClientItem is sometimes blank!
 
- 	//  (a COleServerItem is blank by default)
 
- 	return FALSE;
 
- }
 
- /////////////////////////////////////////////////////////////////////////////
 
- // CDocItem diagnostics
 
- #ifdef _DEBUG
 
- void CDocItem::AssertValid() const
 
- {
 
- 	CObject::AssertValid();
 
- 	if (m_pDocument != NULL)
 
- 		m_pDocument->AssertValid();
 
- }
 
- void CDocItem::Dump(CDumpContext& dc) const
 
- {
 
- 	CCmdTarget::Dump(dc);
 
- 	dc << "m_pDocument = " << (void*)m_pDocument;
 
- 	dc << "\n";
 
- }
 
- #endif //_DEBUG
 
- /////////////////////////////////////////////////////////////////////////////
 
- // Inline function declarations expanded out-of-line
 
- #ifndef _AFX_ENABLE_INLINES
 
- // expand inlines for OLE general APIs
 
- static char _szAfxOleInl[] = "afxole.inl";
 
- #undef THIS_FILE
 
- #define THIS_FILE _szAfxOleInl
 
- #define _AFXOLE_INLINE
 
- #include "afxole.inl"
 
- #endif //!_AFX_ENABLE_INLINES
 
- #ifdef AFX_INIT_SEG
 
- #pragma code_seg(AFX_INIT_SEG)
 
- #endif
 
- IMPLEMENT_SERIAL(CDocItem, CCmdTarget, 0)
 
- IMPLEMENT_DYNAMIC(COleDocument, CDocument)
 
- // These IMPLEMENT_DYNAMICs here for .OBJ granularity reasons.
 
- IMPLEMENT_DYNAMIC(COleClientItem, CDocItem)
 
- IMPLEMENT_DYNAMIC(COleServerItem, CDocItem)
 
- /////////////////////////////////////////////////////////////////////////////
 
 
  |