/************************************************************************* ** ** OLE 2 Sample Code ** ** oleapp.c ** ** This file contains functions and methods that are common to ** server and the client version of the app. This includes the class ** factory methods and all OleApp functions. ** ** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved ** *************************************************************************/ #include "outline.h" #include OLEDBGDATA extern LPOUTLINEAPP g_lpApp; extern IUnknownVtbl g_OleApp_UnknownVtbl; extern IUnknownVtbl g_OleDoc_UnknownVtbl; extern IPersistFileVtbl g_OleDoc_PersistFileVtbl; extern IOleItemContainerVtbl g_OleDoc_OleItemContainerVtbl; extern IExternalConnectionVtbl g_OleDoc_ExternalConnectionVtbl; extern IDataObjectVtbl g_OleDoc_DataObjectVtbl; #if defined( USE_DRAGDROP ) extern IDropTargetVtbl g_OleDoc_DropTargetVtbl; extern IDropSourceVtbl g_OleDoc_DropSourceVtbl; #endif // USE_DRAGDROP #if defined( OLE_SERVER ) extern IOleObjectVtbl g_SvrDoc_OleObjectVtbl; extern IPersistStorageVtbl g_SvrDoc_PersistStorageVtbl; #if defined( SVR_TREATAS ) extern IStdMarshalInfoVtbl g_SvrDoc_StdMarshalInfoVtbl; #endif // SVR_TREATAS extern IUnknownVtbl g_PseudoObj_UnknownVtbl; extern IOleObjectVtbl g_PseudoObj_OleObjectVtbl; extern IDataObjectVtbl g_PseudoObj_DataObjectVtbl; #if defined( INPLACE_SVR ) extern IOleInPlaceObjectVtbl g_SvrDoc_OleInPlaceObjectVtbl; extern IOleInPlaceActiveObjectVtbl g_SvrDoc_OleInPlaceActiveObjectVtbl; #endif // INPLACE_SVR #endif // OLE_SERVER #if defined( OLE_CNTR ) extern IOleUILinkContainerVtbl g_CntrDoc_OleUILinkContainerVtbl; extern IUnknownVtbl g_CntrLine_UnknownVtbl; extern IOleClientSiteVtbl g_CntrLine_OleClientSiteVtbl; extern IAdviseSinkVtbl g_CntrLine_AdviseSinkVtbl; #if defined( INPLACE_CNTR ) extern IOleInPlaceSiteVtbl g_CntrLine_OleInPlaceSiteVtbl; extern IOleInPlaceFrameVtbl g_CntrApp_OleInPlaceFrameVtbl; extern BOOL g_fInsideOutContainer; #endif // INPLACE_CNTR #endif // OLE_CNTR // REVIEW: these are NOT useful end-user messages static char ErrMsgCreateCF[] = "Can't create Class Factory!"; static char ErrMsgRegCF[] = "Can't register Class Factory!"; static char ErrMsgRegMF[] = "Can't register Message Filter!"; extern UINT g_uMsgHelp; /* OleApp_InitInstance * ------------------- * * Initialize the app instance by creating the main frame window and * performing app instance specific initializations * (eg. initializing interface Vtbls). * * RETURNS: TRUE if the memory could be allocated, and the server app * was properly initialized. * FALSE otherwise * */ BOOL OleApp_InitInstance(LPOLEAPP lpOleApp, HINSTANCE hInst, int nCmdShow) { LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; HRESULT hrErr; DWORD dwBuildVersion = OleBuildVersion(); LPMALLOC lpMalloc = NULL; OLEDBG_BEGIN3("OleApp_InitInstance\r\n") lpOleApp->m_fOleInitialized = FALSE; /* OLE2NOTE: check if the build version of the OLE2 DLL's match ** what our application is expecting. */ if (HIWORD(dwBuildVersion) != rmm || LOWORD(dwBuildVersion) < rup) { OleDbgAssertSz(0, "ERROR: OLE 2.0 DLL's are NOT compatible!"); #if !defined( _DEBUG ) return FALSE; // Wrong version of DLL's #endif } #if defined( _DEBUG ) /* OLE2NOTE: Use a special debug allocator to help track down ** memory leaks. */ OleStdCreateDbAlloc(0, &lpMalloc); #endif /* OLE2NOTE: the OLE libraries must be properly initialized before ** making any calls. OleInitialize automatically calls ** CoInitialize. we will use the default task memory allocator ** therefore we pass NULL to OleInitialize. */ OLEDBG_BEGIN2("OleInitialize called\r\n") hrErr = OleInitialize(lpMalloc); if (FAILED(hrErr)) { // Replacing the allocator may not be legal - try initializing // without overriding the allocator hrErr = OleInitialize(NULL); } OLEDBG_END2 #if defined( _DEBUG ) /* OLE2NOTE: release the special debug allocator so that only OLE is ** holding on to it. later when OleUninitialize is called, then ** the debug allocator object will be destroyed. when the debug ** allocator object is destoyed, it will report (to the Output ** Debug Terminal) whether there are any memory leaks. */ if (lpMalloc) lpMalloc->lpVtbl->Release(lpMalloc); #endif if (hrErr != NOERROR) { OutlineApp_ErrorMessage(lpOutlineApp,"OLE initialization failed!"); goto error; } /***************************************************************** ** OLE2NOTE: we must remember the fact that OleInitialize has ** been call successfully. the very last thing an app must ** be do is properly shut down OLE by calling ** OleUninitialize. This call MUST be guarded! it is only ** allowable to call OleUninitialize if OleInitialize has ** been called SUCCESSFULLY. *****************************************************************/ lpOleApp->m_fOleInitialized = TRUE; // Initialize the OLE 2.0 interface method tables. if (! OleApp_InitVtbls(lpOleApp)) goto error; // Register OLE 2.0 clipboard formats. lpOleApp->m_cfEmbedSource = RegisterClipboardFormat(CF_EMBEDSOURCE); lpOleApp->m_cfEmbeddedObject = RegisterClipboardFormat( CF_EMBEDDEDOBJECT ); lpOleApp->m_cfLinkSource = RegisterClipboardFormat(CF_LINKSOURCE); lpOleApp->m_cfFileName = RegisterClipboardFormat(CF_FILENAME); lpOleApp->m_cfObjectDescriptor = RegisterClipboardFormat(CF_OBJECTDESCRIPTOR); lpOleApp->m_cfLinkSrcDescriptor = RegisterClipboardFormat(CF_LINKSRCDESCRIPTOR); lpOleApp->m_cRef = 0; lpOleApp->m_cDoc = 0; lpOleApp->m_fUserCtrl = FALSE; lpOleApp->m_dwRegClassFac = 0; lpOleApp->m_lpClassFactory = NULL; lpOleApp->m_cModalDlgActive = 0; INIT_INTERFACEIMPL( &lpOleApp->m_Unknown, &g_OleApp_UnknownVtbl, lpOleApp ); #if defined( USE_DRAGDROP ) // delay before dragging should start, in milliseconds lpOleApp->m_nDragDelay = GetProfileInt( "windows", "DragDelay", DD_DEFDRAGDELAY ); // minimum distance (radius) before drag should start, in pixels lpOleApp->m_nDragMinDist = GetProfileInt( "windows", "DragMinDist", DD_DEFDRAGMINDIST ); // delay before scrolling, in milliseconds lpOleApp->m_nScrollDelay = GetProfileInt( "windows", "DragScrollDelay", DD_DEFSCROLLDELAY ); // inset-width of the hot zone, in pixels lpOleApp->m_nScrollInset = GetProfileInt( "windows", "DragScrollInset", DD_DEFSCROLLINSET ); // scroll interval, in milliseconds lpOleApp->m_nScrollInterval = GetProfileInt( "windows", "DragScrollInterval", DD_DEFSCROLLINTERVAL ); #if defined( IF_SPECIAL_DD_CURSORS_NEEDED ) // This would be used if the app wanted to have custom drag/drop cursors lpOleApp->m_hcursorDragNone = LoadCursor ( hInst, "DragNoneCur" ); lpOleApp->m_hcursorDragCopy = LoadCursor ( hInst, "DragCopyCur" ); lpOleApp->m_hcursorDragMove = LoadCursor ( hInst, "DragMoveCur" ); lpOleApp->m_hcursorDragLink = LoadCursor ( hInst, "DragLinkCur" ); #endif // IF_SPECIAL_DD_CURSORS_NEEDED #endif // USE_DRAGDROP lpOleApp->m_lpMsgFilter = NULL; #if defined( USE_MSGFILTER ) /* OLE2NOTE: Register our message filter upon app startup. the ** message filter is used to handle concurrency. ** we will use a standard implementation of IMessageFilter that ** is included as part of the OLE2UI library. */ lpOleApp->m_lpMsgFilter = NULL; if (! OleApp_RegisterMessageFilter(lpOleApp)) goto error; /* OLE2NOTE: because our app is initially INVISIBLE, we must ** DISABLE the busy dialog. we should NOT put up any dialogs if ** our app is invisible. when our app window is made visible, ** then the busy dialog will be enabled. */ OleStdMsgFilter_EnableBusyDialog(lpOleApp->m_lpMsgFilter, FALSE); #endif // USE_MSGFILTER #if defined( OLE_SERVER ) /* OLE2NOTE: perform initialization specific for an OLE server */ if (! ServerApp_InitInstance((LPSERVERAPP)lpOutlineApp, hInst, nCmdShow)) goto error; #endif #if defined( OLE_CNTR ) /* OLE2NOTE: perform initialization specific for an OLE container */ // Register help message g_uMsgHelp = RegisterWindowMessage(SZOLEUI_MSG_HELP); if (! ContainerApp_InitInstance((LPCONTAINERAPP)lpOutlineApp, hInst, nCmdShow)) goto error; #endif #if defined( OLE_CNTR ) lpOleApp->m_hStdPal = OleStdCreateStandardPalette(); #endif OLEDBG_END3 return TRUE; error: OLEDBG_END3 return FALSE; } /* * OleApp_TerminateApplication * --------------------------- * Perform proper OLE application cleanup before shutting down */ void OleApp_TerminateApplication(LPOLEAPP lpOleApp) { OLEDBG_BEGIN3("OleApp_TerminateApplication\r\n") /* OLE2NOTE: perform a clean shut down for OLE. at this point our ** App refcnt should be 0, or else we should never have reached ** this point! */ OleDbgAssertSz(lpOleApp->m_cRef == 0, "App NOT shut down properly"); if(lpOleApp->m_fOleInitialized) { OLEDBG_BEGIN2("OleUninitialize called\r\n") OleUninitialize(); OLEDBG_END2 } OLEDBG_END3 } /* OleApp_ParseCmdLine * ------------------- * * Parse the command line for any execution flags/arguments. * OLE2NOTE: check if "-Embedding" switch is given. */ BOOL OleApp_ParseCmdLine(LPOLEAPP lpOleApp, LPSTR lpszCmdLine, int nCmdShow) { LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; char szFileName[256]; /* buffer for filename in command line */ BOOL fStatus = TRUE; BOOL fEmbedding = FALSE; OLEDBG_BEGIN3("OleApp_ParseCmdLine\r\n") szFileName[0] = '\0'; ParseCmdLine(lpszCmdLine, &fEmbedding, (LPSTR)szFileName); #if defined( MDI_VERSION ) /* OLE2NOTE: an MDI app would ALWAYS register its ClassFactory. it ** can handle multiple objects at the same time, while an SDI ** application can only handle a single embedded or file-based ** object at a time. */ fStatus = OleApp_RegisterClassFactory(lpOleApp); #endif if(fEmbedding) { if (szFileName[0] == '\0') { /***************************************************************** ** App was launched with /Embedding. ** We must register our ClassFactory with OLE, remain hidden ** (the app window is initially created not visible), and ** wait for OLE to call IClassFactory::CreateInstance ** method. We do not automatically create a document as we ** do when the app is launched by the user from the ** FileManager. We must NOT make our app window visible ** until told to do so by our container. ** ** OLE2NOTE: Because we are an SDI app, we only register our ** ClassFactory if we are launched with the /Embedding ** flag WITHOUT a filename. an MDI app would ALWAYS ** register its ClassFactory. it can handle multiple ** objects at the same time, while an SDI application ** can only handle a single embedded or file-based ** object at a time. *****************************************************************/ #if defined( SDI_VERSION ) fStatus = OleApp_RegisterClassFactory(lpOleApp); #endif } else { /***************************************************************** ** App was launched with /Embedding . ** We must create a document and load the file and ** register it in the RunningObjectTable BEFORE we ** enter our GetMessage loop (ie. before we yield). ** One way to perform these tasks is to call the same ** interface methods that OLE 2.0 calls for linking to a ** file: ** IClassFactory::CreateInstance ** IPersistFile::Load ** ** We must NOT make our app window visible until told to ** do so by our container. An application will be ** launched in this manner by an OLE 1.0 application ** link situation (eg. double clicking a linked object ** or OleCreateLinkFromFile called). ** ** OLE2NOTE: Because we are an SDI app, we should NOT ** register our ClassFactory when we are launched with the ** /Embedding flag. our SDI instance can only ** handle a single embedded or file-based object. ** an MDI app WOULD register its ClassFactory at all ** times because it can handle multiple objects. *****************************************************************/ // allocate a new document object lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); if (! lpOutlineApp->m_lpDoc) { OLEDBG_END3 return FALSE; } /* OLE2NOTE: initially the Doc object is created with a 0 ref ** count. in order to have a stable Doc object during the ** process of initializing the new Doc instance, ** we intially AddRef the Doc ref cnt and later ** Release it. This initial AddRef is artificial; it is simply ** done to guarantee that a harmless QueryInterface followed by ** a Release does not inadvertantly force our object to destroy ** itself prematurely. */ OleDoc_AddRef((LPOLEDOC)lpOutlineApp->m_lpDoc); /* OLE2NOTE: OutlineDoc_LoadFromFile will register our document ** in the RunningObjectTable. this registration will ** AddRef our document. therefore our document will not ** be destroyed when we release the artificial AddRef */ fStatus = OutlineDoc_LoadFromFile( lpOutlineApp->m_lpDoc, (LPSTR)szFileName); OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); // rel AddRef OLEDBG_END3 return fStatus; } } else { /***************************************************************** ** App was launched by the user (without /Embedding) and ** therefore is marked to be under user control. ** In this case, because we are an SDI app, we do NOT ** register our ClassFactory with OLE. This app instance can ** only manage one document at a time (either a user ** document or an embedded object document). An MDI app ** would register its ClassFactory here. ** ** We must create a document for the user (either ** initialized from a file given on the command line or ** initialized as an untitled document. We must also make ** our app window visible to the user. *****************************************************************/ // allocate a new document object lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); if (! lpOutlineApp->m_lpDoc) goto error; /* OLE2NOTE: initially the Doc object is created with a 0 ref ** count. in order to have a stable Doc object during the ** process of initializing the new Doc instance, ** we intially AddRef the Doc ref cnt and later ** Release it. This initial AddRef is artificial; it is simply ** done to guarantee that a harmless QueryInterface followed by ** a Release does not inadvertantly force our object to destroy ** itself prematurely. */ OleDoc_AddRef((LPOLEDOC)lpOutlineApp->m_lpDoc); if(*szFileName) { // initialize the document from the specified file if (! OutlineDoc_LoadFromFile(lpOutlineApp->m_lpDoc, szFileName)) goto error; } else { // set the doc to an (Untitled) doc. if (! OutlineDoc_InitNewFile(lpOutlineApp->m_lpDoc)) goto error; } // position and size the new doc window OutlineApp_ResizeWindows(lpOutlineApp); OutlineDoc_ShowWindow(lpOutlineApp->m_lpDoc); // calls OleDoc_Lock OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc);// rel AddRef above // show main app window ShowWindow(lpOutlineApp->m_hWndApp, nCmdShow); UpdateWindow(lpOutlineApp->m_hWndApp); #if defined( OLE_CNTR ) ContainerDoc_UpdateLinks((LPCONTAINERDOC)lpOutlineApp->m_lpDoc); #endif } OLEDBG_END3 return fStatus; error: // REVIEW: should load string from string resource OutlineApp_ErrorMessage( lpOutlineApp, "Could not create document--Out of Memory" ); if (lpOutlineApp->m_lpDoc) // rel artificial AddRef above OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); OLEDBG_END3 return FALSE; } /* OleApp_CloseAllDocsAndExitCommand * --------------------------------- * * Close all active documents and exit the app. * Because this is an SDI, there is only one document * If the doc was modified, prompt the user if he wants to save it. * * Returns: * TRUE if the app is successfully closed * FALSE if failed or aborted * * OLE2NOTE: in the OLE version, we can NOT directly * destroy the App object. we can only take all * necessary actions to ensure that our object receives * all of its Releases from clients holding onto * pointers (eg. closing all docs and flushing the * clipboard) and then we must hide our window and wait * actually for our refcnt to reach 0. when it reaches 0, * our destructor (OutlineApp_Destroy) will be called. * each document addref's the app object in order to * guarentee that the app does not shut down while the doc * is still open. closing all docs, will release these * refcnt's. if there are now more open documents AND the * app is not under the control of the user (ie. launched by * OLE) then the app will now shut down. the OleApp_Release * function executes this shut down procedure. after closing * all docs, then releasing the user refcnt will force the * app to shut down. */ BOOL OleApp_CloseAllDocsAndExitCommand( LPOLEAPP lpOleApp, BOOL fForceEndSession ) { LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; DWORD dwSaveOption = (fForceEndSession ? OLECLOSE_NOSAVE : OLECLOSE_PROMPTSAVE); /* OLE2NOTE: in order to have a stable App object during the ** process of closing, we intially AddRef the App ref cnt and ** later Release it. This initial AddRef is artificial; it is ** simply done to guarantee that our App object does not ** destroy itself until the end of this routine. */ OleApp_AddRef(lpOleApp); /* Because this is an SDI app, there is only one document. ** Close the doc. if it is successfully closed and the app will ** not automatically exit, then also exit the app. ** if this were an MDI app, we would loop through and close all ** open MDI child documents. */ #if defined( OLE_SERVER ) if (!fForceEndSession && lpOutlineApp->m_lpDoc->m_docInitType == DOCTYPE_EMBEDDED) dwSaveOption = OLECLOSE_SAVEIFDIRTY; #endif if (! OutlineDoc_Close(lpOutlineApp->m_lpDoc, dwSaveOption)) { OleApp_Release(lpOleApp); return FALSE; // User Aborted shutdown } #if defined( _DEBUG ) OleDbgAssertSz( lpOutlineApp->m_lpDoc==NULL, "Closed doc NOT properly destroyed" ); #endif #if defined( OLE_CNTR ) /* if we currently have data on the clipboard then we must tell ** the clipboard to release our clipboard data object ** (document) */ if (lpOutlineApp->m_lpClipboardDoc) OleApp_FlushClipboard(lpOleApp); #endif OleApp_HideWindow(lpOleApp); /* OLE2NOTE: this call forces all external connections to our ** object to close down and therefore guarantees that we receive ** all releases associated with those external connections. */ OLEDBG_BEGIN2("CoDisconnectObject(lpApp) called\r\n") CoDisconnectObject((LPUNKNOWN)&lpOleApp->m_Unknown, 0); OLEDBG_END2 OleApp_Release(lpOleApp); // release artificial AddRef above return TRUE; } /* OleApp_ShowWindow * ----------------- * * Show the window of the app to the user. * make sure app window is visible and bring the app to the top. * IF fGiveUserCtrl == TRUE * THEN give the user the control over the life-time of the app. */ void OleApp_ShowWindow(LPOLEAPP lpOleApp, BOOL fGiveUserCtrl) { LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; OLEDBG_BEGIN3("OleApp_ShowWindow\r\n") /* OLE2NOTE: while the application is visible and under user ** control, we do NOT want it to be prematurely destroyed when ** the user closes a document. thus we must inform OLE to hold ** an external lock on our application on behalf of the user. ** this arranges that OLE holds at least 1 reference to our ** application that will NOT be released until we release this ** external lock. later, when the application window is hidden, we ** will release this external lock. */ if (fGiveUserCtrl && ! lpOleApp->m_fUserCtrl) { lpOleApp->m_fUserCtrl = TRUE; OleApp_Lock(lpOleApp, TRUE /* fLock */, 0 /* not applicable */); } // we must show our App window and force it to have input focus ShowWindow(lpOutlineApp->m_hWndApp, SW_SHOWNORMAL); SetFocus(lpOutlineApp->m_hWndApp); /* OLE2NOTE: because our app is now visible, we can enable the busy ** dialog. we should NOT put up any dialogs if our app is ** invisible. */ OleApp_EnableBusyDialogs(lpOleApp, TRUE, TRUE); OLEDBG_END3 } /* OleApp_HideWindow * ----------------- * * Hide the window of the app from the user. * take away the control of the app by the user. */ void OleApp_HideWindow(LPOLEAPP lpOleApp) { LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; OLEDBG_BEGIN3("OleApp_HideWindow\r\n") /* OLE2NOTE: the application is now being hidden, so we must release ** the external lock that was made on behalf of the user. ** if this is that last external lock on our application, thus ** enabling our application to complete its shutdown operation. */ if (lpOleApp->m_fUserCtrl) { lpOleApp->m_fUserCtrl = FALSE; OleApp_Lock(lpOleApp, FALSE /*fLock*/, TRUE /*fLastUnlockReleases*/); } ShowWindow(lpOutlineApp->m_hWndApp, SW_HIDE); /* OLE2NOTE: because our app is now INVISIBLE, we must DISABLE the busy ** dialog. we should NOT put up any dialogs if our app is ** invisible. */ OleApp_EnableBusyDialogs(lpOleApp, FALSE, FALSE); OLEDBG_END3 } /* OleApp_Lock ** ----------- ** Lock/Unlock the App object. if the last lock is unlocked and ** fLastUnlockReleases == TRUE, then the app object will shut down ** (ie. it will recieve its final release and its refcnt will go to 0). */ HRESULT OleApp_Lock(LPOLEAPP lpOleApp, BOOL fLock, BOOL fLastUnlockReleases) { HRESULT hrErr; #if defined( _DEBUG ) if (fLock) { OLEDBG_BEGIN2("CoLockObjectExternal(lpApp,TRUE) called\r\n") } else { if (fLastUnlockReleases) OLEDBG_BEGIN2("CoLockObjectExternal(lpApp,FALSE,TRUE) called\r\n") else OLEDBG_BEGIN2("CoLockObjectExternal(lpApp,FALSE,FALSE) called\r\n") } #endif // _DEBUG OleApp_AddRef(lpOleApp); // artificial AddRef to make object stable hrErr = CoLockObjectExternal( (LPUNKNOWN)&lpOleApp->m_Unknown, fLock, fLastUnlockReleases); OleApp_Release(lpOleApp); // release artificial AddRef above OLEDBG_END2 return hrErr; } /* OleApp_Destroy * -------------- * * Free all OLE related resources that had been allocated for the app. */ void OleApp_Destroy(LPOLEAPP lpOleApp) { // OLE2NOTE: Revoke our message filter upon app shutdown. OleApp_RevokeMessageFilter(lpOleApp); // OLE2NOTE: Revoke our ClassFactory upon app shutdown. OleApp_RevokeClassFactory(lpOleApp); #if defined( IF_SPECIAL_DD_CURSORS_NEEDED ) // This would be used if the app wanted to have custom drag/drop cursors DestroyCursor(lpOleApp->m_hcursorDragNone); DestroyCursor(lpOleApp->m_hcursorDragCopy); DestroyCursor(lpOleApp->m_hcursorDragLink); DestroyCursor(lpOleApp->m_hcursorDragMove); #endif // IF_SPECIAL_DD_CURSORS_NEEDED #if defined( OLE_CNTR ) if (lpOleApp->m_hStdPal) { DeleteObject(lpOleApp->m_hStdPal); lpOleApp->m_hStdPal = NULL; } #endif } /* OleApp_DocLockApp ** ----------------- ** Add a lock on the App on behalf of the Doc. the App may not close ** while the Doc exists. ** ** when a document is first created, it calls this method to ** guarantee that the application stays alive (OleDoc_Init). ** when a document is destroyed, it calls ** OleApp_DocUnlockApp to release this hold on the app. */ void OleApp_DocLockApp(LPOLEAPP lpOleApp) { ULONG cDoc; OLEDBG_BEGIN3("OleApp_DocLockApp\r\n") cDoc = ++lpOleApp->m_cDoc; OleDbgOutRefCnt3("OleApp_DocLockApp: cDoc++\r\n", lpOleApp, cDoc); OleApp_Lock(lpOleApp, TRUE /* fLock */, 0 /* not applicable */); OLEDBG_END3 return; } /* OleApp_DocUnlockApp ** ------------------- ** Forget all references to a closed document. ** Release the lock on the App on behalf of the Doc. if this was the ** last lock on the app, then it will shutdown. */ void OleApp_DocUnlockApp(LPOLEAPP lpOleApp, LPOUTLINEDOC lpOutlineDoc) { ULONG cDoc; OLEDBG_BEGIN3("OleApp_DocUnlockApp\r\n") /* OLE2NOTE: when there are no open documents and the app is not ** under the control of the user then revoke our ClassFactory to ** enable the app to shut down. */ cDoc = --lpOleApp->m_cDoc; #if defined( _DEBUG ) OleDbgAssertSz ( lpOleApp->m_cDoc >= 0, "DocUnlockApp called with cDoc == 0"); OleDbgOutRefCnt3( "OleApp_DocUnlockApp: cDoc--\r\n", lpOleApp, cDoc); #endif OleApp_Lock(lpOleApp, FALSE /* fLock */, TRUE /* fLastUnlockReleases */); OLEDBG_END3 return; } /* OleApp_HideIfNoReasonToStayVisible ** ---------------------------------- ** ** if there are no more documents visible to the user and the app ** itself is not under user control, then it has no reason to stay ** visible. we thus should hide the app. we can not directly destroy ** the app, because it may be validly being used programatically by ** another client application and should remain running. the app ** should simply be hidden from the user. */ void OleApp_HideIfNoReasonToStayVisible(LPOLEAPP lpOleApp) { LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; LPOUTLINEDOC lpOutlineDoc; OLEDBG_BEGIN3("OleApp_HideIfNoReasonToStayVisible\r\n") if (lpOleApp->m_fUserCtrl) { OLEDBG_END3 return; // remain visible; user in control of app } /* Because this is an SDI app, there is only one user document. ** check if it is visible to the user. an MDI app would loop over ** all open MDI child documents to see if any are visible. */ lpOutlineDoc = (LPOUTLINEDOC)lpOutlineApp->m_lpDoc; if (lpOutlineDoc && IsWindowVisible(lpOutlineDoc->m_hWndDoc)) return; // remain visible; the doc is visible to the user // if we reached here, the app should be hidden OleApp_HideWindow(lpOleApp); OLEDBG_END3 } /* OleApp_AddRef ** ------------- ** ** increment the ref count of the App object. ** ** Returns the new ref count on the object */ ULONG OleApp_AddRef(LPOLEAPP lpOleApp) { ++lpOleApp->m_cRef; #if defined( _DEBUG ) OleDbgOutRefCnt4( "OleApp_AddRef: cRef++\r\n", lpOleApp, lpOleApp->m_cRef ); #endif return lpOleApp->m_cRef; } /* OleApp_Release ** -------------- ** ** decrement the ref count of the App object. ** if the ref count goes to 0, then the app object is destroyed. ** ** Returns the remaining ref count on the object */ ULONG OleApp_Release (LPOLEAPP lpOleApp) { ULONG cRef; cRef = --lpOleApp->m_cRef; #if defined( _DEBUG ) OleDbgAssertSz (lpOleApp->m_cRef >= 0, "Release called with cRef == 0"); OleDbgOutRefCnt4( "OleApp_AddRef: cRef--\r\n", lpOleApp, cRef); #endif // _DEBUG /********************************************************************* ** OLE2NOTE: when the ClassFactory refcnt == 0, then destroy it. ** ** otherwise the ClassFactory is still in use. ** *********************************************************************/ if(cRef == 0) OutlineApp_Destroy((LPOUTLINEAPP)lpOleApp); return cRef; } /* OleApp_QueryInterface ** --------------------- ** ** Retrieve a pointer to an interface on the app object. ** ** OLE2NOTE: this function will AddRef the ref cnt of the object. ** ** Returns NOERROR if interface is successfully retrieved. ** E_NOINTERFACE if the interface is not supported */ HRESULT OleApp_QueryInterface ( LPOLEAPP lpOleApp, REFIID riid, LPVOID FAR* lplpvObj ) { SCODE sc; /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */ *lplpvObj = NULL; if (IsEqualIID(riid, &IID_IUnknown)) { OleDbgOut4("OleApp_QueryInterface: IUnknown* RETURNED\r\n"); *lplpvObj = (LPVOID) &lpOleApp->m_Unknown; OleApp_AddRef(lpOleApp); sc = S_OK; } else { sc = E_NOINTERFACE; } OleDbgQueryInterfaceMethod(*lplpvObj); return ResultFromScode(sc); } /* OleApp_RejectInComingCalls ** ------------------------- ** Reject/Handle in coming OLE (LRPC) calls. ** ** OLE2NOTE: if the app is in a state when it can NOT handle in ** coming OLE method calls from an external process (eg. the app has ** an application modal dialog up), then it should call ** OleApp_RejectInComingCalls(TRUE). in this state the ** IMessageFilter::HandleInComingCall method will return ** SERVERCALL_RETRYLATER. this tells the caller to try again in a ** little while. normally the calling app will put up a dialog (see ** OleUIBusy dialog) in this situation informing the user of the ** situation. the user then is normally given the option to ** "Switch To..." the busy application, retry, or cancel the ** operation. when the app is ready to continue processing such ** calls, it should call OleApp_RejectInComingCalls(FALSE). in this ** state, SERVERCALL_ISHANDLED is returned by ** IMessageFilter::HandleInComingCall. */ void OleApp_RejectInComingCalls(LPOLEAPP lpOleApp, BOOL fReject) { #if defined( _DEBUG ) if (fReject) OleDbgOut3("OleApp_RejectInComingCalls(TRUE)\r\n"); else OleDbgOut3("OleApp_RejectInComingCalls(FALSE)\r\n"); #endif // _DEBUG OleDbgAssert(lpOleApp->m_lpMsgFilter != NULL); if (! lpOleApp->m_lpMsgFilter) return; OleStdMsgFilter_SetInComingCallStatus( lpOleApp->m_lpMsgFilter, (fReject ? SERVERCALL_RETRYLATER : SERVERCALL_ISHANDLED) ); } /* OleApp_DisableBusyDialogs ** ------------------------- ** Disable the Busy and NotResponding dialogs. ** ** Returns previous enable state so that it can be restored by ** calling OleApp_ReEnableBusyDialogs. */ void OleApp_DisableBusyDialogs( LPOLEAPP lpOleApp, BOOL FAR* lpfPrevBusyEnable, BOOL FAR* lpfPrevNREnable ) { if (lpOleApp->m_lpMsgFilter) { *lpfPrevNREnable = OleStdMsgFilter_EnableNotRespondingDialog( lpOleApp->m_lpMsgFilter, FALSE); *lpfPrevBusyEnable = OleStdMsgFilter_EnableBusyDialog( lpOleApp->m_lpMsgFilter, FALSE); } } /* OleApp_EnableBusyDialogs ** ------------------------ ** Set the enable state of the Busy and NotResponding dialogs. ** ** This function is typically used after a call to ** OleApp_DisableBusyDialogs in order to restore the previous enable ** state of the dialogs. */ void OleApp_EnableBusyDialogs( LPOLEAPP lpOleApp, BOOL fPrevBusyEnable, BOOL fPrevNREnable ) { if (lpOleApp->m_lpMsgFilter) { OleStdMsgFilter_EnableNotRespondingDialog( lpOleApp->m_lpMsgFilter, fPrevNREnable); OleStdMsgFilter_EnableBusyDialog( lpOleApp->m_lpMsgFilter, fPrevBusyEnable); } } /* OleApp_PreModalDialog ** --------------------- ** Keep track that a modal dialog is about to be brought up. ** ** while a modal dialog is up we need to take special actions: ** 1. we do NOT want to initialize our tool bar buttons on ** WM_ACTIVATEAPP. the tool bar is not accessible. ** 2. we want to reject new top-level, incoming LRPC calls ** (return SERVERCALL_RETRYLATER from IMessageFilter:: ** HandleInComingCall). ** 3. (IN-PLACE SERVER) tell our in-place container to disable ** modeless dialogs by calling IOleInPlaceFrame:: ** EnableModeless(FALSE). ** 4. (IN-PLACE CONTAINER) tell our UIActive in-place object to ** disable modeless dialogs by calling IOleInPlaceActiveObject:: ** EnableModeless(FALSE). */ void OleApp_PreModalDialog(LPOLEAPP lpOleApp, LPOLEDOC lpOleDoc) { if (lpOleApp->m_cModalDlgActive == 0) { // top-level modal dialog is being brought up #if defined( USE_FRAMETOOLS ) LPFRAMETOOLS lptb; if (lpOleDoc) lptb = ((LPOUTLINEDOC)lpOleDoc)->m_lpFrameTools; else lptb = OutlineApp_GetFrameTools((LPOUTLINEAPP)lpOleApp); if (lptb) FrameTools_EnableWindow(lptb, FALSE); #endif // USE_FRAMETOOLS OleApp_RejectInComingCalls(lpOleApp, TRUE); #if defined( INPLACE_SVR ) { LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; /* if the document bringing up the modal dialog is ** currently a UIActive in-place object, then tell the ** top-level in-place frame to disable its modeless ** dialogs. */ if (lpServerDoc && lpServerDoc->m_fUIActive && lpServerDoc->m_lpIPData && lpServerDoc->m_lpIPData->lpFrame) { OLEDBG_BEGIN2("IOleInPlaceFrame::EnableModless(FALSE) called\r\n"); lpServerDoc->m_lpIPData->lpFrame->lpVtbl->EnableModeless( lpServerDoc->m_lpIPData->lpFrame, FALSE); OLEDBG_END2 } } #endif // INPLACE_SVR #if defined( INPLACE_CNTR ) { LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOleApp; /* if the document bringing up the modal dialog is an ** in-place container that has a UIActive object, then ** tell the UIActive object to disable its modeless ** dialogs. */ if (lpContainerApp->m_lpIPActiveObj) { OLEDBG_BEGIN2("IOleInPlaceActiveObject::EnableModless(FALSE) called\r\n"); lpContainerApp->m_lpIPActiveObj->lpVtbl->EnableModeless( lpContainerApp->m_lpIPActiveObj, FALSE); OLEDBG_END2 } } #endif // INPLACE_CNTR } lpOleApp->m_cModalDlgActive++; } /* OleApp_PostModalDialog ** ---------------------- ** Keep track that a modal dialog is being brought down. this call ** balances the OleApp_PreModalDialog call. */ void OleApp_PostModalDialog(LPOLEAPP lpOleApp, LPOLEDOC lpOleDoc) { lpOleApp->m_cModalDlgActive--; if (lpOleApp->m_cModalDlgActive == 0) { // last modal dialog is being brought down #if defined( USE_FRAMETOOLS ) LPFRAMETOOLS lptb; if (lpOleDoc) lptb = ((LPOUTLINEDOC)lpOleDoc)->m_lpFrameTools; else lptb = OutlineApp_GetFrameTools((LPOUTLINEAPP)lpOleApp); if (lptb) { FrameTools_EnableWindow(lptb, TRUE); FrameTools_UpdateButtons(lptb, (LPOUTLINEDOC)lpOleDoc); } #endif // USE_FRAMETOOLS OleApp_RejectInComingCalls(lpOleApp, FALSE); #if defined( INPLACE_SVR ) { LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; /* if the document bringing down the modal dialog is ** currently a UIActive in-place object, then tell the ** top-level in-place frame it can re-enable its ** modeless dialogs. */ if (lpServerDoc && lpServerDoc->m_fUIActive && lpServerDoc->m_lpIPData && lpServerDoc->m_lpIPData->lpFrame) { OLEDBG_BEGIN2("IOleInPlaceFrame::EnableModless(TRUE) called\r\n"); lpServerDoc->m_lpIPData->lpFrame->lpVtbl->EnableModeless( lpServerDoc->m_lpIPData->lpFrame, TRUE); OLEDBG_END2 } } #endif // INPLACE_SVR #if defined( INPLACE_CNTR ) { LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOleApp; /* if the document bringing down the modal dialog is an ** in-place container that has a UIActive object, then ** tell the UIActive object it can re-enable its ** modeless dialogs. */ if (lpContainerApp->m_lpIPActiveObj) { OLEDBG_BEGIN2("IOleInPlaceActiveObject::EnableModless(TRUE) called\r\n"); lpContainerApp->m_lpIPActiveObj->lpVtbl->EnableModeless( lpContainerApp->m_lpIPActiveObj, TRUE); OLEDBG_END2 } } #endif // INPLACE_CNTR } } /* OleApp_InitVtbls * ---------------- * * initialize the methods in all of the interface Vtbl's * * OLE2NOTE: we only need one copy of each Vtbl. When an object which * exposes an interface is instantiated, its lpVtbl is intialized * to point to the single copy of the Vtbl. * */ BOOL OleApp_InitVtbls (LPOLEAPP lpOleApp) { BOOL fStatus; // OleApp::IUnknown method table OleStdInitVtbl(&g_OleApp_UnknownVtbl, sizeof(IUnknownVtbl)); g_OleApp_UnknownVtbl.QueryInterface = OleApp_Unk_QueryInterface; g_OleApp_UnknownVtbl.AddRef = OleApp_Unk_AddRef; g_OleApp_UnknownVtbl.Release = OleApp_Unk_Release; fStatus = OleStdCheckVtbl( &g_OleApp_UnknownVtbl, sizeof(IUnknownVtbl), "IUnknown" ); if (! fStatus) return FALSE; // OleDoc::IUnknown method table OleStdInitVtbl(&g_OleDoc_UnknownVtbl, sizeof(IUnknownVtbl)); g_OleDoc_UnknownVtbl.QueryInterface = OleDoc_Unk_QueryInterface; g_OleDoc_UnknownVtbl.AddRef = OleDoc_Unk_AddRef; g_OleDoc_UnknownVtbl.Release = OleDoc_Unk_Release; fStatus = OleStdCheckVtbl( &g_OleDoc_UnknownVtbl, sizeof(IUnknownVtbl), "IUnknown" ); if (! fStatus) return FALSE; // OleDoc::IPersistFile method table OleStdInitVtbl(&g_OleDoc_PersistFileVtbl, sizeof(IPersistFileVtbl)); g_OleDoc_PersistFileVtbl.QueryInterface = OleDoc_PFile_QueryInterface; g_OleDoc_PersistFileVtbl.AddRef = OleDoc_PFile_AddRef; g_OleDoc_PersistFileVtbl.Release = OleDoc_PFile_Release; g_OleDoc_PersistFileVtbl.GetClassID = OleDoc_PFile_GetClassID; g_OleDoc_PersistFileVtbl.IsDirty = OleDoc_PFile_IsDirty; g_OleDoc_PersistFileVtbl.Load = OleDoc_PFile_Load; g_OleDoc_PersistFileVtbl.Save = OleDoc_PFile_Save; g_OleDoc_PersistFileVtbl.SaveCompleted = OleDoc_PFile_SaveCompleted; g_OleDoc_PersistFileVtbl.GetCurFile = OleDoc_PFile_GetCurFile; fStatus = OleStdCheckVtbl( &g_OleDoc_PersistFileVtbl, sizeof(IPersistFileVtbl), "IPersistFile" ); if (! fStatus) return FALSE; // OleDoc::IOleItemContainer method table OleStdInitVtbl(&g_OleDoc_OleItemContainerVtbl, sizeof(IOleItemContainerVtbl)); g_OleDoc_OleItemContainerVtbl.QueryInterface = OleDoc_ItemCont_QueryInterface; g_OleDoc_OleItemContainerVtbl.AddRef = OleDoc_ItemCont_AddRef; g_OleDoc_OleItemContainerVtbl.Release = OleDoc_ItemCont_Release; g_OleDoc_OleItemContainerVtbl.ParseDisplayName = OleDoc_ItemCont_ParseDisplayName; g_OleDoc_OleItemContainerVtbl.EnumObjects= OleDoc_ItemCont_EnumObjects; g_OleDoc_OleItemContainerVtbl.LockContainer = OleDoc_ItemCont_LockContainer; g_OleDoc_OleItemContainerVtbl.GetObject = OleDoc_ItemCont_GetObject; g_OleDoc_OleItemContainerVtbl.GetObjectStorage = OleDoc_ItemCont_GetObjectStorage; g_OleDoc_OleItemContainerVtbl.IsRunning = OleDoc_ItemCont_IsRunning; fStatus = OleStdCheckVtbl( &g_OleDoc_OleItemContainerVtbl, sizeof(IOleItemContainerVtbl), "IOleItemContainer" ); if (! fStatus) return FALSE; // OleDoc::IExternalConnection method table OleStdInitVtbl( &g_OleDoc_ExternalConnectionVtbl,sizeof(IExternalConnectionVtbl)); g_OleDoc_ExternalConnectionVtbl.QueryInterface = OleDoc_ExtConn_QueryInterface; g_OleDoc_ExternalConnectionVtbl.AddRef = OleDoc_ExtConn_AddRef; g_OleDoc_ExternalConnectionVtbl.Release = OleDoc_ExtConn_Release; g_OleDoc_ExternalConnectionVtbl.AddConnection = OleDoc_ExtConn_AddConnection; g_OleDoc_ExternalConnectionVtbl.ReleaseConnection = OleDoc_ExtConn_ReleaseConnection; fStatus = OleStdCheckVtbl( &g_OleDoc_ExternalConnectionVtbl, sizeof(IExternalConnectionVtbl), "IExternalConnection" ); if (! fStatus) return FALSE; // OleDoc::IDataObject method table OleStdInitVtbl(&g_OleDoc_DataObjectVtbl, sizeof(IDataObjectVtbl)); g_OleDoc_DataObjectVtbl.QueryInterface = OleDoc_DataObj_QueryInterface; g_OleDoc_DataObjectVtbl.AddRef = OleDoc_DataObj_AddRef; g_OleDoc_DataObjectVtbl.Release = OleDoc_DataObj_Release; g_OleDoc_DataObjectVtbl.GetData = OleDoc_DataObj_GetData; g_OleDoc_DataObjectVtbl.GetDataHere = OleDoc_DataObj_GetDataHere; g_OleDoc_DataObjectVtbl.QueryGetData = OleDoc_DataObj_QueryGetData; g_OleDoc_DataObjectVtbl.GetCanonicalFormatEtc = OleDoc_DataObj_GetCanonicalFormatEtc; g_OleDoc_DataObjectVtbl.SetData = OleDoc_DataObj_SetData; g_OleDoc_DataObjectVtbl.EnumFormatEtc = OleDoc_DataObj_EnumFormatEtc; g_OleDoc_DataObjectVtbl.DAdvise = OleDoc_DataObj_DAdvise; g_OleDoc_DataObjectVtbl.DUnadvise = OleDoc_DataObj_DUnadvise; g_OleDoc_DataObjectVtbl.EnumDAdvise = OleDoc_DataObj_EnumDAdvise; fStatus = OleStdCheckVtbl( &g_OleDoc_DataObjectVtbl, sizeof(IDataObjectVtbl), "IDataObject" ); if (! fStatus) return FALSE; #if defined( USE_DRAGDROP ) // OleDoc::IDropTarget method table OleStdInitVtbl(&g_OleDoc_DropTargetVtbl, sizeof(IDropTargetVtbl)); g_OleDoc_DropTargetVtbl.QueryInterface= OleDoc_DropTarget_QueryInterface; g_OleDoc_DropTargetVtbl.AddRef = OleDoc_DropTarget_AddRef; g_OleDoc_DropTargetVtbl.Release = OleDoc_DropTarget_Release; g_OleDoc_DropTargetVtbl.DragEnter = OleDoc_DropTarget_DragEnter; g_OleDoc_DropTargetVtbl.DragOver = OleDoc_DropTarget_DragOver; g_OleDoc_DropTargetVtbl.DragLeave = OleDoc_DropTarget_DragLeave; g_OleDoc_DropTargetVtbl.Drop = OleDoc_DropTarget_Drop; fStatus = OleStdCheckVtbl( &g_OleDoc_DropTargetVtbl, sizeof(IDropTargetVtbl), "IDropTarget" ); if (! fStatus) return FALSE; // OleDoc::IDropSource method table OleStdInitVtbl(&g_OleDoc_DropSourceVtbl, sizeof(IDropSourceVtbl)); g_OleDoc_DropSourceVtbl.QueryInterface = OleDoc_DropSource_QueryInterface; g_OleDoc_DropSourceVtbl.AddRef = OleDoc_DropSource_AddRef; g_OleDoc_DropSourceVtbl.Release = OleDoc_DropSource_Release; g_OleDoc_DropSourceVtbl.QueryContinueDrag = OleDoc_DropSource_QueryContinueDrag; g_OleDoc_DropSourceVtbl.GiveFeedback = OleDoc_DropSource_GiveFeedback; fStatus = OleStdCheckVtbl( &g_OleDoc_DropSourceVtbl, sizeof(IDropSourceVtbl), "IDropSource" ); if (! fStatus) return FALSE; #endif // USE_DRAGDROP #if defined( OLE_SERVER ) // Initialize the server specific interface method tables. if (! ServerApp_InitVtbls((LPSERVERAPP)lpOleApp)) return FALSE; #endif #if defined( OLE_CNTR ) // Initialize the container specific interface method tables. if (! ContainerApp_InitVtbls((LPCONTAINERAPP)lpOleApp)) return FALSE; #endif return TRUE; }; /* OleApp_InitMenu * --------------- * * Enable or Disable menu items depending on the state of * the appliation. * The OLE versions of the Outline sample app add a PasteSpecial command. * Also, the container version add InsertObject and ObjectVerb menu items. */ void OleApp_InitMenu( LPOLEAPP lpOleApp, LPOLEDOC lpOleDoc, HMENU hMenu ) { BOOL bMsgFilterInstalled = FALSE; BOOL bRejecting = FALSE; if (!lpOleApp || !hMenu) return; OLEDBG_BEGIN3("OleApp_InitMenu\r\n") /* ** Enable/disable menu items for Message Filter */ bMsgFilterInstalled = (lpOleApp->m_lpMsgFilter != NULL); bRejecting = bMsgFilterInstalled && OleStdMsgFilter_GetInComingCallStatus(lpOleApp->m_lpMsgFilter) != SERVERCALL_ISHANDLED; CheckMenuItem(hMenu, IDM_D_INSTALLMSGFILTER, bMsgFilterInstalled ? MF_CHECKED : MF_UNCHECKED); EnableMenuItem(hMenu, IDM_D_REJECTINCOMING, bMsgFilterInstalled ? MF_ENABLED : MF_GRAYED); CheckMenuItem(hMenu, IDM_D_REJECTINCOMING, bRejecting ? MF_CHECKED : MF_UNCHECKED); #if defined( OLE_CNTR ) { LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc; BOOL fShowObject; fShowObject = ContainerDoc_GetShowObjectFlag(lpContainerDoc); CheckMenuItem( hMenu, IDM_O_SHOWOBJECT, (fShowObject ? MF_CHECKED : MF_UNCHECKED) ); #if defined( INPLACE_CNTR ) && defined( _DEBUG ) CheckMenuItem( hMenu, IDM_D_INSIDEOUT, g_fInsideOutContainer ? MF_CHECKED:MF_UNCHECKED); #endif // INPLACE_CNTR && _DEBUG } #endif // OLE_CNTR OLEDBG_END3 } /* OleApp_UpdateEditMenu * --------------------- * * Purpose: * Update the Edit menuitems of the App according to the state of * OutlineDoc * * Parameter: * lpOutlineDoc pointer to the document * hMenuEdit edit menu handle */ void OleApp_UpdateEditMenu( LPOLEAPP lpOleApp, LPOUTLINEDOC lpOutlineDoc, HMENU hMenuEdit ) { int nFmtEtc; UINT uEnablePaste = MF_GRAYED; UINT uEnablePasteLink = MF_GRAYED; LPDATAOBJECT lpClipboardDataObj; LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc; HRESULT hrErr; BOOL fPrevEnable1; BOOL fPrevEnable2; if (!lpOleApp || !lpOutlineDoc || !hMenuEdit) return; if (!OleDoc_GetUpdateEditMenuFlag(lpOleDoc)) /* OLE2NOTE: if the flag is not set, we don't have to update ** the edit menu again. This blocks repetitive updating when ** the user move the mouse across Edit menu while holding ** down the button */ return; OLEDBG_BEGIN3("OleApp_InitEditMenu\r\n") /* OLE2NOTE: we do not want to ever give the busy dialog when we ** are trying to put up our menus. eg. even if the source of ** data on the clipboard is busy, we do not want put up the busy ** dialog. thus we will disable the dialog and at the end ** re-enable it. */ OleApp_DisableBusyDialogs(lpOleApp, &fPrevEnable1, &fPrevEnable2); // check if there is data on the clipboard that we can paste/paste link OLEDBG_BEGIN2("OleGetClipboard called\r\n") hrErr = OleGetClipboard((LPDATAOBJECT FAR*)&lpClipboardDataObj); OLEDBG_END2 if (hrErr == NOERROR) { nFmtEtc = OleStdGetPriorityClipboardFormat( lpClipboardDataObj, lpOleApp->m_arrPasteEntries, lpOleApp->m_nPasteEntries ); if (nFmtEtc >= 0) uEnablePaste = MF_ENABLED; // there IS a format we like OLEDBG_BEGIN2("OleQueryLinkFromData called\r\n") hrErr = OleQueryLinkFromData(lpClipboardDataObj); OLEDBG_END2 if(hrErr == NOERROR) uEnablePasteLink = MF_ENABLED; OleStdRelease((LPUNKNOWN)lpClipboardDataObj); } EnableMenuItem(hMenuEdit, IDM_E_PASTE, uEnablePaste); EnableMenuItem(hMenuEdit, IDM_E_PASTESPECIAL, uEnablePaste); #if defined( OLE_CNTR ) if (ContainerDoc_GetNextLink((LPCONTAINERDOC)lpOutlineDoc, NULL)) EnableMenuItem(hMenuEdit, IDM_E_EDITLINKS, MF_ENABLED); else EnableMenuItem(hMenuEdit, IDM_E_EDITLINKS, MF_GRAYED); { LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOleApp; HMENU hMenuVerb = NULL; LPOLEOBJECT lpOleObj = NULL; LPCONTAINERLINE lpContainerLine = NULL; BOOL fSelIsOleObject; EnableMenuItem(hMenuEdit, IDM_E_PASTELINK, uEnablePasteLink); /* check if selection is a single line that contains an OleObject */ fSelIsOleObject = ContainerDoc_IsSelAnOleObject( (LPCONTAINERDOC)lpOutlineDoc, &IID_IOleObject, (LPUNKNOWN FAR*)&lpOleObj, NULL, /* we don't need the line index */ (LPCONTAINERLINE FAR*)&lpContainerLine ); if (hMenuEdit != NULL) { /* If the current line is an ContainerLine, add the object ** verb sub menu to the Edit menu. if the line is not an ** ContainerLine, (lpOleObj==NULL) then disable the ** Edit.Object command. this helper API takes care of ** building the verb menu as appropriate. */ OleUIAddVerbMenu( (LPOLEOBJECT)lpOleObj, (lpContainerLine ? lpContainerLine->m_lpszShortType:NULL), hMenuEdit, POS_OBJECT, IDM_E_OBJECTVERBMIN, 0, // no uIDVerbMax enforced TRUE, // Add Convert menu item IDM_E_CONVERTVERB, // ID for Convert menu item (HMENU FAR*) &hMenuVerb ); #if defined( USE_STATUSBAR_LATER ) /* setup status messages for the object verb menu */ if (hMenuVerb) { // REVIEW: this string should come from a string resource. // REVIEW: this doesn't work for dynamically created menus AssignPopupMessage( hMenuVerb, "Open, edit or interact with an object" ); } #endif // USE_STATUSBAR_LATER } if (lpOleObj) OleStdRelease((LPUNKNOWN)lpOleObj); } #endif // OLE_CNTR // re-enable the Busy/NotResponding dialogs OleApp_EnableBusyDialogs(lpOleApp, fPrevEnable1, fPrevEnable2); OleDoc_SetUpdateEditMenuFlag(lpOleDoc, FALSE); OLEDBG_END3 } /* OleApp_RegisterClassFactory * --------------------------- * * Register our app's ClassFactory with OLE. * */ BOOL OleApp_RegisterClassFactory(LPOLEAPP lpOleApp) { HRESULT hrErr; if (lpOleApp->m_lpClassFactory) return TRUE; // already registered OLEDBG_BEGIN3("OleApp_RegisterClassFactory\r\n") /****************************************************************** ** An SDI app must register its ClassFactory if it is launched ** for embedding (/Embedding command line option specified). ** An MDI app must register its ClassFactory in all cases, ******************************************************************/ lpOleApp->m_lpClassFactory = AppClassFactory_Create(); if (! lpOleApp->m_lpClassFactory) { OutlineApp_ErrorMessage(g_lpApp, ErrMsgCreateCF); goto error; } OLEDBG_BEGIN2("CoRegisterClassObject called\r\n") hrErr = CoRegisterClassObject( &CLSID_APP, (LPUNKNOWN)lpOleApp->m_lpClassFactory, CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &lpOleApp->m_dwRegClassFac ); OLEDBG_END2 if(hrErr != NOERROR) { OleDbgOutHResult("CoRegisterClassObject returned", hrErr); OutlineApp_ErrorMessage(g_lpApp, ErrMsgRegCF); goto error; } OLEDBG_END3 return TRUE; error: if (lpOleApp->m_lpClassFactory) { OleStdRelease((LPUNKNOWN)lpOleApp->m_lpClassFactory); lpOleApp->m_lpClassFactory = NULL; } OLEDBG_END3 return FALSE; } /* OleApp_RevokeClassFactory * ------------------------- * * Revoke our app's ClassFactory. * */ void OleApp_RevokeClassFactory(LPOLEAPP lpOleApp) { HRESULT hrErr; if (lpOleApp->m_lpClassFactory) { OLEDBG_BEGIN2("CoRevokeClassObject called\r\n") hrErr = CoRevokeClassObject(lpOleApp->m_dwRegClassFac); OLEDBG_END2 #if defined( _DEBUG ) if (hrErr != NOERROR) { OleDbgOutHResult("CoRevokeClassObject returned", hrErr); } #endif // we just release here; other folks may still have // a pointer to our class factory, so we can't // do any checks on the reference count. OleStdRelease((LPUNKNOWN)lpOleApp->m_lpClassFactory); lpOleApp->m_lpClassFactory = NULL; } } #if defined( USE_MSGFILTER ) /* OleApp_RegisterMessageFilter * ---------------------------- * Register our IMessageFilter*. the message filter is used to handle * concurrency. we will use a standard implementation of IMessageFilter * that is included as part of the OLE2UI library. */ BOOL OleApp_RegisterMessageFilter(LPOLEAPP lpOleApp) { HRESULT hrErr; LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; if (lpOleApp->m_lpMsgFilter == NULL) { // Register our message filter. lpOleApp->m_lpfnMsgPending = (MSGPENDINGPROC)MessagePendingProc; lpOleApp->m_lpMsgFilter = OleStdMsgFilter_Create( g_lpApp->m_hWndApp, (LPSTR)APPNAME, lpOleApp->m_lpfnMsgPending, NULL /* Busy dialog callback hook function */ ); OLEDBG_BEGIN2("CoRegisterMessageFilter called\r\n") hrErr = CoRegisterMessageFilter( lpOleApp->m_lpMsgFilter, NULL /* don't need previous message filter */ ); OLEDBG_END2 if(hrErr != NOERROR) { OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgRegMF); return FALSE; } } return TRUE; } /* OleApp_RevokeMessageFilter * -------------------------- * Revoke our IMessageFilter*. the message filter is used to handle * concurrency. we will use a standard implementation of IMessageFilter * that is included as part of the OLE2UI library. */ void OleApp_RevokeMessageFilter(LPOLEAPP lpOleApp) { LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; if (lpOleApp->m_lpMsgFilter != NULL) { // Revoke our message filter OLEDBG_BEGIN2("CoRegisterMessageFilter(NULL) called\r\n") CoRegisterMessageFilter(NULL, NULL); OLEDBG_END2 if (lpOleApp->m_lpfnMsgPending) { lpOleApp->m_lpfnMsgPending = NULL; } OleStdVerifyRelease( (LPUNKNOWN)lpOleApp->m_lpMsgFilter, "Release MessageFilter FAILED!" ); lpOleApp->m_lpMsgFilter = NULL; } } /* MessagePendingProc * ------------------ * * Callback function for the IMessageFilter::MessagePending procedure. This * function is called when a message is received by our application while * we are waiting for an OLE call to complete. We are essentially * blocked at this point, waiting for a response from the other OLE application. * We should not process any messages which might cause another OLE call * to become blocked, or any other call which might cause re-entrancy problems. * * For this application, only process WM_PAINT messages. A more sophisticated * application might allow certain menu messages and menu items to be processed * also. * * RETURNS: TRUE if we processed the message, FALSE if we did not. */ BOOL FAR PASCAL EXPORT MessagePendingProc(MSG FAR *lpMsg) { // Our application is only handling WM_PAINT messages when we are blocked switch (lpMsg->message) { case WM_PAINT: OleDbgOut2("WM_PAINT dispatched while blocked\r\n"); DispatchMessage(lpMsg); break; } return FALSE; // return PENDINGMSG_WAITDEFPROCESS from MessagePending } #endif // USE_MSGFILTER /* OleApp_FlushClipboard * --------------------- * * Force the Windows clipboard to release our clipboard DataObject. */ void OleApp_FlushClipboard(LPOLEAPP lpOleApp) { LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; LPOLEDOC lpClipboardDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc; OLEDBG_BEGIN3("OleApp_FlushClipboard\r\n") /* OLE2NOTE: if for some reason our clipboard data transfer ** document is still held on to by an external client, we want ** to forceably break all external connections. */ OLEDBG_BEGIN2("CoDisconnectObject called\r\n") CoDisconnectObject((LPUNKNOWN)&lpClipboardDoc->m_Unknown, 0); OLEDBG_END2 OLEDBG_BEGIN2("OleFlushClipboard called\r\n") OleFlushClipboard(); OLEDBG_END2 lpOutlineApp->m_lpClipboardDoc = NULL; OLEDBG_END3 } /* OleApp_NewCommand * ----------------- * * Start a new untitled document (File.New command). */ void OleApp_NewCommand(LPOLEAPP lpOleApp) { LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; LPOUTLINEDOC lpOutlineDoc = lpOutlineApp->m_lpDoc; if (! OutlineDoc_Close(lpOutlineDoc, OLECLOSE_PROMPTSAVE)) return; OleDbgAssertSz(lpOutlineApp->m_lpDoc==NULL,"Closed doc NOT properly destroyed"); lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); if (! lpOutlineApp->m_lpDoc) goto error; /* OLE2NOTE: initially the Doc object is created with a 0 ref ** count. in order to have a stable Doc object during the ** process of initializing the new Doc instance, ** we intially AddRef the Doc ref cnt and later ** Release it. This initial AddRef is artificial; it is simply ** done to guarantee that a harmless QueryInterface followed by ** a Release does not inadvertantly force our object to destroy ** itself prematurely. */ OleDoc_AddRef((LPOLEDOC)lpOutlineApp->m_lpDoc); // set the doc to an (Untitled) doc. if (! OutlineDoc_InitNewFile(lpOutlineApp->m_lpDoc)) goto error; // position and size the new doc window OutlineApp_ResizeWindows(lpOutlineApp); OutlineDoc_ShowWindow(lpOutlineApp->m_lpDoc); // calls OleDoc_Lock OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); // rel artificial AddRef return; error: // REVIEW: should load string from string resource OutlineApp_ErrorMessage(lpOutlineApp, "Could not create new document"); if (lpOutlineApp->m_lpDoc) { // releasing the artificial AddRef above will destroy the document OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); lpOutlineApp->m_lpDoc = NULL; } return; } /* OleApp_OpenCommand * ------------------ * * Load a document from file (File.Open command). */ void OleApp_OpenCommand(LPOLEAPP lpOleApp) { LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; LPOUTLINEDOC lpOutlineDoc = lpOutlineApp->m_lpDoc; OPENFILENAME ofn; char szFilter[]=APPFILENAMEFILTER; char szFileName[256]; UINT i; DWORD dwSaveOption = OLECLOSE_PROMPTSAVE; BOOL fStatus = TRUE; if (! OutlineDoc_CheckSaveChanges(lpOutlineDoc, &dwSaveOption)) return; // abort opening new doc for(i=0; szFilter[i]; i++) if(szFilter[i]=='|') szFilter[i]='\0'; _fmemset((LPOPENFILENAME)&ofn,0,sizeof(OPENFILENAME)); szFileName[0]='\0'; ofn.lStructSize=sizeof(OPENFILENAME); ofn.hwndOwner=lpOutlineApp->m_hWndApp; ofn.lpstrFilter=(LPSTR)szFilter; ofn.lpstrFile=(LPSTR)szFileName; ofn.nMaxFile=sizeof(szFileName); ofn.Flags=OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; ofn.lpstrDefExt=DEFEXTENSION; OleApp_PreModalDialog(lpOleApp, (LPOLEDOC)lpOutlineApp->m_lpDoc); fStatus = GetOpenFileName((LPOPENFILENAME)&ofn); OleApp_PostModalDialog(lpOleApp, (LPOLEDOC)lpOutlineApp->m_lpDoc); if(! fStatus) return; // user canceled file open dialog OutlineDoc_Close(lpOutlineDoc, OLECLOSE_NOSAVE); OleDbgAssertSz(lpOutlineApp->m_lpDoc==NULL,"Closed doc NOT properly destroyed"); lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); if (! lpOutlineApp->m_lpDoc) goto error; /* OLE2NOTE: initially the Doc object is created with a 0 ref ** count. in order to have a stable Doc object during the ** process of initializing the new Doc instance, ** we intially AddRef the Doc ref cnt and later ** Release it. This initial AddRef is artificial; it is simply ** done to guarantee that a harmless QueryInterface followed by ** a Release does not inadvertantly force our object to destroy ** itself prematurely. */ OleDoc_AddRef((LPOLEDOC)lpOutlineApp->m_lpDoc); fStatus=OutlineDoc_LoadFromFile(lpOutlineApp->m_lpDoc, (LPSTR)szFileName); if (! fStatus) { // loading the doc failed; create an untitled instead // releasing the artificial AddRef above will destroy the document OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); if (! lpOutlineApp->m_lpDoc) goto error; OleDoc_AddRef((LPOLEDOC)lpOutlineApp->m_lpDoc); if (! OutlineDoc_InitNewFile(lpOutlineApp->m_lpDoc)) goto error; } // position and size the new doc window OutlineApp_ResizeWindows(lpOutlineApp); OutlineDoc_ShowWindow(lpOutlineApp->m_lpDoc); #if defined( OLE_CNTR ) UpdateWindow(lpOutlineApp->m_hWndApp); ContainerDoc_UpdateLinks((LPCONTAINERDOC)lpOutlineApp->m_lpDoc); #endif OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); // rel artificial AddRef return; error: // REVIEW: should load string from string resource OutlineApp_ErrorMessage(lpOutlineApp, "Could not create new document"); if (lpOutlineApp->m_lpDoc) { // releasing the artificial AddRef above will destroy the document OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); lpOutlineApp->m_lpDoc = NULL; } return; } #if defined( OLE_CNTR ) /* OLE2NOTE: forward the WM_QUERYNEWPALETTE message (via ** SendMessage) to UIActive in-place object if there is one. ** this gives the UIActive object the opportunity to select ** and realize its color palette as the FOREGROUND palette. ** this is optional for in-place containers. if a container ** prefers to force its color palette as the foreground ** palette then it should NOT forward the this message. or ** the container can give the UIActive object priority; if ** the UIActive object returns 0 from the WM_QUERYNEWPALETTE ** message (ie. it did not realize its own palette), then ** the container can realize its palette. ** (see ContainerDoc_ForwardPaletteChangedMsg for more info) ** ** (It is a good idea for containers to use the standard ** palette even if they do not use colors themselves. this ** will allow embedded object to get a good distribution of ** colors when they are being drawn by the container) ** */ LRESULT OleApp_QueryNewPalette(LPOLEAPP lpOleApp) { #if defined( INPLACE_CNTR ) LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOleApp; if (lpContainerApp && lpContainerApp->m_hWndUIActiveObj) { if (SendMessage(lpContainerApp->m_hWndUIActiveObj, WM_QUERYNEWPALETTE, (WPARAM)0, (LPARAM)0)) { /* Object selected its palette as foreground palette */ return (LRESULT)1; } } #endif // INPLACE_CNTR return wSelectPalette(((LPOUTLINEAPP)lpOleApp)->m_hWndApp, lpOleApp->m_hStdPal, FALSE/*fBackground*/); } #endif // OLE_CNTR /* This is just a helper routine */ LRESULT wSelectPalette(HWND hWnd, HPALETTE hPal, BOOL fBackground) { HDC hdc; HPALETTE hOldPal; UINT iPalChg = 0; if (hPal == 0) return (LRESULT)0; hdc = GetDC(hWnd); hOldPal = SelectPalette(hdc, hPal, fBackground); iPalChg = RealizePalette(hdc); SelectPalette(hdc, hOldPal, TRUE /*fBackground*/); ReleaseDC(hWnd, hdc); if (iPalChg > 0) InvalidateRect(hWnd, NULL, TRUE); return (LRESULT)1; } /************************************************************************* ** OleApp::IUnknown interface implementation *************************************************************************/ STDMETHODIMP OleApp_Unk_QueryInterface( LPUNKNOWN lpThis, REFIID riid, LPVOID FAR* lplpvObj ) { LPOLEAPP lpOleApp = ((struct CAppUnknownImpl FAR*)lpThis)->lpOleApp; return OleApp_QueryInterface(lpOleApp, riid, lplpvObj); } STDMETHODIMP_(ULONG) OleApp_Unk_AddRef(LPUNKNOWN lpThis) { LPOLEAPP lpOleApp = ((struct CAppUnknownImpl FAR*)lpThis)->lpOleApp; OleDbgAddRefMethod(lpThis, "IUnknown"); return OleApp_AddRef(lpOleApp); } STDMETHODIMP_(ULONG) OleApp_Unk_Release (LPUNKNOWN lpThis) { LPOLEAPP lpOleApp = ((struct CAppUnknownImpl FAR*)lpThis)->lpOleApp; OleDbgReleaseMethod(lpThis, "IUnknown"); return OleApp_Release(lpOleApp); } #if defined( OLE_SERVER ) /************************************************************************* ** ServerDoc Supprt Functions Used by Server versions *************************************************************************/ /* ServerApp_InitInstance * ---------------------- * * Initialize the app instance by creating the main frame window and * performing app instance specific initializations * (eg. initializing interface Vtbls). * * RETURNS: TRUE if the memory could be allocated, and the server app * was properly initialized. * FALSE otherwise * */ BOOL ServerApp_InitInstance( LPSERVERAPP lpServerApp, HINSTANCE hInst, int nCmdShow ) { LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp; LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp; /* Setup arrays used by IDataObject::EnumFormatEtc. ** ** OLE2NOTE: The order that the formats are listed for GetData is very ** significant. It should be listed in order of highest fidelity ** formats to least fidelity formats. A common ordering will be: ** 1. private app formats ** 2. EmbedSource ** 3. lower fidelity interchange formats ** 4. pictures (metafile, dib, etc.) ** (graphic-related apps offer pictures 1st!) ** 5. LinkSource */ /* m_arrDocGetFmts array enumerates the formats that a ServerDoc ** DataTransferDoc object can offer (give) through a ** IDataObject::GetData call. a ServerDoc DataTransferDoc offers ** data formats in the following order: ** 1. CF_OUTLINE ** 2. CF_EMBEDSOURCE ** 3. CF_OBJECTDESCRIPTOR ** 4. CF_TEXT ** 5. CF_METAFILEPICT ** 6. CF_LINKSOURCE * ** 7. CF_LINKSRCDESCRIPTOR * ** ** * NOTE: CF_LINKSOURCE and CF_LINKSRCDESCRIPTOR is only ** offered if the doc is able to give ** a Moniker which references the data. CF_LINKSOURCE is ** deliberately listed last in this array of possible formats. ** if the doc does not have a Moniker then the last element of ** this array is not used. (see SvrDoc_DataObj_EnumFormatEtc). ** ** NOTE: The list of formats that a USER ServerDoc document can ** offer is a static list and is registered in the registration ** database for the SVROUTL class. The ** IDataObject::EnumFormatEtc method returns OLE_S_USEREG in the ** case the document is a user docuemt (ie. created via ** File.New, File.Open, InsertObject in a container, or ** IPersistFile::Load during binding a link source). this tells ** OLE to enumerate the formats automatically using the data the ** the REGDB. */ lpOleApp->m_arrDocGetFmts[0].cfFormat = lpOutlineApp->m_cfOutline; lpOleApp->m_arrDocGetFmts[0].ptd = NULL; lpOleApp->m_arrDocGetFmts[0].dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrDocGetFmts[0].tymed = TYMED_HGLOBAL; lpOleApp->m_arrDocGetFmts[0].lindex = -1; lpOleApp->m_arrDocGetFmts[1].cfFormat = lpOleApp->m_cfEmbedSource; lpOleApp->m_arrDocGetFmts[1].ptd = NULL; lpOleApp->m_arrDocGetFmts[1].dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrDocGetFmts[1].tymed = TYMED_ISTORAGE; lpOleApp->m_arrDocGetFmts[1].lindex = -1; lpOleApp->m_arrDocGetFmts[2].cfFormat = CF_TEXT; lpOleApp->m_arrDocGetFmts[2].ptd = NULL; lpOleApp->m_arrDocGetFmts[2].dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrDocGetFmts[2].tymed = TYMED_HGLOBAL; lpOleApp->m_arrDocGetFmts[2].lindex = -1; lpOleApp->m_arrDocGetFmts[3].cfFormat = CF_METAFILEPICT; lpOleApp->m_arrDocGetFmts[3].ptd = NULL; lpOleApp->m_arrDocGetFmts[3].dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrDocGetFmts[3].tymed = TYMED_MFPICT; lpOleApp->m_arrDocGetFmts[3].lindex = -1; lpOleApp->m_arrDocGetFmts[4].cfFormat = lpOleApp->m_cfObjectDescriptor; lpOleApp->m_arrDocGetFmts[4].ptd = NULL; lpOleApp->m_arrDocGetFmts[4].dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrDocGetFmts[4].tymed = TYMED_HGLOBAL; lpOleApp->m_arrDocGetFmts[4].lindex = -1; lpOleApp->m_arrDocGetFmts[5].cfFormat = lpOleApp->m_cfLinkSource; lpOleApp->m_arrDocGetFmts[5].ptd = NULL; lpOleApp->m_arrDocGetFmts[5].dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrDocGetFmts[5].tymed = TYMED_ISTREAM; lpOleApp->m_arrDocGetFmts[5].lindex = -1; lpOleApp->m_arrDocGetFmts[6].cfFormat = lpOleApp->m_cfLinkSrcDescriptor; lpOleApp->m_arrDocGetFmts[6].ptd = NULL; lpOleApp->m_arrDocGetFmts[6].dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrDocGetFmts[6].tymed = TYMED_HGLOBAL; lpOleApp->m_arrDocGetFmts[6].lindex = -1; lpOleApp->m_nDocGetFmts = 7; /* m_arrPasteEntries array enumerates the formats that a ServerDoc ** object can accept (get) from the clipboard. ** The formats are listed in priority order. ** ServerDoc accept data formats in the following order: ** 1. CF_OUTLINE ** 2. CF_TEXT */ // REVIEW: strings should be loaded from string resource lpOleApp->m_arrPasteEntries[0].fmtetc.cfFormat =lpOutlineApp->m_cfOutline; lpOleApp->m_arrPasteEntries[0].fmtetc.ptd = NULL; lpOleApp->m_arrPasteEntries[0].fmtetc.dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrPasteEntries[0].fmtetc.tymed = TYMED_HGLOBAL; lpOleApp->m_arrPasteEntries[0].fmtetc.lindex = -1; lpOleApp->m_arrPasteEntries[0].lpstrFormatName = "Outline Data"; lpOleApp->m_arrPasteEntries[0].lpstrResultText = "Outline Data"; lpOleApp->m_arrPasteEntries[0].dwFlags = OLEUIPASTE_PASTEONLY; lpOleApp->m_arrPasteEntries[1].fmtetc.cfFormat = CF_TEXT; lpOleApp->m_arrPasteEntries[1].fmtetc.ptd = NULL; lpOleApp->m_arrPasteEntries[1].fmtetc.dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrPasteEntries[1].fmtetc.tymed = TYMED_HGLOBAL; lpOleApp->m_arrPasteEntries[1].fmtetc.lindex = -1; lpOleApp->m_arrPasteEntries[1].lpstrFormatName = "Text"; lpOleApp->m_arrPasteEntries[1].lpstrResultText = "text"; lpOleApp->m_arrPasteEntries[1].dwFlags = OLEUIPASTE_PASTEONLY; lpOleApp->m_nPasteEntries = 2; /** m_arrLinkTypes array enumerates the link types that a ServerDoc ** object can accept from the clipboard. ServerDoc does NOT ** accept any type of link from the clipboard. ServerDoc can ** only be the source of a link. it can not contain links. */ lpOleApp->m_nLinkTypes = 0; #if defined( INPLACE_SVR ) lpServerApp->m_hAccelBaseApp = NULL; lpServerApp->m_hAccelIPSvr = LoadAccelerators( hInst, "InPlaceSvrOutlAccel" ); lpServerApp->m_lpIPData = NULL; lpServerApp->m_hMenuEdit = GetSubMenu ( lpOutlineApp->m_hMenuApp, POS_EDITMENU ); lpServerApp->m_hMenuLine = GetSubMenu ( lpOutlineApp->m_hMenuApp, POS_LINEMENU ); lpServerApp->m_hMenuName = GetSubMenu ( lpOutlineApp->m_hMenuApp, POS_NAMEMENU ); lpServerApp->m_hMenuOptions = GetSubMenu ( lpOutlineApp->m_hMenuApp, POS_OPTIONSMENU ); lpServerApp->m_hMenuDebug = GetSubMenu ( lpOutlineApp->m_hMenuApp, POS_DEBUGMENU ); lpServerApp->m_hMenuHelp = GetSubMenu ( lpOutlineApp->m_hMenuApp, POS_HELPMENU ); #endif // INPLACE_SVR return TRUE; } /* ServerApp_InitVtbls * ------------------- * * initialize the methods in all of the interface Vtbl's * * OLE2NOTE: we only need one copy of each Vtbl. When an object which * exposes an interface is instantiated, its lpVtbl is intialized * to point to the single copy of the Vtbl. * */ BOOL ServerApp_InitVtbls (LPSERVERAPP lpServerApp) { BOOL fStatus; // ServerDoc::IOleObject method table OleStdInitVtbl(&g_SvrDoc_OleObjectVtbl, sizeof(IOleObjectVtbl)); g_SvrDoc_OleObjectVtbl.QueryInterface = SvrDoc_OleObj_QueryInterface; g_SvrDoc_OleObjectVtbl.AddRef = SvrDoc_OleObj_AddRef; g_SvrDoc_OleObjectVtbl.Release = SvrDoc_OleObj_Release; g_SvrDoc_OleObjectVtbl.SetClientSite = SvrDoc_OleObj_SetClientSite; g_SvrDoc_OleObjectVtbl.GetClientSite = SvrDoc_OleObj_GetClientSite; g_SvrDoc_OleObjectVtbl.SetHostNames = SvrDoc_OleObj_SetHostNames; g_SvrDoc_OleObjectVtbl.Close = SvrDoc_OleObj_Close; g_SvrDoc_OleObjectVtbl.SetMoniker = SvrDoc_OleObj_SetMoniker; g_SvrDoc_OleObjectVtbl.GetMoniker = SvrDoc_OleObj_GetMoniker; g_SvrDoc_OleObjectVtbl.InitFromData = SvrDoc_OleObj_InitFromData; g_SvrDoc_OleObjectVtbl.GetClipboardData = SvrDoc_OleObj_GetClipboardData; g_SvrDoc_OleObjectVtbl.DoVerb = SvrDoc_OleObj_DoVerb; g_SvrDoc_OleObjectVtbl.EnumVerbs = SvrDoc_OleObj_EnumVerbs; g_SvrDoc_OleObjectVtbl.Update = SvrDoc_OleObj_Update; g_SvrDoc_OleObjectVtbl.IsUpToDate = SvrDoc_OleObj_IsUpToDate; g_SvrDoc_OleObjectVtbl.GetUserClassID = SvrDoc_OleObj_GetUserClassID; g_SvrDoc_OleObjectVtbl.GetUserType = SvrDoc_OleObj_GetUserType; g_SvrDoc_OleObjectVtbl.SetExtent = SvrDoc_OleObj_SetExtent; g_SvrDoc_OleObjectVtbl.GetExtent = SvrDoc_OleObj_GetExtent; g_SvrDoc_OleObjectVtbl.Advise = SvrDoc_OleObj_Advise; g_SvrDoc_OleObjectVtbl.Unadvise = SvrDoc_OleObj_Unadvise; g_SvrDoc_OleObjectVtbl.EnumAdvise = SvrDoc_OleObj_EnumAdvise; g_SvrDoc_OleObjectVtbl.GetMiscStatus = SvrDoc_OleObj_GetMiscStatus; g_SvrDoc_OleObjectVtbl.SetColorScheme = SvrDoc_OleObj_SetColorScheme; fStatus = OleStdCheckVtbl( &g_SvrDoc_OleObjectVtbl, sizeof(IOleObjectVtbl), "IOleObject" ); if (! fStatus) return FALSE; // ServerDoc::IPersistStorage method table OleStdInitVtbl(&g_SvrDoc_PersistStorageVtbl, sizeof(IPersistStorageVtbl)); g_SvrDoc_PersistStorageVtbl.QueryInterface = SvrDoc_PStg_QueryInterface; g_SvrDoc_PersistStorageVtbl.AddRef = SvrDoc_PStg_AddRef; g_SvrDoc_PersistStorageVtbl.Release = SvrDoc_PStg_Release; g_SvrDoc_PersistStorageVtbl.GetClassID = SvrDoc_PStg_GetClassID; g_SvrDoc_PersistStorageVtbl.IsDirty = SvrDoc_PStg_IsDirty; g_SvrDoc_PersistStorageVtbl.InitNew = SvrDoc_PStg_InitNew; g_SvrDoc_PersistStorageVtbl.Load = SvrDoc_PStg_Load; g_SvrDoc_PersistStorageVtbl.Save = SvrDoc_PStg_Save; g_SvrDoc_PersistStorageVtbl.SaveCompleted = SvrDoc_PStg_SaveCompleted; g_SvrDoc_PersistStorageVtbl.HandsOffStorage = SvrDoc_PStg_HandsOffStorage; fStatus = OleStdCheckVtbl( &g_SvrDoc_PersistStorageVtbl, sizeof(IPersistStorageVtbl), "IPersistStorage" ); if (! fStatus) return FALSE; #if defined( SVR_TREATAS ) // ServerDoc::IStdMarshalInfo method table OleStdInitVtbl( &g_SvrDoc_StdMarshalInfoVtbl, sizeof(IStdMarshalInfoVtbl)); g_SvrDoc_StdMarshalInfoVtbl.QueryInterface = SvrDoc_StdMshl_QueryInterface; g_SvrDoc_StdMarshalInfoVtbl.AddRef = SvrDoc_StdMshl_AddRef; g_SvrDoc_StdMarshalInfoVtbl.Release = SvrDoc_StdMshl_Release; g_SvrDoc_StdMarshalInfoVtbl.GetClassForHandler = SvrDoc_StdMshl_GetClassForHandler; fStatus = OleStdCheckVtbl( &g_SvrDoc_StdMarshalInfoVtbl, sizeof(IStdMarshalInfoVtbl), "IStdMarshalInfo" ); if (! fStatus) return FALSE; #endif // SVR_TREATAS #if defined( INPLACE_SVR ) // ServerDoc::IOleInPlaceObject method table OleStdInitVtbl( &g_SvrDoc_OleInPlaceObjectVtbl, sizeof(IOleInPlaceObjectVtbl) ); g_SvrDoc_OleInPlaceObjectVtbl.QueryInterface = SvrDoc_IPObj_QueryInterface; g_SvrDoc_OleInPlaceObjectVtbl.AddRef = SvrDoc_IPObj_AddRef; g_SvrDoc_OleInPlaceObjectVtbl.Release = SvrDoc_IPObj_Release; g_SvrDoc_OleInPlaceObjectVtbl.GetWindow = SvrDoc_IPObj_GetWindow; g_SvrDoc_OleInPlaceObjectVtbl.ContextSensitiveHelp = SvrDoc_IPObj_ContextSensitiveHelp; g_SvrDoc_OleInPlaceObjectVtbl.InPlaceDeactivate = SvrDoc_IPObj_InPlaceDeactivate; g_SvrDoc_OleInPlaceObjectVtbl.UIDeactivate = SvrDoc_IPObj_UIDeactivate; g_SvrDoc_OleInPlaceObjectVtbl.SetObjectRects = SvrDoc_IPObj_SetObjectRects; g_SvrDoc_OleInPlaceObjectVtbl.ReactivateAndUndo = SvrDoc_IPObj_ReactivateAndUndo; fStatus = OleStdCheckVtbl( &g_SvrDoc_OleInPlaceObjectVtbl, sizeof(IOleInPlaceObjectVtbl), "IOleInPlaceObject" ); if (! fStatus) return FALSE; // ServerDoc::IOleInPlaceActiveObject method table OleStdInitVtbl( &g_SvrDoc_OleInPlaceActiveObjectVtbl, sizeof(IOleInPlaceActiveObjectVtbl) ); g_SvrDoc_OleInPlaceActiveObjectVtbl.QueryInterface = SvrDoc_IPActiveObj_QueryInterface; g_SvrDoc_OleInPlaceActiveObjectVtbl.AddRef = SvrDoc_IPActiveObj_AddRef; g_SvrDoc_OleInPlaceActiveObjectVtbl.Release = SvrDoc_IPActiveObj_Release; g_SvrDoc_OleInPlaceActiveObjectVtbl.GetWindow = SvrDoc_IPActiveObj_GetWindow; g_SvrDoc_OleInPlaceActiveObjectVtbl.ContextSensitiveHelp = SvrDoc_IPActiveObj_ContextSensitiveHelp; g_SvrDoc_OleInPlaceActiveObjectVtbl.TranslateAccelerator = SvrDoc_IPActiveObj_TranslateAccelerator; g_SvrDoc_OleInPlaceActiveObjectVtbl.OnFrameWindowActivate = SvrDoc_IPActiveObj_OnFrameWindowActivate; g_SvrDoc_OleInPlaceActiveObjectVtbl.OnDocWindowActivate = SvrDoc_IPActiveObj_OnDocWindowActivate; g_SvrDoc_OleInPlaceActiveObjectVtbl.ResizeBorder = SvrDoc_IPActiveObj_ResizeBorder; g_SvrDoc_OleInPlaceActiveObjectVtbl.EnableModeless = SvrDoc_IPActiveObj_EnableModeless; fStatus = OleStdCheckVtbl( &g_SvrDoc_OleInPlaceActiveObjectVtbl, sizeof(IOleInPlaceActiveObjectVtbl), "IOleInPlaceActiveObject" ); if (! fStatus) return FALSE; #endif // PseudoObj::IUnknown method table OleStdInitVtbl(&g_PseudoObj_UnknownVtbl, sizeof(IUnknownVtbl)); g_PseudoObj_UnknownVtbl.QueryInterface = PseudoObj_Unk_QueryInterface; g_PseudoObj_UnknownVtbl.AddRef = PseudoObj_Unk_AddRef; g_PseudoObj_UnknownVtbl.Release = PseudoObj_Unk_Release; fStatus = OleStdCheckVtbl( &g_PseudoObj_UnknownVtbl, sizeof(IUnknownVtbl), "IUnknown" ); if (! fStatus) return FALSE; // PseudoObj::IOleObject method table OleStdInitVtbl(&g_PseudoObj_OleObjectVtbl, sizeof(IOleObjectVtbl)); g_PseudoObj_OleObjectVtbl.QueryInterface= PseudoObj_OleObj_QueryInterface; g_PseudoObj_OleObjectVtbl.AddRef = PseudoObj_OleObj_AddRef; g_PseudoObj_OleObjectVtbl.Release = PseudoObj_OleObj_Release; g_PseudoObj_OleObjectVtbl.SetClientSite = PseudoObj_OleObj_SetClientSite; g_PseudoObj_OleObjectVtbl.GetClientSite = PseudoObj_OleObj_GetClientSite; g_PseudoObj_OleObjectVtbl.SetHostNames = PseudoObj_OleObj_SetHostNames; g_PseudoObj_OleObjectVtbl.Close = PseudoObj_OleObj_Close; g_PseudoObj_OleObjectVtbl.SetMoniker = PseudoObj_OleObj_SetMoniker; g_PseudoObj_OleObjectVtbl.GetMoniker = PseudoObj_OleObj_GetMoniker; g_PseudoObj_OleObjectVtbl.InitFromData = PseudoObj_OleObj_InitFromData; g_PseudoObj_OleObjectVtbl.GetClipboardData = PseudoObj_OleObj_GetClipboardData; g_PseudoObj_OleObjectVtbl.DoVerb = PseudoObj_OleObj_DoVerb; g_PseudoObj_OleObjectVtbl.EnumVerbs = PseudoObj_OleObj_EnumVerbs; g_PseudoObj_OleObjectVtbl.Update = PseudoObj_OleObj_Update; g_PseudoObj_OleObjectVtbl.IsUpToDate = PseudoObj_OleObj_IsUpToDate; g_PseudoObj_OleObjectVtbl.GetUserType = PseudoObj_OleObj_GetUserType; g_PseudoObj_OleObjectVtbl.GetUserClassID= PseudoObj_OleObj_GetUserClassID; g_PseudoObj_OleObjectVtbl.SetExtent = PseudoObj_OleObj_SetExtent; g_PseudoObj_OleObjectVtbl.GetExtent = PseudoObj_OleObj_GetExtent; g_PseudoObj_OleObjectVtbl.Advise = PseudoObj_OleObj_Advise; g_PseudoObj_OleObjectVtbl.Unadvise = PseudoObj_OleObj_Unadvise; g_PseudoObj_OleObjectVtbl.EnumAdvise = PseudoObj_OleObj_EnumAdvise; g_PseudoObj_OleObjectVtbl.GetMiscStatus = PseudoObj_OleObj_GetMiscStatus; g_PseudoObj_OleObjectVtbl.SetColorScheme= PseudoObj_OleObj_SetColorScheme; fStatus = OleStdCheckVtbl( &g_PseudoObj_OleObjectVtbl, sizeof(IOleObjectVtbl), "IOleObject" ); if (! fStatus) return FALSE; // ServerDoc::IDataObject method table OleStdInitVtbl(&g_PseudoObj_DataObjectVtbl, sizeof(IDataObjectVtbl)); g_PseudoObj_DataObjectVtbl.QueryInterface = PseudoObj_DataObj_QueryInterface; g_PseudoObj_DataObjectVtbl.AddRef = PseudoObj_DataObj_AddRef; g_PseudoObj_DataObjectVtbl.Release = PseudoObj_DataObj_Release; g_PseudoObj_DataObjectVtbl.GetData = PseudoObj_DataObj_GetData; g_PseudoObj_DataObjectVtbl.GetDataHere = PseudoObj_DataObj_GetDataHere; g_PseudoObj_DataObjectVtbl.QueryGetData = PseudoObj_DataObj_QueryGetData; g_PseudoObj_DataObjectVtbl.GetCanonicalFormatEtc = PseudoObj_DataObj_GetCanonicalFormatEtc; g_PseudoObj_DataObjectVtbl.SetData = PseudoObj_DataObj_SetData; g_PseudoObj_DataObjectVtbl.EnumFormatEtc= PseudoObj_DataObj_EnumFormatEtc; g_PseudoObj_DataObjectVtbl.DAdvise = PseudoObj_DataObj_DAdvise; g_PseudoObj_DataObjectVtbl.DUnadvise = PseudoObj_DataObj_DUnadvise; g_PseudoObj_DataObjectVtbl.EnumDAdvise = PseudoObj_DataObj_EnumAdvise; fStatus = OleStdCheckVtbl( &g_PseudoObj_DataObjectVtbl, sizeof(IDataObjectVtbl), "IDataObject" ); if (! fStatus) return FALSE; return TRUE; } #endif // OLE_SERVER #if defined( OLE_CNTR ) /************************************************************************* ** ContainerDoc Supprt Functions Used by Container versions *************************************************************************/ /* ContainerApp_InitInstance * ------------------------- * * Initialize the app instance by creating the main frame window and * performing app instance specific initializations * (eg. initializing interface Vtbls). * * RETURNS: TRUE if the memory could be allocated, and the server app * was properly initialized. * FALSE otherwise * */ BOOL ContainerApp_InitInstance( LPCONTAINERAPP lpContainerApp, HINSTANCE hInst, int nCmdShow ) { LPOLEAPP lpOleApp = (LPOLEAPP)lpContainerApp; LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpContainerApp; lpContainerApp->m_cfCntrOutl=RegisterClipboardFormat(CONTAINERDOCFORMAT); if(! lpContainerApp->m_cfCntrOutl) { // REVIEW: should load string from string resource OutlineApp_ErrorMessage(lpOutlineApp, "Can't register clipboard format!"); return FALSE; } #if defined( INPLACE_CNTR ) lpContainerApp->m_fPendingUIDeactivate = FALSE; lpContainerApp->m_fMustResizeClientArea = FALSE; lpContainerApp->m_lpIPActiveObj = NULL; lpContainerApp->m_hWndUIActiveObj = NULL; lpContainerApp->m_hAccelIPCntr = LoadAccelerators( hInst, "InPlaceCntrOutlAccel" ); lpContainerApp->m_hMenuFile = GetSubMenu ( lpOutlineApp->m_hMenuApp, POS_FILEMENU ); lpContainerApp->m_hMenuView = GetSubMenu ( lpOutlineApp->m_hMenuApp, POS_VIEWMENU ); lpContainerApp->m_hMenuDebug = GetSubMenu ( lpOutlineApp->m_hMenuApp, POS_DEBUGMENU ); INIT_INTERFACEIMPL( &lpContainerApp->m_OleInPlaceFrame, &g_CntrApp_OleInPlaceFrameVtbl, lpContainerApp ); #endif /* Setup arrays used by IDataObject::EnumFormatEtc. This is used to ** support copy/paste and drag/drop operations. ** ** OLE2NOTE: The order that the formats are listed for GetData is very ** significant. It should be listed in order of highest fidelity ** formats to least fidelity formats. A common ordering will be: ** 1. private app formats ** 2. CF_EMBEDSOURCE or CF_EMBEDOBJECT (as appropriate) ** 3. lower fidelity interchange formats ** 4. CF_METAFILEPICT ** (graphic-related apps might offer picture 1st!) ** 5. CF_OBJECTDESCRIPTOR ** 6. CF_LINKSOURCE ** 6. CF_LINKSRCDESCRIPTOR */ /* m_arrDocGetFmts array enumerates the formats that a ContainerDoc ** object can offer (give) through a IDataObject::GetData call ** when the selection copied is NOT a single embedded object. ** when a single embedded object this list of formats available ** is built dynamically depending on the object copied. (see ** ContainerDoc_SetupDocGetFmts). ** The formats are listed in priority order. ** ContainerDoc objects accept data formats in the following order: ** 1. CF_CNTROUTL ** 2. CF_OUTLINE ** 3. CF_TEXT ** 4. CF_OBJECTDESCRIPTOR ** ** OLE2NOTE: CF_OBJECTDESCRIPTOR format is used to describe the ** data on the clipboard. this information is intended to be ** used, for example, to drive the PasteSpecial dialog. it is ** useful to render CF_OBJECTDESCRIPTOR format even when the ** data on the clipboard does NOT include CF_EMBEDDEDOBJECT ** format or CF_EMBEDSOURCE format as when a selection that is ** not a single OLE object is copied from the container only ** version CNTROUTL. by rendering CF_OBJECTDESCRIPTOR format the ** app can indicate a useful string to identifiy the source of ** the copy to the user. */ lpOleApp->m_arrDocGetFmts[0].cfFormat = lpContainerApp->m_cfCntrOutl; lpOleApp->m_arrDocGetFmts[0].ptd = NULL; lpOleApp->m_arrDocGetFmts[0].dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrDocGetFmts[0].tymed = TYMED_ISTORAGE; lpOleApp->m_arrDocGetFmts[0].lindex = -1; lpOleApp->m_arrDocGetFmts[1].cfFormat = lpOutlineApp->m_cfOutline; lpOleApp->m_arrDocGetFmts[1].ptd = NULL; lpOleApp->m_arrDocGetFmts[1].dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrDocGetFmts[1].tymed = TYMED_HGLOBAL; lpOleApp->m_arrDocGetFmts[1].lindex = -1; lpOleApp->m_arrDocGetFmts[2].cfFormat = CF_TEXT; lpOleApp->m_arrDocGetFmts[2].ptd = NULL; lpOleApp->m_arrDocGetFmts[2].dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrDocGetFmts[2].tymed = TYMED_HGLOBAL; lpOleApp->m_arrDocGetFmts[2].lindex = -1; lpOleApp->m_arrDocGetFmts[3].cfFormat = lpOleApp->m_cfObjectDescriptor; lpOleApp->m_arrDocGetFmts[3].ptd = NULL; lpOleApp->m_arrDocGetFmts[3].dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrDocGetFmts[3].tymed = TYMED_HGLOBAL; lpOleApp->m_arrDocGetFmts[3].lindex = -1; lpOleApp->m_nDocGetFmts = 4; /* m_arrSingleObjGetFmts array enumerates the formats that a ** ContainerDoc object can offer (give) through a ** IDataObject::GetData call when the selection copied IS a ** single OLE object. ** ContainerDoc objects accept data formats in the following order: ** 1. CF_CNTROUTL ** 2. CF_EMBEDDEDOBJECT ** 3. CF_OBJECTDESCRIPTOR ** 4. CF_METAFILEPICT (note DVASPECT will vary) ** 5. CF_LINKSOURCE * ** 6. CF_LINKSRCDESCRIPTOR * ** ** * OLE2NOTE: CF_LINKSOURCE and CF_LINKSRCDESCRIPTOR is only ** offered if the OLE 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), then we want to offer ** CF_LINKSOURCE format. 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. ** the simplest way to determine if an object can be linked to ** on the inside is to call IOleObject::GetMiscStatus and test ** to see if the OLEMISC_CANTLINKINSIDE bit is NOT set. ** ** OLE2NOTE: optionally, a container that wants to have a ** potentially richer data transfer, can enumerate the data ** formats from the OLE object's cache and offer them too. if ** the object has a special handler, then it might be able to ** render additional data formats. */ lpContainerApp->m_arrSingleObjGetFmts[0].cfFormat = lpContainerApp->m_cfCntrOutl; lpContainerApp->m_arrSingleObjGetFmts[0].ptd = NULL; lpContainerApp->m_arrSingleObjGetFmts[0].dwAspect = DVASPECT_CONTENT; lpContainerApp->m_arrSingleObjGetFmts[0].tymed = TYMED_ISTORAGE; lpContainerApp->m_arrSingleObjGetFmts[0].lindex = -1; lpContainerApp->m_arrSingleObjGetFmts[1].cfFormat = lpOleApp->m_cfEmbeddedObject; lpContainerApp->m_arrSingleObjGetFmts[1].ptd = NULL; lpContainerApp->m_arrSingleObjGetFmts[1].dwAspect = DVASPECT_CONTENT; lpContainerApp->m_arrSingleObjGetFmts[1].tymed = TYMED_ISTORAGE; lpContainerApp->m_arrSingleObjGetFmts[1].lindex = -1; lpContainerApp->m_arrSingleObjGetFmts[2].cfFormat = lpOleApp->m_cfObjectDescriptor; lpContainerApp->m_arrSingleObjGetFmts[2].ptd = NULL; lpContainerApp->m_arrSingleObjGetFmts[2].dwAspect = DVASPECT_CONTENT; lpContainerApp->m_arrSingleObjGetFmts[2].tymed = TYMED_HGLOBAL; lpContainerApp->m_arrSingleObjGetFmts[2].lindex = -1; lpContainerApp->m_arrSingleObjGetFmts[3].cfFormat = CF_METAFILEPICT; lpContainerApp->m_arrSingleObjGetFmts[3].ptd = NULL; lpContainerApp->m_arrSingleObjGetFmts[3].dwAspect = DVASPECT_CONTENT; lpContainerApp->m_arrSingleObjGetFmts[3].tymed = TYMED_MFPICT; lpContainerApp->m_arrSingleObjGetFmts[3].lindex = -1; lpContainerApp->m_arrSingleObjGetFmts[4].cfFormat = lpOleApp->m_cfLinkSource; lpContainerApp->m_arrSingleObjGetFmts[4].ptd = NULL; lpContainerApp->m_arrSingleObjGetFmts[4].dwAspect = DVASPECT_CONTENT; lpContainerApp->m_arrSingleObjGetFmts[4].tymed = TYMED_ISTREAM; lpContainerApp->m_arrSingleObjGetFmts[4].lindex = -1; lpContainerApp->m_arrSingleObjGetFmts[5].cfFormat = lpOleApp->m_cfLinkSrcDescriptor; lpContainerApp->m_arrSingleObjGetFmts[5].ptd = NULL; lpContainerApp->m_arrSingleObjGetFmts[5].dwAspect = DVASPECT_CONTENT; lpContainerApp->m_arrSingleObjGetFmts[5].tymed = TYMED_HGLOBAL; lpContainerApp->m_arrSingleObjGetFmts[5].lindex = -1; lpContainerApp->m_nSingleObjGetFmts = 6; /* NOTE: the Container-Only version of Outline does NOT offer ** IDataObject interface from its User documents and the ** IDataObject interface available from DataTransferDoc's do NOT ** support SetData. IDataObject interface is required by objects ** which can be embedded or linked. the Container-only app only ** allows linking to its contained objects, NOT the data of the ** container itself. */ /* m_arrPasteEntries array enumerates the formats that a ContainerDoc ** object can accept from the clipboard. this array is used to ** support the PasteSpecial dialog. ** The formats are listed in priority order. ** ContainerDoc objects accept data formats in the following order: ** 1. CF_CNTROUTL ** 2. CF_OUTLINE ** 3. CF_EMBEDDEDOBJECT ** 4. CF_TEXT ** 5. CF_METAFILEPICT ** 6. CF_DIB ** 7. CF_BITMAP ** 8. CF_LINKSOURCE ** ** NOTE: specifying CF_EMBEDDEDOBJECT in the PasteEntry array ** indicates that the caller is interested in pasting OLE ** objects (ie. the caller calls OleCreateFromData). the ** OleUIPasteSpecial dialog and OleStdGetPriorityClipboardFormat ** call OleQueryCreateFromData to see if an OLE object format is ** available. thus, in fact if CF_EMBEDSOURCE or CF_FILENAME are ** available from the data source then and OLE object can be ** created and this entry will be matched. the caller should ** only specify one object type format. ** CF_FILENAME format (as generated by copying a file to ** the clipboard from the FileManager) is considered an object ** format; OleCreatFromData creates an object if the file has an ** associated class (see GetClassFile API) or if no class it ** creates an OLE 1.0 Package object. this format can also be ** paste linked by calling OleCreateLinkFromData. */ // REVIEW: strings should be loaded from string resource lpOleApp->m_arrPasteEntries[0].fmtetc.cfFormat = lpContainerApp->m_cfCntrOutl; lpOleApp->m_arrPasteEntries[0].fmtetc.ptd = NULL; lpOleApp->m_arrPasteEntries[0].fmtetc.dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrPasteEntries[0].fmtetc.tymed = TYMED_ISTORAGE; lpOleApp->m_arrPasteEntries[0].fmtetc.lindex = -1; lpOleApp->m_arrPasteEntries[0].lpstrFormatName = "Container Outline Data"; lpOleApp->m_arrPasteEntries[0].lpstrResultText = "Container Outline Data"; lpOleApp->m_arrPasteEntries[0].dwFlags = OLEUIPASTE_PASTEONLY; lpOleApp->m_arrPasteEntries[1].fmtetc.cfFormat =lpOutlineApp->m_cfOutline; lpOleApp->m_arrPasteEntries[1].fmtetc.ptd = NULL; lpOleApp->m_arrPasteEntries[1].fmtetc.dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrPasteEntries[1].fmtetc.tymed = TYMED_HGLOBAL; lpOleApp->m_arrPasteEntries[1].fmtetc.lindex = -1; lpOleApp->m_arrPasteEntries[1].lpstrFormatName = "Outline Data"; lpOleApp->m_arrPasteEntries[1].lpstrResultText = "Outline Data"; lpOleApp->m_arrPasteEntries[1].dwFlags = OLEUIPASTE_PASTEONLY; lpOleApp->m_arrPasteEntries[2].fmtetc.cfFormat = lpOleApp->m_cfEmbeddedObject; lpOleApp->m_arrPasteEntries[2].fmtetc.ptd = NULL; lpOleApp->m_arrPasteEntries[2].fmtetc.dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrPasteEntries[2].fmtetc.tymed = TYMED_ISTORAGE; lpOleApp->m_arrPasteEntries[2].fmtetc.lindex = -1; lpOleApp->m_arrPasteEntries[2].lpstrFormatName = "%s"; lpOleApp->m_arrPasteEntries[2].lpstrResultText = "%s"; lpOleApp->m_arrPasteEntries[2].dwFlags = OLEUIPASTE_PASTE | OLEUIPASTE_ENABLEICON; lpOleApp->m_arrPasteEntries[3].fmtetc.cfFormat = CF_TEXT; lpOleApp->m_arrPasteEntries[3].fmtetc.ptd = NULL; lpOleApp->m_arrPasteEntries[3].fmtetc.dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrPasteEntries[3].fmtetc.tymed = TYMED_HGLOBAL; lpOleApp->m_arrPasteEntries[3].fmtetc.lindex = -1; lpOleApp->m_arrPasteEntries[3].lpstrFormatName = "Text"; lpOleApp->m_arrPasteEntries[3].lpstrResultText = "text"; lpOleApp->m_arrPasteEntries[3].dwFlags = OLEUIPASTE_PASTEONLY; lpOleApp->m_arrPasteEntries[4].fmtetc.cfFormat = CF_METAFILEPICT; lpOleApp->m_arrPasteEntries[4].fmtetc.ptd = NULL; lpOleApp->m_arrPasteEntries[4].fmtetc.dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrPasteEntries[4].fmtetc.tymed = TYMED_MFPICT; lpOleApp->m_arrPasteEntries[4].fmtetc.lindex = -1; lpOleApp->m_arrPasteEntries[4].lpstrFormatName = "Picture (Metafile)"; lpOleApp->m_arrPasteEntries[4].lpstrResultText = "a static picture"; lpOleApp->m_arrPasteEntries[4].dwFlags = OLEUIPASTE_PASTEONLY; lpOleApp->m_arrPasteEntries[5].fmtetc.cfFormat = CF_DIB; lpOleApp->m_arrPasteEntries[5].fmtetc.ptd = NULL; lpOleApp->m_arrPasteEntries[5].fmtetc.dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrPasteEntries[5].fmtetc.tymed = TYMED_HGLOBAL; lpOleApp->m_arrPasteEntries[5].fmtetc.lindex = -1; lpOleApp->m_arrPasteEntries[5].lpstrFormatName = "Picture (DIB)"; lpOleApp->m_arrPasteEntries[5].lpstrResultText = "a static picture"; lpOleApp->m_arrPasteEntries[5].dwFlags = OLEUIPASTE_PASTEONLY; lpOleApp->m_arrPasteEntries[6].fmtetc.cfFormat = CF_BITMAP; lpOleApp->m_arrPasteEntries[6].fmtetc.ptd = NULL; lpOleApp->m_arrPasteEntries[6].fmtetc.dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrPasteEntries[6].fmtetc.tymed = TYMED_GDI; lpOleApp->m_arrPasteEntries[6].fmtetc.lindex = -1; lpOleApp->m_arrPasteEntries[6].lpstrFormatName = "Picture (Bitmap)"; lpOleApp->m_arrPasteEntries[6].lpstrResultText = "a static picture"; lpOleApp->m_arrPasteEntries[6].dwFlags = OLEUIPASTE_PASTEONLY; lpOleApp->m_arrPasteEntries[7].fmtetc.cfFormat = lpOleApp->m_cfLinkSource; lpOleApp->m_arrPasteEntries[7].fmtetc.ptd = NULL; lpOleApp->m_arrPasteEntries[7].fmtetc.dwAspect = DVASPECT_CONTENT; lpOleApp->m_arrPasteEntries[7].fmtetc.tymed = TYMED_ISTREAM; lpOleApp->m_arrPasteEntries[7].fmtetc.lindex = -1; lpOleApp->m_arrPasteEntries[7].lpstrFormatName = "%s"; lpOleApp->m_arrPasteEntries[7].lpstrResultText = "%s"; lpOleApp->m_arrPasteEntries[7].dwFlags = OLEUIPASTE_LINKTYPE1 | OLEUIPASTE_ENABLEICON; lpOleApp->m_nPasteEntries = 8; /* m_arrLinkTypes array enumerates the link types that a ContainerDoc ** object can accept from the clipboard */ lpOleApp->m_arrLinkTypes[0] = lpOleApp->m_cfLinkSource; lpOleApp->m_nLinkTypes = 1; return TRUE; } /* ContainerApp_InitVtbls ** ---------------------- ** ** initialize the interface Vtbl's used to support the OLE 2.0 ** Container functionality. */ BOOL ContainerApp_InitVtbls(LPCONTAINERAPP lpApp) { BOOL fStatus; // ContainerDoc::IOleUILinkContainer method table OleStdInitVtbl( &g_CntrDoc_OleUILinkContainerVtbl, sizeof(IOleUILinkContainerVtbl) ); g_CntrDoc_OleUILinkContainerVtbl.QueryInterface = CntrDoc_LinkCont_QueryInterface; g_CntrDoc_OleUILinkContainerVtbl.AddRef = CntrDoc_LinkCont_AddRef; g_CntrDoc_OleUILinkContainerVtbl.Release = CntrDoc_LinkCont_Release; g_CntrDoc_OleUILinkContainerVtbl.GetNextLink = CntrDoc_LinkCont_GetNextLink; g_CntrDoc_OleUILinkContainerVtbl.SetLinkUpdateOptions = CntrDoc_LinkCont_SetLinkUpdateOptions; g_CntrDoc_OleUILinkContainerVtbl.GetLinkUpdateOptions = CntrDoc_LinkCont_GetLinkUpdateOptions; g_CntrDoc_OleUILinkContainerVtbl.SetLinkSource = CntrDoc_LinkCont_SetLinkSource; g_CntrDoc_OleUILinkContainerVtbl.GetLinkSource = CntrDoc_LinkCont_GetLinkSource; g_CntrDoc_OleUILinkContainerVtbl.OpenLinkSource = CntrDoc_LinkCont_OpenLinkSource; g_CntrDoc_OleUILinkContainerVtbl.UpdateLink = CntrDoc_LinkCont_UpdateLink; g_CntrDoc_OleUILinkContainerVtbl.CancelLink = CntrDoc_LinkCont_CancelLink; fStatus = OleStdCheckVtbl( &g_CntrDoc_OleUILinkContainerVtbl, sizeof(IOleUILinkContainerVtbl), "IOleUILinkContainer" ); if (! fStatus) return FALSE; #if defined( INPLACE_CNTR ) // ContainerApp::IOleInPlaceFrame interface method table OleStdInitVtbl( &g_CntrApp_OleInPlaceFrameVtbl, sizeof(g_CntrApp_OleInPlaceFrameVtbl) ); g_CntrApp_OleInPlaceFrameVtbl.QueryInterface = CntrApp_IPFrame_QueryInterface; g_CntrApp_OleInPlaceFrameVtbl.AddRef = CntrApp_IPFrame_AddRef; g_CntrApp_OleInPlaceFrameVtbl.Release = CntrApp_IPFrame_Release; g_CntrApp_OleInPlaceFrameVtbl.GetWindow = CntrApp_IPFrame_GetWindow; g_CntrApp_OleInPlaceFrameVtbl.ContextSensitiveHelp = CntrApp_IPFrame_ContextSensitiveHelp; g_CntrApp_OleInPlaceFrameVtbl.GetBorder = CntrApp_IPFrame_GetBorder; g_CntrApp_OleInPlaceFrameVtbl.RequestBorderSpace = CntrApp_IPFrame_RequestBorderSpace; g_CntrApp_OleInPlaceFrameVtbl.SetBorderSpace = CntrApp_IPFrame_SetBorderSpace; g_CntrApp_OleInPlaceFrameVtbl.SetActiveObject = CntrApp_IPFrame_SetActiveObject; g_CntrApp_OleInPlaceFrameVtbl.InsertMenus = CntrApp_IPFrame_InsertMenus; g_CntrApp_OleInPlaceFrameVtbl.SetMenu = CntrApp_IPFrame_SetMenu; g_CntrApp_OleInPlaceFrameVtbl.RemoveMenus = CntrApp_IPFrame_RemoveMenus; g_CntrApp_OleInPlaceFrameVtbl.SetStatusText = CntrApp_IPFrame_SetStatusText; g_CntrApp_OleInPlaceFrameVtbl.EnableModeless = CntrApp_IPFrame_EnableModeless; g_CntrApp_OleInPlaceFrameVtbl.TranslateAccelerator = CntrApp_IPFrame_TranslateAccelerator; fStatus = OleStdCheckVtbl( &g_CntrApp_OleInPlaceFrameVtbl, sizeof(g_CntrApp_OleInPlaceFrameVtbl), "IOleInPlaceFrame" ); if (! fStatus) return FALSE; #endif // INPLACE_CNTR // ContainerLine::IUnknown interface method table OleStdInitVtbl( &g_CntrLine_UnknownVtbl, sizeof(g_CntrLine_UnknownVtbl) ); g_CntrLine_UnknownVtbl.QueryInterface = CntrLine_Unk_QueryInterface; g_CntrLine_UnknownVtbl.AddRef = CntrLine_Unk_AddRef; g_CntrLine_UnknownVtbl.Release = CntrLine_Unk_Release; fStatus = OleStdCheckVtbl( &g_CntrLine_UnknownVtbl, sizeof(g_CntrLine_UnknownVtbl), "IUnknown" ); if (! fStatus) return FALSE; // ContainerLine::IOleClientSite interface method table OleStdInitVtbl( &g_CntrLine_OleClientSiteVtbl, sizeof(g_CntrLine_OleClientSiteVtbl) ); g_CntrLine_OleClientSiteVtbl.QueryInterface = CntrLine_CliSite_QueryInterface; g_CntrLine_OleClientSiteVtbl.AddRef = CntrLine_CliSite_AddRef; g_CntrLine_OleClientSiteVtbl.Release = CntrLine_CliSite_Release; g_CntrLine_OleClientSiteVtbl.SaveObject = CntrLine_CliSite_SaveObject; g_CntrLine_OleClientSiteVtbl.GetMoniker = CntrLine_CliSite_GetMoniker; g_CntrLine_OleClientSiteVtbl.GetContainer = CntrLine_CliSite_GetContainer; g_CntrLine_OleClientSiteVtbl.ShowObject = CntrLine_CliSite_ShowObject; g_CntrLine_OleClientSiteVtbl.OnShowWindow = CntrLine_CliSite_OnShowWindow; g_CntrLine_OleClientSiteVtbl.RequestNewObjectLayout = CntrLine_CliSite_RequestNewObjectLayout; fStatus = OleStdCheckVtbl( &g_CntrLine_OleClientSiteVtbl, sizeof(g_CntrLine_OleClientSiteVtbl), "IOleClientSite" ); if (! fStatus) return FALSE; // ContainerLine::IAdviseSink interface method table OleStdInitVtbl( &g_CntrLine_AdviseSinkVtbl, sizeof(g_CntrLine_AdviseSinkVtbl) ); g_CntrLine_AdviseSinkVtbl.QueryInterface= CntrLine_AdvSink_QueryInterface; g_CntrLine_AdviseSinkVtbl.AddRef = CntrLine_AdvSink_AddRef; g_CntrLine_AdviseSinkVtbl.Release = CntrLine_AdvSink_Release; g_CntrLine_AdviseSinkVtbl.OnDataChange = CntrLine_AdvSink_OnDataChange; g_CntrLine_AdviseSinkVtbl.OnViewChange = CntrLine_AdvSink_OnViewChange; g_CntrLine_AdviseSinkVtbl.OnRename = CntrLine_AdvSink_OnRename; g_CntrLine_AdviseSinkVtbl.OnSave = CntrLine_AdvSink_OnSave; g_CntrLine_AdviseSinkVtbl.OnClose = CntrLine_AdvSink_OnClose; fStatus = OleStdCheckVtbl( &g_CntrLine_AdviseSinkVtbl, sizeof(g_CntrLine_AdviseSinkVtbl), "IAdviseSink" ); if (! fStatus) return FALSE; #if defined( INPLACE_CNTR ) // ContainerLine::IOleInPlaceSite interface method table OleStdInitVtbl( &g_CntrLine_OleInPlaceSiteVtbl, sizeof(g_CntrLine_OleInPlaceSiteVtbl) ); g_CntrLine_OleInPlaceSiteVtbl.QueryInterface = CntrLine_IPSite_QueryInterface; g_CntrLine_OleInPlaceSiteVtbl.AddRef = CntrLine_IPSite_AddRef; g_CntrLine_OleInPlaceSiteVtbl.Release = CntrLine_IPSite_Release; g_CntrLine_OleInPlaceSiteVtbl.GetWindow = CntrLine_IPSite_GetWindow; g_CntrLine_OleInPlaceSiteVtbl.ContextSensitiveHelp = CntrLine_IPSite_ContextSensitiveHelp; g_CntrLine_OleInPlaceSiteVtbl.CanInPlaceActivate = CntrLine_IPSite_CanInPlaceActivate; g_CntrLine_OleInPlaceSiteVtbl.OnInPlaceActivate = CntrLine_IPSite_OnInPlaceActivate; g_CntrLine_OleInPlaceSiteVtbl.OnUIActivate = CntrLine_IPSite_OnUIActivate; g_CntrLine_OleInPlaceSiteVtbl.GetWindowContext = CntrLine_IPSite_GetWindowContext; g_CntrLine_OleInPlaceSiteVtbl.Scroll = CntrLine_IPSite_Scroll; g_CntrLine_OleInPlaceSiteVtbl.OnUIDeactivate = CntrLine_IPSite_OnUIDeactivate; g_CntrLine_OleInPlaceSiteVtbl.OnInPlaceDeactivate = CntrLine_IPSite_OnInPlaceDeactivate; g_CntrLine_OleInPlaceSiteVtbl.DiscardUndoState = CntrLine_IPSite_DiscardUndoState; g_CntrLine_OleInPlaceSiteVtbl.DeactivateAndUndo = CntrLine_IPSite_DeactivateAndUndo; g_CntrLine_OleInPlaceSiteVtbl.OnPosRectChange = CntrLine_IPSite_OnPosRectChange; fStatus = OleStdCheckVtbl( &g_CntrLine_OleInPlaceSiteVtbl, sizeof(g_CntrLine_OleInPlaceSiteVtbl), "IOleInPlaceSite" ); if (! fStatus) return FALSE; #endif // INPLACE_CNTR return TRUE; } #endif // OLE_CNTR