Annotation of mstools/ole20/samples/outline/oledoc.c, revision 1.1.1.1

1.1       root        1: /*************************************************************************
                      2: **
                      3: **    OLE 2 Server Sample Code
                      4: **
                      5: **    oledoc.c
                      6: **
                      7: **    This file contains general OleDoc methods and related support
                      8: **    functions. OleDoc implementation is used by both the Container
                      9: **    versions and the Server (Object) versions of the Outline Sample.
                     10: **    
                     11: **    This file includes general support for the following:
                     12: **    1. show/hide doc window
                     13: **    2. QueryInterface, AddRef, Release
                     14: **    3. document locking (calls CoLockObjectExternal)
                     15: **    4. document shutdown (Close, Destroy)
                     16: **    5. clipboard support
                     17: **    
                     18: **    OleDoc Object
                     19: **      exposed interfaces:
                     20: **          IUnknown
                     21: **          IPersistFile
                     22: **          IOleItemContainer
                     23: **          IDataObject
                     24: **    
                     25: **    (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
                     26: **
                     27: *************************************************************************/
                     28: 
                     29: 
                     30: #include "outline.h"
                     31: 
                     32: OLEDBGDATA
                     33: 
                     34: extern LPOUTLINEAPP             g_lpApp;
                     35: 
                     36: extern IUnknownVtbl             g_OleDoc_UnknownVtbl;
                     37: extern IPersistFileVtbl         g_OleDoc_PersistFileVtbl;
                     38: extern IOleItemContainerVtbl    g_OleDoc_OleItemContainerVtbl;
                     39: extern IDataObjectVtbl          g_OleDoc_DataObjectVtbl;
                     40: 
                     41: #if defined( USE_DRAGDROP )
                     42: extern IDropTargetVtbl          g_OleDoc_DropTargetVtbl;
                     43: extern IDropSourceVtbl          g_OleDoc_DropSourceVtbl;
                     44: #endif  // USE_DRAGDROP
                     45: 
                     46: #if defined( INPLACE_CNTR )
                     47: extern BOOL g_fInsideOutContainer;
                     48: #endif 
                     49: 
                     50: 
                     51: /* OleDoc_Init
                     52:  * -----------
                     53:  *
                     54:  *  Initialize the fields of a new OleDoc object. The object is initially
                     55:  *  not associated with a file or an (Untitled) document. This function sets
                     56:  *  the docInitType to DOCTYPE_UNKNOWN. After calling this function the
                     57:  *  caller should call:
                     58:  *      1.) Doc_InitNewFile to set the OleDoc to (Untitled)
                     59:  *      2.) Doc_LoadFromFile to associate the OleDoc with a file.
                     60:  *  This function creates a new window for the document.
                     61:  *
                     62:  *  NOTE: the window is initially created with a NIL size. it must be
                     63:  *        sized and positioned by the caller. also the document is initially
                     64:  *        created invisible. the caller must call OutlineDoc_ShowWindow
                     65:  *        after sizing it to make the document window visible.
                     66:  */
                     67: BOOL OleDoc_Init(LPOLEDOC lpOleDoc, BOOL fDataTransferDoc)
                     68: {
                     69:     LPOLEAPP   lpOleApp = (LPOLEAPP)g_lpApp;
                     70:     LPLINELIST lpLL     = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
                     71: 
                     72:     lpOleDoc->m_cRef                        = 0;
                     73:     lpOleDoc->m_cLock                       = 0;
                     74: 
                     75:     lpOleDoc->m_dwRegROT                    = 0;
                     76:     lpOleDoc->m_lpFileMoniker               = NULL;
                     77:     lpOleDoc->m_fLinkSourceAvail            = FALSE;
                     78:     lpOleDoc->m_lpSrcDocOfCopy              = NULL;
                     79:     lpOleDoc->m_fObjIsClosing               = FALSE;
                     80:     lpOleDoc->m_fObjIsDestroying            = FALSE;
                     81:     lpOleDoc->m_fUpdateEditMenu             = FALSE;
                     82: 
                     83: #if defined( USE_DRAGDROP )
                     84:     lpOleDoc->m_dwTimeEnterScrollArea       = 0;
                     85:     lpOleDoc->m_lastdwScrollDir             = SCROLLDIR_NULL;
                     86:     lpOleDoc->m_fRegDragDrop                = FALSE;
                     87:     lpOleDoc->m_fLocalDrag                  = FALSE;
                     88:     lpOleDoc->m_fCanDropCopy                = FALSE;
                     89:     lpOleDoc->m_fCanDropLink                = FALSE;
                     90:     lpOleDoc->m_fLocalDrop                  = FALSE;
                     91:     lpOleDoc->m_fDragLeave                  = FALSE;
                     92:     lpOleDoc->m_fPendingDrag                = FALSE;
                     93: #endif
                     94: 
                     95:     INIT_INTERFACEIMPL(
                     96:             &lpOleDoc->m_Unknown,
                     97:             &g_OleDoc_UnknownVtbl,
                     98:             lpOleDoc
                     99:     );
                    100: 
                    101:     INIT_INTERFACEIMPL(
                    102:             &lpOleDoc->m_PersistFile,
                    103:             &g_OleDoc_PersistFileVtbl,
                    104:             lpOleDoc
                    105:     );
                    106: 
                    107:     INIT_INTERFACEIMPL(
                    108:             &lpOleDoc->m_OleItemContainer,
                    109:             &g_OleDoc_OleItemContainerVtbl,
                    110:             lpOleDoc
                    111:     );
                    112: 
                    113:     INIT_INTERFACEIMPL(
                    114:             &lpOleDoc->m_DataObject,
                    115:             &g_OleDoc_DataObjectVtbl,
                    116:             lpOleDoc
                    117:     );
                    118: 
                    119: #if defined( USE_DRAGDROP )
                    120:     INIT_INTERFACEIMPL(
                    121:             &lpOleDoc->m_DropSource,
                    122:             &g_OleDoc_DropSourceVtbl,
                    123:             lpOleDoc
                    124:     );
                    125: 
                    126:     INIT_INTERFACEIMPL(
                    127:             &lpOleDoc->m_DropTarget,
                    128:             &g_OleDoc_DropTargetVtbl,
                    129:             lpOleDoc
                    130:     );
                    131: #endif  // USE_DRAGDROP
                    132: 
                    133:     /*
                    134:     ** OLE2NOTE: each user level document addref's the app object in
                    135:     **    order to guarentee that the app does not shut down while the
                    136:     **    doc is still open.
                    137:     */
                    138: 
                    139:     // OLE2NOTE: data transfer documents should not hold the app alive
                    140:     if (! fDataTransferDoc)
                    141:         OleApp_DocLockApp(lpOleApp);
                    142: 
                    143: #if defined( OLE_SERVER )
                    144: 
                    145:     /* OLE2NOTE: perform initialization specific for an OLE server */
                    146:     if (! ServerDoc_Init((LPSERVERDOC)lpOleDoc, fDataTransferDoc))
                    147:         return FALSE;
                    148: 
                    149: #elif defined( OLE_CNTR )
                    150: 
                    151:     /* OLE2NOTE: perform initialization specific for an OLE container */
                    152:     if (! ContainerDoc_Init((LPCONTAINERDOC)lpOleDoc, fDataTransferDoc))
                    153:         return FALSE;
                    154: 
                    155: #endif
                    156: 
                    157:     return TRUE;
                    158: }
                    159: 
                    160: 
                    161: 
                    162: /* OleDoc_InitNewFile
                    163:  * ------------------
                    164:  *
                    165:  *  Initialize the document to be a new (Untitled) document.
                    166:  *  This function sets the docInitType to DOCTYPE_NEW.
                    167:  *
                    168:  *  OLE2NOTE: if this is a visible user document then generate a unique
                    169:  *  untitled name that we can use to register in the RunningObjectTable.
                    170:  *  We need a unique name so that clients can link to data in this document
                    171:  *  even when the document is in the un-saved (untitled) state. it would be
                    172:  *  ambiguous to register two documents titled "Outline1" in the ROT. we
                    173:  *  thus generate the lowest numbered document that is not already
                    174:  *  registered in the ROT.
                    175:  */
                    176: BOOL OleDoc_InitNewFile(LPOLEDOC lpOleDoc)
                    177: {
                    178:     LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
                    179: 
                    180:     static UINT uUnique = 1;
                    181: 
                    182:     OleDbgAssert(lpOutlineDoc->m_docInitType == DOCTYPE_UNKNOWN);
                    183: 
                    184: #if defined( OLE_CNTR )
                    185:     {
                    186:         LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc;
                    187: 
                    188:         OleDbgAssertSz(lpContainerDoc->m_lpStg == NULL,
                    189:                 "Setting to untitled with current file open"
                    190:         );
                    191: 
                    192:         /* Create a temp, (delete-on-release) file base storage
                    193:         **  for the untitled document.
                    194:         */
                    195:         lpContainerDoc->m_lpStg = OleStdCreateRootStorage(
                    196:                 NULL,
                    197:                 STGM_SHARE_EXCLUSIVE
                    198:         );
                    199:         if (! lpContainerDoc->m_lpStg) return FALSE;
                    200:     }
                    201: #endif
                    202: 
                    203:     lpOutlineDoc->m_docInitType = DOCTYPE_NEW;
                    204: 
                    205:     if (! lpOutlineDoc->m_fDataTransferDoc) {
                    206:         /* OLE2NOTE: choose a unique name for a Moniker so that
                    207:         **    potential clients can link to our new, untitled document.
                    208:         **    if links are established (and currently are connected),
                    209:         **    then they will be notified that we have been renamed when
                    210:         **    this document is saved to a file.
                    211:         */
                    212: 
                    213:         lpOleDoc->m_fLinkSourceAvail = TRUE;
                    214: 
                    215:         // REVIEW: should load UNTITLED string from string resource
                    216:         OleStdCreateTempFileMoniker(
                    217:                 UNTITLED,
                    218:                 (UINT FAR*)&uUnique,
                    219:                 lpOutlineDoc->m_szFileName,
                    220:                 &lpOleDoc->m_lpFileMoniker
                    221:         );
                    222: 
                    223:         OLEDBG_BEGIN3("OleStdRegisterAsRunning called\r\n")
                    224:         OleStdRegisterAsRunning(
                    225:                 (LPUNKNOWN)&lpOleDoc->m_PersistFile,
                    226:                 (LPMONIKER)lpOleDoc->m_lpFileMoniker,
                    227:                 &lpOleDoc->m_dwRegROT
                    228:         );
                    229:         OLEDBG_END3
                    230: 
                    231:         lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName;
                    232:         OutlineDoc_SetTitle(lpOutlineDoc);
                    233:     } else {
                    234:         lstrcpy(lpOutlineDoc->m_szFileName, UNTITLED);
                    235:         lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName;
                    236:     }
                    237: 
                    238:     return TRUE;
                    239: }
                    240: 
                    241: 
                    242: /* OleDoc_ShowWindow
                    243:  * -----------------
                    244:  *
                    245:  *      Show the window of the document to the user.
                    246:  *      make sure app window is visible and bring the document to the top.
                    247:  *      if the document is a file-based document or a new untitled
                    248:  *      document, give the user the control over the life-time of the doc.
                    249:  */
                    250: void OleDoc_ShowWindow(LPOLEDOC lpOleDoc)
                    251: {
                    252:     LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
                    253:     LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
                    254:     LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
                    255:     LPLINELIST lpLL     = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
                    256: #if defined( OLE_SERVER )
                    257:     LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
                    258: #endif // OLE_SERVER
                    259: 
                    260:     OLEDBG_BEGIN3("OleDoc_ShowWindow\r\n")
                    261: 
                    262:     /* OLE2NOTE: while the document is visible, we do NOT want it to be
                    263:     **    prematurely destroyed when a linking client disconnects. thus
                    264:     **    we must inform OLE to hold an external lock on our document.
                    265:     **    this arranges that OLE holds at least 1 reference to our
                    266:     **    document that will NOT be released until we release this
                    267:     **    external lock. later, when the document window is hidden, we
                    268:     **    will release this external lock.
                    269:     */
                    270:     if (! IsWindowVisible(lpOutlineDoc->m_hWndDoc)) 
                    271:         OleDoc_Lock(lpOleDoc, TRUE /* fLock */, 0 /* not applicable */);
                    272: 
                    273: #if defined( USE_DRAGDROP )
                    274:     /* OLE2NOTE: since our window is now being made visible, we will
                    275:     **    register our window as a potential drop target. when the
                    276:     **    window is hidden there is no reason to be registered as a
                    277:     **    drop target.
                    278:     */
                    279:     if (! lpOleDoc->m_fRegDragDrop) {
                    280:         OLEDBG_BEGIN2("RegisterDragDrop called\r\n")
                    281:         RegisterDragDrop(
                    282:                 LineList_GetWindow(lpLL),
                    283:                 (LPDROPTARGET)&lpOleDoc->m_DropTarget
                    284:         );
                    285:         OLEDBG_END2
                    286:         lpOleDoc->m_fRegDragDrop = TRUE;
                    287:     }
                    288: #endif  // USE_DRAGDROP
                    289: 
                    290: #if defined( USE_FRAMETOOLS )
                    291:     {
                    292:         /* OLE2NOTE: we need to enable our frame level tools
                    293:         */
                    294:         FrameTools_Enable(lpOutlineDoc->m_lpFrameTools, TRUE);
                    295:     }
                    296: #endif // USE_FRAMETOOLS
                    297: 
                    298: #if defined( OLE_SERVER )
                    299: 
                    300:     if (lpOutlineDoc->m_docInitType == DOCTYPE_EMBEDDED &&
                    301:             lpServerDoc->m_lpOleClientSite != NULL) {
                    302: 
                    303:         /* OLE2NOTE: we must also ask our container to show itself if
                    304:         **    it is not already visible and to scroll us into view. we
                    305:         **    must make sure to call this BEFORE showing our server's
                    306:         **    window and taking focus. we do not want our container's
                    307:         **    window to end up on top.
                    308:         */
                    309:         OLEDBG_BEGIN2("IOleClientSite::ShowObject called\r\n");
                    310:         lpServerDoc->m_lpOleClientSite->lpVtbl->ShowObject(
                    311:                 lpServerDoc->m_lpOleClientSite
                    312:         );
                    313:         OLEDBG_END2
                    314: 
                    315:         /* OLE2NOTE: if we are an embedded object and we are not
                    316:         **    in-place active in our containers window, we must inform our
                    317:         **    embedding container that our window is opening.
                    318:         **    the container must now hatch our object.
                    319:         */
                    320: 
                    321: #if defined( INPLACE_SVR )
                    322:         if (! lpServerDoc->m_fInPlaceActive)
                    323: #endif
                    324:         {
                    325:             OLEDBG_BEGIN2("IOleClientSite::OnShowWindow(TRUE) called\r\n");
                    326:             lpServerDoc->m_lpOleClientSite->lpVtbl->OnShowWindow(
                    327:                     lpServerDoc->m_lpOleClientSite,
                    328:                     TRUE
                    329:             );
                    330:             OLEDBG_END2
                    331:         }
                    332: 
                    333:         /* OLE2NOTE: the life-time of our document is controlled by our
                    334:         **    client and NOT by the user. we are not an independent
                    335:         **    file-level object. we simply want to show our window here.
                    336:         **
                    337:         **    if we are not in-place active (ie. we are opening
                    338:         **    our own window), we must make sure our main app window is
                    339:         **    visible. we do not, however, want to give the user
                    340:         **    control of the App window; we do not want OleApp_ShowWindow
                    341:         **    to call OleApp_Lock on behalf of the user.
                    342:         */
                    343:         if (! IsWindowVisible(lpOutlineApp->m_hWndApp) || 
                    344:                 IsIconic(lpOutlineApp->m_hWndApp)) {
                    345: #if defined( INPLACE_SVR )
                    346:             if (! ((LPSERVERDOC)lpOleDoc)->m_fInPlaceActive)
                    347: #endif
                    348:                 OleApp_ShowWindow(lpOleApp, FALSE /* fGiveUserCtrl */);
                    349:             SetFocus(lpOutlineDoc->m_hWndDoc);
                    350:         }
                    351:         
                    352:     } else
                    353: #endif  // OLE_SERVER
                    354: 
                    355:     {    // DOCTYPE_NEW || DOCTYPE_FROMFILE
                    356: 
                    357:         // we must make sure our app window is visible
                    358:         OleApp_ShowWindow(lpOleApp, TRUE /* fGiveUserCtrl */);
                    359:     }
                    360: 
                    361:     // make document window visible and make sure it is not minimized
                    362:     ShowWindow(lpOutlineDoc->m_hWndDoc, SW_SHOWNORMAL);
                    363:     SetFocus(lpOutlineDoc->m_hWndDoc);
                    364: 
                    365:     OLEDBG_END3
                    366: }
                    367: 
                    368: 
                    369: /* OleDoc_HideWindow
                    370:  * -----------------
                    371:  *
                    372:  *      Hide the window of the document from the user.
                    373:  *      take away the control of the document by the user.
                    374:  */
                    375: void OleDoc_HideWindow(LPOLEDOC lpOleDoc, BOOL fShutdown)
                    376: {
                    377:     LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
                    378:     LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
                    379:     LPLINELIST lpLL     = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
                    380: 
                    381:     if (! IsWindowVisible(lpOutlineDoc->m_hWndDoc))
                    382:         return;     // already visible
                    383: 
                    384:     OLEDBG_BEGIN3("OleDoc_HideWindow\r\n")
                    385: 
                    386: #if defined( USE_DRAGDROP )
                    387:     // The document's window is being hidden, revoke it as a DropTarget
                    388:     if (lpOleDoc->m_fRegDragDrop) {
                    389:         OLEDBG_BEGIN2("RevokeDragDrop called\r\n");
                    390:         RevokeDragDrop(LineList_GetWindow(lpLL));
                    391:         OLEDBG_END2
                    392: 
                    393:         lpOleDoc->m_fRegDragDrop = FALSE ;
                    394:     }
                    395: #endif  // USE_DRAGDROP
                    396: 
                    397:     /* OLE2NOTE: the document is now being hidden, so we must release
                    398:     **    the external lock made when the document was made visible.
                    399:     **    if this is a shutdown situation (fShutdown==TRUE), then OLE
                    400:     **    is instructed to release our document. if this is that last
                    401:     **    external lock on our document, thus enabling our document to
                    402:     **    complete its shutdown operation. If This is not a shutdown
                    403:     **    situation (eg. in-place server hiding its window when
                    404:     **    UIDeactivating or IOleObject::DoVerb(OLEVERB_HIDE) is called),
                    405:     **    then OLE is told to NOT immediately release the document.
                    406:     **    this leaves the document in an unstable state where the next
                    407:     **    Lock/Unlock sequence will shut the document down (eg. a
                    408:     **    linking client connecting and disconnecting).
                    409:     */
                    410:     if (fShutdown && IsWindowVisible(lpOutlineDoc->m_hWndDoc)) 
                    411:         OleDoc_Lock(lpOleDoc, FALSE /* fLock */, fShutdown);
                    412: 
                    413:     ShowWindow(((LPOUTLINEDOC)lpOleDoc)->m_hWndDoc, SW_HIDE);
                    414: 
                    415: #if defined( OLE_SERVER )
                    416:     {
                    417:         LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
                    418: 
                    419:         /* OLE2NOTE: if we are an embedded object and we are not
                    420:         **    in-place active, we must inform our
                    421:         **    embedding container that our window is hiding (closing
                    422:         **    from the user's perspective). the container must now
                    423:         **    un-hatch our object.
                    424:         */
                    425:         if (lpServerDoc->m_lpOleClientSite != NULL
                    426: #if defined( INPLACE_SVR )
                    427:             && !lpServerDoc->m_fInPlaceVisible
                    428: #endif
                    429:         ) {
                    430:             OLEDBG_BEGIN2("IOleClientSite::OnShowWindow(FALSE) called\r\n");
                    431:             lpServerDoc->m_lpOleClientSite->lpVtbl->OnShowWindow(
                    432:                     lpServerDoc->m_lpOleClientSite,
                    433:                     FALSE
                    434:             );
                    435:             OLEDBG_END2
                    436:         }
                    437:     }
                    438: #endif
                    439: 
                    440:     /* OLE2NOTE: if there are no more documents visible to the user.
                    441:     **    and the app itself is not under user control, then
                    442:     **    it has no reason to stay visible. we thus should hide the
                    443:     **    app. we can not directly destroy the app, because it may be
                    444:     **    validly being used programatically by another client
                    445:     **    application and should remain running. it should simply be
                    446:     **    hidded from the user.
                    447:     */
                    448:     OleApp_HideIfNoReasonToStayVisible(lpOleApp);
                    449:     OLEDBG_END3
                    450: }
                    451: 
                    452: 
                    453: /* OleDoc_Lock
                    454: ** -----------
                    455: **    Lock/Unlock the Doc object. if the last lock is unlocked and
                    456: **    fLastUnlockReleases == TRUE, then the Doc object will shut down
                    457: **    (ie. it will recieve its final release and its refcnt will go to 0).
                    458: */
                    459: HRESULT OleDoc_Lock(LPOLEDOC lpOleDoc, BOOL fLock, BOOL fLastUnlockReleases)
                    460: {
                    461:     HRESULT hrErr;
                    462: 
                    463: #if defined( _DEBUG )
                    464:     if (fLock) {
                    465:         OLEDBG_BEGIN2("CoLockObjectExternal(lpDoc,TRUE) called\r\n")
                    466:     } else {
                    467:         if (fLastUnlockReleases) 
                    468:             OLEDBG_BEGIN2("CoLockObjectExternal(lpDoc,FALSE,TRUE) called\r\n")
                    469:         else
                    470:             OLEDBG_BEGIN2("CoLockObjectExternal(lpDoc,FALSE,FALSE) called\r\n")
                    471:     }
                    472: #endif  // _DEBUG
                    473: 
                    474:     OleDoc_AddRef(lpOleDoc);       // artificial AddRef to make object stable
                    475: 
                    476:     hrErr = CoLockObjectExternal(
                    477:             (LPUNKNOWN)&lpOleDoc->m_Unknown, fLock, fLastUnlockReleases);
                    478: 
                    479:     OleDoc_Release(lpOleDoc);       // release artificial AddRef above
                    480: 
                    481:     OLEDBG_END2
                    482:     return hrErr;
                    483: }
                    484: 
                    485: 
                    486: /* OleDoc_AddRef
                    487: ** -------------
                    488: **
                    489: **  increment the ref count of the document object.
                    490: **
                    491: **    Returns the new ref count on the object
                    492: */
                    493: ULONG OleDoc_AddRef(LPOLEDOC lpOleDoc)
                    494: {
                    495:     ++lpOleDoc->m_cRef;
                    496: 
                    497:     OleDbgOutRefCnt4(
                    498:             "OleDoc_AddRef: cRef++\r\n",
                    499:             lpOleDoc,
                    500:             lpOleDoc->m_cRef
                    501:     );
                    502: 
                    503:     return lpOleDoc->m_cRef;
                    504: }
                    505: 
                    506: 
                    507: /* OleDoc_Release
                    508: ** --------------
                    509: **
                    510: **  decrement the ref count of the document object.
                    511: **    if the ref count goes to 0, then the document is destroyed.
                    512: **
                    513: **    Returns the remaining ref count on the object
                    514: */
                    515: ULONG OleDoc_Release (LPOLEDOC lpOleDoc)
                    516: {
                    517:     ULONG cRef;
                    518:     LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
                    519:     LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
                    520: 
                    521:     OleDbgAssertSz (lpOleDoc->m_cRef > 0, "Release called with cRef == 0");
                    522: 
                    523:     /*********************************************************************
                    524:     ** OLE2NOTE: when the obj refcnt == 0, then destroy the object.     **
                    525:     **     otherwise the object is still in use.                        **
                    526:     *********************************************************************/
                    527: 
                    528:     cRef = --lpOleDoc->m_cRef;
                    529: 
                    530:     OleDbgOutRefCnt4(
                    531:             "OleDoc_Release: cRef--\r\n", lpOleDoc, cRef);
                    532: 
                    533:     if (cRef == 0)
                    534:         OutlineDoc_Destroy((LPOUTLINEDOC)lpOleDoc);
                    535: 
                    536:     return cRef;
                    537: }
                    538: 
                    539: 
                    540: /* OleDoc_QueryInterface
                    541: ** ---------------------
                    542: **
                    543: ** Retrieve a pointer to an interface on the document object.
                    544: **
                    545: **    OLE2NOTE: this function will AddRef the ref cnt of the object.
                    546: **
                    547: **    Returns S_OK if interface is successfully retrieved.
                    548: **            S_FALSE if the interface is not supported
                    549: */
                    550: HRESULT OleDoc_QueryInterface(
                    551:         LPOLEDOC          lpOleDoc,
                    552:         REFIID            riid,
                    553:         LPVOID FAR*       lplpvObj
                    554: )
                    555: {
                    556:     LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
                    557:     SCODE sc = E_NOINTERFACE;
                    558: 
                    559:     /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */
                    560:     *lplpvObj = NULL;
                    561: 
                    562:     if (IsEqualIID(riid, &IID_IUnknown)) {
                    563:         OleDbgOut4("OleDoc_QueryInterface: IUnknown* RETURNED\r\n");
                    564: 
                    565:         *lplpvObj = (LPVOID) &lpOleDoc->m_Unknown;
                    566:         OleDoc_AddRef(lpOleDoc);
                    567:         sc = S_OK;
                    568:     }
                    569:     else if(lpOutlineDoc->m_fDataTransferDoc
                    570:             && IsEqualIID(riid, &IID_IDataObject)) {
                    571:         OleDbgOut4("OleDoc_QueryInterface: IDataObject* RETURNED\r\n");
                    572: 
                    573:         *lplpvObj = (LPVOID) &lpOleDoc->m_DataObject;
                    574:         OleDoc_AddRef(lpOleDoc);
                    575:         sc = S_OK;
                    576:     }
                    577: 
                    578: #if defined( USE_DRAGDROP )
                    579: 
                    580:     /* DropSource is only needed on a DataTransferDoc */
                    581:     else if(lpOutlineDoc->m_fDataTransferDoc
                    582:             && IsEqualIID(riid, &IID_IDropSource)) {
                    583: 
                    584:         OleDbgOut4("OleDoc_QueryInterface: IDropSource* RETURNED\r\n");
                    585: 
                    586:         *lplpvObj = (LPVOID) &lpOleDoc->m_DropSource;
                    587:         OleDoc_AddRef(lpOleDoc);
                    588:         sc = S_OK;
                    589:     }
                    590: #endif
                    591: 
                    592:     /* OLE2NOTE: if this document is a DataTransferDocument used to
                    593:     **    support a clipboard or drag/drop operation, then it should
                    594:     **    only expose IUnknown, IDataObject, and IDropSource
                    595:     **    interfaces. if the document is a normal user document, then
                    596:     **    we will also continue to consider our other interfaces.
                    597:     */
                    598:     if (lpOutlineDoc->m_fDataTransferDoc)
                    599:         goto done;
                    600: 
                    601:     if(IsEqualIID(riid, &IID_IPersist) || IsEqualIID(riid, &IID_IPersistFile)) {
                    602:         OleDbgOut4("OleDoc_QueryInterface: IPersistFile* RETURNED\r\n");
                    603: 
                    604:         *lplpvObj = (LPVOID) &lpOleDoc->m_PersistFile;
                    605:         OleDoc_AddRef(lpOleDoc);
                    606:         sc = S_OK;
                    607:     }
                    608:     else if(IsEqualIID(riid, &IID_IOleItemContainer) ||
                    609:             IsEqualIID(riid, &IID_IOleContainer) ||
                    610:             IsEqualIID(riid, &IID_IParseDisplayName) ) {
                    611:         OleDbgOut4("OleDoc_QueryInterface: IOleItemContainer* RETURNED\r\n");
                    612: 
                    613:         *lplpvObj = (LPVOID) &lpOleDoc->m_OleItemContainer;
                    614:         OleDoc_AddRef(lpOleDoc);
                    615:         sc = S_OK;
                    616:     }
                    617: 
                    618: #if defined( USE_DRAGDROP )
                    619: 
                    620:     else if(IsEqualIID(riid, &IID_IDropTarget)) {
                    621:         OleDbgOut4("OleDoc_QueryInterface: IDropTarget* RETURNED\r\n");
                    622: 
                    623:         *lplpvObj = (LPVOID) &lpOleDoc->m_DropTarget;
                    624:         OleDoc_AddRef(lpOleDoc);
                    625:         sc = S_OK;
                    626:     }
                    627: #endif
                    628: 
                    629: #if defined( OLE_CNTR ) && defined ( IID_IOleUILinkContainer )
                    630: 
                    631:     else if (IsEqualIID(riid, &IID_IOleUILinkContainer)) {
                    632:         OleDbgOut4("OleDoc_QueryInterface: IOleUILinkContainer* RETURNED\r\n");
                    633: 
                    634:         *lplpvObj=(LPVOID)&((LPCONTAINERERDOC)lpOleDoc)->m_OleUILinkContainer;
                    635:         OleDoc_AddRef(lpOleDoc);
                    636:         sc = S_OK;
                    637:     }
                    638: #endif
                    639: 
                    640: #if defined( OLE_SERVER )
                    641: 
                    642:     /* OLE2NOTE: if OLE server version, than also offer the server
                    643:     **    specific interfaces: IOleObject and IPersistStorage.
                    644:     */
                    645:     else if (IsEqualIID(riid, &IID_IOleObject)) {
                    646:         OleDbgOut4("OleDoc_QueryInterface: IOleObject* RETURNED\r\n");
                    647: 
                    648:         *lplpvObj = (LPVOID) &((LPSERVERDOC)lpOleDoc)->m_OleObject;
                    649:         OleDoc_AddRef(lpOleDoc);
                    650:         sc = S_OK;
                    651:     }
                    652:     else if(IsEqualIID(riid, &IID_IPersistStorage)) {
                    653:         OleDbgOut4("OleDoc_QueryInterface: IPersistStorage* RETURNED\r\n");
                    654: 
                    655:         *lplpvObj = (LPVOID) &((LPSERVERDOC)lpOleDoc)->m_PersistStorage;
                    656:         OleDoc_AddRef(lpOleDoc);
                    657:         sc = S_OK;
                    658:     }
                    659:     else if(IsEqualIID(riid, &IID_IDataObject)) {
                    660:         OleDbgOut4("OleDoc_QueryInterface: IDataObject* RETURNED\r\n");
                    661: 
                    662:         *lplpvObj = (LPVOID) &lpOleDoc->m_DataObject;
                    663:         OleDoc_AddRef(lpOleDoc);
                    664:         sc = S_OK;
                    665:     }
                    666: 
                    667: #if defined( SVR_TREATAS )
                    668:     else if(IsEqualIID(riid, &IID_IStdMarshalInfo)) {
                    669:         OleDbgOut4("OleDoc_QueryInterface: IStdMarshalInfo* RETURNED\r\n");
                    670: 
                    671:         *lplpvObj = (LPVOID) &((LPSERVERDOC)lpOleDoc)->m_StdMarshalInfo;
                    672:         OleDoc_AddRef(lpOleDoc);
                    673:         sc = S_OK;
                    674:     }
                    675: #endif  // SVR_TREATAS
                    676: 
                    677: #if defined( INPLACE_SVR )
                    678:     else if (IsEqualIID(riid, &IID_IOleWindow) ||
                    679:              IsEqualIID(riid, &IID_IOleInPlaceObject)) {
                    680:         OleDbgOut4("OleDoc_QueryInterface: IOleInPlaceObject* RETURNED\r\n");
                    681: 
                    682:         *lplpvObj = (LPVOID) &((LPSERVERDOC)lpOleDoc)->m_OleInPlaceObject;
                    683:         OleDoc_AddRef(lpOleDoc);
                    684:         sc = S_OK;
                    685:     }
                    686: #endif // INPLACE_SVR
                    687: #endif // OLE_SERVER
                    688: 
                    689: done:
                    690:     OleDbgQueryInterfaceMethod(*lplpvObj);
                    691: 
                    692:     return ResultFromScode(sc);
                    693: }
                    694: 
                    695: 
                    696: /* OleDoc_Close
                    697:  * ------------
                    698:  *
                    699:  *  Close the document.
                    700:  *      This functions performs the actions that are in common to all
                    701:  *      document types which derive from OleDoc (eg. ContainerDoc and
                    702:  *      ServerDoc) which are required to close a document.
                    703:  *
                    704:  *  Returns:
                    705:  *      FALSE -- user canceled the closing of the doc.
                    706:  *      TRUE -- the doc was successfully closed
                    707:  */
                    708: 
                    709: BOOL OleDoc_Close(LPOLEDOC lpOleDoc, DWORD dwSaveOption)
                    710: {
                    711:     LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
                    712:     LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
                    713:     LPOLEDOC lpClipboardDoc;
                    714:     LPLINELIST lpLL     = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
                    715: 
                    716:     if (! lpOleDoc)
                    717:         return TRUE;    // active doc's are already destroyed
                    718: 
                    719:     if (lpOleDoc->m_fObjIsClosing)
                    720:         return TRUE;    // Closing is already in progress
                    721: 
                    722:     OLEDBG_BEGIN3("OleDoc_Close\r\n")
                    723: 
                    724:     if (! OutlineDoc_CheckSaveChanges((LPOUTLINEDOC)lpOleDoc, dwSaveOption)) {
                    725:         OLEDBG_END3
                    726:         return FALSE;           // cancel closing the doc
                    727:     }
                    728: 
                    729:     lpOleDoc->m_fObjIsClosing = TRUE;   // guard against recursive call
                    730: 
                    731:     /* OLE2NOTE: in order to have a stable app and doc during the
                    732:     **    process of closing, we intially AddRef the App and Doc ref
                    733:     **    cnts and later Release them. These initial AddRefs are
                    734:     **    artificial; they simply guarantee that these objects do not
                    735:     **    get destroyed until the end of this routine.
                    736:     */
                    737:     OleApp_AddRef(lpOleApp);
                    738:     OleDoc_AddRef(lpOleDoc);
                    739: 
                    740: #if defined( OLE_CNTR )
                    741:     {
                    742:         LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc;
                    743: 
                    744:         /* OLE2NOTE: force all OLE objects to close. this forces all
                    745:         **    OLE object to transition from running to loaded. we can
                    746:         **    NOT exit if any embeddings are still running.
                    747:         **    if an object can't be closed then we will abort closing
                    748:         **    our document.
                    749:         */
                    750:         if (! ContainerDoc_CloseAllOleObjects(lpContainerDoc)) {
                    751:             OleDoc_Release(lpOleDoc);       // release artificial AddRef above
                    752:             OleApp_Release(lpOleApp);       // release artificial AddRef above
                    753:             lpOleDoc->m_fObjIsClosing = FALSE; // guard against recursive call
                    754: 
                    755:             OLEDBG_END3
                    756:             return FALSE;
                    757:         }
                    758:     }
                    759: #endif
                    760: 
                    761: #if defined( INPLACE_SVR )
                    762:     /* OLE2NOTE: if the server is currently in-place active we must
                    763:     **    deactivate it now before closing
                    764:     */
                    765:     ServerDoc_DoInPlaceDeactivate((LPSERVERDOC)lpOleDoc); 
                    766: #endif
                    767: 
                    768:     /* OLE2NOTE: if this document is the source of data for the 
                    769:     **    clipboard, then flush the clipboard. it is important to flush
                    770:     **    the clipboard BEFORE calling sending any notifications to
                    771:     **    clients (eg. IOleClientSite::OnShowWindow(FALSE)) which could
                    772:     **    give them a chance to run and try to get our clipboard data 
                    773:     **    object that we want to destroy. (eg. our app tries to
                    774:     **    update the paste button of the toolbar when
                    775:     **    WM_ACTIVATEAPP is received.) 
                    776:     */
                    777:     lpClipboardDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc;
                    778:     if (lpClipboardDoc && 
                    779:         lpClipboardDoc->m_lpSrcDocOfCopy == lpOleDoc) {
                    780:         OleApp_FlushClipboard(lpOleApp);
                    781:     }
                    782: 
                    783:     /* OLE2NOTE: Revoke the object from the Running Object Table. it is
                    784:     **    best if the object is revoke prior to calling
                    785:     **    COLockObjectExternal(FALSE,TRUE) which is called when the
                    786:     **    document window is hidden from the user.
                    787:     */
                    788:     OLEDBG_BEGIN3("OleStdRevokeAsRunning called\r\n")
                    789:     OleStdRevokeAsRunning(&lpOleDoc->m_dwRegROT);
                    790:     OLEDBG_END3
                    791: 
                    792:     /* OLE2NOTE: if the user is in control of the document, the user
                    793:     **    accounts for one refcnt on the document. Closing the
                    794:     **    document is achieved by releasing the object on behalf of
                    795:     **    the user. if the document is not referenced by any other
                    796:     **    clients, then the document will also be destroyed. if it
                    797:     **    is referenced by other clients, then it will remain until
                    798:     **    they release it. it is important to hide the window and call
                    799:     **    IOleClientSite::OnShowWindow(FALSE) BEFORE sending OnClose
                    800:     **    notification.
                    801:     */
                    802:     OleDoc_HideWindow(lpOleDoc, TRUE);
                    803: 
                    804: #if defined( OLE_SERVER )
                    805:     {
                    806:         LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
                    807:         LPSERVERNAMETABLE lpServerNameTable =
                    808:             (LPSERVERNAMETABLE)((LPOUTLINEDOC)lpOleDoc)->m_lpNameTable;
                    809: 
                    810:         /* OLE2NOTE: force all pseudo objects to close. this informs all
                    811:         **    linking clients of pseudo objects to release their PseudoObj.
                    812:         */
                    813:         ServerNameTable_CloseAllPseudoObjs(lpServerNameTable);
                    814: 
                    815:         /* OLE2NOTE: send last OnDataChange notification to clients
                    816:         **    that have registered for data notifications when object
                    817:         **    stops running (ADVF_DATAONSTOP), if the data in our
                    818:         **    object has ever changed. it is best to only send this
                    819:         **    notification if necessary.
                    820:         */
                    821:         if (lpServerDoc->m_fSendDataOnStop 
                    822:                 && lpServerDoc->m_lpDataAdviseHldr) {
                    823:             ServerDoc_SendAdvise(
                    824:                     (LPSERVERDOC)lpOleDoc,
                    825:                     OLE_ONDATACHANGE,
                    826:                     NULL,   /* lpmkDoc -- not relevant here */
                    827:                     ADVF_DATAONSTOP
                    828:             );
                    829: 
                    830:             /* OLE2NOTE: we just sent the last data notification that we
                    831:             **    need to send; release our DataAdviseHolder. we SHOULD be
                    832:             **    the only one using it.
                    833:             */
                    834: 
                    835:             OleStdVerifyRelease(
                    836:                     (LPUNKNOWN)lpServerDoc->m_lpDataAdviseHldr,
                    837:                     "DataAdviseHldr not released properly"
                    838:             );
                    839:             lpServerDoc->m_lpDataAdviseHldr = NULL;
                    840:         }
                    841: 
                    842:         // OLE2NOTE: inform all of our linking clients that we are closing.
                    843: 
                    844: 
                    845:         if (lpServerDoc->m_lpOleAdviseHldr) {
                    846:             ServerDoc_SendAdvise(
                    847:                     (LPSERVERDOC)lpOleDoc,
                    848:                     OLE_ONCLOSE,
                    849:                     NULL,   /* lpmkDoc -- not relevant here */
                    850:                     0       /* advf -- not relevant here */
                    851:             );
                    852: 
                    853:             /* OLE2NOTE: OnClose is the last notification that we need to
                    854:             **    send; release our OleAdviseHolder. we SHOULD be the only
                    855:             **    one using it. this will make our destructor realize that
                    856:             **    OnClose notification has already been sent.
                    857:             */
                    858:             OleStdVerifyRelease(
                    859:                     (LPUNKNOWN)lpServerDoc->m_lpOleAdviseHldr,
                    860:                     "OleAdviseHldr not released properly"
                    861:             );
                    862:             lpServerDoc->m_lpOleAdviseHldr = NULL;
                    863:         }
                    864: 
                    865:         /* release our Container's ClientSite. */
                    866:         if(lpServerDoc->m_lpOleClientSite) {
                    867:             OleStdRelease((LPUNKNOWN)lpServerDoc->m_lpOleClientSite);
                    868:             lpServerDoc->m_lpOleClientSite = NULL;
                    869:         }
                    870:     }
                    871: #endif
                    872: 
                    873:     /* OLE2NOTE: this call forces all external connections to our
                    874:     **    object to close down and therefore guarantees that we receive
                    875:     **    all releases associated with those external connections.
                    876:     */
                    877:     OLEDBG_BEGIN2("CoDisconnectObject(lpDoc) called\r\n")
                    878:     CoDisconnectObject((LPUNKNOWN)&lpOleDoc->m_Unknown, 0);
                    879:     OLEDBG_END2
                    880: 
                    881:     OleDoc_Release(lpOleDoc);       // release artificial AddRef above
                    882:     OleApp_Release(lpOleApp);       // release artificial AddRef above
                    883: 
                    884:     OLEDBG_END3
                    885:     return TRUE;
                    886: }
                    887: 
                    888: 
                    889: /* OleDoc_Destroy
                    890:  * --------------
                    891:  *  
                    892:  *  Free all OLE related resources that had been allocated for a document.  
                    893:  */
                    894: void OleDoc_Destroy(LPOLEDOC lpOleDoc)
                    895: {
                    896:     LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
                    897:     LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
                    898: 
                    899:     if (lpOleDoc->m_fObjIsDestroying) 
                    900:         return;     // Doc destruction is already in progress
                    901:     
                    902:     lpOleDoc->m_fObjIsDestroying = TRUE;    // guard against recursive call
                    903: 
                    904:     /* OLE2NOTE: if the document destructor is called directly because
                    905:     **    the object's refcnt went to 0 (ie. without OleDoc_Close first
                    906:     **    being called), then we need to make sure that the document is
                    907:     **    properly closed before destroying the object. this scenario
                    908:     **    could arise during a silent-update of a link. calling
                    909:     **    OleDoc_Close here guarantees that the clipboard will be
                    910:     **    properly flushed, the doc's moniker will be properly revoked,
                    911:     **    the document will be saved if necessary, etc.
                    912:     */
                    913:     if (!lpOutlineDoc->m_fDataTransferDoc && !lpOleDoc->m_fObjIsClosing)
                    914:         OleDoc_Close(lpOleDoc, OLECLOSE_SAVEIFDIRTY);
                    915: 
                    916: #if defined( OLE_SERVER )
                    917:     {
                    918:         LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
                    919:         /* OLE2NOTE: perform processing specific for an OLE server */
                    920: 
                    921: #if defined( SVR_TREATAS )
                    922:         if (lpServerDoc->m_lpszTreatAsType) {
                    923:             OleStdFreeString(lpServerDoc->m_lpszTreatAsType, NULL);
                    924:             lpServerDoc->m_lpszTreatAsType = NULL;
                    925:         }
                    926: #endif // SVR_TREATAS
                    927: 
                    928: #if defined( INPLACE_SVR )
                    929:         if (IsWindow(lpServerDoc->m_hWndHatch))
                    930:             DestroyWindow(lpServerDoc->m_hWndHatch);
                    931: #endif  // INPLACE_SVR
                    932:     }
                    933: #endif  // OLE_SERVER
                    934: 
                    935: 
                    936: #if defined( OLE_CNTR )
                    937:     {
                    938:         LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc;
                    939:         /* OLE2NOTE: perform processing specific for an OLE container */
                    940: 
                    941:         if (lpContainerDoc->m_lpStg) {
                    942:             /* release our doc storage. */
                    943:             OleStdRelease((LPUNKNOWN)lpContainerDoc->m_lpStg);
                    944:             lpContainerDoc->m_lpStg = NULL;
                    945:         }
                    946:     }
                    947: #endif  // OLE_CNTR
                    948: 
                    949:     if (lpOleDoc->m_lpFileMoniker) {
                    950:         OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpFileMoniker);
                    951:         lpOleDoc->m_lpFileMoniker = NULL;
                    952:     }
                    953: 
                    954:     /*****************************************************************
                    955:     ** OLE2NOTE: each document addref's the app object in order to  **
                    956:     **    guarentee that the app does not shut down while the doc   **
                    957:     **    is still open. since this doc is now destroyed, we will   **
                    958:     **    release this refcnt now. if there are now more open       **
                    959:     **    documents AND the app is not under the control of the     **
                    960:     **    user (ie. launched by OLE) then the app will revoke its   **
                    961:     **    ClassFactory. if there are no more references to the      **
                    962:     **    ClassFactory after it is revoked, then the app will shut  **
                    963:     **    down. this whole procedure is triggered by calling        **
                    964:     **    OutlineApp_DocUnlockApp.                                  **
                    965:     *****************************************************************/
                    966: 
                    967:     OutlineApp_DocUnlockApp(lpOutlineApp, lpOutlineDoc);
                    968: }
                    969: 
                    970: 
                    971: /* OleDoc_SetUpdateEditMenuFlag
                    972:  * ----------------------------
                    973:  *
                    974:  *  Purpose:
                    975:  *      Set/clear the UpdateEditMenuFlag in OleDoc.
                    976:  *
                    977:  *  Parameters:
                    978:  *      fUpdate     new value of the flag
                    979:  *
                    980:  *  Returns:
                    981:  */
                    982: void OleDoc_SetUpdateEditMenuFlag(LPOLEDOC lpOleDoc, BOOL fUpdate)
                    983: {
                    984:     if (!lpOleDoc)
                    985:         return;
                    986: 
                    987:     lpOleDoc->m_fUpdateEditMenu = fUpdate;
                    988: }
                    989: 
                    990: 
                    991: /* OleDoc_GetUpdateEditMenuFlag
                    992:  * ----------------------------
                    993:  *
                    994:  *  Purpose:
                    995:  *      Get the value of the UpdateEditMenuFlag in OleDoc
                    996:  *
                    997:  *  Parameters:
                    998:  *
                    999:  *  Returns:
                   1000:  *      value of the flag
                   1001:  */
                   1002: BOOL OleDoc_GetUpdateEditMenuFlag(LPOLEDOC lpOleDoc)
                   1003: {
                   1004:     if (!lpOleDoc)
                   1005:         return FALSE;
                   1006: 
                   1007:     return lpOleDoc->m_fUpdateEditMenu;
                   1008: }
                   1009: 
                   1010: 
                   1011: 
                   1012: /*************************************************************************
                   1013: ** OleDoc::IUnknown interface implementation
                   1014: *************************************************************************/
                   1015: 
                   1016: STDMETHODIMP OleDoc_Unk_QueryInterface(
                   1017:         LPUNKNOWN           lpThis,
                   1018:         REFIID              riid,
                   1019:         LPVOID FAR*         lplpvObj
                   1020: )
                   1021: {
                   1022:     LPOLEDOC lpOleDoc = ((struct CDocUnknownImpl FAR*)lpThis)->lpOleDoc;
                   1023: 
                   1024:     return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);
                   1025: }
                   1026: 
                   1027: 
                   1028: STDMETHODIMP_(ULONG) OleDoc_Unk_AddRef(LPUNKNOWN lpThis)
                   1029: {
                   1030:     LPOLEDOC lpOleDoc = ((struct CDocUnknownImpl FAR*)lpThis)->lpOleDoc;
                   1031: 
                   1032:     OleDbgAddRefMethod(lpThis, "IUnknown");
                   1033: 
                   1034:     return OleDoc_AddRef(lpOleDoc);
                   1035: }
                   1036: 
                   1037: 
                   1038: STDMETHODIMP_(ULONG) OleDoc_Unk_Release (LPUNKNOWN lpThis)
                   1039: {
                   1040:     LPOLEDOC lpOleDoc = ((struct CDocUnknownImpl FAR*)lpThis)->lpOleDoc;
                   1041: 
                   1042:     OleDbgReleaseMethod(lpThis, "IUnknown");
                   1043: 
                   1044:     return OleDoc_Release(lpOleDoc);
                   1045: }

unix.superglobalmegacorp.com

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