Annotation of mstools/ole20/samples/outline/linking.c, revision 1.1.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.