You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
546 lines
15 KiB
546 lines
15 KiB
/****************************** 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
|
|
* Curts created NT version
|
|
*
|
|
\***************************************************************************/
|
|
|
|
#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);
|
|
|
|
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,
|
|
ErrQueryReleaseMethod,
|
|
|
|
ErrRequestData, // requestdata
|
|
ErrObjectLong, // objectLong
|
|
GenChangeData // change data of the existing object
|
|
};
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenRelease (LPOLEOBJECT lpoleobj)
|
|
{
|
|
LPOBJECT_GEN lpobj = (LPOBJECT_GEN)lpoleobj;
|
|
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 (
|
|
LPOLEOBJECT lpoleobj,
|
|
LPOLESTREAM lpstream
|
|
){
|
|
DWORD dwFileVer = GetFileVersion(lpoleobj);
|
|
LPOBJECT_GEN lpobj = (LPOBJECT_GEN)lpoleobj;
|
|
LPSTR lpData;
|
|
OLESTATUS retVal = OLE_OK;
|
|
DWORD dwClipFormat = 0;
|
|
char formatName[MAX_STR];
|
|
|
|
if (!lpobj->hData)
|
|
return OLE_ERROR_BLANK;
|
|
|
|
if (PutBytes (lpstream, (LPSTR) &dwFileVer, 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 (
|
|
LPOLEOBJECT lpoleobjsrc,
|
|
LPOLECLIENT lpclient,
|
|
LHCLIENTDOC lhclientdoc,
|
|
OLE_LPCSTR lpobjname,
|
|
LPOLEOBJECT FAR * lplpoleobj
|
|
){
|
|
LPOBJECT_GEN lpobjsrc = (LPOBJECT_GEN)lpoleobjsrc;
|
|
|
|
if (!lpobjsrc->hData)
|
|
return OLE_ERROR_BLANK;
|
|
|
|
if (!CheckClientDoc ((LPCLIENTDOC) lhclientdoc))
|
|
return OLE_ERROR_HANDLE;
|
|
|
|
if (!(*lplpoleobj = (LPOLEOBJECT)GenCreateObject (lpobjsrc->hData, lpclient,
|
|
FALSE, lhclientdoc,
|
|
(LPSTR)lpobjname, lpobjsrc->head.ctype)))
|
|
return OLE_ERROR_MEMORY;
|
|
else {
|
|
((LPOBJECT_GEN)(*lplpoleobj))->cfFormat = lpobjsrc->cfFormat;
|
|
((LPOBJECT_GEN)(*lplpoleobj))->aClass = DuplicateAtom (lpobjsrc->aClass);
|
|
return OLE_OK;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenEqual (
|
|
LPOLEOBJECT lpoleobj1,
|
|
LPOLEOBJECT lpoleobj2
|
|
){
|
|
LPOBJECT_GEN lpobj1 = (LPOBJECT_GEN)lpoleobj1;
|
|
LPOBJECT_GEN lpobj2 = (LPOBJECT_GEN)lpoleobj2;
|
|
|
|
if (CmpGlobals (lpobj1->hData, lpobj2->hData))
|
|
return OLE_OK;
|
|
|
|
return OLE_ERROR_NOT_EQUAL;
|
|
}
|
|
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenCopy (LPOLEOBJECT lpoleobj)
|
|
{
|
|
LPOBJECT_GEN lpobj = (LPOBJECT_GEN)lpoleobj;
|
|
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 (
|
|
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 = (OLECLIPFORMAT)RegisterClipboardFormat ((LPSTR) "Rich Text Format");
|
|
else
|
|
lpobj->cfFormat = 0;
|
|
}
|
|
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 = (OLECLIPFORMAT)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;
|
|
}
|
|
}
|
|
|
|
return OLE_OK;
|
|
|
|
errMem:
|
|
GlobalFree (hData);
|
|
|
|
errLoad:
|
|
OleDelete ((LPOLEOBJECT)lpobj);
|
|
*lplpobj = NULL;
|
|
return OLE_ERROR_STREAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LPOBJECT_GEN INTERNAL GenCreateObject (
|
|
HANDLE hData,
|
|
LPOLECLIENT lpclient,
|
|
BOOL fDelete,
|
|
LHCLIENTDOC lhclientdoc,
|
|
LPCSTR lpobjname,
|
|
LONG objType
|
|
){
|
|
LPOBJECT_GEN lpobj;
|
|
|
|
if (!hData)
|
|
return NULL;
|
|
|
|
if (lpobj = GenCreateBlank (lhclientdoc, (LPSTR)lpobjname, objType, (ATOM)0)) {
|
|
if (GenChangeData ((LPOLEOBJECT)lpobj, hData, lpclient, fDelete) != OLE_OK) {
|
|
GenRelease ((LPOLEOBJECT)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 (
|
|
LPOLEOBJECT lpoleobj,
|
|
HANDLE hSrcData,
|
|
LPOLECLIENT lpclient,
|
|
BOOL fDelete
|
|
){
|
|
LPOBJECT_GEN lpobj = (LPOBJECT_GEN)lpoleobj;
|
|
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 = (DWORD)GlobalSize (hDestData);
|
|
|
|
return OLE_OK;
|
|
}
|
|
|
|
|
|
|
|
LPOBJECT_GEN FARINTERNAL GenCreateBlank(
|
|
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 (
|
|
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 (
|
|
LPOLEOBJECT lpobj,
|
|
LPLONG lptype
|
|
){
|
|
UNREFERENCED_PARAMETER(lpobj);
|
|
UNREFERENCED_PARAMETER(lptype);
|
|
|
|
return OLE_ERROR_GENERIC;;
|
|
}
|
|
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenSetData (
|
|
LPOLEOBJECT lpoleobj,
|
|
OLECLIPFORMAT cfFormat,
|
|
HANDLE hData
|
|
){
|
|
LPOBJECT_GEN lpobj = (LPOBJECT_GEN)lpoleobj;
|
|
|
|
if (lpobj->cfFormat != cfFormat)
|
|
return OLE_ERROR_FORMAT;
|
|
|
|
if (!hData)
|
|
return OLE_ERROR_BLANK;
|
|
|
|
GlobalFree (lpobj->hData);
|
|
lpobj->hData = hData;
|
|
lpobj->sizeBytes = (DWORD)GlobalSize (hData);
|
|
return OLE_OK;
|
|
}
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenGetData (
|
|
LPOLEOBJECT lpoleobj,
|
|
OLECLIPFORMAT cfFormat,
|
|
LPHANDLE lphandle
|
|
){
|
|
LPOBJECT_GEN lpobj = (LPOBJECT_GEN)lpoleobj;
|
|
|
|
if (cfFormat != lpobj->cfFormat)
|
|
return OLE_ERROR_FORMAT;
|
|
|
|
if (!(*lphandle = lpobj->hData))
|
|
return OLE_ERROR_BLANK;
|
|
|
|
return OLE_OK;
|
|
|
|
}
|
|
|
|
|
|
OLECLIPFORMAT FARINTERNAL GenEnumFormat (
|
|
LPOLEOBJECT lpoleobj,
|
|
OLECLIPFORMAT cfFormat
|
|
){
|
|
LPOBJECT_GEN lpobj = (LPOBJECT_GEN)lpoleobj;
|
|
|
|
if (!cfFormat)
|
|
return lpobj->cfFormat;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
OLESTATUS FARINTERNAL GenQueryBounds (
|
|
LPOLEOBJECT lpoleobj,
|
|
LPRECT lpRc
|
|
){
|
|
LPOBJECT_GEN lpobj = (LPOBJECT_GEN)lpoleobj;
|
|
|
|
lpRc->right = 0;
|
|
lpRc->left = 0;
|
|
lpRc->top = 0;
|
|
lpRc->bottom = 0;
|
|
return OLE_ERROR_GENERIC;
|
|
}
|
|
|