317 lines
7.5 KiB
C
317 lines
7.5 KiB
C
|
/****************************** 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
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
|
||
|
#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;
|
||
|
|
||
|
#pragma alloc_text(_TEXT, CheckClientDoc, CheckPointer)
|
||
|
|
||
|
|
||
|
OLESTATUS FAR PASCAL OleRegisterClientDoc (lpClassName, lpDocName, future, lplhclientdoc)
|
||
|
LPSTR lpClassName;
|
||
|
LPSTR lpDocName;
|
||
|
LONG future;
|
||
|
LHCLIENTDOC FAR * lplhclientdoc;
|
||
|
{
|
||
|
HANDLE hdoc = NULL;
|
||
|
LPCLIENTDOC lpdoc;
|
||
|
OLESTATUS retVal;
|
||
|
ATOM aClass, aDoc;
|
||
|
|
||
|
|
||
|
#ifdef FIREWALLS
|
||
|
if (!bShowed && (ole_flags & DEBUG_MESSAGEBOX))
|
||
|
ShowVersion ();
|
||
|
#endif
|
||
|
|
||
|
Puts ("OleRegisterClientDoc");
|
||
|
|
||
|
PROBE_MODE(bProtMode);
|
||
|
FARPROBE_WRITE(lplhclientdoc);
|
||
|
*lplhclientdoc = NULL;
|
||
|
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;
|
||
|
|
||
|
// 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 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, lpNewDocName)
|
||
|
LHCLIENTDOC lhclientdoc;
|
||
|
LPSTR 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 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 lhclientdoc;
|
||
|
{
|
||
|
if (!CheckClientDoc ((LPCLIENTDOC) lhclientdoc))
|
||
|
return OLE_ERROR_HANDLE;
|
||
|
|
||
|
return OLE_OK;
|
||
|
}
|
||
|
|
||
|
OLESTATUS FAR PASCAL OleEnumObjects (lhclientdoc, lplpobj)
|
||
|
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 (lpdoc, lpobj)
|
||
|
LPCLIENTDOC lpdoc;
|
||
|
LPOLEOBJECT lpobj;
|
||
|
{
|
||
|
if (!lpobj)
|
||
|
return lpdoc->lpHeadObj;
|
||
|
|
||
|
return lpobj->lpNextObj;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL FARINTERNAL CheckClientDoc (lpdoc)
|
||
|
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 (lpdoc, lpobj, lpobjname)
|
||
|
LPCLIENTDOC lpdoc;
|
||
|
LPOLEOBJECT lpobj;
|
||
|
LPSTR lpobjname;
|
||
|
{
|
||
|
if (lpobjname)
|
||
|
lpobj->aObjName = GlobalAddAtom (lpobjname);
|
||
|
else
|
||
|
lpobj->aObjName = NULL;
|
||
|
|
||
|
// 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 (lpobj)
|
||
|
LPOLEOBJECT lpobj;
|
||
|
{
|
||
|
LPCLIENTDOC lpdoc;
|
||
|
|
||
|
if (!(lpdoc = (LPCLIENTDOC) lpobj->lhclientdoc))
|
||
|
return;
|
||
|
|
||
|
if (lpobj->aObjName) {
|
||
|
GlobalDeleteAtom (lpobj->aObjName);
|
||
|
lpobj->aObjName = NULL;
|
||
|
}
|
||
|
|
||
|
// 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 = NULL;
|
||
|
}
|
||
|
|