/****************************** 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 #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; }