summaryrefslogblamecommitdiffstats
path: root/private/windows/ole/client/doc.c
blob: f0a5bbeac674fd04ffec1a6edc767ddf2b704f15 (plain) (tree)































































































































































































































































































































                                                                              
/****************************** Module Header ******************************\
* Module Name: doc.c
*
* PURPOSE: Contains client document maipulation routines.
*
* Created: Jan 1991
*
* Copyright (c) 1991  Microsoft Corporation
*
* History:
*   Srinik  01/11/1191  Orginal
*   curts created portable version for WIN16/32
*
\***************************************************************************/

#include <windows.h>
#include "dll.h"

#ifdef FIREWALLS
extern BOOL     bShowed;
extern void FARINTERNAL ShowVersion (void);
#endif

LPCLIENTDOC lpHeadDoc = NULL;
LPCLIENTDOC lpTailDoc  = NULL;

extern ATOM aClipDoc;
extern int  iUnloadableDll;

#ifdef WIN16
#pragma alloc_text(_TEXT, CheckClientDoc, CheckPointer)
#endif

OLESTATUS FAR PASCAL OleRegisterClientDoc(
    LPCSTR               lpClassName,
    LPCSTR               lpDocName,
    LONG                future,
    LHCLIENTDOC FAR *   lplhclientdoc
){
    HANDLE      hdoc = NULL;
    LPCLIENTDOC lpdoc;
    OLESTATUS   retVal;
    ATOM        aClass, aDoc;

    UNREFERENCED_PARAMETER(future);

#ifdef FIREWALLS
    if (!bShowed && (ole_flags & DEBUG_MESSAGEBOX))
        ShowVersion ();
#endif

    Puts ("OleRegisterClientDoc");

    PROBE_MODE(bProtMode);
    FARPROBE_WRITE(lplhclientdoc);
    *lplhclientdoc = 0;
    FARPROBE_READ(lpClassName);
    FARPROBE_READ(lpDocName);
    if (!lpDocName[0])
        return OLE_ERROR_NAME;

    aDoc = GlobalAddAtom (lpDocName);
    aClass = GlobalAddAtom (lpClassName);

    if (!(hdoc = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_SHARE,
                        sizeof(CLIENTDOC)))
            || !(lpdoc = (LPCLIENTDOC) GlobalLock (hdoc))) {
        retVal =  OLE_ERROR_MEMORY;
        goto err;
    }

    lpdoc->docId[0] = 'C';
    lpdoc->docId[1] = 'D';
    lpdoc->aClass   = aClass;
    lpdoc->aDoc     = aDoc;
    lpdoc->hdoc     = hdoc;
    lpdoc->dwFileVer= (DWORD)MAKELONG(wReleaseVer,OS_WIN16);

    // Documents are doubly linked

    if (!lpHeadDoc) {
#ifdef FIREWALLS
        ASSERT(!lpTailDoc, "lpTailDoc is not NULL");
#endif
        lpHeadDoc = lpTailDoc = lpdoc;
    }
    else {
        lpTailDoc->lpNextDoc = lpdoc;
        lpdoc->lpPrevDoc = lpTailDoc;
        lpTailDoc = lpdoc;
    }

    *lplhclientdoc = (LHCLIENTDOC) lpdoc;

    // inform the link manager;
    return OLE_OK;

err:
    if (aClass)
        GlobalDeleteAtom (aClass);

    if (aDoc)
        GlobalDeleteAtom (aDoc);

    if (hdoc)
        GlobalFree (hdoc);

    return retVal;
}


OLESTATUS FAR PASCAL OleRevokeClientDoc (
   LHCLIENTDOC lhclientdoc
){
    LPCLIENTDOC lpdoc;

    Puts ("OleRevokeClientDoc");

    // if there is any handler dll that can be freed up, free it now.
    // Otherwise it might become too late if the app quits.
    if (iUnloadableDll)
        UnloadDll ();

    if (!CheckClientDoc (lpdoc = (LPCLIENTDOC) lhclientdoc))
        return OLE_ERROR_HANDLE;

    if (lpdoc->lpHeadObj) {
        ASSERT (0, "OleRevokeClientDoc() called without freeing all objects");
        return OLE_ERROR_NOT_EMPTY;
    }

    if (lpdoc->aClass)
        GlobalDeleteAtom (lpdoc->aClass);

    if (lpdoc->aDoc)
        GlobalDeleteAtom (lpdoc->aDoc);

    // if only one doc is in the list then it's prev and next docs are NULL

    if (lpdoc == lpHeadDoc)
        lpHeadDoc = lpdoc->lpNextDoc;

    if (lpdoc == lpTailDoc)
        lpTailDoc = lpdoc->lpPrevDoc;

    if (lpdoc->lpPrevDoc)
        lpdoc->lpPrevDoc->lpNextDoc = lpdoc->lpNextDoc;

    if (lpdoc->lpNextDoc)
        lpdoc->lpNextDoc->lpPrevDoc = lpdoc->lpPrevDoc;

    GlobalUnlock (lpdoc->hdoc);
    GlobalFree (lpdoc->hdoc);

    // inform link manager
    return OLE_OK;
}


OLESTATUS FAR PASCAL OleRenameClientDoc (
    LHCLIENTDOC lhclientdoc,
    LPCSTR       lpNewDocName
){
    LPCLIENTDOC lpdoc;
    ATOM        aNewDoc;
    LPOLEOBJECT lpobj = NULL;

    if (!CheckClientDoc (lpdoc = (LPCLIENTDOC) lhclientdoc))
        return OLE_ERROR_HANDLE;

    FARPROBE_READ(lpNewDocName);

    aNewDoc = GlobalAddAtom (lpNewDocName);
    if (aNewDoc == lpdoc->aDoc) {
        if (aNewDoc)
            GlobalDeleteAtom (aNewDoc);
        return OLE_OK;
    }

    // Document name has changed. So, change the topic of all embedded objects
    if (lpdoc->aDoc)
        GlobalDeleteAtom (lpdoc->aDoc);
    lpdoc->aDoc = aNewDoc;

    while (lpobj = DocGetNextObject (lpdoc, lpobj)) {
        if (lpobj->ctype == CT_EMBEDDED)
            if (OleQueryReleaseStatus (lpobj) != OLE_BUSY)
                SetEmbeddedTopic ((LPOBJECT_LE) lpobj);
    }

    return OLE_OK;
}


OLESTATUS FAR PASCAL OleRevertClientDoc (
    LHCLIENTDOC lhclientdoc
){
    // if there is any handler dll that can be freed up, free it now.
    // Otherwise it might become too late if the app quits.
    if (iUnloadableDll)
        UnloadDll ();

    if (!CheckClientDoc ((LPCLIENTDOC) lhclientdoc))
        return OLE_ERROR_HANDLE;

    return OLE_OK;
}


OLESTATUS FAR PASCAL OleSavedClientDoc (
    LHCLIENTDOC lhclientdoc
){
    if (!CheckClientDoc ((LPCLIENTDOC) lhclientdoc))
        return OLE_ERROR_HANDLE;

    return OLE_OK;
}

OLESTATUS FAR PASCAL OleEnumObjects (
    LHCLIENTDOC         lhclientdoc,
    LPOLEOBJECT FAR *   lplpobj
){
    if (!CheckClientDoc ((LPCLIENTDOC) lhclientdoc))
        return OLE_ERROR_HANDLE;

    FARPROBE_WRITE(lplpobj);

    if (*lplpobj) {
        // we are making lhclientdoc field of the object NULL at deletion
        // time. The check (*lpobj->lhclientdoc != lhclientdoc) will take care
        // of the case where same chunk of memory is allocated again for the
        // same pointer and old contents are not erased yet.
        if (!FarCheckObject (*lplpobj)
                || ((*lplpobj)->lhclientdoc != lhclientdoc))
            return OLE_ERROR_OBJECT;
    }

    *lplpobj = DocGetNextObject ((LPCLIENTDOC) lhclientdoc, *lplpobj);
    return OLE_OK;
}



LPOLEOBJECT INTERNAL DocGetNextObject (
    LPCLIENTDOC lpdoc,
    LPOLEOBJECT lpobj
){
    if (!lpobj)
        return lpdoc->lpHeadObj;

    return lpobj->lpNextObj;
}


BOOL FARINTERNAL CheckClientDoc (
    LPCLIENTDOC lpdoc
){
    if (!CheckPointer(lpdoc, WRITE_ACCESS))
        return FALSE;

    if ((lpdoc->docId[0] == 'C') && (lpdoc->docId[1] == 'D'))
        return TRUE;
    return FALSE;
}


void FARINTERNAL DocAddObject (
    LPCLIENTDOC lpdoc,
    LPOLEOBJECT lpobj,
    LPCSTR      lpobjname
){
    if (lpobjname)
        lpobj->aObjName = GlobalAddAtom (lpobjname);
    else
        lpobj->aObjName = (ATOM)0;

    // Objects of a doc are doubly linked

    if (!lpdoc->lpHeadObj)
        lpdoc->lpHeadObj = lpdoc->lpTailObj = lpobj;
    else {
        lpdoc->lpTailObj->lpNextObj = lpobj;
        lpobj->lpPrevObj = lpdoc->lpTailObj;
        lpdoc->lpTailObj = lpobj;
    }
    lpobj->lhclientdoc = (LHCLIENTDOC)lpdoc;
}


void FARINTERNAL DocDeleteObject (
    LPOLEOBJECT lpobj
){
    LPCLIENTDOC lpdoc;

    if (!(lpdoc = (LPCLIENTDOC) lpobj->lhclientdoc))
        return;

    if (lpobj->aObjName) {
        GlobalDeleteAtom (lpobj->aObjName);
        lpobj->aObjName = (ATOM)0;
    }

    // Remove this obj from object chain of the relevant client doc.
    // The objects of a doc are doubly linked.

    if (lpdoc->lpHeadObj == lpobj)
        lpdoc->lpHeadObj = lpobj->lpNextObj;

    if (lpdoc->lpTailObj == lpobj)
        lpdoc->lpTailObj = lpobj->lpPrevObj;

    if (lpobj->lpPrevObj)
        lpobj->lpPrevObj->lpNextObj = lpobj->lpNextObj;

    if (lpobj->lpNextObj)
        lpobj->lpNextObj->lpPrevObj = lpobj->lpPrevObj;

    lpobj->lhclientdoc = 0;
}