532 lines
15 KiB
C
532 lines
15 KiB
C
/****************************** Module Header ******************************\
|
|
* Module Name: GENERIC.C
|
|
*
|
|
* Handles all API routines for the generic sub-dll of the ole dll.
|
|
* Since the data format is unknown, all the routines are written with the
|
|
* assumption that all the relevant data is placed in a single global data
|
|
* segment. Note that this assumption is not valid for metafiles, bitmaps, and
|
|
* and there can always be some other formats with such idiosyncracies. To
|
|
* accommodate those cases the rendering dll writer should replace the relevant
|
|
* routines after the creation of the generic object. If for a given class this
|
|
* assumption (about data format) is valid then the dll writer need to replace
|
|
* only the Draw and QueryBounds functions.
|
|
*
|
|
* Created: November-1990
|
|
*
|
|
* Copyright (c) 1990, 1991 Microsoft Corporation
|
|
*
|
|
* History:
|
|
*
|
|
* Srinik, Raor (11/05/90) Designed, coded
|
|
*
|
|
\***************************************************************************/
|
|
|
|
#include <windows.h>
|
|
#include "dll.h"
|
|
#include "pict.h"
|
|
|
|
char aMacText[4] = {'T', 'E', 'X', 'T'};
|
|
char aMacRtf[4] = "RTF";
|
|
|
|
extern OLESTATUS FARINTERNAL wCreateDummyMetaFile (LPOBJECT_MF, int, int);
|
|
|
|
#pragma alloc_text(_TEXT, GenSaveToStream, GenLoadFromStream, GetBytes, PutBytes, PutStrWithLen, PutAtomIntoStream, GenQueryBounds)
|
|
|
|
|
|
OLEOBJECTVTBL vtblGEN = {
|
|
|
|
ErrQueryProtocol, // check whether the speced protocol is supported
|
|
|
|
GenRelease, // Release
|
|
ErrShow, // Show
|
|
ErrPlay, // plat
|
|
GenGetData, // Get the object data
|
|
GenSetData, // Set the object data
|
|
ErrSetTargetDevice, //
|
|
|
|
ErrSetBounds, // set viewport bounds
|
|
GenEnumFormat, // enumerate supported formats
|
|
ErrSetColorScheme, //
|
|
GenRelease, // delete
|
|
ErrSetHostNames, //
|
|
|
|
GenSaveToStream, // write to file
|
|
GenClone, // clone object
|
|
ErrCopyFromLink, // Create embedded from Link
|
|
|
|
GenEqual, // compares the given objects for data equality
|
|
|
|
GenCopy, // copy to clip
|
|
|
|
GenDraw, // draw the object
|
|
|
|
ErrActivate, // open
|
|
ErrExecute, // excute
|
|
ErrClose, // Stop
|
|
ErrUpdate, // Update
|
|
ErrReconnect, // Reconnect
|
|
|
|
ErrObjectConvert, // convert object to specified type
|
|
|
|
ErrGetUpdateOptions, // update options
|
|
ErrSetUpdateOptions, // update options
|
|
|
|
ObjRename, // Change Object name
|
|
ObjQueryName, // Get current object name
|
|
|
|
GenQueryType, // Object type
|
|
GenQueryBounds, // QueryBounds
|
|
ObjQuerySize, // Find the size of the object
|
|
ErrQueryOpen, // Query open
|
|
ErrQueryOutOfDate, // query whether object is current
|
|
|
|
ErrQueryRelease, // release related stuff
|
|
ErrQueryRelease,
|
|
ErrQueryRelease,
|
|
|
|
ErrRequestData, // requestdata
|
|
ErrObjectLong, // objectLong
|
|
GenChangeData // change data of the existing object
|
|
};
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenRelease (lpobj)
|
|
LPOBJECT_GEN lpobj;
|
|
{
|
|
HOBJECT hobj;
|
|
|
|
if (lpobj->hData) {
|
|
GlobalFree (lpobj->hData);
|
|
lpobj->hData = NULL;
|
|
}
|
|
|
|
if (lpobj->aClass)
|
|
GlobalDeleteAtom (lpobj->aClass);
|
|
|
|
if (lpobj->head.lhclientdoc)
|
|
DocDeleteObject ((LPOLEOBJECT) lpobj);
|
|
|
|
if (hobj = lpobj->head.hobj){
|
|
lpobj->head.hobj = NULL;
|
|
GlobalUnlock (hobj);
|
|
GlobalFree (hobj);
|
|
}
|
|
|
|
return OLE_OK;
|
|
}
|
|
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenSaveToStream (lpobj, lpstream)
|
|
LPOBJECT_GEN lpobj;
|
|
LPOLESTREAM lpstream;
|
|
{
|
|
LPSTR lpData;
|
|
OLESTATUS retVal = OLE_OK;
|
|
DWORD dwClipFormat = NULL;
|
|
char formatName[MAX_STR];
|
|
|
|
if (!lpobj->hData)
|
|
return OLE_ERROR_BLANK;
|
|
|
|
if (PutBytes (lpstream, (LPSTR) &dwVerToFile, sizeof(LONG)))
|
|
return OLE_ERROR_STREAM;
|
|
|
|
if (PutBytes (lpstream, (LPSTR) &lpobj->head.ctype, sizeof(LONG)))
|
|
return OLE_ERROR_STREAM;
|
|
|
|
if (PutAtomIntoStream (lpstream, lpobj->aClass))
|
|
return OLE_ERROR_STREAM;
|
|
|
|
if (lpobj->cfFormat < 0xC000)
|
|
// then it is a predefined format
|
|
dwClipFormat = lpobj->cfFormat;
|
|
|
|
if (PutBytes (lpstream, (LPSTR) &dwClipFormat, sizeof(DWORD)))
|
|
return OLE_ERROR_STREAM;
|
|
|
|
if (!dwClipFormat) {
|
|
if (!GetClipboardFormatName (lpobj->cfFormat, (LPSTR) formatName,
|
|
sizeof(formatName)))
|
|
return OLE_ERROR_FORMAT;
|
|
|
|
if (PutStrWithLen (lpstream, formatName))
|
|
return OLE_ERROR_STREAM;
|
|
}
|
|
|
|
if (!lpobj->sizeBytes)
|
|
return OLE_ERROR_BLANK;
|
|
|
|
if (PutBytes (lpstream, (LPSTR) &lpobj->sizeBytes, sizeof(DWORD)))
|
|
return OLE_ERROR_STREAM;
|
|
|
|
if (!(lpData = GlobalLock (lpobj->hData)))
|
|
return OLE_ERROR_MEMORY;
|
|
|
|
if (PutBytes (lpstream, lpData, lpobj->sizeBytes))
|
|
retVal = OLE_ERROR_STREAM;
|
|
|
|
GlobalUnlock (lpobj->hData);
|
|
return retVal;
|
|
}
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenClone (lpobjsrc, lpclient, lhclientdoc, lpobjname, lplpobj)
|
|
LPOBJECT_GEN lpobjsrc;
|
|
LPOLECLIENT lpclient;
|
|
LHCLIENTDOC lhclientdoc;
|
|
LPSTR lpobjname;
|
|
LPOBJECT_GEN FAR * lplpobj;
|
|
{
|
|
if (!lpobjsrc->hData)
|
|
return OLE_ERROR_BLANK;
|
|
|
|
if (!CheckClientDoc ((LPCLIENTDOC) lhclientdoc))
|
|
return OLE_ERROR_HANDLE;
|
|
|
|
if (!(*lplpobj = GenCreateObject (lpobjsrc->hData, lpclient,
|
|
FALSE, lhclientdoc,
|
|
lpobjname, lpobjsrc->head.ctype)))
|
|
return OLE_ERROR_MEMORY;
|
|
else {
|
|
(*lplpobj)->cfFormat = lpobjsrc->cfFormat;
|
|
(*lplpobj)->aClass = DuplicateAtom (lpobjsrc->aClass);
|
|
return OLE_OK;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenEqual (lpobj1, lpobj2)
|
|
LPOBJECT_GEN lpobj1;
|
|
LPOBJECT_GEN lpobj2;
|
|
{
|
|
if (CmpGlobals (lpobj1->hData, lpobj2->hData))
|
|
return OLE_OK;
|
|
|
|
return OLE_ERROR_NOT_EQUAL;
|
|
}
|
|
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenCopy (lpobj)
|
|
LPOBJECT_GEN lpobj;
|
|
{
|
|
HANDLE hData;
|
|
|
|
if (!lpobj->hData)
|
|
return OLE_ERROR_BLANK;
|
|
|
|
if (!(hData = DuplicateGlobal (lpobj->hData, GMEM_MOVEABLE)))
|
|
return OLE_ERROR_MEMORY;
|
|
|
|
SetClipboardData (lpobj->cfFormat, hData);
|
|
return OLE_OK;
|
|
}
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenLoadFromStream (lpstream, lpclient, lhclientdoc, lpobjname, lplpobj, objType, aClass, cfFormat)
|
|
LPOLESTREAM lpstream;
|
|
LPOLECLIENT lpclient;
|
|
LHCLIENTDOC lhclientdoc;
|
|
LPSTR lpobjname;
|
|
LPOLEOBJECT FAR * lplpobj;
|
|
LONG objType;
|
|
ATOM aClass;
|
|
OLECLIPFORMAT cfFormat;
|
|
{
|
|
LPOBJECT_GEN lpobj = NULL;
|
|
OLESTATUS retVal = OLE_ERROR_STREAM;
|
|
HANDLE hData;
|
|
LPSTR lpData;
|
|
DWORD dwClipFormat;
|
|
char formatName[MAX_STR];
|
|
LONG length;
|
|
|
|
if (!(*lplpobj = (LPOLEOBJECT) (lpobj = GenCreateBlank(lhclientdoc,
|
|
lpobjname, objType,
|
|
aClass)))) {
|
|
if (aClass)
|
|
GlobalDeleteAtom(aClass);
|
|
return OLE_ERROR_MEMORY;
|
|
}
|
|
|
|
if (GetBytes (lpstream, (LPSTR) &dwClipFormat, sizeof (DWORD)))
|
|
goto errLoad;
|
|
|
|
// If object is from MAC then we will keep the data intact if the data
|
|
// format is either TEXT or RTF
|
|
if (HIWORD(dwVerFromFile) == OS_MAC) {
|
|
if (dwClipFormat == *((DWORD *) aMacText))
|
|
lpobj->cfFormat = CF_TEXT;
|
|
else if (dwClipFormat == *((DWORD *) aMacRtf))
|
|
lpobj->cfFormat = RegisterClipboardFormat ((LPSTR) "Rich Text Format");
|
|
else
|
|
lpobj->cfFormat = NULL;
|
|
}
|
|
else {
|
|
// object is created on windows
|
|
if (!dwClipFormat) {
|
|
// this is new file format. format name string follows
|
|
if (GetBytes (lpstream, (LPSTR) &length, sizeof (LONG))
|
|
|| GetBytes (lpstream, (LPSTR)formatName, length)
|
|
|| (!(lpobj->cfFormat = RegisterClipboardFormat ((LPSTR) formatName))))
|
|
goto errLoad;
|
|
}
|
|
else if ((lpobj->cfFormat = (WORD) dwClipFormat) >= 0xc000) {
|
|
// if format is not predefined and file format is old, then use
|
|
// what value is passed to you through "cfFormat" argument
|
|
lpobj->cfFormat = cfFormat;
|
|
}
|
|
}
|
|
|
|
if (GetBytes (lpstream, (LPSTR) &lpobj->sizeBytes, sizeof (DWORD)))
|
|
goto errLoad;
|
|
|
|
lpobj->head.lpclient = lpclient;
|
|
|
|
retVal = OLE_ERROR_MEMORY;
|
|
if (!(hData = GlobalAlloc (GMEM_MOVEABLE, lpobj->sizeBytes)))
|
|
goto errLoad;
|
|
|
|
if (!(lpData = GlobalLock (hData)))
|
|
goto errMem;
|
|
|
|
if (GetBytes (lpstream, lpData, lpobj->sizeBytes)) {
|
|
retVal = OLE_ERROR_STREAM;
|
|
GlobalUnlock (hData);
|
|
goto errMem;
|
|
}
|
|
|
|
lpobj->hData = hData;
|
|
GlobalUnlock (hData);
|
|
|
|
// if the object is from MAC then we want delete this and create blank
|
|
// metafile object, which draws a rectangle
|
|
if ((HIWORD(dwVerFromFile) == OS_MAC) && !lpobj->cfFormat) {
|
|
LPOBJECT_MF lpobjMf;
|
|
|
|
OleDelete ((LPOLEOBJECT)lpobj); // delete generic object
|
|
|
|
// Now create a dummy metafile object which draws a rectangle of size
|
|
// 1" x 1". Note that 1" = 2540 HIMETRIC units
|
|
lpobjMf = MfCreateBlank (lhclientdoc, lpobjname, objType);
|
|
lpobjMf->head.cx = lpobjMf->mfp.xExt = 2540;
|
|
lpobjMf->head.cy = - (lpobjMf->mfp.yExt = 2540);
|
|
if ((retVal = wCreateDummyMetaFile (lpobjMf, lpobjMf->mfp.xExt,
|
|
lpobjMf->mfp.yExt)) != OLE_OK) {
|
|
OleDelete ((LPOLEOBJECT) lpobjMf);
|
|
return retVal;
|
|
}
|
|
|
|
*lplpobj = (LPOLEOBJECT) lpobjMf;
|
|
}
|
|
|
|
return OLE_OK;
|
|
|
|
errMem:
|
|
GlobalFree (hData);
|
|
|
|
errLoad:
|
|
OleDelete ((LPOLEOBJECT)lpobj);
|
|
*lplpobj = NULL;
|
|
return OLE_ERROR_STREAM;
|
|
}
|
|
|
|
|
|
|
|
|
|
LPOBJECT_GEN INTERNAL GenCreateObject (hData, lpclient, fDelete, lhclientdoc, lpobjname, objType)
|
|
HANDLE hData;
|
|
LPOLECLIENT lpclient;
|
|
BOOL fDelete;
|
|
LHCLIENTDOC lhclientdoc;
|
|
LPSTR lpobjname;
|
|
LONG objType;
|
|
{
|
|
LPOBJECT_GEN lpobj;
|
|
|
|
if (!hData)
|
|
return NULL;
|
|
|
|
if (lpobj = GenCreateBlank (lhclientdoc, lpobjname, objType, NULL)) {
|
|
if (GenChangeData (lpobj, hData, lpclient, fDelete) != OLE_OK) {
|
|
GenRelease (lpobj);
|
|
lpobj = NULL;
|
|
}
|
|
}
|
|
|
|
return lpobj;
|
|
}
|
|
|
|
|
|
// If the routine fails then the object will be left with it's old data.
|
|
// If fDelete is TRUE, then hNewData will be deleted whether the routine
|
|
// is successful or not.
|
|
|
|
OLESTATUS FARINTERNAL GenChangeData (lpobj, hSrcData, lpclient, fDelete)
|
|
LPOBJECT_GEN lpobj;
|
|
HANDLE hSrcData;
|
|
LPOLECLIENT lpclient;
|
|
BOOL fDelete;
|
|
{
|
|
HANDLE hDestData;
|
|
|
|
if (!fDelete) {
|
|
if (!(hDestData = DuplicateGlobal (hSrcData, GMEM_MOVEABLE)))
|
|
return OLE_ERROR_MEMORY;
|
|
}
|
|
else {
|
|
// change the ownership to yourself
|
|
if (!(hDestData = GlobalReAlloc(hSrcData,0L,GMEM_MODIFY|GMEM_SHARE))){
|
|
hDestData = DuplicateGlobal (hSrcData, GMEM_MOVEABLE);
|
|
GlobalFree (hSrcData);
|
|
if (!hDestData)
|
|
return OLE_ERROR_MEMORY;
|
|
}
|
|
}
|
|
|
|
lpobj->head.lpclient = lpclient;
|
|
if (lpobj->hData)
|
|
GlobalFree (lpobj->hData);
|
|
lpobj->hData = hDestData;
|
|
lpobj->sizeBytes = GlobalSize (hDestData);
|
|
|
|
return OLE_OK;
|
|
}
|
|
|
|
|
|
|
|
LPOBJECT_GEN FARINTERNAL GenCreateBlank(lhclientdoc, lpobjname, objType, aClass)
|
|
LHCLIENTDOC lhclientdoc;
|
|
LPSTR lpobjname;
|
|
LONG objType;
|
|
ATOM aClass;
|
|
{
|
|
HOBJECT hobj;
|
|
LPOBJECT_GEN lpobj;
|
|
|
|
if ((hobj = GlobalAlloc (GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof (OBJECT_GEN)))
|
|
== NULL)
|
|
return NULL;
|
|
|
|
if (!(lpobj = (LPOBJECT_GEN) GlobalLock (hobj))){
|
|
GlobalFree (hobj);
|
|
return NULL;
|
|
}
|
|
|
|
lpobj->head.objId[0] = 'L';
|
|
lpobj->head.objId[1] = 'E';
|
|
lpobj->head.mm = MM_TEXT;
|
|
lpobj->head.ctype = objType;
|
|
lpobj->head.lpvtbl = (LPOLEOBJECTVTBL)&vtblGEN;
|
|
lpobj->head.iTable = INVALID_INDEX;
|
|
lpobj->head.hobj = hobj;
|
|
lpobj->aClass = aClass;
|
|
|
|
if (objType == CT_STATIC)
|
|
DocAddObject ((LPCLIENTDOC) lhclientdoc,
|
|
(LPOLEOBJECT) lpobj, lpobjname);
|
|
|
|
return lpobj;
|
|
}
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenPaste (lpclient, lhclientdoc, lpobjname, lplpobj, lpClass, cfFormat, objType)
|
|
LPOLECLIENT lpclient;
|
|
LHCLIENTDOC lhclientdoc;
|
|
LPSTR lpobjname;
|
|
LPOLEOBJECT FAR * lplpobj;
|
|
LPSTR lpClass;
|
|
OLECLIPFORMAT cfFormat;
|
|
LONG objType;
|
|
{
|
|
HANDLE hData = NULL;
|
|
|
|
*lplpobj = NULL;
|
|
if (!cfFormat)
|
|
return OLE_ERROR_FORMAT;
|
|
|
|
if (!(hData = GetClipboardData(cfFormat)))
|
|
return OLE_ERROR_MEMORY;
|
|
|
|
if (!(*lplpobj = (LPOLEOBJECT) GenCreateObject (hData, lpclient,
|
|
FALSE, lhclientdoc,
|
|
lpobjname, objType)))
|
|
return OLE_ERROR_MEMORY;
|
|
|
|
((LPOBJECT_GEN)(*lplpobj))->cfFormat = cfFormat;
|
|
((LPOBJECT_GEN)(*lplpobj))->aClass = GlobalAddAtom (lpClass);
|
|
return OLE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenQueryType (lpobj, lptype)
|
|
LPOLEOBJECT lpobj;
|
|
LPLONG lptype;
|
|
{
|
|
return OLE_ERROR_GENERIC;;
|
|
}
|
|
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenSetData (lpobj, cfFormat, hData)
|
|
LPOBJECT_GEN lpobj;
|
|
OLECLIPFORMAT cfFormat;
|
|
HANDLE hData;
|
|
{
|
|
|
|
if (lpobj->cfFormat != cfFormat)
|
|
return OLE_ERROR_FORMAT;
|
|
|
|
if (!hData)
|
|
return OLE_ERROR_BLANK;
|
|
|
|
GlobalFree (lpobj->hData);
|
|
lpobj->hData = hData;
|
|
lpobj->sizeBytes = GlobalSize (hData);
|
|
return OLE_OK;
|
|
}
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenGetData (lpobj, cfFormat, lphandle)
|
|
LPOBJECT_GEN lpobj;
|
|
OLECLIPFORMAT cfFormat;
|
|
LPHANDLE lphandle;
|
|
{
|
|
if (cfFormat != lpobj->cfFormat)
|
|
return OLE_ERROR_FORMAT;
|
|
|
|
if (!(*lphandle = lpobj->hData))
|
|
return OLE_ERROR_BLANK;
|
|
|
|
return OLE_OK;
|
|
|
|
}
|
|
|
|
|
|
OLECLIPFORMAT FARINTERNAL GenEnumFormat (lpobj, cfFormat)
|
|
LPOBJECT_GEN lpobj;
|
|
OLECLIPFORMAT cfFormat;
|
|
{
|
|
if (!cfFormat)
|
|
return lpobj->cfFormat;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenQueryBounds (lpobj, lpRc)
|
|
LPOBJECT_GEN lpobj;
|
|
LPRECT lpRc;
|
|
{
|
|
lpRc->right = 0;
|
|
lpRc->left = 0;
|
|
lpRc->top = 0;
|
|
lpRc->bottom = 0;
|
|
return OLE_ERROR_GENERIC;
|
|
}
|
|
|