Annotation of mstools/ole20/samples/outline/linking.c, revision 1.1

1.1     ! root        1: /*************************************************************************
        !             2: ** 
        !             3: **    OLE 2 Sample Code
        !             4: **    
        !             5: **    linking.c
        !             6: **    
        !             7: **    This file contains the major interfaces, methods and related support
        !             8: **    functions for implementing linking to items. The code
        !             9: **    contained in this file is used by BOTH the Container and Server
        !            10: **    (Object) versions of the Outline sample code. 
        !            11: **    
        !            12: **    As a server SVROUTL supports linking to the whole document object
        !            13: **    (either a file-based document or as an embedded object). It also
        !            14: **    supports linking to ranges (or PseudoObjects). 
        !            15: **    
        !            16: **    As a container CNTROUTL supports linking to embedded objects.
        !            17: **    (see file svrpsobj.c for Pseudo Object implementation)
        !            18: **    
        !            19: **    OleDoc Object
        !            20: **      exposed interfaces:
        !            21: **          IPersistFile
        !            22: **          IOleItemContainer
        !            23: **    
        !            24: **    (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
        !            25: **
        !            26: *************************************************************************/
        !            27: 
        !            28: #include "outline.h"
        !            29: 
        !            30: OLEDBGDATA
        !            31: 
        !            32: extern LPOUTLINEAPP             g_lpApp;
        !            33: 
        !            34: 
        !            35: 
        !            36: /*************************************************************************
        !            37: ** OleDoc::IPersistFile interface implementation
        !            38: *************************************************************************/
        !            39: 
        !            40: STDMETHODIMP OleDoc_PFile_QueryInterface(
        !            41:         LPPERSISTFILE       lpThis,
        !            42:         REFIID              riid,
        !            43:         LPVOID FAR*         lplpvObj
        !            44: )
        !            45: {
        !            46:     LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
        !            47: 
        !            48:     return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);
        !            49: }
        !            50: 
        !            51: 
        !            52: STDMETHODIMP_(ULONG) OleDoc_PFile_AddRef(LPPERSISTFILE lpThis)
        !            53: {
        !            54:     LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
        !            55: 
        !            56:     OleDbgAddRefMethod(lpThis, "IPersistFile");
        !            57: 
        !            58:     return OleDoc_AddRef(lpOleDoc);
        !            59: }
        !            60: 
        !            61: 
        !            62: STDMETHODIMP_(ULONG) OleDoc_PFile_Release (LPPERSISTFILE lpThis)
        !            63: {
        !            64:     LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
        !            65: 
        !            66:     OleDbgReleaseMethod(lpThis, "IPersistFile");
        !            67: 
        !            68:     return OleDoc_Release(lpOleDoc);
        !            69: }
        !            70: 
        !            71: 
        !            72: STDMETHODIMP OleDoc_PFile_GetClassID (
        !            73:         LPPERSISTFILE       lpThis,
        !            74:         CLSID FAR*          lpclsid
        !            75: )
        !            76: {
        !            77:     LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
        !            78:     LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
        !            79: 
        !            80:     OleDbgOut2("OleDoc_PFile_GetClassID\r\n");
        !            81: 
        !            82: #if defined( OLE_SERVER ) && defined( SVR_TREATAS )
        !            83: 
        !            84:     /* OLE2NOTE: we must be carefull to return the correct CLSID here.
        !            85:     **    if we are currently preforming a "TreatAs (aka. ActivateAs)"
        !            86:     **    operation then we need to return the class of the object
        !            87:     **    written in the storage of the object. otherwise we would
        !            88:     **    return our own class id. 
        !            89:     */
        !            90:     return ServerDoc_GetClassID((LPSERVERDOC)lpOleDoc, lpclsid);
        !            91: #else
        !            92:     *lpclsid = CLSID_APP;
        !            93: #endif 
        !            94:     return NOERROR;
        !            95: }
        !            96: 
        !            97: 
        !            98: STDMETHODIMP  OleDoc_PFile_IsDirty(LPPERSISTFILE lpThis)
        !            99: {
        !           100:     LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
        !           101: 
        !           102:     OleDbgOut2("OleDoc_PFile_IsDirty\r\n");
        !           103: 
        !           104:     if (OutlineDoc_IsModified((LPOUTLINEDOC)lpOleDoc))
        !           105:         return NOERROR;
        !           106:     else
        !           107:         return ResultFromScode(S_FALSE);
        !           108: }
        !           109: 
        !           110: 
        !           111: STDMETHODIMP OleDoc_PFile_Load (
        !           112:         LPPERSISTFILE       lpThis,
        !           113:         LPCSTR              lpszFileName,
        !           114:         DWORD               grfMode
        !           115: )
        !           116: {
        !           117:     LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
        !           118:     SCODE sc;
        !           119: 
        !           120:     OLEDBG_BEGIN2("OleDoc_PFile_Load\r\n")
        !           121: 
        !           122:     /* OLE2NOTE: grfMode passed from the caller indicates if the caller
        !           123:     **    needs Read or ReadWrite permissions. if appropriate the
        !           124:     **    callee should open the file with the requested permissions.
        !           125:     **    the caller will normally not impose sharing permissions.
        !           126:     **    
        !           127:     **    the sample code currently always opens its file ReadWrite.
        !           128:     */
        !           129: 
        !           130:     if (OutlineDoc_LoadFromFile((LPOUTLINEDOC)lpOleDoc, (LPSTR)lpszFileName))
        !           131:         sc = S_OK;
        !           132:     else
        !           133:         sc = S_FALSE;
        !           134: 
        !           135:     OLEDBG_END2
        !           136:     return ResultFromScode(sc);
        !           137: }
        !           138: 
        !           139: 
        !           140: STDMETHODIMP OleDoc_PFile_Save (
        !           141:         LPPERSISTFILE       lpThis,
        !           142:         LPCSTR              lpszFileName,
        !           143:         BOOL                fRemember
        !           144: )
        !           145: {
        !           146:     LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
        !           147:     LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
        !           148:     SCODE sc;
        !           149: 
        !           150:     OLEDBG_BEGIN2("OleDoc_PFile_Save\r\n")
        !           151: 
        !           152:     /* OLE2NOTE: it is only legal to perform a Save or SaveAs operation
        !           153:     **    on a file-based document. if the document is an embedded
        !           154:     **    object then we can not be changed to a file-base object.
        !           155:     **    
        !           156:     **      fRemember   lpszFileName     Type of Save    
        !           157:     **    ----------------------------------------------
        !           158:     **        N/A         NULL           SAVE            
        !           159:     **        TRUE        ! NULL         SAVE AS         
        !           160:     **        FALSE       ! NULL         SAVE COPY AS    
        !           161:     */
        !           162:     if ( (lpszFileName==NULL || (lpszFileName != NULL && fRemember))
        !           163:             && ((lpOutlineDoc->m_docInitType != DOCTYPE_FROMFILE 
        !           164:                 && lpOutlineDoc->m_docInitType != DOCTYPE_NEW)) ) {
        !           165:         OLEDBG_END2
        !           166:         return ResultFromScode(E_INVALIDARG);
        !           167:     }
        !           168: 
        !           169:     if (OutlineDoc_SaveToFile(
        !           170:             (LPOUTLINEDOC)lpOleDoc,
        !           171:             lpszFileName,
        !           172:             lpOutlineDoc->m_cfSaveFormat,
        !           173:             fRemember)) {
        !           174:         sc = S_OK;
        !           175:     } else
        !           176:         sc = E_FAIL;
        !           177: 
        !           178:     OLEDBG_END2
        !           179:     return ResultFromScode(sc);
        !           180: }
        !           181: 
        !           182: 
        !           183: STDMETHODIMP OleDoc_PFile_SaveCompleted (
        !           184:         LPPERSISTFILE       lpThis,
        !           185:         LPCSTR              lpszFileName
        !           186: )
        !           187: {
        !           188:     LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
        !           189:     LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
        !           190: 
        !           191:     OLEDBG_BEGIN2("OleDoc_PFile_SaveCompleted\r\n")
        !           192: 
        !           193:     /* OLE2NOTE: this method should be called in the Save or SaveAs 
        !           194:     **    situtations. it is illegal to call this method unless we are a 
        !           195:     **    file-based object (we should also NOT be of type DOCTYPE_NEW
        !           196:     **    either because IPersistFile::Save should have been called by
        !           197:     **    now.
        !           198:     */
        !           199:     if (lpOutlineDoc->m_docInitType != DOCTYPE_FROMFILE) {
        !           200:         OLEDBG_END2
        !           201:         return ResultFromScode(E_INVALIDARG);
        !           202:     }
        !           203: 
        !           204:     // Clear dirty flag upon save or saveAs
        !           205:     OutlineDoc_SetModified(lpOutlineDoc, FALSE, FALSE, FALSE);
        !           206: 
        !           207: #if defined( OLE_SERVER )
        !           208: 
        !           209:     /* OLE2NOTE: this method should be called in the Save or SaveAs 
        !           210:     **    situtations. it informs us that the caller is done with the data
        !           211:     **    in the file. Until SaveCompleted call is finished, we may not 
        !           212:     **    change the contents of the file. since we do not normally
        !           213:     **    scribble in our file, we do not have to care about this.
        !           214:     */
        !           215:     ServerDoc_SendAdvise (
        !           216:             (LPSERVERDOC)lpOleDoc, 
        !           217:             OLE_ONSAVE, 
        !           218:             NULL,      /* lpmkDoc -- not relevant here */
        !           219:             0          /* advf -- not relevant here */
        !           220:     );
        !           221: 
        !           222: #endif  // OLE_SERVER
        !           223: 
        !           224:     OLEDBG_END2
        !           225:     return NOERROR;
        !           226: }
        !           227: 
        !           228: 
        !           229: STDMETHODIMP OleDoc_PFile_GetCurFile (
        !           230:         LPPERSISTFILE   lpThis,
        !           231:         LPSTR FAR*      lplpszFileName
        !           232: )
        !           233: {
        !           234:     LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
        !           235:     LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
        !           236:     LPMALLOC lpMalloc;
        !           237:     LPSTR lpsz;
        !           238:     SCODE sc;
        !           239: 
        !           240:     OleDbgOut2("OleDoc_PFile_GetCurFile\r\n");
        !           241: 
        !           242:     /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */
        !           243:     *lplpszFileName = NULL;
        !           244: 
        !           245:     /*********************************************************************
        !           246:     ** OLE2NOTE: memory returned for the lplpszFileName must be
        !           247:     **    allocated appropriately using the current registered IMalloc
        !           248:     **    interface. the allows the ownership of the memory to be
        !           249:     **    passed to the caller (even if in another process).
        !           250:     *********************************************************************/
        !           251: 
        !           252:     CoGetMalloc(MEMCTX_TASK, &lpMalloc);
        !           253:     if (! lpMalloc) {
        !           254:         return ResultFromScode(E_FAIL);
        !           255:     }
        !           256: 
        !           257:     if (lpOutlineDoc->m_docInitType == DOCTYPE_FROMFILE) {
        !           258:         /* valid filename associated; return file name */
        !           259:         lpsz = (LPSTR)lpMalloc->lpVtbl->Alloc(
        !           260:                 lpMalloc,
        !           261:                 lstrlen((LPSTR)lpOutlineDoc->m_szFileName)+1
        !           262:         );
        !           263:         lstrcpy(lpsz, (LPSTR)lpOutlineDoc->m_szFileName);
        !           264:         sc = S_OK;
        !           265:     } else {
        !           266:         /* no file associated; return default file name prompt */
        !           267:         lpsz=(LPSTR)lpMalloc->lpVtbl->Alloc(lpMalloc, sizeof(DEFEXTENSION)+3);
        !           268:         wsprintf(lpsz, "*.%s", DEFEXTENSION);
        !           269:         sc = S_FALSE;
        !           270:     }
        !           271: 
        !           272:     OleStdRelease((LPUNKNOWN)lpMalloc);
        !           273:     *lplpszFileName = lpsz;
        !           274:     return ResultFromScode(sc);
        !           275: }
        !           276: 
        !           277: 
        !           278: /*************************************************************************
        !           279: ** OleDoc::IOleItemContainer interface implementation
        !           280: *************************************************************************/
        !           281: 
        !           282: STDMETHODIMP OleDoc_ItemCont_QueryInterface(
        !           283:         LPOLEITEMCONTAINER  lpThis,
        !           284:         REFIID              riid,
        !           285:         LPVOID FAR*         lplpvObj
        !           286: )
        !           287: {
        !           288:     LPOLEDOC lpOleDoc =
        !           289:             ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
        !           290: 
        !           291:     return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);
        !           292: }
        !           293: 
        !           294: 
        !           295: STDMETHODIMP_(ULONG) OleDoc_ItemCont_AddRef(LPOLEITEMCONTAINER lpThis)
        !           296: {
        !           297:     LPOLEDOC lpOleDoc =
        !           298:             ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
        !           299: 
        !           300:     OleDbgAddRefMethod(lpThis, "IOleItemContainer");
        !           301: 
        !           302:     return OleDoc_AddRef((LPOLEDOC)lpOleDoc);
        !           303: }
        !           304: 
        !           305: 
        !           306: STDMETHODIMP_(ULONG) OleDoc_ItemCont_Release(LPOLEITEMCONTAINER lpThis)
        !           307: {
        !           308:     LPOLEDOC lpOleDoc =
        !           309:             ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
        !           310: 
        !           311:     OleDbgReleaseMethod(lpThis, "IOleItemContainer");
        !           312: 
        !           313:     return OleDoc_Release((LPOLEDOC)lpOleDoc);
        !           314: }
        !           315: 
        !           316: 
        !           317: STDMETHODIMP OleDoc_ItemCont_ParseDisplayName(
        !           318:         LPOLEITEMCONTAINER  lpThis,
        !           319:         LPBC                lpbc,
        !           320:         LPSTR               lpszDisplayName,
        !           321:         ULONG FAR*          lpchEaten,
        !           322:         LPMONIKER FAR*      lplpmkOut
        !           323: )
        !           324: {
        !           325:     LPOLEDOC lpOleDoc =
        !           326:             ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
        !           327:     char szItemName[MAXNAMESIZE];
        !           328:     LPUNKNOWN lpUnk;
        !           329:     HRESULT hrErr;
        !           330: 
        !           331:     OleDbgOut2("OleDoc_ItemCont_ParseDisplayName\r\n");
        !           332: 
        !           333:     /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */
        !           334:     *lplpmkOut = NULL;
        !           335: 
        !           336:     *lpchEaten = OleStdGetItemToken(
        !           337:             lpszDisplayName,
        !           338:             szItemName,
        !           339:             sizeof(szItemName)
        !           340:     );
        !           341: 
        !           342:     /* OLE2NOTE: get a pointer to a running instance of the object. we
        !           343:     **    should force the object to go running if necessary (even if
        !           344:     **    this means launching its server EXE). this is the meaining of
        !           345:     **    BINDSPEED_INDEFINITE. Parsing a Moniker is known to be an
        !           346:     **    "EXPENSIVE" operation.
        !           347:     */
        !           348:     hrErr = OleDoc_ItemCont_GetObject(
        !           349:             lpThis, 
        !           350:             szItemName, 
        !           351:             BINDSPEED_INDEFINITE,
        !           352:             lpbc, 
        !           353:             &IID_IUnknown,
        !           354:             (LPVOID FAR*)&lpUnk
        !           355:     );
        !           356: 
        !           357:     if (hrErr == NOERROR) {
        !           358:         OleStdRelease(lpUnk);   // item name FOUND; don't need obj ptr.
        !           359:         CreateItemMoniker(OLESTDDELIM, szItemName, lplpmkOut);
        !           360:     } else
        !           361:         *lpchEaten = 0;     // item name is NOT valid
        !           362: 
        !           363:     return hrErr;
        !           364: }
        !           365: 
        !           366: 
        !           367: STDMETHODIMP OleDoc_ItemCont_EnumObjects(
        !           368:         LPOLEITEMCONTAINER  lpThis,
        !           369:         DWORD               grfFlags,
        !           370:         LPENUMUNKNOWN FAR*  lplpenumUnknown
        !           371: )
        !           372: {
        !           373:     LPOLEDOC lpOleDoc =
        !           374:             ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
        !           375: 
        !           376:     OLEDBG_BEGIN2("OleDoc_ItemCont_EnumObjects\r\n")
        !           377: 
        !           378:     /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */
        !           379:     *lplpenumUnknown = NULL;
        !           380: 
        !           381:     /* OLE2NOTE: this method should be implemented to allow programatic
        !           382:     **    clients the ability to what elements the container holds.
        !           383:     **    this method is NOT called in the standard linking scenarios.
        !           384:     **    
        !           385:     **    grfFlags can be one of the following:
        !           386:     **        OLECONTF_EMBEDDINGS   -- enumerate embedded objects
        !           387:     **        OLECONTF_LINKS        -- enumerate linked objects
        !           388:     **        OLECONTF_OTHERS       -- enumerate non-OLE compound doc objs
        !           389:     **        OLECONTF_ONLYUSER     -- enumerate only objs named by user
        !           390:     **        OLECONTF_ONLYIFRUNNING-- enumerate only objs in running state
        !           391:     */
        !           392: 
        !           393:     OleDbgAssertSz(0, "NOT YET IMPLEMENTED!");
        !           394: 
        !           395:     OLEDBG_END2
        !           396:     return ResultFromScode(E_NOTIMPL);
        !           397: }
        !           398: 
        !           399: 
        !           400: STDMETHODIMP OleDoc_ItemCont_LockContainer(
        !           401:         LPOLEITEMCONTAINER  lpThis,
        !           402:         BOOL                fLock
        !           403: )
        !           404: {
        !           405:     LPOLEDOC lpOleDoc =
        !           406:             ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
        !           407:     HRESULT hrErr;
        !           408: 
        !           409:     OLEDBG_BEGIN2("OleDoc_ItemCont_LockContainer\r\n")
        !           410: 
        !           411: #if defined( _DEBUG )
        !           412:     if (fLock) {
        !           413:         ++lpOleDoc->m_cLock;
        !           414: 
        !           415:         OleDbgOutRefCnt3(
        !           416:                 "OleDoc_ItemCont_LockContainer: cLock++\r\n", 
        !           417:                 lpOleDoc, lpOleDoc->m_cLock);
        !           418:     } else {
        !           419: 
        !           420:         /* OLE2NOTE: when there are no open documents and the app is not
        !           421:         **    under the control of the user and there are no outstanding
        !           422:         **    locks on the app, then revoke our ClassFactory to enable the
        !           423:         **    app to shut down.
        !           424:         */
        !           425:         OleDbgAssertSz (lpOleDoc->m_cLock > 0,
        !           426:                 "OleDoc_ItemCont_LockContainer(FALSE) called with cLock == 0"
        !           427:         );
        !           428: 
        !           429:         --lpOleDoc->m_cLock;
        !           430: 
        !           431:         if (lpOleDoc->m_cLock == 0) {
        !           432:             OleDbgOutRefCnt2(
        !           433:                     "OleDoc_ItemCont_LockContainer: UNLOCKED\r\n", 
        !           434:                     lpOleDoc, lpOleDoc->m_cLock);
        !           435:         } else {
        !           436:             OleDbgOutRefCnt3(
        !           437:                     "OleDoc_ItemCont_LockContainer: cLock--\r\n",
        !           438:                     lpOleDoc, lpOleDoc->m_cLock);
        !           439:         }
        !           440:     }
        !           441: #endif  // _DEBUG
        !           442:         
        !           443:     /* OLE2NOTE: in order to hold the document alive we call
        !           444:     **    CoLockObjectExternal to add a strong reference to our Doc
        !           445:     **    object. this will keep the Doc alive when all other external
        !           446:     **    references release us. whenever an embedded object goes
        !           447:     **    running a LockContainer(TRUE) is called. when the embedded
        !           448:     **    object shuts down (ie. transitions from running to loaded)
        !           449:     **    LockContainer(FALSE) is called. if the user issues File.Close
        !           450:     **    the document will shut down in any case ignoring any
        !           451:     **    outstanding LockContainer locks because CoDisconnectObject is
        !           452:     **    called in OleDoc_Close. this will forceably break any
        !           453:     **    existing strong reference counts including counts that we add
        !           454:     **    ourselves by calling CoLockObjectExternal and guarantee that
        !           455:     **    the Doc object gets its final release (ie. cRefs goes to 0).
        !           456:     */
        !           457:     hrErr = OleDoc_Lock(lpOleDoc, fLock, TRUE /* fLastUnlockReleases */);
        !           458: 
        !           459:     OLEDBG_END2
        !           460:     return hrErr;
        !           461: }
        !           462: 
        !           463: 
        !           464: STDMETHODIMP OleDoc_ItemCont_GetObject(
        !           465:         LPOLEITEMCONTAINER  lpThis,
        !           466:         LPSTR               lpszItem,
        !           467:         DWORD               dwSpeedNeeded,
        !           468:         LPBINDCTX           lpbc,
        !           469:         REFIID              riid,
        !           470:         LPVOID FAR*         lplpvObject
        !           471: )
        !           472: {
        !           473:     LPOLEDOC lpOleDoc =
        !           474:             ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
        !           475:     HRESULT hrErr;
        !           476: 
        !           477:     OLEDBG_BEGIN2("OleDoc_ItemCont_GetObject\r\n")
        !           478: 
        !           479:     /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */
        !           480:     *lplpvObject = NULL;
        !           481: 
        !           482: #if defined( OLE_SERVER )
        !           483: 
        !           484:     /* OLE2NOTE: SERVER ONLY version should return PseudoObjects with
        !           485:     **    BINDSPEED_IMMEDIATE, thus the dwSpeedNeeded is not important
        !           486:     **    in the case of a pure server.
        !           487:     */
        !           488:     hrErr = ServerDoc_GetObject(
        !           489:             (LPSERVERDOC)lpOleDoc, lpszItem,riid,lplpvObject);
        !           490: 
        !           491: #elif defined( OLE_CNTR )
        !           492: 
        !           493:     /* OLE2NOTE: dwSpeedNeeded indicates how long the caller is willing
        !           494:     **    to wait for us to get the object:
        !           495:     **      BINDSPEED_IMMEDIATE -- only if obj already loaded && IsRunning
        !           496:     **      BINDSPEED_MODERATE  -- load obj if necessary && if IsRunning
        !           497:     **      BINDSPEED_INDEFINITE-- force obj to load and run if necessary
        !           498:     */
        !           499:     hrErr = ContainerDoc_GetObject(
        !           500:             (LPCONTAINERDOC)lpOleDoc,lpszItem,dwSpeedNeeded,riid,lplpvObject);
        !           501: #endif
        !           502: 
        !           503:     OLEDBG_END2
        !           504:     return hrErr;
        !           505: }
        !           506: 
        !           507: 
        !           508: STDMETHODIMP OleDoc_ItemCont_GetObjectStorage(
        !           509:         LPOLEITEMCONTAINER  lpThis,
        !           510:         LPSTR               lpszItem,
        !           511:         LPBINDCTX           lpbc,
        !           512:         REFIID              riid,
        !           513:         LPVOID FAR*         lplpvStorage
        !           514: )
        !           515: {
        !           516:     LPOLEDOC lpOleDoc =
        !           517:             ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
        !           518: 
        !           519:     OleDbgOut2("OleDoc_ItemCont_GetObjectStorage\r\n");
        !           520: 
        !           521:     /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */
        !           522:     *lplpvStorage = NULL;
        !           523: 
        !           524: #if defined( OLE_SERVER )
        !           525: 
        !           526:     /* OLE2NOTE: in the SERVER ONLY version, item names identify pseudo
        !           527:     **    objects. pseudo objects, do NOT have identifiable storage.
        !           528:     */
        !           529:     return ResultFromScode(E_FAIL);
        !           530: 
        !           531: 
        !           532: #elif defined( OLE_CNTR )
        !           533: 
        !           534:     // We can only return an IStorage* type pointer
        !           535:     if (! IsEqualIID(riid, &IID_IStorage))
        !           536:         return ResultFromScode(E_FAIL);
        !           537: 
        !           538:     return ContainerDoc_GetObjectStorage(
        !           539:             (LPCONTAINERDOC)lpOleDoc,
        !           540:             lpszItem,
        !           541:             (LPSTORAGE FAR*)lplpvStorage
        !           542:     );
        !           543: #endif
        !           544: }
        !           545: 
        !           546: 
        !           547: STDMETHODIMP OleDoc_ItemCont_IsRunning(
        !           548:         LPOLEITEMCONTAINER  lpThis,
        !           549:         LPSTR               lpszItem
        !           550: )
        !           551: {
        !           552:     LPOLEDOC lpOleDoc =
        !           553:             ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
        !           554:     HRESULT hrErr;
        !           555: 
        !           556:     OLEDBG_BEGIN2("OleDoc_ItemCont_IsRunning\r\n")
        !           557: 
        !           558:     /* OLE2NOTE: Check if item name is valid. if so then return if
        !           559:     **    Object is running. PseudoObjects in the Server version are
        !           560:     **    always considered running. Ole objects in the container must
        !           561:     **    be checked if they are running. 
        !           562:     */
        !           563: 
        !           564: #if defined( OLE_SERVER )
        !           565: 
        !           566:     hrErr = ServerDoc_IsRunning((LPSERVERDOC)lpOleDoc, lpszItem);
        !           567: 
        !           568: #elif defined( OLE_CNTR )
        !           569: 
        !           570:     hrErr = ContainerDoc_IsRunning((LPCONTAINERDOC)lpOleDoc, lpszItem);
        !           571: 
        !           572: #endif
        !           573: 
        !           574:     OLEDBG_END2
        !           575:     return hrErr;
        !           576: }
        !           577: 
        !           578: 
        !           579: /*************************************************************************
        !           580: ** OleDoc Common Support Functions
        !           581: *************************************************************************/
        !           582: 
        !           583: 
        !           584: /* OleDoc_GetFullMoniker
        !           585: ** ---------------------
        !           586: **    Return the full, absolute moniker of the document.
        !           587: **
        !           588: **    NOTE: the caller must release the pointer returned when done.
        !           589: */
        !           590: LPMONIKER OleDoc_GetFullMoniker(LPOLEDOC lpOleDoc, DWORD dwAssign)
        !           591: {
        !           592:     LPMONIKER lpMoniker = NULL;
        !           593: 
        !           594:     OLEDBG_BEGIN3("OleDoc_GetFullMoniker\r\n")
        !           595: 
        !           596:     if (lpOleDoc->m_lpSrcDocOfCopy) {
        !           597:         /* CASE I: this document was created for a copy or drag/drop
        !           598:         **    operation. generate the moniker which identifies the
        !           599:         **    source document of the original copy.
        !           600:         */
        !           601:         if (! lpOleDoc->m_fLinkSourceAvail)
        !           602:             goto done;        // we already know a moniker is not available
        !           603: 
        !           604:         lpMoniker = OleDoc_GetFullMoniker(
        !           605:                 lpOleDoc->m_lpSrcDocOfCopy,
        !           606:                 dwAssign
        !           607:         );
        !           608:     }
        !           609:     else if (lpOleDoc->m_lpFileMoniker) {
        !           610: 
        !           611:         /* CASE II: this document is a top-level user document (either
        !           612:         **    file-based or untitled). return the FileMoniker stored
        !           613:         **    with the document; it uniquely identifies the document.
        !           614:         */
        !           615: 
        !           616:         // we must AddRef the moniker to pass out a ptr
        !           617:         lpOleDoc->m_lpFileMoniker->lpVtbl->AddRef(lpOleDoc->m_lpFileMoniker);
        !           618: 
        !           619:         lpMoniker = lpOleDoc->m_lpFileMoniker;
        !           620:     }
        !           621: 
        !           622: #if defined( OLE_SERVER )
        !           623: 
        !           624:     else if (((LPSERVERDOC)lpOleDoc)->m_lpOleClientSite) {
        !           625: 
        !           626:         /* CASE III: this document is an embedded object, ask our
        !           627:         **    container for our moniker.
        !           628:         */
        !           629:         OLEDBG_BEGIN2("IOleClientSite::GetMoniker called\r\n");
        !           630:         ((LPSERVERDOC)lpOleDoc)->m_lpOleClientSite->lpVtbl->GetMoniker(
        !           631:                 ((LPSERVERDOC)lpOleDoc)->m_lpOleClientSite,
        !           632:                 dwAssign,
        !           633:                 OLEWHICHMK_OBJFULL,
        !           634:                 &lpMoniker
        !           635:         );
        !           636:         OLEDBG_END2
        !           637:     }
        !           638: 
        !           639: #endif
        !           640: 
        !           641:     else {
        !           642:         lpMoniker = NULL;
        !           643:     }
        !           644: 
        !           645: done:
        !           646:     OLEDBG_END3
        !           647:     return lpMoniker;
        !           648: }
        !           649: 
        !           650: 
        !           651: /* OleDoc_DocRenamedUpdate
        !           652: ** -----------------------
        !           653: **    Update the documents registration in the running object table (ROT).
        !           654: **    Also inform all embedded OLE objects (container only) and/or psedudo
        !           655: **    objects (server only) that the name of the document has changed.
        !           656: */
        !           657: void OleDoc_DocRenamedUpdate(LPOLEDOC lpOleDoc, LPMONIKER lpmkDoc)
        !           658: {
        !           659:     OLEDBG_BEGIN3("OleDoc_DocRenamedUpdate\r\n")
        !           660: 
        !           661:     OleDoc_AddRef(lpOleDoc);
        !           662: 
        !           663:     /* OLE2NOTE: we must re-register ourselves as running when we
        !           664:     **    get a new moniker assigned (ie. when we are renamed).
        !           665:     */
        !           666:     OLEDBG_BEGIN3("OleStdRegisterAsRunning called\r\n")
        !           667:     OleStdRegisterAsRunning(
        !           668:             (LPUNKNOWN)&lpOleDoc->m_Unknown,
        !           669:             lpmkDoc,
        !           670:             &lpOleDoc->m_dwRegROT
        !           671:     );
        !           672:     OLEDBG_END3
        !           673: 
        !           674: #if defined( OLE_SERVER )
        !           675:     {
        !           676:         LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
        !           677: 
        !           678:         /* OLE2NOTE: inform any linking clients that the document has been
        !           679:         **    renamed. in addition, any currently active pseudo objects
        !           680:         **    should also inform their clients.
        !           681:         */
        !           682:         ServerDoc_SendAdvise (
        !           683:                 lpServerDoc,
        !           684:                 OLE_ONRENAME,
        !           685:                 lpmkDoc,
        !           686:                 0        /* advf -- not relevant here */
        !           687:         );
        !           688:     }
        !           689: 
        !           690: #elif defined( OLE_CNTR )
        !           691:     {
        !           692:         LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc;
        !           693: 
        !           694:         /* OLE2NOTE: must tell all OLE objects that our container
        !           695:         **    moniker changed.
        !           696:         */
        !           697:         ContainerDoc_InformAllOleObjectsDocRenamed(
        !           698:                 lpContainerDoc,
        !           699:                 lpmkDoc
        !           700:         );
        !           701:     }
        !           702: #endif
        !           703: 
        !           704:     OleDoc_Release(lpOleDoc);       // release artificial AddRef above
        !           705:     OLEDBG_END3
        !           706: }
        !           707: 
        !           708: 
        !           709: 
        !           710: #if defined( OLE_SERVER )
        !           711: 
        !           712: /*************************************************************************
        !           713: ** ServerDoc Supprt Functions Used by Server versions
        !           714: *************************************************************************/
        !           715: 
        !           716: 
        !           717: /* ServerDoc_PseudoObjLockDoc
        !           718: ** --------------------------
        !           719: **    Add a lock on the Doc on behalf of the PseudoObject. the Doc may not 
        !           720: **    close while the Doc exists.
        !           721: **
        !           722: **    when a pseudo object is first created, it calls this method to
        !           723: **    guarantee that the document stays alive (PseudoObj_Init).
        !           724: **    when a pseudo object is destroyed, it call
        !           725: **    ServerDoc_PseudoObjUnlockDoc to release this hold on the document.
        !           726: */
        !           727: void ServerDoc_PseudoObjLockDoc(LPSERVERDOC lpServerDoc)
        !           728: {
        !           729:        LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc;
        !           730:     ULONG cPseudoObj;
        !           731: 
        !           732:     cPseudoObj = ++lpServerDoc->m_cPseudoObj;
        !           733: 
        !           734:     OleDbgOutRefCnt3(
        !           735:             "ServerDoc_PseudoObjLockDoc: cPseudoObj++\r\n", 
        !           736:             lpServerDoc, 
        !           737:             cPseudoObj
        !           738:     );
        !           739: 
        !           740:     OleDoc_Lock(lpOleDoc, TRUE /* fLock */, 0 /* not applicable */);
        !           741:     return;
        !           742: }
        !           743: 
        !           744: 
        !           745: /* ServerDoc_PseudoObjUnlockDoc
        !           746: ** ----------------------------
        !           747: **    Release the lock on the Doc on behalf of the PseudoObject. if this was 
        !           748: **    the last lock on the Doc, then it will shutdown.
        !           749: */
        !           750: void ServerDoc_PseudoObjUnlockDoc(
        !           751:                LPSERVERDOC                     lpServerDoc, 
        !           752:                LPPSEUDOOBJ                     lpPseudoObj
        !           753: )
        !           754: {
        !           755:     ULONG cPseudoObj;
        !           756:     LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc;
        !           757: 
        !           758:     OLEDBG_BEGIN3("ServerDoc_PseudoObjUnlockDoc\r\n")
        !           759: 
        !           760:     /* OLE2NOTE: when there are no active pseudo objects in the Doc and
        !           761:     **    the Doc is not visible, and if there are no outstanding locks 
        !           762:     **    on the Doc, then this is a "silent update"
        !           763:     **    situation. our Doc is being used programatically by some
        !           764:     **    client; it is NOT accessible to the user because it is
        !           765:     **    NOT visible. thus since all Locks have been released, we
        !           766:     **    will close the document. if the app is only running due
        !           767:     **    to the presence of this document, then the app will now
        !           768:     **    also shut down.
        !           769:     */
        !           770:     OleDbgAssertSz (
        !           771:                        lpServerDoc->m_cPseudoObj > 0, 
        !           772:                        "PseudoObjUnlockDoc called with cPseudoObj == 0"
        !           773:        );
        !           774: 
        !           775:     cPseudoObj = --lpServerDoc->m_cPseudoObj;
        !           776: 
        !           777:     OleDbgOutRefCnt3(
        !           778:             "ServerDoc_PseudoObjUnlockDoc: cPseudoObj--\r\n", 
        !           779:             lpServerDoc, 
        !           780:             cPseudoObj
        !           781:     );
        !           782: 
        !           783:     OleDoc_Lock(lpOleDoc, FALSE /* fLock */, TRUE /* fLastUnlockReleases */);
        !           784:     
        !           785:     OLEDBG_END3
        !           786:     return;
        !           787: }
        !           788: 
        !           789: 
        !           790: /* ServerDoc_GetObject
        !           791: ** -------------------
        !           792: **    
        !           793: **    Return a pointer to an object identified by an item string
        !           794: **    (lpszItem). For a server-only app, the object returned will be a
        !           795: **    pseudo object.
        !           796: */
        !           797: HRESULT ServerDoc_GetObject(
        !           798:         LPSERVERDOC             lpServerDoc, 
        !           799:         LPSTR                   lpszItem, 
        !           800:         REFIID                  riid, 
        !           801:         LPVOID FAR*             lplpvObject
        !           802: )
        !           803: {
        !           804:     LPPSEUDOOBJ lpPseudoObj;
        !           805:     LPSERVERNAMETABLE lpServerNameTable = 
        !           806:             (LPSERVERNAMETABLE)((LPOUTLINEDOC)lpServerDoc)->m_lpNameTable;
        !           807:     
        !           808:     *lplpvObject = NULL;
        !           809: 
        !           810:     /* Get the PseudoObj which corresponds to an item name. if the item
        !           811:     **    name does NOT exist in the name table then NO object is
        !           812:     **    returned. the ServerNameTable_GetPseudoObj routine finds a
        !           813:     **    name entry corresponding to the item name, it then checks if
        !           814:     **    a PseudoObj has already been allocated. if so, it returns the
        !           815:     **    existing object, otherwise it allocates a new PseudoObj.
        !           816:     */
        !           817:     lpPseudoObj = ServerNameTable_GetPseudoObj(
        !           818:             lpServerNameTable,
        !           819:             lpszItem,
        !           820:             lpServerDoc
        !           821:     );
        !           822: 
        !           823:     if (! lpPseudoObj) {
        !           824:         *lplpvObject = NULL;        
        !           825:         return ResultFromScode(MK_E_NOOBJECT);
        !           826:     }
        !           827: 
        !           828:     // return the desired interface pointer of the pseudo object.
        !           829:     return PseudoObj_QueryInterface(lpPseudoObj, riid, lplpvObject);
        !           830: }
        !           831: 
        !           832: 
        !           833: /* ServerDoc_IsRunning
        !           834: ** -------------------
        !           835: **    
        !           836: **    Check if the object identified by an item string (lpszItem) is in
        !           837: **    the running state. For a server-only app, if the item name exists in 
        !           838: **    in the NameTable then the item name is considered running. 
        !           839: **    IOleItemContainer::GetObject would succeed.
        !           840: */
        !           841: 
        !           842: HRESULT ServerDoc_IsRunning(LPSERVERDOC lpServerDoc, LPSTR lpszItem)
        !           843: {
        !           844:     LPOUTLINENAMETABLE lpOutlineNameTable = 
        !           845:             ((LPOUTLINEDOC)lpServerDoc)->m_lpNameTable;
        !           846:     LPSERVERNAME lpServerName;
        !           847:     
        !           848:     lpServerName = (LPSERVERNAME)OutlineNameTable_FindName(
        !           849:             lpOutlineNameTable,
        !           850:             lpszItem
        !           851:     );
        !           852: 
        !           853:     if (lpServerName) 
        !           854:         return NOERROR;
        !           855:     else 
        !           856:         return ResultFromScode(MK_E_NOOBJECT);
        !           857: }
        !           858: 
        !           859: 
        !           860: /* ServerDoc_GetSelRelMoniker
        !           861: ** --------------------------
        !           862: **    Retrieve the relative item moniker which identifies the given
        !           863: **    selection (lplrSel). 
        !           864: **    
        !           865: **    Returns NULL if a moniker can NOT be created.
        !           866: */
        !           867: 
        !           868: LPMONIKER ServerDoc_GetSelRelMoniker(
        !           869:         LPSERVERDOC             lpServerDoc, 
        !           870:         LPLINERANGE             lplrSel,    
        !           871:         DWORD                   dwAssign
        !           872: )
        !           873: {
        !           874:     LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
        !           875:     LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
        !           876:     LPSERVERNAMETABLE lpServerNameTable = 
        !           877:             (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable;
        !           878:     LPOUTLINENAMETABLE lpOutlineNameTable = 
        !           879:             (LPOUTLINENAMETABLE)lpServerNameTable;
        !           880:     LPOUTLINENAME lpOutlineName;
        !           881:     LPMONIKER lpmk;
        !           882: 
        !           883:     lpOutlineName=OutlineNameTable_FindNamedRange(lpOutlineNameTable,lplrSel);
        !           884: 
        !           885:     if (lpOutlineName) {
        !           886:         /* the selection range already has a name assigned */
        !           887:         CreateItemMoniker(OLESTDDELIM, lpOutlineName->m_szName, &lpmk);
        !           888:     } else {
        !           889:         char szbuf[MAXNAMESIZE];
        !           890: 
        !           891:         switch (dwAssign) {
        !           892: 
        !           893:             case GETMONIKER_FORCEASSIGN:
        !           894:             
        !           895:                 /* Force the assignment of the name. This is called when a
        !           896:                 **    Paste Link actually occurs. At this point we want to
        !           897:                 **    create a Name and add it to the NameTable in order to
        !           898:                 **    track the source of the link. This name (as all
        !           899:                 **    names) will be updated upon editing of the document.
        !           900:                 */
        !           901:                 wsprintf(
        !           902:                         szbuf, 
        !           903:                         "%s %ld",
        !           904:                         (LPSTR)DEFRANGENAMEPREFIX, 
        !           905:                         ++(lpServerDoc->m_nNextRangeNo)
        !           906:                 );
        !           907: 
        !           908:                 lpOutlineName = OutlineApp_CreateName(lpOutlineApp);
        !           909: 
        !           910:                 if (lpOutlineName) {
        !           911:                     lstrcpy(lpOutlineName->m_szName, szbuf);
        !           912:                     lpOutlineName->m_nStartLine = lplrSel->m_nStartLine;
        !           913:                     lpOutlineName->m_nEndLine = lplrSel->m_nEndLine;
        !           914:                     OutlineDoc_AddName(lpOutlineDoc, lpOutlineName);
        !           915:                 } else {
        !           916:                     // REVIEW: do we need "Out-of-Memory" error message here?
        !           917:                 }
        !           918:                 break;
        !           919:                 
        !           920:             case GETMONIKER_TEMPFORUSER:
        !           921: 
        !           922:                 /* Create a name to show to the user in the Paste
        !           923:                 **    Special dialog but do NOT yet incur the overhead
        !           924:                 **    of adding a Name to the NameTable. The Moniker
        !           925:                 **    generated should be useful to display to the user
        !           926:                 **    to indicate the source of the copy, but will NOT
        !           927:                 **    be used to create a link directly (the caller
        !           928:                 **    should ask again for a moniker specifying FORCEASSIGN).
        !           929:                 **    we will generate the name that would be the next
        !           930:                 **    auto-generated range name, BUT will NOT actually
        !           931:                 **    increment the range counter.
        !           932:                 */
        !           933:                 wsprintf(
        !           934:                         szbuf, 
        !           935:                         "%s %ld",
        !           936:                         (LPSTR)DEFRANGENAMEPREFIX, 
        !           937:                         (lpServerDoc->m_nNextRangeNo)+1
        !           938:                 );
        !           939:                 break;
        !           940: 
        !           941:             case GETMONIKER_ONLYIFTHERE:
        !           942: 
        !           943:                 /* the caller only wants a name if one has already been
        !           944:                 **    assigned. we have already above checked if the
        !           945:                 **    current selection has a name, so we will simply
        !           946:                 **    return NULL here. 
        !           947:                 */
        !           948:                 return NULL;    // no moniker is assigned
        !           949:                 
        !           950:             default:
        !           951:                 return NULL;    // unknown flag given
        !           952:         }
        !           953: 
        !           954:         CreateItemMoniker(OLESTDDELIM, szbuf, &lpmk);
        !           955:     }
        !           956:     return lpmk;
        !           957: }
        !           958: 
        !           959: 
        !           960: /* ServerDoc_GetSelFullMoniker
        !           961: ** ---------------------------
        !           962: **    Retrieve the full absolute moniker which identifies the given 
        !           963: **    selection (lplrSel).
        !           964: **    this moniker is created as a composite of the absolute moniker for 
        !           965: **    the entire document appended with an item moniker which identifies 
        !           966: **    the selection relative to the document.
        !           967: **    Returns NULL if a moniker can NOT be created.
        !           968: */
        !           969: LPMONIKER ServerDoc_GetSelFullMoniker(
        !           970:         LPSERVERDOC             lpServerDoc, 
        !           971:         LPLINERANGE             lplrSel,    
        !           972:         DWORD                   dwAssign
        !           973: )
        !           974: {
        !           975:     LPMONIKER lpmkDoc = NULL;
        !           976:     LPMONIKER lpmkItem = NULL;
        !           977:     LPMONIKER lpmkFull = NULL;
        !           978: 
        !           979:     lpmkDoc = OleDoc_GetFullMoniker(
        !           980:             (LPOLEDOC)lpServerDoc,
        !           981:             dwAssign
        !           982:     );
        !           983:     if (! lpmkDoc) return NULL;
        !           984: 
        !           985:     lpmkItem = ServerDoc_GetSelRelMoniker(
        !           986:             lpServerDoc,
        !           987:             lplrSel,
        !           988:             dwAssign
        !           989:     );
        !           990:     if (lpmkItem) {
        !           991:         CreateGenericComposite(lpmkDoc, lpmkItem, (LPMONIKER FAR*)&lpmkFull);
        !           992:         OleStdRelease((LPUNKNOWN)lpmkItem);
        !           993:     }
        !           994: 
        !           995:     if (lpmkDoc) 
        !           996:         OleStdRelease((LPUNKNOWN)lpmkDoc);
        !           997: 
        !           998:     return lpmkFull;
        !           999: }
        !          1000: 
        !          1001: 
        !          1002: /* ServerNameTable_EditLineUpdate
        !          1003:  * -------------------------------
        !          1004:  *
        !          1005:  *      Update the table when a line at nEditIndex is edited.
        !          1006:  */
        !          1007: void ServerNameTable_EditLineUpdate(
        !          1008:         LPSERVERNAMETABLE       lpServerNameTable, 
        !          1009:         int                     nEditIndex
        !          1010: )
        !          1011: {
        !          1012:     LPOUTLINENAMETABLE lpOutlineNameTable = 
        !          1013:                                         (LPOUTLINENAMETABLE)lpServerNameTable;
        !          1014:     LPOUTLINENAME lpOutlineName;
        !          1015:     LINERANGE lrSel;
        !          1016:     LPPSEUDOOBJ lpPseudoObj;
        !          1017:     int i;
        !          1018: 
        !          1019:     for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
        !          1020:         lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i);
        !          1021: 
        !          1022:         lpPseudoObj = ((LPSERVERNAME)lpOutlineName)->m_lpPseudoObj;
        !          1023:         
        !          1024:         /* if there is a pseudo object associated with this name, then
        !          1025:         **    check if the line that was modified is included within
        !          1026:         **    the named range.
        !          1027:         */
        !          1028:         if (lpPseudoObj) {
        !          1029:             OutlineName_GetSel(lpOutlineName, &lrSel);
        !          1030: 
        !          1031:             if(((int)lrSel.m_nStartLine <= nEditIndex) &&
        !          1032:                 ((int)lrSel.m_nEndLine >= nEditIndex)) {
        !          1033: 
        !          1034:                 // inform linking clients data has changed
        !          1035:                 PseudoObj_SendAdvise(
        !          1036:                                                lpPseudoObj, 
        !          1037:                                                OLE_ONDATACHANGE, 
        !          1038:                                                NULL,   /* lpmkDoc -- not relevant here */
        !          1039:                                                0       /* advf -- no flags necessary */
        !          1040:                                );
        !          1041:             }
        !          1042:             
        !          1043:         }
        !          1044:     }
        !          1045: }
        !          1046: 
        !          1047: 
        !          1048: /* ServerNameTable_InformAllPseudoObjectsDocRenamed
        !          1049:  * ------------------------------------------------
        !          1050:  *
        !          1051:  *      Inform all pseudo object clients that the name of the pseudo 
        !          1052:  *      object has changed.
        !          1053:  */
        !          1054: void ServerNameTable_InformAllPseudoObjectsDocRenamed(
        !          1055:         LPSERVERNAMETABLE       lpServerNameTable, 
        !          1056:         LPMONIKER               lpmkDoc
        !          1057: )
        !          1058: {
        !          1059:     LPOUTLINENAMETABLE lpOutlineNameTable = 
        !          1060:                                         (LPOUTLINENAMETABLE)lpServerNameTable;
        !          1061:     LPOUTLINENAME lpOutlineName;
        !          1062:     LPPSEUDOOBJ lpPseudoObj;
        !          1063:     LPMONIKER lpmkObj;
        !          1064:     int i;
        !          1065: 
        !          1066:     OLEDBG_BEGIN2("ServerNameTable_InformAllPseudoObjectsDocRenamed\r\n");
        !          1067: 
        !          1068:     for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
        !          1069:         lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i);
        !          1070: 
        !          1071:         lpPseudoObj = ((LPSERVERNAME)lpOutlineName)->m_lpPseudoObj;
        !          1072:         
        !          1073:         /* if there is a pseudo object associated with this name, then
        !          1074:         **    send OnRename advise to its linking clients.
        !          1075:         */
        !          1076:         if (lpPseudoObj && 
        !          1077:             ((lpmkObj=PseudoObj_GetFullMoniker(lpPseudoObj,lpmkDoc))!=NULL)) {
        !          1078: 
        !          1079:             // inform the clients that the name has changed
        !          1080:             PseudoObj_SendAdvise (
        !          1081:                                        lpPseudoObj, 
        !          1082:                                        OLE_ONRENAME, 
        !          1083:                                        lpmkObj,
        !          1084:                                        0               /* advf -- not relevant here */
        !          1085:                        );
        !          1086:         }
        !          1087:     }
        !          1088:     OLEDBG_END2
        !          1089: }
        !          1090: 
        !          1091: 
        !          1092: /* ServerNameTable_InformAllPseudoObjectsDocSaved
        !          1093:  * ------------------------------------------------
        !          1094:  *
        !          1095:  *      Inform all pseudo object clients that the name of the pseudo 
        !          1096:  *      object has changed.
        !          1097:  */
        !          1098: void ServerNameTable_InformAllPseudoObjectsDocSaved(
        !          1099:         LPSERVERNAMETABLE       lpServerNameTable, 
        !          1100:         LPMONIKER               lpmkDoc
        !          1101: )
        !          1102: {
        !          1103:     LPOUTLINENAMETABLE lpOutlineNameTable = 
        !          1104:                                         (LPOUTLINENAMETABLE)lpServerNameTable;
        !          1105:     LPOUTLINENAME lpOutlineName;
        !          1106:     LPPSEUDOOBJ lpPseudoObj;
        !          1107:     LPMONIKER lpmkObj;
        !          1108:     int i;
        !          1109: 
        !          1110:     OLEDBG_BEGIN2("ServerNameTable_InformAllPseudoObjectsDocSaved\r\n");
        !          1111: 
        !          1112:     for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
        !          1113:         lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i);
        !          1114: 
        !          1115:         lpPseudoObj = ((LPSERVERNAME)lpOutlineName)->m_lpPseudoObj;
        !          1116:         
        !          1117:         /* if there is a pseudo object associated with this name, then
        !          1118:         **    send OnSave advise to its linking clients.
        !          1119:         */
        !          1120:         if (lpPseudoObj && 
        !          1121:             ((lpmkObj=PseudoObj_GetFullMoniker(lpPseudoObj,lpmkDoc))!=NULL)) {
        !          1122: 
        !          1123:             // inform the clients that the name has been saved
        !          1124:             PseudoObj_SendAdvise (
        !          1125:                                        lpPseudoObj, 
        !          1126:                                        OLE_ONSAVE, 
        !          1127:                                        NULL,   /* lpmkDoc -- not relevant here */
        !          1128:                                        0       /* advf -- not relevant here */
        !          1129:                        );
        !          1130:         }
        !          1131:     }
        !          1132:     OLEDBG_END2
        !          1133: }
        !          1134: 
        !          1135: 
        !          1136: /* ServerNameTable_SendPendingAdvises
        !          1137:  * ----------------------------------
        !          1138:  *
        !          1139:  *      Send any pending change notifications for pseudo objects.
        !          1140:  *  while ReDraw is diabled on the ServerDoc, then change advise 
        !          1141:  *  notifications are not sent to pseudo object clients.
        !          1142:  */
        !          1143: void ServerNameTable_SendPendingAdvises(LPSERVERNAMETABLE lpServerNameTable)
        !          1144: {
        !          1145:     LPOUTLINENAMETABLE lpOutlineNameTable = 
        !          1146:                                         (LPOUTLINENAMETABLE)lpServerNameTable;
        !          1147:     LPSERVERNAME lpServerName;
        !          1148:     int i;
        !          1149: 
        !          1150:     for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
        !          1151:         lpServerName = (LPSERVERNAME)OutlineNameTable_GetName(
        !          1152:                 lpOutlineNameTable, 
        !          1153:                 i
        !          1154:         );
        !          1155:         ServerName_SendPendingAdvises(lpServerName);
        !          1156:     }
        !          1157: }
        !          1158: 
        !          1159: 
        !          1160: /* ServerNameTable_GetPseudoObj 
        !          1161: ** ----------------------------
        !          1162: ** 
        !          1163: **    Return a pointer to a pseudo object identified by an item string
        !          1164: **    (lpszItem). if the pseudo object already exists, then return the
        !          1165: **    existing object, otherwise allocate a new pseudo object.
        !          1166: */
        !          1167: LPPSEUDOOBJ ServerNameTable_GetPseudoObj(
        !          1168:         LPSERVERNAMETABLE       lpServerNameTable, 
        !          1169:         LPSTR                   lpszItem, 
        !          1170:         LPSERVERDOC             lpServerDoc
        !          1171: )
        !          1172: {
        !          1173:     LPSERVERNAME lpServerName;
        !          1174:     
        !          1175:     lpServerName = (LPSERVERNAME)OutlineNameTable_FindName(
        !          1176:             (LPOUTLINENAMETABLE)lpServerNameTable,
        !          1177:             lpszItem
        !          1178:     );
        !          1179: 
        !          1180:     if (lpServerName) 
        !          1181:         return ServerName_GetPseudoObj(lpServerName, lpServerDoc);
        !          1182:     else 
        !          1183:         return NULL;
        !          1184: }
        !          1185: 
        !          1186: 
        !          1187: /* ServerNameTable_CloseAllPseudoObjs
        !          1188:  * ----------------------------------
        !          1189:  *
        !          1190:  *  Force all pseudo objects to close. this results in sending OnClose 
        !          1191:  *  notification to each pseudo object's linking clients.
        !          1192:  */
        !          1193: void ServerNameTable_CloseAllPseudoObjs(LPSERVERNAMETABLE lpServerNameTable)
        !          1194: {
        !          1195:     LPOUTLINENAMETABLE lpOutlineNameTable = 
        !          1196:                                         (LPOUTLINENAMETABLE)lpServerNameTable;
        !          1197:     LPSERVERNAME lpServerName;
        !          1198:     int i;
        !          1199: 
        !          1200:        OLEDBG_BEGIN3("ServerNameTable_CloseAllPseudoObjs\r\n")
        !          1201: 
        !          1202:     for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
        !          1203:         lpServerName = (LPSERVERNAME)OutlineNameTable_GetName(
        !          1204:                 lpOutlineNameTable, 
        !          1205:                 i
        !          1206:         );
        !          1207:         ServerName_ClosePseudoObj(lpServerName);
        !          1208:     }
        !          1209:        
        !          1210:        OLEDBG_END3
        !          1211: }
        !          1212: 
        !          1213: 
        !          1214: 
        !          1215: /* ServerName_SetSel
        !          1216:  * -----------------
        !          1217:  *
        !          1218:  *      Change the line range of a  name.
        !          1219:  */
        !          1220: void ServerName_SetSel(
        !          1221:         LPSERVERNAME            lpServerName, 
        !          1222:         LPLINERANGE             lplrSel, 
        !          1223:         BOOL                    fRangeModified
        !          1224: )
        !          1225: {
        !          1226:     LPOUTLINENAME lpOutlineName = (LPOUTLINENAME)lpServerName;
        !          1227:     BOOL fPseudoObjChanged = fRangeModified;
        !          1228: 
        !          1229:     if (lpOutlineName->m_nStartLine != lplrSel->m_nStartLine) {
        !          1230:         lpOutlineName->m_nStartLine = lplrSel->m_nStartLine;
        !          1231:         fPseudoObjChanged = TRUE;
        !          1232:     }
        !          1233: 
        !          1234:     if (lpOutlineName->m_nEndLine != lplrSel->m_nEndLine) {
        !          1235:         lpOutlineName->m_nEndLine = lplrSel->m_nEndLine;
        !          1236:         fPseudoObjChanged = TRUE;
        !          1237:     }
        !          1238: 
        !          1239:     /* OLE2NOTE: if the range of an active pseudo object has
        !          1240:     **    changed, then inform any linking clients that the object
        !          1241:     **    has changed.
        !          1242:     */
        !          1243:     if (lpServerName->m_lpPseudoObj && fPseudoObjChanged) {
        !          1244:         PseudoObj_SendAdvise(
        !          1245:                 lpServerName->m_lpPseudoObj, 
        !          1246:                                OLE_ONDATACHANGE, 
        !          1247:                                NULL,   /* lpmkDoc -- not relevant here */
        !          1248:                                0       /* advf -- no flags necessary */
        !          1249:                );
        !          1250:     }
        !          1251: }
        !          1252: 
        !          1253: 
        !          1254: /* ServerName_SendPendingAdvises
        !          1255:  * -----------------------------
        !          1256:  *
        !          1257:  *      Send any pending change notifications for the associated 
        !          1258:  *  pseudo objects for this name (if one exists).
        !          1259:  *  while ReDraw is diabled on the ServerDoc, then change advise 
        !          1260:  *  notifications are not sent to pseudo object clients.
        !          1261:  */
        !          1262: void ServerName_SendPendingAdvises(LPSERVERNAME lpServerName)
        !          1263: {
        !          1264:     if (! lpServerName->m_lpPseudoObj) 
        !          1265:         return;     // no associated pseudo object
        !          1266: 
        !          1267:     if (lpServerName->m_lpPseudoObj->m_fDataChanged) 
        !          1268:         PseudoObj_SendAdvise(
        !          1269:                 lpServerName->m_lpPseudoObj, 
        !          1270:                                OLE_ONDATACHANGE, 
        !          1271:                                NULL,   /* lpmkDoc -- not relevant here */
        !          1272:                                0       /* advf -- no flags necessary */
        !          1273:                );
        !          1274: }
        !          1275: 
        !          1276: 
        !          1277: /* ServerName_GetPseudoObj
        !          1278: ** -----------------------
        !          1279: ** 
        !          1280: **    Return a pointer to a pseudo object associated to a ServerName.
        !          1281: **    if the pseudo object already exists, then return the
        !          1282: **    existing object, otherwise allocate a new pseudo object.
        !          1283: **    
        !          1284: **    NOTE: the PseudoObj is returned with a 0 refcnt if first created,
        !          1285: **    else the existing refcnt is unchanged. 
        !          1286: */
        !          1287: LPPSEUDOOBJ ServerName_GetPseudoObj(
        !          1288:         LPSERVERNAME            lpServerName, 
        !          1289:         LPSERVERDOC             lpServerDoc
        !          1290: )
        !          1291: {
        !          1292:     // Check if a PseudoObj already exists
        !          1293:     if (lpServerName->m_lpPseudoObj) 
        !          1294:         return lpServerName->m_lpPseudoObj;
        !          1295: 
        !          1296:     // A PseudoObj does NOT already exist, allocate a new one.
        !          1297:     lpServerName->m_lpPseudoObj=(LPPSEUDOOBJ) New((DWORD)sizeof(PSEUDOOBJ));
        !          1298:     if (lpServerName->m_lpPseudoObj == NULL) {
        !          1299:         OleDbgAssertSz(lpServerName->m_lpPseudoObj != NULL, 
        !          1300:                                                 "Error allocating PseudoObj");
        !          1301:         return NULL; 
        !          1302:     }
        !          1303: 
        !          1304:     PseudoObj_Init(lpServerName->m_lpPseudoObj, lpServerName, lpServerDoc);
        !          1305:     return lpServerName->m_lpPseudoObj;
        !          1306: }
        !          1307: 
        !          1308: 
        !          1309: /* ServerName_ClosePseudoObj
        !          1310:  * -------------------------
        !          1311:  *
        !          1312:  *      if there is an associated pseudo objects for this name (if one 
        !          1313:  *  exists), then close it. this results in sending OnClose 
        !          1314:  *  notification to the pseudo object's linking clients.
        !          1315:  */
        !          1316: void ServerName_ClosePseudoObj(LPSERVERNAME lpServerName)
        !          1317: {
        !          1318:     if (! lpServerName->m_lpPseudoObj) 
        !          1319:         return;     // no associated pseudo object
        !          1320: 
        !          1321:     PseudoObj_Close(lpServerName->m_lpPseudoObj);
        !          1322: }
        !          1323: 
        !          1324: 
        !          1325: #endif  // OLE_SERVER
        !          1326: 
        !          1327: 
        !          1328: #if defined( OLE_CNTR )
        !          1329: 
        !          1330: 
        !          1331: /*************************************************************************
        !          1332: ** ContainerDoc Supprt Functions Used by Container versions
        !          1333: *************************************************************************/
        !          1334: 
        !          1335: 
        !          1336: /* ContainerDoc_InformAllOleObjectsDocRenamed
        !          1337: ** ------------------------------------------
        !          1338: **    Inform all OLE objects that the name of the ContainerDoc has changed.
        !          1339: */
        !          1340: void ContainerDoc_InformAllOleObjectsDocRenamed(
        !          1341:         LPCONTAINERDOC          lpContainerDoc,
        !          1342:         LPMONIKER               lpmkDoc
        !          1343: )
        !          1344: {
        !          1345:     LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
        !          1346:     int i;
        !          1347:     LPLINE lpLine;
        !          1348: 
        !          1349:     for (i = 0; i < lpLL->m_nNumLines; i++) {
        !          1350:         lpLine=LineList_GetLine(lpLL, i);
        !          1351: 
        !          1352:         if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
        !          1353:             LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
        !          1354: 
        !          1355:             /* OLE2NOTE: if the OLE object is already loaded AND the
        !          1356:             **    object already has a moniker assigned, then we need
        !          1357:             **    to inform it that the moniker of the ContainerDoc has
        !          1358:             **    changed. of course, this means the full moniker of
        !          1359:             **    the object has changed. to do this we call
        !          1360:             **    IOleObject::SetMoniker. this will force the OLE
        !          1361:             **    object to re-register in the RunningObjectTable if it
        !          1362:             **    is currently in the running state. it is not in the
        !          1363:             **    running state, the object handler can make not that
        !          1364:             **    the object has a new moniker. if the object is not
        !          1365:             **    currently loaded, SetMoniker will be called
        !          1366:             **    automatically later when the object is loaded by the
        !          1367:             **    function ContainerLine_LoadOleObject.
        !          1368:             **    also if the object is a linked object, we always want
        !          1369:             **    to call SetMoniker on the link so that in case the
        !          1370:             **    link source is contained within our same container,
        !          1371:             **    the link source will be tracked. the link rebuilds
        !          1372:             **    its absolute moniker if it has a relative moniker.
        !          1373:             */
        !          1374:             if (lpContainerLine->m_lpOleObj) {
        !          1375:                 if (lpContainerLine->m_fMonikerAssigned ||
        !          1376:                     lpContainerLine->m_fIsLink) {
        !          1377:                     OLEDBG_BEGIN2("IOleObject::SetMoniker called\r\n")
        !          1378:                     lpContainerLine->m_lpOleObj->lpVtbl->SetMoniker(
        !          1379:                             lpContainerLine->m_lpOleObj,
        !          1380:                             OLEWHICHMK_CONTAINER,
        !          1381:                             lpmkDoc
        !          1382:                     );
        !          1383:                     OLEDBG_END2
        !          1384:                 }
        !          1385:                 
        !          1386:                 /* OLE2NOTE: we must call IOleObject::SetHostNames so
        !          1387:                 **    any open objects can update their window titles.
        !          1388:                 */
        !          1389:                 OLEDBG_BEGIN2("IOleObject::SetHostNames called\r\n")
        !          1390:                 lpContainerLine->m_lpOleObj->lpVtbl->SetHostNames(
        !          1391:                         lpContainerLine->m_lpOleObj,
        !          1392:                         (LPSTR)APPNAME,
        !          1393:                         ((LPOUTLINEDOC)lpContainerDoc)->m_lpszDocTitle
        !          1394:                 );
        !          1395:                 OLEDBG_END2
        !          1396:             }
        !          1397:         }
        !          1398:     }
        !          1399: }
        !          1400: 
        !          1401: 
        !          1402: /* ContainerDoc_GetObject
        !          1403: ** ----------------------
        !          1404: **    Return a pointer to the desired interface of an object identified
        !          1405: **    by an item string (lpszItem). the object returned will be an OLE
        !          1406: **    object (either link or embedding).
        !          1407: **
        !          1408: **      OLE2NOTE: we must force the object to run because we are
        !          1409: **          REQUIRED to return a pointer the OLE object in the
        !          1410: **          RUNNING state.
        !          1411: **
        !          1412: **    dwSpeedNeeded indicates how long the caller is willing
        !          1413: **    to wait for us to get the object:
        !          1414: **      BINDSPEED_IMMEDIATE -- only if obj already loaded && IsRunning
        !          1415: **      BINDSPEED_MODERATE  -- load obj if necessary && if IsRunning
        !          1416: **      BINDSPEED_INDEFINITE-- force obj to load and run if necessary
        !          1417: */
        !          1418: HRESULT ContainerDoc_GetObject(
        !          1419:         LPCONTAINERDOC          lpContainerDoc,
        !          1420:         LPSTR                   lpszItem,
        !          1421:         DWORD                   dwSpeedNeeded,
        !          1422:         REFIID                  riid,
        !          1423:         LPVOID FAR*             lplpvObject
        !          1424: )
        !          1425: {
        !          1426:     LPLINELIST  lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
        !          1427:     int         i;
        !          1428:     LPLINE      lpLine;
        !          1429:     BOOL        fMatchFound = FALSE;
        !          1430:     DWORD       dwStatus;
        !          1431:     HRESULT     hrErr;
        !          1432: 
        !          1433:     *lplpvObject = NULL;
        !          1434: 
        !          1435:     for (i = 0; i < lpLL->m_nNumLines; i++) {
        !          1436:         lpLine=LineList_GetLine(lpLL, i);
        !          1437: 
        !          1438:         if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
        !          1439:             LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
        !          1440: 
        !          1441:             if (lstrcmp(lpContainerLine->m_szStgName, lpszItem) == 0) {
        !          1442: 
        !          1443:                 fMatchFound = TRUE;     // valid item name
        !          1444: 
        !          1445:                 // check if object is loaded.
        !          1446:                 if (lpContainerLine->m_lpOleObj == NULL) {
        !          1447: 
        !          1448:                     // if BINDSPEED_IMMEDIATE is requested, object must
        !          1449:                     // ALREADY be loadded.
        !          1450:                     if (dwSpeedNeeded == BINDSPEED_IMMEDIATE)
        !          1451:                         return ResultFromScode(MK_E_EXCEEDEDDEADLINE);
        !          1452: 
        !          1453:                     ContainerLine_LoadOleObject(lpContainerLine);
        !          1454:                     if (! lpContainerLine->m_lpOleObj) 
        !          1455:                         return ResultFromScode(E_OUTOFMEMORY);
        !          1456:                 }
        !          1457: 
        !          1458:                 /* OLE2NOTE: check if the object is allowed to be linked
        !          1459:                 **    to from the inside (ie. we are allowed to
        !          1460:                 **    give out a moniker which binds to the running
        !          1461:                 **    OLE object). if the object is an OLE
        !          1462:                 **    2.0 embedded object then it is allowed to be
        !          1463:                 **    linked to from the inside. if the object is
        !          1464:                 **    either an OleLink or an OLE 1.0 embedding
        !          1465:                 **    then it can not be linked to from the inside.
        !          1466:                 **    if we were a container/server app then we
        !          1467:                 **    could offer linking to the outside of the
        !          1468:                 **    object (ie. a pseudo object within our
        !          1469:                 **    document). we are a container only app that
        !          1470:                 **    does not support linking to ranges of its data.
        !          1471:                 */
        !          1472:                 OLEDBG_BEGIN2("IOleObject::GetMiscStatus called\r\n");
        !          1473:                 lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus(
        !          1474:                         lpContainerLine->m_lpOleObj, 
        !          1475:                         DVASPECT_CONTENT, /* aspect is not important */
        !          1476:                         (LPDWORD)&dwStatus
        !          1477:                 );
        !          1478:                 OLEDBG_END2
        !          1479:                 if (dwStatus & OLEMISC_CANTLINKINSIDE) 
        !          1480:                     return ResultFromScode(MK_E_NOOBJECT);
        !          1481: 
        !          1482:                 // check if object is running.
        !          1483:                 if (! OleIsRunning(lpContainerLine->m_lpOleObj)) {
        !          1484: 
        !          1485:                     // if BINDSPEED_MODERATE is requested, object must
        !          1486:                     // ALREADY be running.
        !          1487:                     if (dwSpeedNeeded == BINDSPEED_MODERATE)
        !          1488:                         return ResultFromScode(MK_E_EXCEEDEDDEADLINE);
        !          1489: 
        !          1490:                     /* OLE2NOTE: we have found a match for the item name.
        !          1491:                     **    now we must return a pointer to the desired
        !          1492:                     **    interface on the RUNNING object. we must
        !          1493:                     **    carefully load the object and initially ask for
        !          1494:                     **    an interface that we are sure the loaded form of
        !          1495:                     **    the object supports. if we immediately ask the
        !          1496:                     **    loaded object for the desired interface, the
        !          1497:                     **    QueryInterface call might fail if it is an
        !          1498:                     **    interface that is supported only when the object
        !          1499:                     **    is running. thus we force the object to load and
        !          1500:                     **    return its IUnknown*. then we force the object to
        !          1501:                     **    run, and then finally, we can ask for the
        !          1502:                     **    actually requested interface.
        !          1503:                     */
        !          1504:                     hrErr = ContainerLine_RunOleObject(lpContainerLine);
        !          1505:                     if (hrErr != NOERROR) {
        !          1506:                         /* OLE2NOTE: this demonstrates an example use of
        !          1507:                         **    PropagateResult. this allows us to return an
        !          1508:                         **    SCODE of our choosing, but still passing
        !          1509:                         **    along the error context of the previous
        !          1510:                         **    error. in the future this will be used to
        !          1511:                         **    stack up error contexts.
        !          1512:                         */
        !          1513:                         return PropagateResult(hrErr, E_FAIL);
        !          1514:                     }
        !          1515:                 }
        !          1516: 
        !          1517:                 // Retrieve the requested interface
        !          1518:                 *lplpvObject = OleStdQueryInterface(
        !          1519:                         (LPUNKNOWN)lpContainerLine->m_lpOleObj, riid);
        !          1520: 
        !          1521:                 break;  // Match FOUND!
        !          1522:             }
        !          1523:         }
        !          1524:     }
        !          1525: 
        !          1526:     if (*lplpvObject != NULL) {
        !          1527:         return NOERROR;
        !          1528:     } else
        !          1529:         return (fMatchFound ? ResultFromScode(E_NOINTERFACE) 
        !          1530:                             : ResultFromScode(MK_E_NOOBJECT));
        !          1531: }
        !          1532: 
        !          1533: 
        !          1534: /* ContainerDoc_GetObjectStorage
        !          1535: ** -----------------------------
        !          1536: **    Return a pointer to the IStorage* used by the object identified
        !          1537: **    by an item string (lpszItem). the object identified could be either
        !          1538: **    an OLE object (either link or embedding).
        !          1539: */
        !          1540: HRESULT ContainerDoc_GetObjectStorage(
        !          1541:         LPCONTAINERDOC          lpContainerDoc,
        !          1542:         LPSTR                   lpszItem,
        !          1543:         LPSTORAGE FAR*          lplpStg
        !          1544: )
        !          1545: {
        !          1546:     LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
        !          1547:     int i;
        !          1548:     LPLINE lpLine;
        !          1549: 
        !          1550:     *lplpStg = NULL;
        !          1551: 
        !          1552:     for (i = 0; i < lpLL->m_nNumLines; i++) {
        !          1553:         lpLine=LineList_GetLine(lpLL, i);
        !          1554: 
        !          1555:         if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
        !          1556:             LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
        !          1557: 
        !          1558:             if (lstrcmp(lpContainerLine->m_szStgName, lpszItem) == 0) {
        !          1559: 
        !          1560:                 *lplpStg = lpContainerLine->m_lpStg;
        !          1561:                 break;  // Match FOUND!
        !          1562:             }
        !          1563:         }
        !          1564:     }
        !          1565: 
        !          1566:     if (*lplpStg != NULL) {
        !          1567:         return NOERROR;
        !          1568:     } else
        !          1569:         return ResultFromScode(MK_E_NOOBJECT);
        !          1570: }
        !          1571: 
        !          1572: 
        !          1573: /* ContainerDoc_IsRunning
        !          1574: ** ----------------------
        !          1575: **    Check if the object identified by an item string (lpszItem) is in
        !          1576: **    the running state.
        !          1577: **    For a container-only app, a check is made if the OLE object
        !          1578: **    associated with the item name is running.
        !          1579: */
        !          1580: HRESULT ContainerDoc_IsRunning(LPCONTAINERDOC   lpContainerDoc, LPSTR lpszItem)
        !          1581: {
        !          1582:     LPLINELIST  lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
        !          1583:     int         i;
        !          1584:     LPLINE      lpLine;
        !          1585:     DWORD       dwStatus;
        !          1586: 
        !          1587:     for (i = 0; i < lpLL->m_nNumLines; i++) {
        !          1588:         lpLine=LineList_GetLine(lpLL, i);
        !          1589: 
        !          1590:         if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
        !          1591:             LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
        !          1592: 
        !          1593:             if (lstrcmp(lpContainerLine->m_szStgName, lpszItem) == 0) {
        !          1594: 
        !          1595:                 /* OLE2NOTE: we have found a match for the item name.
        !          1596:                 **    now we must check if the OLE object is running.
        !          1597:                 **    we will load the object if not already loaded.
        !          1598:                 */
        !          1599:                 if (! lpContainerLine->m_lpOleObj) {
        !          1600:                     ContainerLine_LoadOleObject(lpContainerLine);
        !          1601:                     if (! lpContainerLine->m_lpOleObj) 
        !          1602:                         return ResultFromScode(E_OUTOFMEMORY);
        !          1603:                 }
        !          1604:                                
        !          1605:                 /* OLE2NOTE: check if the object is allowed to be linked
        !          1606:                 **    to from the inside (ie. we are allowed to
        !          1607:                 **    give out a moniker which binds to the running
        !          1608:                 **    OLE object). if the object is an OLE
        !          1609:                 **    2.0 embedded object then it is allowed to be
        !          1610:                 **    linked to from the inside. if the object is
        !          1611:                 **    either an OleLink or an OLE 1.0 embedding
        !          1612:                 **    then it can not be linked to from the inside.
        !          1613:                 **    if we were a container/server app then we
        !          1614:                 **    could offer linking to the outside of the
        !          1615:                 **    object (ie. a pseudo object within our
        !          1616:                 **    document). we are a container only app that
        !          1617:                 **    does not support linking to ranges of its data.
        !          1618:                 */
        !          1619:                 OLEDBG_BEGIN2("IOleObject::GetMiscStatus called\r\n")
        !          1620:                 lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus(
        !          1621:                         lpContainerLine->m_lpOleObj, 
        !          1622:                         DVASPECT_CONTENT, /* aspect is not important */
        !          1623:                         (LPDWORD)&dwStatus
        !          1624:                 );
        !          1625:                 OLEDBG_END2
        !          1626:                 if (dwStatus & OLEMISC_CANTLINKINSIDE) 
        !          1627:                     return ResultFromScode(MK_E_NOOBJECT);
        !          1628: 
        !          1629:                 if (OleIsRunning(lpContainerLine->m_lpOleObj))
        !          1630:                     return NOERROR;
        !          1631:                 else
        !          1632:                     return ResultFromScode(S_FALSE);
        !          1633:             }
        !          1634:         }
        !          1635:     }
        !          1636: 
        !          1637:     // no object was found corresponding to the item name
        !          1638:     return ResultFromScode(MK_E_NOOBJECT);
        !          1639: }
        !          1640: 
        !          1641: #endif  // OLE_CNTR

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.