LINKING.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:61k
源码类别:
Windows编程
开发平台:
Visual C++
- /*************************************************************************
- **
- ** OLE 2 Sample Code
- **
- ** linking.c
- **
- ** This file contains the major interfaces, methods and related support
- ** functions for implementing linking to items. The code
- ** contained in this file is used by BOTH the Container and Server
- ** (Object) versions of the Outline sample code.
- **
- ** As a server SVROUTL supports linking to the whole document object
- ** (either a file-based document or as an embedded object). It also
- ** supports linking to ranges (or PseudoObjects).
- **
- ** As a container CNTROUTL supports linking to embedded objects.
- ** (see file svrpsobj.c for Pseudo Object implementation)
- **
- ** OleDoc Object
- ** exposed interfaces:
- ** IPersistFile
- ** IOleItemContainer
- ** IExternalConnection
- **
- ** (c) Copyright Microsoft Corp. 1992 - 1997 All Rights Reserved
- **
- *************************************************************************/
- #include "outline.h"
- OLEDBGDATA
- extern LPOUTLINEAPP g_lpApp;
- /*************************************************************************
- ** OleDoc::IPersistFile interface implementation
- *************************************************************************/
- // IPersistFile::QueryInterface
- STDMETHODIMP OleDoc_PFile_QueryInterface(
- LPPERSISTFILE lpThis,
- REFIID riid,
- LPVOID FAR* lplpvObj
- )
- {
- LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
- return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);
- }
- // IPersistFile::AddRef
- STDMETHODIMP_(ULONG) OleDoc_PFile_AddRef(LPPERSISTFILE lpThis)
- {
- LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
- OleDbgAddRefMethod(lpThis, "IPersistFile");
- return OleDoc_AddRef(lpOleDoc);
- }
- // IPersistFile::Release
- STDMETHODIMP_(ULONG) OleDoc_PFile_Release (LPPERSISTFILE lpThis)
- {
- LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
- OleDbgReleaseMethod(lpThis, "IPersistFile");
- return OleDoc_Release(lpOleDoc);
- }
- // IPersistFile::GetClassID
- STDMETHODIMP OleDoc_PFile_GetClassID (
- LPPERSISTFILE lpThis,
- CLSID FAR* lpclsid
- )
- {
- LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
- LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
- OleDbgOut2("OleDoc_PFile_GetClassIDrn");
- #if defined( OLE_SERVER ) && defined( SVR_TREATAS )
- /* NOTE: we must be carefull to return the correct CLSID here.
- ** if we are currently preforming a "TreatAs (aka. ActivateAs)"
- ** operation then we need to return the class of the object
- ** written in the storage of the object. otherwise we would
- ** return our own class id.
- */
- return ServerDoc_GetClassID((LPSERVERDOC)lpOleDoc, lpclsid);
- #else
- *lpclsid = CLSID_APP;
- #endif
- return NOERROR;
- }
- // IPersistFile::IsDirty
- STDMETHODIMP OleDoc_PFile_IsDirty(LPPERSISTFILE lpThis)
- {
- LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
- OleDbgOut2("OleDoc_PFile_IsDirtyrn");
- if (OutlineDoc_IsModified((LPOUTLINEDOC)lpOleDoc))
- return NOERROR;
- else
- return S_FALSE;
- }
- // IPersistFile::Load
- STDMETHODIMP OleDoc_PFile_Load (
- LPPERSISTFILE lpThis,
- LPCOLESTR lpszFileName,
- DWORD grfMode
- )
- {
- LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
- SCODE sc;
- OLEDBG_BEGIN2("OleDoc_PFile_Loadrn")
- /* NOTE: grfMode passed from the caller indicates if the caller
- ** needs Read or ReadWrite permissions. if appropriate the
- ** callee should open the file with the requested permissions.
- ** the caller will normally not impose sharing permissions.
- **
- ** the sample code currently always opens its file ReadWrite.
- */
- if (OutlineDoc_LoadFromFile((LPOUTLINEDOC)lpOleDoc, (LPOLESTR)lpszFileName))
- sc = S_OK;
- else
- sc = E_FAIL;
- OLEDBG_END2
- return sc;
- }
- // IPersistFile::Save
- STDMETHODIMP OleDoc_PFile_Save (
- LPPERSISTFILE lpThis,
- LPCOLESTR lpszFileName,
- BOOL fRemember
- )
- {
- LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
- LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
- SCODE sc;
- OLEDBG_BEGIN2("OleDoc_PFile_Savern")
- /* NOTE: it is only legal to perform a Save or SaveAs operation
- ** on a file-based document. if the document is an embedded
- ** object then we can not be changed to a file-base object.
- **
- ** fRemember lpszFileName Type of Save
- ** ----------------------------------------------
- ** TRUE NULL SAVE
- ** TRUE ! NULL SAVE AS
- ** FALSE ! NULL SAVE COPY AS
- ** FALSE NULL ***error***
- */
- if ( (lpszFileName==NULL || (lpszFileName != NULL && fRemember))
- && ((lpOutlineDoc->m_docInitType != DOCTYPE_FROMFILE
- && lpOutlineDoc->m_docInitType != DOCTYPE_NEW)) ) {
- OLEDBG_END2
- return E_INVALIDARG;
- }
- if (OutlineDoc_SaveToFile(
- (LPOUTLINEDOC)lpOleDoc,
- lpszFileName,
- lpOutlineDoc->m_cfSaveFormat,
- fRemember)) {
- sc = S_OK;
- } else
- sc = E_FAIL;
- OLEDBG_END2
- return sc;
- }
- // IPersistFile::SaveCompleted
- STDMETHODIMP OleDoc_PFile_SaveCompleted (
- LPPERSISTFILE lpThis,
- LPCOLESTR lpszFileName
- )
- {
- LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
- LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
- OleDbgOut2("OleDoc_PFile_SaveCompletedrn");
- /* This method is called after IPersistFile::Save is called. during
- ** the period between Save and SaveCompleted the object must
- ** consider itself in NOSCRIBBLE mode (ie. it is NOT allowed to
- ** write to its file. here the object can clear its NOSCRIBBLE
- ** mode flag. the outline app never scribbles to its storage, so
- ** we have nothing to do.
- */
- return NOERROR;
- }
- // IPersistFile::GetCurFile
- STDMETHODIMP OleDoc_PFile_GetCurFile (
- LPPERSISTFILE lpThis,
- LPOLESTR FAR* lplpszFileName
- )
- {
- LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
- LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
- LPMALLOC lpMalloc;
- LPOLESTR lpsz;
- SCODE sc;
- char szAnsiStr[256];
- OleDbgOut2("OleDoc_PFile_GetCurFilern");
- /* NOTE: we must make sure to set all out ptr parameters to NULL. */
- *lplpszFileName = NULL;
- /*********************************************************************
- ** NOTE: memory returned for the lplpszFileName must be
- ** allocated appropriately using the current registered IMalloc
- ** interface. the allows the ownership of the memory to be
- ** passed to the caller (even if in another process).
- *********************************************************************/
- CoGetMalloc(MEMCTX_TASK, &lpMalloc);
- if (! lpMalloc) {
- return E_FAIL;
- }
- if (lpOutlineDoc->m_docInitType == DOCTYPE_FROMFILE) {
- /* valid filename associated; return file name */
- lpsz = /*(LPOLESTR)*/lpMalloc->lpVtbl->Alloc(
- lpMalloc,
- (OLESTRLEN(lpOutlineDoc->m_szFileName)+1)*sizeof(OLECHAR)
- );
- if (! lpsz) {
- sc = E_OUTOFMEMORY;
- goto error;
- }
- OLESTRCPY(lpsz, /*(LPOLESTR)*/lpOutlineDoc->m_szFileName);
- sc = S_OK;
- } else {
- /* no file associated; return default file name prompt */
- lpsz=/*(LPOLESTR)*/lpMalloc->lpVtbl->Alloc(lpMalloc, (lstrlen(DEFEXTENSION)+3)*sizeof(OLECHAR));
- wsprintf(szAnsiStr, "*.%s", DEFEXTENSION);
- A2W (szAnsiStr, lpsz, OLEUI_CCHPATHMAX);
- sc = S_FALSE;
- }
- error:
- OleStdRelease((LPUNKNOWN)lpMalloc);
- *lplpszFileName = lpsz;
- return sc;
- }
- /*************************************************************************
- ** OleDoc::IOleItemContainer interface implementation
- *************************************************************************/
- // IOleItemContainer::QueryInterface
- STDMETHODIMP OleDoc_ItemCont_QueryInterface(
- LPOLEITEMCONTAINER lpThis,
- REFIID riid,
- LPVOID FAR* lplpvObj
- )
- {
- LPOLEDOC lpOleDoc =
- ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
- return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);
- }
- // IOleItemContainer::AddRef
- STDMETHODIMP_(ULONG) OleDoc_ItemCont_AddRef(LPOLEITEMCONTAINER lpThis)
- {
- LPOLEDOC lpOleDoc =
- ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
- OleDbgAddRefMethod(lpThis, "IOleItemContainer");
- return OleDoc_AddRef((LPOLEDOC)lpOleDoc);
- }
- // IOleItemContainer::Release
- STDMETHODIMP_(ULONG) OleDoc_ItemCont_Release(LPOLEITEMCONTAINER lpThis)
- {
- LPOLEDOC lpOleDoc =
- ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
- OleDbgReleaseMethod(lpThis, "IOleItemContainer");
- return OleDoc_Release((LPOLEDOC)lpOleDoc);
- }
- // IOleItemContainer::ParseDisplayName
- STDMETHODIMP OleDoc_ItemCont_ParseDisplayName(
- LPOLEITEMCONTAINER lpThis,
- LPBC lpbc,
- LPOLESTR lpszDisplayName,
- ULONG FAR* lpchEaten,
- LPMONIKER FAR* lplpmkOut
- )
- {
- LPOLEDOC lpOleDoc =
- ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
- OLECHAR szItemName[MAXNAMESIZE];
- LPUNKNOWN lpUnk;
- HRESULT hrErr;
- OleDbgOut2("OleDoc_ItemCont_ParseDisplayNamern");
- /* NOTE: we must make sure to set all out ptr parameters to NULL. */
- *lplpmkOut = NULL;
- *lpchEaten = OleStdGetItemToken(
- lpszDisplayName,
- szItemName,
- MAXNAMESIZE*sizeof(OLECHAR)
- );
- /* NOTE: get a pointer to a running instance of the object. we
- ** should force the object to go running if necessary (even if
- ** this means launching its server EXE). this is the meaining of
- ** BINDSPEED_INDEFINITE. Parsing a Moniker is known to be an
- ** "EXPENSIVE" operation.
- */
- hrErr = OleDoc_ItemCont_GetObject(
- lpThis,
- szItemName,
- BINDSPEED_INDEFINITE,
- lpbc,
- &IID_IUnknown,
- (LPVOID FAR*)&lpUnk
- );
- if (hrErr == NOERROR) {
- OleStdRelease(lpUnk); // item name FOUND; don't need obj ptr.
- CreateItemMoniker(OLESTR("\"), szItemName, lplpmkOut);
- } else
- *lpchEaten = 0; // item name is NOT valid
- return hrErr;
- }
- // IOleItemContainer::EnumObjects
- STDMETHODIMP OleDoc_ItemCont_EnumObjects(
- LPOLEITEMCONTAINER lpThis,
- DWORD grfFlags,
- LPENUMUNKNOWN FAR* lplpenumUnknown
- )
- {
- LPOLEDOC lpOleDoc =
- ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
- OLEDBG_BEGIN2("OleDoc_ItemCont_EnumObjectsrn")
- /* NOTE: we must make sure to set all out ptr parameters to NULL. */
- *lplpenumUnknown = NULL;
- /* NOTE: this method should be implemented to allow programatic
- ** clients the ability to what elements the container holds.
- ** this method is NOT called in the standard linking scenarios.
- **
- ** grfFlags can be one of the following:
- ** OLECONTF_EMBEDDINGS -- enumerate embedded objects
- ** OLECONTF_LINKS -- enumerate linked objects
- ** OLECONTF_OTHERS -- enumerate non-OLE compound doc objs
- ** OLECONTF_ONLYUSER -- enumerate only objs named by user
- ** OLECONTF_ONLYIFRUNNING-- enumerate only objs in running state
- */
- OleDbgAssertSz(0, "NOT YET IMPLEMENTED!");
- OLEDBG_END2
- return E_NOTIMPL;
- }
- // IOleItemContainer::LockContainer
- STDMETHODIMP OleDoc_ItemCont_LockContainer(
- LPOLEITEMCONTAINER lpThis,
- BOOL fLock
- )
- {
- LPOLEDOC lpOleDoc =
- ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
- HRESULT hrErr;
- OLEDBG_BEGIN2("OleDoc_ItemCont_LockContainerrn")
- #if defined( _DEBUG )
- if (fLock) {
- ++lpOleDoc->m_cCntrLock;
- OleDbgOutRefCnt3(
- "OleDoc_ItemCont_LockContainer: cLock++rn",
- lpOleDoc,
- lpOleDoc->m_cCntrLock
- );
- } else {
- /* NOTE: when there are no open documents and the app is not
- ** under the control of the user and there are no outstanding
- ** locks on the app, then revoke our ClassFactory to enable the
- ** app to shut down.
- */
- --lpOleDoc->m_cCntrLock;
- OleDbgAssertSz (
- lpOleDoc->m_cCntrLock >= 0,
- "OleDoc_ItemCont_LockContainer(FALSE) called with cLock == 0"
- );
- if (lpOleDoc->m_cCntrLock == 0) {
- OleDbgOutRefCnt2(
- "OleDoc_ItemCont_LockContainer: UNLOCKEDrn",
- lpOleDoc, lpOleDoc->m_cCntrLock);
- } else {
- OleDbgOutRefCnt3(
- "OleDoc_ItemCont_LockContainer: cLock--rn",
- lpOleDoc, lpOleDoc->m_cCntrLock);
- }
- }
- #endif // _DEBUG
- /* NOTE: in order to hold the document alive we call
- ** CoLockObjectExternal to add a strong reference to our Doc
- ** object. this will keep the Doc alive when all other external
- ** references release us. whenever an embedded object goes
- ** running a LockContainer(TRUE) is called. when the embedded
- ** object shuts down (ie. transitions from running to loaded)
- ** LockContainer(FALSE) is called. if the user issues File.Close
- ** the document will shut down in any case ignoring any
- ** outstanding LockContainer locks because CoDisconnectObject is
- ** called in OleDoc_Close. this will forceably break any
- ** existing strong reference counts including counts that we add
- ** ourselves by calling CoLockObjectExternal and guarantee that
- ** the Doc object gets its final release (ie. cRefs goes to 0).
- */
- hrErr = OleDoc_Lock(lpOleDoc, fLock, TRUE /* fLastUnlockReleases */);
- OLEDBG_END2
- return hrErr;
- }
- // IOleItemContainer::GetObject
- STDMETHODIMP OleDoc_ItemCont_GetObject(
- LPOLEITEMCONTAINER lpThis,
- LPOLESTR lpszItem,
- DWORD dwSpeedNeeded,
- LPBINDCTX lpbc,
- REFIID riid,
- LPVOID FAR* lplpvObject
- )
- {
- LPOLEDOC lpOleDoc =
- ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
- HRESULT hrErr;
- OLEDBG_BEGIN2("OleDoc_ItemCont_GetObjectrn")
- /* NOTE: we must make sure to set all out ptr parameters to NULL. */
- *lplpvObject = NULL;
- #if defined( OLE_SERVER )
- /* NOTE: SERVER ONLY version should return PseudoObjects with
- ** BINDSPEED_IMMEDIATE, thus the dwSpeedNeeded is not important
- ** in the case of a pure server.
- */
- hrErr = ServerDoc_GetObject(
- (LPSERVERDOC)lpOleDoc, lpszItem,riid,lplpvObject);
- #endif
- #if defined( OLE_CNTR )
- /* NOTE: dwSpeedNeeded indicates how long the caller is willing
- ** to wait for us to get the object:
- ** BINDSPEED_IMMEDIATE -- only if obj already loaded && IsRunning
- ** BINDSPEED_MODERATE -- load obj if necessary && if IsRunning
- ** BINDSPEED_INDEFINITE-- force obj to load and run if necessary
- */
- hrErr = ContainerDoc_GetObject(
- (LPCONTAINERDOC)lpOleDoc,lpszItem,dwSpeedNeeded,riid,lplpvObject);
- #endif
- OLEDBG_END2
- return hrErr;
- }
- // IOleItemContainer::GetObjectStorage
- STDMETHODIMP OleDoc_ItemCont_GetObjectStorage(
- LPOLEITEMCONTAINER lpThis,
- LPOLESTR lpszItem,
- LPBINDCTX lpbc,
- REFIID riid,
- LPVOID FAR* lplpvStorage
- )
- {
- LPOLEDOC lpOleDoc =
- ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
- OleDbgOut2("OleDoc_ItemCont_GetObjectStoragern");
- /* NOTE: we must make sure to set all out ptr parameters to NULL. */
- *lplpvStorage = NULL;
- #if defined( OLE_SERVER )
- /* NOTE: in the SERVER ONLY version, item names identify pseudo
- ** objects. pseudo objects, do NOT have identifiable storage.
- */
- return E_FAIL;
- #endif
- #if defined( OLE_CNTR )
- // We can only return an IStorage* type pointer
- if (! IsEqualIID(riid, &IID_IStorage))
- {
- return E_FAIL;
- }
- return ContainerDoc_GetObjectStorage(
- (LPCONTAINERDOC)lpOleDoc,
- lpszItem,
- (LPSTORAGE FAR*)lplpvStorage
- );
- #endif
- }
- // IOleItemContainer::IsRunning
- STDMETHODIMP OleDoc_ItemCont_IsRunning(
- LPOLEITEMCONTAINER lpThis,
- LPOLESTR lpszItem
- )
- {
- LPOLEDOC lpOleDoc =
- ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
- HRESULT hrErr;
- OLEDBG_BEGIN2("OleDoc_ItemCont_IsRunningrn")
- /* NOTE: Check if item name is valid. if so then return if
- ** Object is running. PseudoObjects in the Server version are
- ** always considered running. Ole objects in the container must
- ** be checked if they are running.
- */
- #if defined( OLE_SERVER )
- hrErr = ServerDoc_IsRunning((LPSERVERDOC)lpOleDoc, lpszItem);
- #endif
- #if defined( OLE_CNTR )
- hrErr = ContainerDoc_IsRunning((LPCONTAINERDOC)lpOleDoc, lpszItem);
- #endif
- OLEDBG_END2
- return hrErr;
- }
- /*************************************************************************
- ** OleDoc::IExternalConnection interface implementation
- *************************************************************************/
- // IExternalConnection::QueryInterface
- STDMETHODIMP OleDoc_ExtConn_QueryInterface(
- LPEXTERNALCONNECTION lpThis,
- REFIID riid,
- LPVOID FAR* lplpvObj
- )
- {
- LPOLEDOC lpOleDoc =
- ((struct CDocExternalConnectionImpl FAR*)lpThis)->lpOleDoc;
- return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);
- }
- // IExternalConnection::AddRef
- STDMETHODIMP_(ULONG) OleDoc_ExtConn_AddRef(LPEXTERNALCONNECTION lpThis)
- {
- LPOLEDOC lpOleDoc =
- ((struct CDocExternalConnectionImpl FAR*)lpThis)->lpOleDoc;
- OleDbgAddRefMethod(lpThis, "IExternalConnection");
- return OleDoc_AddRef(lpOleDoc);
- }
- // IExternalConnection::Release
- STDMETHODIMP_(ULONG) OleDoc_ExtConn_Release (LPEXTERNALCONNECTION lpThis)
- {
- LPOLEDOC lpOleDoc =
- ((struct CDocExternalConnectionImpl FAR*)lpThis)->lpOleDoc;
- OleDbgReleaseMethod(lpThis, "IExternalConnection");
- return OleDoc_Release(lpOleDoc);
- }
- // IExternalConnection::AddConnection
- STDMETHODIMP_(DWORD) OleDoc_ExtConn_AddConnection(
- LPEXTERNALCONNECTION lpThis,
- DWORD extconn,
- DWORD reserved
- )
- {
- LPOLEDOC lpOleDoc =
- ((struct CDocExternalConnectionImpl FAR*)lpThis)->lpOleDoc;
- if( extconn & EXTCONN_STRONG ) {
- #if defined( _DEBUG )
- OleDbgOutRefCnt3(
- "OleDoc_ExtConn_AddConnection: dwStrongExtConn++rn",
- lpOleDoc,
- lpOleDoc->m_dwStrongExtConn + 1
- );
- #endif
- return ++(lpOleDoc->m_dwStrongExtConn);
- } else
- {
- return 0;
- }
- }
- // IExternalConnection::ReleaseConnection
- STDMETHODIMP_(DWORD) OleDoc_ExtConn_ReleaseConnection(
- LPEXTERNALCONNECTION lpThis,
- DWORD extconn,
- DWORD reserved,
- BOOL fLastReleaseCloses
- )
- {
- LPOLEDOC lpOleDoc =
- ((struct CDocExternalConnectionImpl FAR*)lpThis)->lpOleDoc;
- if( extconn & EXTCONN_STRONG ){
- DWORD dwSave = --(lpOleDoc->m_dwStrongExtConn);
- #if defined( _DEBUG )
- OLEDBG_BEGIN2( (fLastReleaseCloses ?
- "OleDoc_ExtConn_ReleaseConnection(TRUE)rn" :
- "OleDoc_ExtConn_ReleaseConnection(FALSE)rn") )
- OleDbgOutRefCnt3(
- "OleDoc_ExtConn_ReleaseConnection: dwStrongExtConn--rn",
- lpOleDoc,
- lpOleDoc->m_dwStrongExtConn
- );
- OleDbgAssertSz (
- lpOleDoc->m_dwStrongExtConn >= 0,
- "OleDoc_ExtConn_ReleaseConnection called with dwStrong == 0"
- );
- #endif // _DEBUG
- if( lpOleDoc->m_dwStrongExtConn == 0 && fLastReleaseCloses )
- OleDoc_Close(lpOleDoc, OLECLOSE_SAVEIFDIRTY);
- OLEDBG_END2
- return dwSave;
- } else
- {
- return 0;
- }
- }
- /*************************************************************************
- ** OleDoc Common Support Functions
- *************************************************************************/
- /* OleDoc_GetFullMoniker
- ** ---------------------
- ** Return the full, absolute moniker of the document.
- **
- ** NOTE: the caller must release the pointer returned when done.
- */
- LPMONIKER OleDoc_GetFullMoniker(LPOLEDOC lpOleDoc, DWORD dwAssign)
- {
- LPMONIKER lpMoniker = NULL;
- OLEDBG_BEGIN3("OleDoc_GetFullMonikerrn")
- if (lpOleDoc->m_lpSrcDocOfCopy) {
- /* CASE I: this document was created for a copy or drag/drop
- ** operation. generate the moniker which identifies the
- ** source document of the original copy.
- */
- if (! lpOleDoc->m_fLinkSourceAvail)
- goto done; // we already know a moniker is not available
- lpMoniker=OleDoc_GetFullMoniker(lpOleDoc->m_lpSrcDocOfCopy, dwAssign);
- }
- else if (lpOleDoc->m_lpFileMoniker) {
- /* CASE II: this document is a top-level user document (either
- ** file-based or untitled). return the FileMoniker stored
- ** with the document; it uniquely identifies the document.
- */
- // we must AddRef the moniker to pass out a ptr
- lpOleDoc->m_lpFileMoniker->lpVtbl->AddRef(lpOleDoc->m_lpFileMoniker);
- lpMoniker = lpOleDoc->m_lpFileMoniker;
- }
- #if defined( OLE_SERVER )
- else if (((LPSERVERDOC)lpOleDoc)->m_lpOleClientSite) {
- /* CASE III: this document is an embedded object, ask our
- ** container for our moniker.
- */
- OLEDBG_BEGIN2("IOleClientSite::GetMoniker calledrn");
- ((LPSERVERDOC)lpOleDoc)->m_lpOleClientSite->lpVtbl->GetMoniker(
- ((LPSERVERDOC)lpOleDoc)->m_lpOleClientSite,
- dwAssign,
- OLEWHICHMK_OBJFULL,
- &lpMoniker
- );
- OLEDBG_END2
- }
- #endif
- else {
- lpMoniker = NULL;
- }
- done:
- OLEDBG_END3
- return lpMoniker;
- }
- /* OleDoc_DocRenamedUpdate
- ** -----------------------
- ** Update the documents registration in the running object table (ROT).
- ** Also inform all embedded OLE objects (container only) and/or psedudo
- ** objects (server only) that the name of the document has changed.
- */
- void OleDoc_DocRenamedUpdate(LPOLEDOC lpOleDoc, LPMONIKER lpmkDoc)
- {
- OLEDBG_BEGIN3("OleDoc_DocRenamedUpdatern")
- OleDoc_AddRef(lpOleDoc);
- /* NOTE: we must re-register ourselves as running when we
- ** get a new moniker assigned (ie. when we are renamed).
- */
- OLEDBG_BEGIN3("OleStdRegisterAsRunning calledrn")
- OleStdRegisterAsRunning(
- (LPUNKNOWN)&lpOleDoc->m_Unknown,
- lpmkDoc,
- &lpOleDoc->m_dwRegROT
- );
- OLEDBG_END3
- #if defined( OLE_SERVER )
- {
- LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
- LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
- /* NOTE: inform any linking clients that the document has been
- ** renamed.
- */
- ServerDoc_SendAdvise (
- lpServerDoc,
- OLE_ONRENAME,
- lpmkDoc,
- 0 /* advf -- not relevant here */
- );
- /* NOTE: inform any clients of pseudo objects
- ** within our document, that our document's
- ** Moniker has changed.
- */
- ServerNameTable_InformAllPseudoObjectsDocRenamed(
- (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable, lpmkDoc);
- }
- #endif
- #if defined( OLE_CNTR )
- {
- LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc;
- /* NOTE: must tell all OLE objects that our container
- ** moniker changed.
- */
- ContainerDoc_InformAllOleObjectsDocRenamed(
- lpContainerDoc,
- lpmkDoc
- );
- }
- #endif
- OleDoc_Release(lpOleDoc); // release artificial AddRef above
- OLEDBG_END3
- }
- #if defined( OLE_SERVER )
- /*************************************************************************
- ** ServerDoc Supprt Functions Used by Server versions
- *************************************************************************/
- /* ServerDoc_PseudoObjLockDoc
- ** --------------------------
- ** Add a lock on the Doc on behalf of the PseudoObject. the Doc may not
- ** close while the Doc exists.
- **
- ** when a pseudo object is first created, it calls this method to
- ** guarantee that the document stays alive (PseudoObj_Init).
- ** when a pseudo object is destroyed, it call
- ** ServerDoc_PseudoObjUnlockDoc to release this hold on the document.
- */
- void ServerDoc_PseudoObjLockDoc(LPSERVERDOC lpServerDoc)
- {
- LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc;
- ULONG cPseudoObj;
- cPseudoObj = ++lpServerDoc->m_cPseudoObj;
- #if defined( _DEBUG )
- OleDbgOutRefCnt3(
- "ServerDoc_PseudoObjLockDoc: cPseudoObj++rn",
- lpServerDoc,
- cPseudoObj
- );
- #endif
- OleDoc_Lock(lpOleDoc, TRUE /* fLock */, 0 /* not applicable */);
- return;
- }
- /* ServerDoc_PseudoObjUnlockDoc
- ** ----------------------------
- ** Release the lock on the Doc on behalf of the PseudoObject. if this was
- ** the last lock on the Doc, then it will shutdown.
- */
- void ServerDoc_PseudoObjUnlockDoc(
- LPSERVERDOC lpServerDoc,
- LPPSEUDOOBJ lpPseudoObj
- )
- {
- ULONG cPseudoObj;
- LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc;
- OLEDBG_BEGIN3("ServerDoc_PseudoObjUnlockDocrn")
- /* NOTE: when there are no active pseudo objects in the Doc and
- ** the Doc is not visible, and if there are no outstanding locks
- ** on the Doc, then this is a "silent update"
- ** situation. our Doc is being used programatically by some
- ** client; it is NOT accessible to the user because it is
- ** NOT visible. thus since all Locks have been released, we
- ** will close the document. if the app is only running due
- ** to the presence of this document, then the app will now
- ** also shut down.
- */
- cPseudoObj = --lpServerDoc->m_cPseudoObj;
- #if defined( _DEBUG )
- OleDbgAssertSz (
- lpServerDoc->m_cPseudoObj >= 0,
- "PseudoObjUnlockDoc called with cPseudoObj == 0"
- );
- OleDbgOutRefCnt3(
- "ServerDoc_PseudoObjUnlockDoc: cPseudoObj--rn",
- lpServerDoc,
- cPseudoObj
- );
- #endif
- OleDoc_Lock(lpOleDoc, FALSE /* fLock */, TRUE /* fLastUnlockReleases */);
- OLEDBG_END3
- return;
- }
- /* ServerDoc_GetObject
- ** -------------------
- **
- ** Return a pointer to an object identified by an item string
- ** (lpszItem). For a server-only app, the object returned will be a
- ** pseudo object.
- */
- HRESULT ServerDoc_GetObject(
- LPSERVERDOC lpServerDoc,
- LPOLESTR lpszItem,
- REFIID riid,
- LPVOID FAR* lplpvObject
- )
- {
- LPPSEUDOOBJ lpPseudoObj;
- LPSERVERNAMETABLE lpServerNameTable =
- (LPSERVERNAMETABLE)((LPOUTLINEDOC)lpServerDoc)->m_lpNameTable;
- *lplpvObject = NULL;
- /* Get the PseudoObj which corresponds to an item name. if the item
- ** name does NOT exist in the name table then NO object is
- ** returned. the ServerNameTable_GetPseudoObj routine finds a
- ** name entry corresponding to the item name, it then checks if
- ** a PseudoObj has already been allocated. if so, it returns the
- ** existing object, otherwise it allocates a new PseudoObj.
- */
- lpPseudoObj = ServerNameTable_GetPseudoObj(
- lpServerNameTable,
- lpszItem,
- lpServerDoc
- );
- if (! lpPseudoObj) {
- *lplpvObject = NULL;
- return MK_E_NOOBJECT;
- }
- // return the desired interface pointer of the pseudo object.
- return PseudoObj_QueryInterface(lpPseudoObj, riid, lplpvObject);
- }
- /* ServerDoc_IsRunning
- ** -------------------
- **
- ** Check if the object identified by an item string (lpszItem) is in
- ** the running state. For a server-only app, if the item name exists in
- ** in the NameTable then the item name is considered running.
- ** IOleItemContainer::GetObject would succeed.
- */
- HRESULT ServerDoc_IsRunning(LPSERVERDOC lpServerDoc, LPOLESTR lpszItem)
- {
- LPOUTLINENAMETABLE lpOutlineNameTable =
- ((LPOUTLINEDOC)lpServerDoc)->m_lpNameTable;
- LPSERVERNAME lpServerName;
- lpServerName = (LPSERVERNAME)OutlineNameTable_FindName(
- lpOutlineNameTable,
- lpszItem
- );
- if (lpServerName)
- return NOERROR;
- else
- return MK_E_NOOBJECT;
- }
- /* ServerDoc_GetSelRelMoniker
- ** --------------------------
- ** Retrieve the relative item moniker which identifies the given
- ** selection (lplrSel).
- **
- ** Returns NULL if a moniker can NOT be created.
- */
- LPMONIKER ServerDoc_GetSelRelMoniker(
- LPSERVERDOC lpServerDoc,
- LPLINERANGE lplrSel,
- DWORD dwAssign
- )
- {
- LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
- LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
- LPSERVERNAMETABLE lpServerNameTable =
- (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable;
- LPOUTLINENAMETABLE lpOutlineNameTable =
- (LPOUTLINENAMETABLE)lpServerNameTable;
- LPOUTLINENAME lpOutlineName;
- LPMONIKER lpmk;
- lpOutlineName=OutlineNameTable_FindNamedRange(lpOutlineNameTable,lplrSel);
- if (lpOutlineName) {
- /* the selection range already has a name assigned */
- CreateItemMoniker(OLESTR("\"), lpOutlineName->m_szName, &lpmk);
- } else {
- char szbuf[MAXNAMESIZE];
- OLECHAR szUniBuf[MAXNAMESIZE];
- switch (dwAssign) {
- case GETMONIKER_FORCEASSIGN:
- /* Force the assignment of the name. This is called when a
- ** Paste Link actually occurs. At this point we want to
- ** create a Name and add it to the NameTable in order to
- ** track the source of the link. This name (as all
- ** names) will be updated upon editing of the document.
- */
- wsprintf(
- szbuf,
- "%s %ld",
- (LPSTR)DEFRANGENAMEPREFIX,
- ++(lpServerDoc->m_nNextRangeNo)
- );
- lpOutlineName = OutlineApp_CreateName(lpOutlineApp);
- if (lpOutlineName) {
- A2W (szbuf, lpOutlineName->m_szName, OLEUI_CCHPATHMAX);
- lpOutlineName->m_nStartLine = lplrSel->m_nStartLine;
- lpOutlineName->m_nEndLine = lplrSel->m_nEndLine;
- OutlineDoc_AddName(lpOutlineDoc, lpOutlineName);
- } else {
- // REVIEW: do we need "Out-of-Memory" error message here?
- }
- break;
- case GETMONIKER_TEMPFORUSER:
- /* Create a name to show to the user in the Paste
- ** Special dialog but do NOT yet incur the overhead
- ** of adding a Name to the NameTable. The Moniker
- ** generated should be useful to display to the user
- ** to indicate the source of the copy, but will NOT
- ** be used to create a link directly (the caller
- ** should ask again for a moniker specifying FORCEASSIGN).
- ** we will generate the name that would be the next
- ** auto-generated range name, BUT will NOT actually
- ** increment the range counter.
- */
- wsprintf(
- szbuf,
- "%s %ld",
- (LPSTR)DEFRANGENAMEPREFIX,
- (lpServerDoc->m_nNextRangeNo)+1
- );
- break;
- case GETMONIKER_ONLYIFTHERE:
- /* the caller only wants a name if one has already been
- ** assigned. we have already above checked if the
- ** current selection has a name, so we will simply
- ** return NULL here.
- */
- return NULL; // no moniker is assigned
- default:
- return NULL; // unknown flag given
- }
- A2W (szbuf, szUniBuf, MAXNAMESIZE);
- CreateItemMoniker(OLESTR("\"), szUniBuf, &lpmk);
- }
- return lpmk;
- }
- /* ServerDoc_GetSelFullMoniker
- ** ---------------------------
- ** Retrieve the full absolute moniker which identifies the given
- ** selection (lplrSel).
- ** this moniker is created as a composite of the absolute moniker for
- ** the entire document appended with an item moniker which identifies
- ** the selection relative to the document.
- ** Returns NULL if a moniker can NOT be created.
- */
- LPMONIKER ServerDoc_GetSelFullMoniker(
- LPSERVERDOC lpServerDoc,
- LPLINERANGE lplrSel,
- DWORD dwAssign
- )
- {
- LPMONIKER lpmkDoc = NULL;
- LPMONIKER lpmkItem = NULL;
- LPMONIKER lpmkFull = NULL;
- lpmkDoc = OleDoc_GetFullMoniker(
- (LPOLEDOC)lpServerDoc,
- dwAssign
- );
- if (! lpmkDoc) return NULL;
- lpmkItem = ServerDoc_GetSelRelMoniker(
- lpServerDoc,
- lplrSel,
- dwAssign
- );
- if (lpmkItem) {
- CreateGenericComposite(lpmkDoc, lpmkItem, (LPMONIKER FAR*)&lpmkFull);
- OleStdRelease((LPUNKNOWN)lpmkItem);
- }
- if (lpmkDoc)
- OleStdRelease((LPUNKNOWN)lpmkDoc);
- return lpmkFull;
- }
- /* ServerNameTable_EditLineUpdate
- * -------------------------------
- *
- * Update the table when a line at nEditIndex is edited.
- */
- void ServerNameTable_EditLineUpdate(
- LPSERVERNAMETABLE lpServerNameTable,
- int nEditIndex
- )
- {
- LPOUTLINENAMETABLE lpOutlineNameTable =
- (LPOUTLINENAMETABLE)lpServerNameTable;
- LPOUTLINENAME lpOutlineName;
- LINERANGE lrSel;
- LPPSEUDOOBJ lpPseudoObj;
- int i;
- for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
- lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i);
- lpPseudoObj = ((LPSERVERNAME)lpOutlineName)->m_lpPseudoObj;
- /* if there is a pseudo object associated with this name, then
- ** check if the line that was modified is included within
- ** the named range.
- */
- if (lpPseudoObj) {
- OutlineName_GetSel(lpOutlineName, &lrSel);
- if(((int)lrSel.m_nStartLine <= nEditIndex) &&
- ((int)lrSel.m_nEndLine >= nEditIndex)) {
- // inform linking clients data has changed
- PseudoObj_SendAdvise(
- lpPseudoObj,
- OLE_ONDATACHANGE,
- NULL, /* lpmkDoc -- not relevant here */
- 0 /* advf -- no flags necessary */
- );
- }
- }
- }
- }
- /* ServerNameTable_InformAllPseudoObjectsDocRenamed
- * ------------------------------------------------
- *
- * Inform all pseudo object clients that the name of the pseudo
- * object has changed.
- */
- void ServerNameTable_InformAllPseudoObjectsDocRenamed(
- LPSERVERNAMETABLE lpServerNameTable,
- LPMONIKER lpmkDoc
- )
- {
- LPOUTLINENAMETABLE lpOutlineNameTable =
- (LPOUTLINENAMETABLE)lpServerNameTable;
- LPOUTLINENAME lpOutlineName;
- LPPSEUDOOBJ lpPseudoObj;
- LPMONIKER lpmkObj;
- int i;
- OLEDBG_BEGIN2("ServerNameTable_InformAllPseudoObjectsDocRenamedrn");
- for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
- lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i);
- lpPseudoObj = ((LPSERVERNAME)lpOutlineName)->m_lpPseudoObj;
- /* if there is a pseudo object associated with this name, then
- ** send OnRename advise to its linking clients.
- */
- if (lpPseudoObj &&
- ((lpmkObj=PseudoObj_GetFullMoniker(lpPseudoObj,lpmkDoc))!=NULL)) {
- // inform the clients that the name has changed
- PseudoObj_SendAdvise (
- lpPseudoObj,
- OLE_ONRENAME,
- lpmkObj,
- 0 /* advf -- not relevant here */
- );
- }
- }
- OLEDBG_END2
- }
- /* ServerNameTable_InformAllPseudoObjectsDocSaved
- * ------------------------------------------------
- *
- * Inform all pseudo object clients that the name of the pseudo
- * object has changed.
- */
- void ServerNameTable_InformAllPseudoObjectsDocSaved(
- LPSERVERNAMETABLE lpServerNameTable,
- LPMONIKER lpmkDoc
- )
- {
- LPOUTLINENAMETABLE lpOutlineNameTable =
- (LPOUTLINENAMETABLE)lpServerNameTable;
- LPOUTLINENAME lpOutlineName;
- LPPSEUDOOBJ lpPseudoObj;
- LPMONIKER lpmkObj;
- int i;
- OLEDBG_BEGIN2("ServerNameTable_InformAllPseudoObjectsDocSavedrn");
- for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
- lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i);
- lpPseudoObj = ((LPSERVERNAME)lpOutlineName)->m_lpPseudoObj;
- /* if there is a pseudo object associated with this name, then
- ** send OnSave advise to its linking clients.
- */
- if (lpPseudoObj &&
- ((lpmkObj=PseudoObj_GetFullMoniker(lpPseudoObj,lpmkDoc))!=NULL)) {
- // inform the clients that the name has been saved
- PseudoObj_SendAdvise (
- lpPseudoObj,
- OLE_ONSAVE,
- NULL, /* lpmkDoc -- not relevant here */
- 0 /* advf -- not relevant here */
- );
- }
- }
- OLEDBG_END2
- }
- /* ServerNameTable_SendPendingAdvises
- * ----------------------------------
- *
- * Send any pending change notifications for pseudo objects.
- * while ReDraw is diabled on the ServerDoc, then change advise
- * notifications are not sent to pseudo object clients.
- */
- void ServerNameTable_SendPendingAdvises(LPSERVERNAMETABLE lpServerNameTable)
- {
- LPOUTLINENAMETABLE lpOutlineNameTable =
- (LPOUTLINENAMETABLE)lpServerNameTable;
- LPSERVERNAME lpServerName;
- int i;
- for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
- lpServerName = (LPSERVERNAME)OutlineNameTable_GetName(
- lpOutlineNameTable,
- i
- );
- ServerName_SendPendingAdvises(lpServerName);
- }
- }
- /* ServerNameTable_GetPseudoObj
- ** ----------------------------
- **
- ** Return a pointer to a pseudo object identified by an item string
- ** (lpszItem). if the pseudo object already exists, then return the
- ** existing object, otherwise allocate a new pseudo object.
- */
- LPPSEUDOOBJ ServerNameTable_GetPseudoObj(
- LPSERVERNAMETABLE lpServerNameTable,
- LPOLESTR lpszItem,
- LPSERVERDOC lpServerDoc
- )
- {
- LPSERVERNAME lpServerName;
- lpServerName = (LPSERVERNAME)OutlineNameTable_FindName(
- (LPOUTLINENAMETABLE)lpServerNameTable,
- lpszItem
- );
- if (lpServerName)
- return ServerName_GetPseudoObj(lpServerName, lpServerDoc);
- else
- return NULL;
- }
- /* ServerNameTable_CloseAllPseudoObjs
- * ----------------------------------
- *
- * Force all pseudo objects to close. this results in sending OnClose
- * notification to each pseudo object's linking clients.
- */
- void ServerNameTable_CloseAllPseudoObjs(LPSERVERNAMETABLE lpServerNameTable)
- {
- LPOUTLINENAMETABLE lpOutlineNameTable =
- (LPOUTLINENAMETABLE)lpServerNameTable;
- LPSERVERNAME lpServerName;
- int i;
- OLEDBG_BEGIN3("ServerNameTable_CloseAllPseudoObjsrn")
- for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
- lpServerName = (LPSERVERNAME)OutlineNameTable_GetName(
- lpOutlineNameTable,
- i
- );
- ServerName_ClosePseudoObj(lpServerName);
- }
- OLEDBG_END3
- }
- /* ServerName_SetSel
- * -----------------
- *
- * Change the line range of a name.
- */
- void ServerName_SetSel(
- LPSERVERNAME lpServerName,
- LPLINERANGE lplrSel,
- BOOL fRangeModified
- )
- {
- LPOUTLINENAME lpOutlineName = (LPOUTLINENAME)lpServerName;
- BOOL fPseudoObjChanged = fRangeModified;
- if (lpOutlineName->m_nStartLine != lplrSel->m_nStartLine) {
- lpOutlineName->m_nStartLine = lplrSel->m_nStartLine;
- fPseudoObjChanged = TRUE;
- }
- if (lpOutlineName->m_nEndLine != lplrSel->m_nEndLine) {
- lpOutlineName->m_nEndLine = lplrSel->m_nEndLine;
- fPseudoObjChanged = TRUE;
- }
- /* NOTE: if the range of an active pseudo object has
- ** changed, then inform any linking clients that the object
- ** has changed.
- */
- if (lpServerName->m_lpPseudoObj && fPseudoObjChanged) {
- PseudoObj_SendAdvise(
- lpServerName->m_lpPseudoObj,
- OLE_ONDATACHANGE,
- NULL, /* lpmkDoc -- not relevant here */
- 0 /* advf -- no flags necessary */
- );
- }
- }
- /* ServerName_SendPendingAdvises
- * -----------------------------
- *
- * Send any pending change notifications for the associated
- * pseudo objects for this name (if one exists).
- * while ReDraw is diabled on the ServerDoc, then change advise
- * notifications are not sent to pseudo object clients.
- */
- void ServerName_SendPendingAdvises(LPSERVERNAME lpServerName)
- {
- if (! lpServerName->m_lpPseudoObj)
- return; // no associated pseudo object
- if (lpServerName->m_lpPseudoObj->m_fDataChanged)
- PseudoObj_SendAdvise(
- lpServerName->m_lpPseudoObj,
- OLE_ONDATACHANGE,
- NULL, /* lpmkDoc -- not relevant here */
- 0 /* advf -- no flags necessary */
- );
- }
- /* ServerName_GetPseudoObj
- ** -----------------------
- **
- ** Return a pointer to a pseudo object associated to a ServerName.
- ** if the pseudo object already exists, then return the
- ** existing object, otherwise allocate a new pseudo object.
- **
- ** NOTE: the PseudoObj is returned with a 0 refcnt if first created,
- ** else the existing refcnt is unchanged.
- */
- LPPSEUDOOBJ ServerName_GetPseudoObj(
- LPSERVERNAME lpServerName,
- LPSERVERDOC lpServerDoc
- )
- {
- // Check if a PseudoObj already exists
- if (lpServerName->m_lpPseudoObj)
- return lpServerName->m_lpPseudoObj;
- // A PseudoObj does NOT already exist, allocate a new one.
- lpServerName->m_lpPseudoObj=(LPPSEUDOOBJ) New((DWORD)sizeof(PSEUDOOBJ));
- if (lpServerName->m_lpPseudoObj == NULL) {
- OleDbgAssertSz(lpServerName->m_lpPseudoObj != NULL, "Error allocating PseudoObj");
- return NULL;
- }
- PseudoObj_Init(lpServerName->m_lpPseudoObj, lpServerName, lpServerDoc);
- return lpServerName->m_lpPseudoObj;
- }
- /* ServerName_ClosePseudoObj
- * -------------------------
- *
- * if there is an associated pseudo objects for this name (if one
- * exists), then close it. this results in sending OnClose
- * notification to the pseudo object's linking clients.
- */
- void ServerName_ClosePseudoObj(LPSERVERNAME lpServerName)
- {
- if (!lpServerName || !lpServerName->m_lpPseudoObj)
- return; // no associated pseudo object
- PseudoObj_Close(lpServerName->m_lpPseudoObj);
- }
- #endif // OLE_SERVER
- #if defined( OLE_CNTR )
- /*************************************************************************
- ** ContainerDoc Supprt Functions Used by Container versions
- *************************************************************************/
- /* ContainerLine_GetRelMoniker
- ** ---------------------------
- ** Retrieve the relative item moniker which identifies the OLE object
- ** relative to the container document.
- **
- ** Returns NULL if a moniker can NOT be created.
- */
- LPMONIKER ContainerLine_GetRelMoniker(
- LPCONTAINERLINE lpContainerLine,
- DWORD dwAssign
- )
- {
- LPMONIKER lpmk = NULL;
- /* NOTE: we should only give out a moniker for the OLE object
- ** if the object is allowed to be linked to from the inside. if
- ** so we are allowed to give out a moniker which binds to the
- ** running OLE object). if the object is an OLE 2.0 embedded
- ** object then it is allowed to be linked to from the inside. if
- ** the object is either an OleLink or an OLE 1.0 embedding
- ** then it can not be linked to from the inside.
- ** if we were a container/server app then we could offer linking
- ** to the outside of the object (ie. a pseudo object within our
- ** document). we are a container only app that does not support
- ** linking to ranges of its data.
- */
- switch (dwAssign) {
- case GETMONIKER_FORCEASSIGN:
- /* Force the assignment of the name. This is called when a
- ** Paste Link actually occurs. From now on we want
- ** to inform the OLE object that its moniker is
- ** assigned and is thus necessary to register itself
- ** in the RunningObjectTable.
- */
- CreateItemMoniker(
- OLESTR("\"), lpContainerLine->m_szStgName, &lpmk);
- /* NOTE: if the OLE object is already loaded and it
- ** is being assigned a moniker for the first time,
- ** then we need to inform it that it now has a moniker
- ** assigned by calling IOleObject::SetMoniker. this
- ** will force the OLE object to register in the
- ** RunningObjectTable when it enters the running
- ** state. if the object is not currently loaded,
- ** SetMoniker will be called automatically later when
- ** the object is loaded by the function
- ** ContainerLine_LoadOleObject.
- */
- if (! lpContainerLine->m_fMonikerAssigned) {
- /* we must remember forever more that this object has a
- ** moniker assigned.
- */
- lpContainerLine->m_fMonikerAssigned = TRUE;
- // we are now dirty and must be saved
- OutlineDoc_SetModified(
- (LPOUTLINEDOC)lpContainerLine->m_lpDoc,
- TRUE, /* fModified */
- FALSE, /* fDataChanged--N/A for container ver. */
- FALSE /* fSizeChanged--N/A for container ver. */
- );
- if (lpContainerLine->m_lpOleObj) {
- OLEDBG_BEGIN2("IOleObject::SetMoniker calledrn")
- lpContainerLine->m_lpOleObj->lpVtbl->SetMoniker(
- lpContainerLine->m_lpOleObj,
- OLEWHICHMK_OBJREL,
- lpmk
- );
- OLEDBG_END2
- }
- }
- break;
- case GETMONIKER_ONLYIFTHERE:
- /* If the OLE object currently has a moniker assigned,
- ** then return it.
- */
- if (lpContainerLine->m_fMonikerAssigned) {
- CreateItemMoniker(
- OLESTR("\"),
- lpContainerLine->m_szStgName,
- &lpmk
- );
- }
- break;
- case GETMONIKER_TEMPFORUSER:
- /* Return the moniker that would be used for the OLE
- ** object but do NOT force moniker assignment at
- ** this point. Since our strategy is to use the
- ** storage name of the object as its item name, we
- ** can simply create the corresponding ItemMoniker
- ** (indepenedent of whether the moniker is currently
- ** assigned or not).
- */
- CreateItemMoniker(
- OLESTR("\"),
- lpContainerLine->m_szStgName,
- &lpmk
- );
- break;
- case GETMONIKER_UNASSIGN:
- lpContainerLine->m_fMonikerAssigned = FALSE;
- break;
- }
- return lpmk;
- }
- /* ContainerLine_GetFullMoniker
- ** ----------------------------
- ** Retrieve the full absolute moniker which identifies the OLE object
- ** in the container document.
- ** this moniker is created as a composite of the absolute moniker for
- ** the entire document appended with an item moniker which identifies
- ** the OLE object relative to the document.
- ** Returns NULL if a moniker can NOT be created.
- */
- LPMONIKER ContainerLine_GetFullMoniker(
- LPCONTAINERLINE lpContainerLine,
- DWORD dwAssign
- )
- {
- LPMONIKER lpmkDoc = NULL;
- LPMONIKER lpmkItem = NULL;
- LPMONIKER lpmkFull = NULL;
- lpmkDoc = OleDoc_GetFullMoniker(
- (LPOLEDOC)lpContainerLine->m_lpDoc,
- dwAssign
- );
- if (! lpmkDoc)
- {
- return NULL;
- }
- lpmkItem = ContainerLine_GetRelMoniker(lpContainerLine, dwAssign);
- if (lpmkItem) {
- CreateGenericComposite(lpmkDoc, lpmkItem, (LPMONIKER FAR*)&lpmkFull);
- OleStdRelease((LPUNKNOWN)lpmkItem);
- }
- if (lpmkDoc)
- OleStdRelease((LPUNKNOWN)lpmkDoc);
- return lpmkFull;
- }
- /* ContainerDoc_InformAllOleObjectsDocRenamed
- ** ------------------------------------------
- ** Inform all OLE objects that the name of the ContainerDoc has changed.
- */
- void ContainerDoc_InformAllOleObjectsDocRenamed(
- LPCONTAINERDOC lpContainerDoc,
- LPMONIKER lpmkDoc
- )
- {
- LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
- int i;
- LPLINE lpLine;
- // artificial AddRef in case someone releases object during call
- OleDoc_AddRef((LPOLEDOC)lpContainerDoc);
- for (i = 0; i < lpLL->m_nNumLines; i++) {
- lpLine=LineList_GetLine(lpLL, i);
- if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
- LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
- /* NOTE: if the OLE object is already loaded AND the
- ** object already has a moniker assigned, then we need
- ** to inform it that the moniker of the ContainerDoc has
- ** changed. of course, this means the full moniker of
- ** the object has changed. to do this we call
- ** IOleObject::SetMoniker. this will force the OLE
- ** object to re-register in the RunningObjectTable if it
- ** is currently in the running state. it is not in the
- ** running state, the object handler can make not that
- ** the object has a new moniker. if the object is not
- ** currently loaded, SetMoniker will be called
- ** automatically later when the object is loaded by the
- ** function ContainerLine_LoadOleObject.
- ** also if the object is a linked object, we always want
- ** to call SetMoniker on the link so that in case the
- ** link source is contained within our same container,
- ** the link source will be tracked. the link rebuilds
- ** its absolute moniker if it has a relative moniker.
- */
- if (lpContainerLine->m_lpOleObj) {
- if (lpContainerLine->m_fMonikerAssigned ||
- lpContainerLine->m_dwLinkType != 0) {
- OLEDBG_BEGIN2("IOleObject::SetMoniker calledrn")
- lpContainerLine->m_lpOleObj->lpVtbl->SetMoniker(
- lpContainerLine->m_lpOleObj,
- OLEWHICHMK_CONTAINER,
- lpmkDoc
- );
- OLEDBG_END2
- }
- /* NOTE: we must call IOleObject::SetHostNames so
- ** any open objects can update their window titles.
- */
- OLEDBG_BEGIN2("IOleObject::SetHostNames calledrn")
- lpContainerLine->m_lpOleObj->lpVtbl->SetHostNames(
- lpContainerLine->m_lpOleObj,
- /*(LPOLESTR)*/APPNAME,
- ((LPOUTLINEDOC)lpContainerDoc)->m_lpszDocTitle
- );
- OLEDBG_END2
- }
- }
- }
- // release artificial AddRef
- OleDoc_Release((LPOLEDOC)lpContainerDoc);
- }
- /* ContainerDoc_GetObject
- ** ----------------------
- ** Return a pointer to the desired interface of an object identified
- ** by an item string (lpszItem). the object returned will be an OLE
- ** object (either link or embedding).
- **
- ** NOTE: we must force the object to run because we are
- ** REQUIRED to return a pointer the OLE object in the
- ** RUNNING state.
- **
- ** dwSpeedNeeded indicates how long the caller is willing
- ** to wait for us to get the object:
- ** BINDSPEED_IMMEDIATE -- only if obj already loaded && IsRunning
- ** BINDSPEED_MODERATE -- load obj if necessary && if IsRunning
- ** BINDSPEED_INDEFINITE-- force obj to load and run if necessary
- */
- HRESULT ContainerDoc_GetObject(
- LPCONTAINERDOC lpContainerDoc,
- LPOLESTR lpszItem,
- DWORD dwSpeedNeeded,
- REFIID riid,
- LPVOID FAR* lplpvObject
- )
- {
- LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
- int i;
- LPLINE lpLine;
- BOOL fMatchFound = FALSE;
- DWORD dwStatus;
- HRESULT hrErr;
- *lplpvObject = NULL;
- for (i = 0; i < lpLL->m_nNumLines; i++) {
- lpLine=LineList_GetLine(lpLL, i);
- if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
- LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
- if (OLESTRCMP(lpContainerLine->m_szStgName, lpszItem) == 0) {
- fMatchFound = TRUE; // valid item name
- // check if object is loaded.
- if (lpContainerLine->m_lpOleObj == NULL) {
- // if BINDSPEED_IMMEDIATE is requested, object must
- // ALREADY be loadded.
- if (dwSpeedNeeded == BINDSPEED_IMMEDIATE)
- return MK_E_EXCEEDEDDEADLINE;
- ContainerLine_LoadOleObject(lpContainerLine);
- if (! lpContainerLine->m_lpOleObj)
- return E_OUTOFMEMORY;
- }
- /* NOTE: check if the object is allowed to be linked
- ** to from the inside (ie. we are allowed to
- ** give out a moniker which binds to the running
- ** OLE object). if the object is an OLE
- ** 2.0 embedded object then it is allowed to be
- ** linked to from the inside. if the object is
- ** either an OleLink or an OLE 1.0 embedding
- ** then it can not be linked to from the inside.
- ** if we were a container/server app then we
- ** could offer linking to the outside of the
- ** object (ie. a pseudo object within our
- ** document). we are a container only app that
- ** does not support linking to ranges of its data.
- */
- OLEDBG_BEGIN2("IOleObject::GetMiscStatus calledrn");
- lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus(
- lpContainerLine->m_lpOleObj,
- DVASPECT_CONTENT, /* aspect is not important */
- (LPDWORD)&dwStatus
- );
- OLEDBG_END2
- if (dwStatus & OLEMISC_CANTLINKINSIDE)
- {
- return MK_E_NOOBJECT;
- }
- // check if object is running.
- if (! OleIsRunning(lpContainerLine->m_lpOleObj)) {
- // if BINDSPEED_MODERATE is requested, object must
- // ALREADY be running.
- if (dwSpeedNeeded == BINDSPEED_MODERATE)
- {
- return MK_E_EXCEEDEDDEADLINE;
- }
- /* NOTE: we have found a match for the item name.
- ** now we must return a pointer to the desired
- ** interface on the RUNNING object. we must
- ** carefully load the object and initially ask for
- ** an interface that we are sure the loaded form of
- ** the object supports. if we immediately ask the
- ** loaded object for the desired interface, the
- ** QueryInterface call might fail if it is an
- ** interface that is supported only when the object
- ** is running. thus we force the object to load and
- ** return its IUnknown*. then we force the object to
- ** run, and then finally, we can ask for the
- ** actually requested interface.
- */
- hrErr = ContainerLine_RunOleObject(lpContainerLine);
- if (hrErr != NOERROR) {
- return hrErr;
- }
- }
- // Retrieve the requested interface
- *lplpvObject = OleStdQueryInterface(
- (LPUNKNOWN)lpContainerLine->m_lpOleObj, riid);
- break; // Match FOUND!
- }
- }
- }
- if (*lplpvObject != NULL) {
- return NOERROR;
- } else
- {
- return (fMatchFound ? E_NOINTERFACE
- : MK_E_NOOBJECT);
- }
- }
- /* ContainerDoc_GetObjectStorage
- ** -----------------------------
- ** Return a pointer to the IStorage* used by the object identified
- ** by an item string (lpszItem). the object identified could be either
- ** an OLE object (either link or embedding).
- */
- HRESULT ContainerDoc_GetObjectStorage(
- LPCONTAINERDOC lpContainerDoc,
- LPOLESTR lpszItem,
- LPSTORAGE FAR* lplpStg
- )
- {
- LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
- int i;
- LPLINE lpLine;
- *lplpStg = NULL;
- for (i = 0; i < lpLL->m_nNumLines; i++) {
- lpLine=LineList_GetLine(lpLL, i);
- if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
- LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
- if (OLESTRCMP(lpContainerLine->m_szStgName, lpszItem) == 0) {
- *lplpStg = lpContainerLine->m_lpStg;
- break; // Match FOUND!
- }
- }
- }
- if (*lplpStg != NULL) {
- return NOERROR;
- } else
- {
- return MK_E_NOOBJECT;
- }
- }
- /* ContainerDoc_IsRunning
- ** ----------------------
- ** Check if the object identified by an item string (lpszItem) is in
- ** the running state.
- ** For a container-only app, a check is made if the OLE object
- ** associated with the item name is running.
- */
- HRESULT ContainerDoc_IsRunning(LPCONTAINERDOC lpContainerDoc, LPOLESTR lpszItem)
- {
- LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
- int i;
- LPLINE lpLine;
- DWORD dwStatus;
- for (i = 0; i < lpLL->m_nNumLines; i++) {
- lpLine=LineList_GetLine(lpLL, i);
- if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
- LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
- if (OLESTRCPY(lpContainerLine->m_szStgName, lpszItem) == 0) {
- /* NOTE: we have found a match for the item name.
- ** now we must check if the OLE object is running.
- ** we will load the object if not already loaded.
- */
- if (! lpContainerLine->m_lpOleObj) {
- ContainerLine_LoadOleObject(lpContainerLine);
- if (! lpContainerLine->m_lpOleObj)
- return E_OUTOFMEMORY;
- }
- /* NOTE: check if the object is allowed to be linked
- ** to from the inside (ie. we are allowed to
- ** give out a moniker which binds to the running
- ** OLE object). if the object is an OLE
- ** 2.0 embedded object then it is allowed to be
- ** linked to from the inside. if the object is
- ** either an OleLink or an OLE 1.0 embedding
- ** then it can not be linked to from the inside.
- ** if we were a container/server app then we
- ** could offer linking to the outside of the
- ** object (ie. a pseudo object within our
- ** document). we are a container only app that
- ** does not support linking to ranges of its data.
- */
- OLEDBG_BEGIN2("IOleObject::GetMiscStatus calledrn")
- lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus(
- lpContainerLine->m_lpOleObj,
- DVASPECT_CONTENT, /* aspect is not important */
- (LPDWORD)&dwStatus
- );
- OLEDBG_END2
- if (dwStatus & OLEMISC_CANTLINKINSIDE)
- {
- return MK_E_NOOBJECT;
- }
- if (OleIsRunning(lpContainerLine->m_lpOleObj))
- {
- return NOERROR;
- }
- else
- {
- return S_FALSE;
- }
- }
- }
- }
- // no object was found corresponding to the item name
- return MK_E_NOOBJECT;
- }
- #endif // OLE_CNTR