home *** CD-ROM | disk | FTP | other *** search
Wrap
/*============================================================================== TER_OLE.C TER Object Linking and Embedding functions TER Editor Developer's Kit Sub Systems, Inc. Software License Agreement (1994) ---------------------------------- This license agreement allows the purchaser the right to modify the source code to incorporate in an application larger than the editor itself. The target application must not be a programmer's utility 'like' a text editor. Sub Systems, Inc. reserves the right to prosecute anybody found to be making illegal copies of the executable software or compiling the source code for the purpose of selling there after. ===============================================================================*/ #if !defined(WIN32) || defined(__TURBOC__) #include "coguid.h" #include "oleguid.h" #else #include "cguid.h" #include "olectlid.h" #endif #include "ole2ver.h" /******************************************************************************* InitOle: Create the OLE client structure *******************************************************************************/ BOOL InitOle(PTERWND w) { DWORD OleVer; HRESULT result; int i,TaskIdx; HTASK CurTask; // check if OLE already initialized for this task CurTask=GetWindowTask(hTerWnd); for (i=0;i<TotalWinTasks;i++) if (WinTask[i].count>0 && WinTask[i].task==CurTask) break; if (i==TotalWinTasks) { // look for an unused slot for (i=0;i<TotalWinTasks;i++) if (WinTask[i].count==0) break; } if (i==TotalWinTasks) { if (TotalWinTasks<MAX_TASKS) { i=TotalWinTasks; WinTask[i].count=0; TotalWinTasks++; } else return PrintError(w,"Ran out of task table!"); } // update the task slot TaskIdx=i; WinTask[TaskIdx].task=CurTask; WinTask[TaskIdx].count++; // initialize OLE if (WinTask[TaskIdx].count==1) { // first window for this application instance OleVer=OleBuildVersion(); if (HIWORD(OleVer) !=rmm || LOWORD(OleVer) < rup) { return PrintError(w,"Invalid OLE version!"); } result=OleInitialize(NULL); if (GetScode(result)!=S_OK && GetScode(result)!=S_FALSE) { PrintOleError(w,result); return PrintError(w,"Error initializing OLE!"); } // create and open a document storage - created one per DLL task result=StgCreateDocfile(NULL,STGM_TRANSACTED|STGM_READWRITE |STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_DELETEONRELEASE,0,&(WinTask[TaskIdx].pDocStg)); if (result!=NOERROR) { PrintOleError(w,result); return PrintError(w,"Error creating OLE storage!"); } } pDocStorage=WinTask[TaskIdx].pDocStg; // use it from the table // create the OLE1 compatible streams OleStreamVtbl.Get=NULL; // Ole stream get callback function OleStreamVtbl.Put=NULL; // Ole stream put callback function // Create the client structure if ( NULL==(OleStreamVtbl.Get=(LPVOID) MakeProcInstance((FARPROC)TerOleGet,hTerInst)) || NULL==(OleStreamVtbl.Put=(LPVOID) MakeProcInstance((FARPROC)TerOlePut,hTerInst)) ){ MessageBox(hTerWnd,"Can not create ole stream callback instances!",NULL,MB_OK); return FALSE; } OleStream.stream.lpstbl=&OleStreamVtbl; OleStream.TerData=w; // enable drag/drop DragAcceptFiles(hTerWnd,TRUE); return TRUE; } /******************************************************************************* ExitOle: Exit ole logic. Called by CloseTer *******************************************************************************/ BOOL ExitOle(PTERWND w) { int i; HTASK CurTask; #if !defined(WIN32) if (OleStreamVtbl.Get) FreeProcInstance((FARPROC)OleStreamVtbl.Get); if (OleStreamVtbl.Put) FreeProcInstance((FARPROC)OleStreamVtbl.Put); #endif DragAcceptFiles(hTerWnd,FALSE); // check if the last window for the task CurTask=GetWindowTask(hTerWnd); for (i=0;i<TotalWinTasks;i++) if (WinTask[i].count>0 && WinTask[i].task==CurTask) break; if (i<TotalWinTasks) { WinTask[i].count--; if (WinTask[i].count==0) { if (WinTask[i].pDocStg) (WinTask[i].pDocStg)->lpVtbl->Release(WinTask[i].pDocStg); OleUninitialize(); } } return TRUE; } /******************************************************************************* OlePostProcessing: This function gets the data from the application's persistence stroage to the IStorage interface residing in OLE2.DLL. *******************************************************************************/ OlePostProcessing(PTERWND w) { return TRUE; } /******************************************************************************* TerPasteSpecial: Accept a string from the user along with other parameters and search for the first instances of the string. *******************************************************************************/ TerPasteSpecial(PTERWND w) { int index,len,i; int select; UINT ClipFormat,PasteFormat; long BuffSize; BYTE class[MAX_WIDTH+1],doc[MAX_WIDTH+1],item[MAX_WIDTH+1],PasteFmts[MAX_PASTE_FORMATS]; BOOL PasteLink=FALSE; if (FontsReleased) RecreateFonts(w,hTerDC); // recreate fonts // Build the source description string ClipFormat=GetOleClipItem(w,class,doc,item); if (ClipFormat>0) { // get the class name BuffSize=sizeof(TempString); RegQueryValue(HKEY_CLASSES_ROOT,class,TempString,&BuffSize); // Build the item string len=lstrlen(doc); for (i=len;i>0;i--) if (doc[i-1]=='\\') break; lstrcpy(TempString1,&(doc[i])); if (lstrlen(TempString1)>0) lstrcat(TempString1," "); lstrcat(TempString1,item); } else { lstrcpy(TempString,"Unknown"); lstrcpy(TempString1,""); } // build the datatype table for (i=0;i<MAX_PASTE_FORMATS;i++) PasteFmts[i]=FALSE; // list of available formats if (IsClipboardFormatAvailable(OwnerLinkClipFormat)) PasteFmts[PASTE_OBJECT]=TRUE; if (IsClipboardFormatAvailable(CF_METAFILEPICT)) PasteFmts[PASTE_PICT]=TRUE; if (IsClipboardFormatAvailable(CF_BITMAP)) PasteFmts[PASTE_BM]=TRUE; if (IsClipboardFormatAvailable(CF_DIB)) PasteFmts[PASTE_DIB]=TRUE; if (IsClipboardFormatAvailable(RtfClipFormat)) PasteFmts[PASTE_RTF]=TRUE; if (IsClipboardFormatAvailable(CF_TEXT)) PasteFmts[PASTE_TEXT]=TRUE; // check if atleast one format available for (i=0;i<MAX_PASTE_FORMATS;i++) if (PasteFmts[i]) break; if (i==MAX_PASTE_FORMATS) return TRUE; // no formats available index=CallDialogBox(w,"PasteSpecialParam",PasteSpecialParam,(long)(LPBYTE)PasteFmts); if (index<0) return TRUE; // operation cancelled // extract the selected clipboard format if (index>=MAX_PASTE_FORMATS) { // Is object linking selected index-=MAX_PASTE_FORMATS; PasteLink=TRUE; } for (i=0;i<MAX_PASTE_FORMATS;i++) { if (PasteFmts[i]) index--; if (index<0) break; } select=i; // selected format // get the paste format if (select==PASTE_TEXT) PasteFormat=CF_TEXT; else if (select==PASTE_RTF) PasteFormat=RtfClipFormat; else if (select==PASTE_PICT) PasteFormat=CF_METAFILEPICT; else if (select==PASTE_DIB) PasteFormat=CF_DIB; else if (select==PASTE_BM) PasteFormat=CF_BITMAP; else PasteFormat=NativeClipFormat; // Retrieve the text formats from the clipboard if (select==PASTE_RTF || select==PASTE_TEXT) return CopyFromClipboard(w,PasteFormat); // Process the ole objects if (select==PASTE_OBJECT) return TerOleFromClipboard(w,PasteFormat,PasteLink); // Process the non-ole picture formats if (select==PASTE_PICT || select==PASTE_DIB || select==PASTE_BM) return TerPastePicture(hTerWnd,PasteFormat,NULL,0,ALIGN_BOT,TRUE); return TRUE; } /******************************************************************************* TerOleFromClipboard: Embed an OLE object from clipboard. *******************************************************************************/ TerOleFromClipboard(PTERWND w, UINT format,BOOL PasteLink) { int obj; LPDATAOBJECT pDataObject; FORMATETC OleFmt; LPSTORAGE pObjStg; LPOLECLIENTSITE pObjSite; STGMEDIUM med; HRESULT result; // Erase any previously highlighted text if (HilightType==HILIGHT_CHAR) BlockDelete(w); if ((obj=FindOpenSlot(w))==-1) return FALSE; // find an empty slot // get the data object from the clipboard result=OleGetClipboard(&pDataObject); if (result!=NOERROR) return PrintError(w,"Error retrieving the clipboard data(TerOleFromClipboard"); // create IOleClientSite and IStorage interfaces for the object if (!TerOlePreCreate(w,obj,&pObjSite,&pObjStg,&OleFmt)) return FALSE; // Create the object if (PasteLink) result=OleCreateLinkFromData(pDataObject,&IID_IOleObject,OLERENDER_FORMAT,&OleFmt,pObjSite,pObjStg,(LPVOID far *)&(TerFont[obj].pObject)); else result=OleCreateFromData(pDataObject,&IID_IOleObject,OLERENDER_FORMAT,&OleFmt,pObjSite,pObjStg,(LPVOID far *)&(TerFont[obj].pObject)); if (result!=NOERROR || !(TerFont[obj].pObject)) { pObjSite->lpVtbl->Release(pObjSite); // release the client site PrintOleError(w,result); wsprintf(TempString,"Object creation error: %lx",(ULONG)result); return PrintError(w,TempString); } // make advisory connection and display the object TerOlePostCreate(w,obj); // retrieve the presentation data if (NOERROR!=(pDataObject->lpVtbl->GetData(pDataObject,&OleFmt,&med)) || med.tymed!=TYMED_MFPICT) { return PrintError(w,"Error retrieving presentation data(TerOleFromClipboard)"); } if (TerCreateMetafile(w,med.u.hGlobal,obj)<0) return FALSE; // extract metafile ReleaseStgMedium(&med); // release data handle pDataObject->lpVtbl->Release(pDataObject); // this data object needs to be released if (PasteLink) TerFont[obj].ObjectType=OBJ_LINK; else TerFont[obj].ObjectType=OBJ_EMBED; TerInsertObjectId(hTerWnd,obj,TRUE); // insert this object into text FitPictureInFrame(w,CurLine,FALSE); return TRUE; } /****************************************************************************** TerInsertObject: Insert a new ole object. This function activates the OLE server. the second part of this function (TerInsertObjectId) is called from the ole post processing function to actually insert the object into the text. ******************************************************************************/ BOOL TerInsertObject(PTERWND w) { int SubKey; int obj; CLSID ClassId; FORMATETC OleFmt; LPSTORAGE pObjStg; LPOLECLIENTSITE pObjSite; HRESULT result; LPOLEOBJECT pObject; if ((SubKey=CallDialogBox(w,"InsertObjectParam",InsertObjectParam,0L))<0) return TRUE; // get the class id RegEnumKey(HKEY_CLASSES_ROOT,SubKey,TempString,sizeof(TempString)-1); result=CLSIDFromProgID(StrToOleStr(TempString,TempString1),&ClassId); if (NOERROR!=result) return PrintError(w,"OLE class not found in the Registration Database!"); // convert to class id // create the object if ((obj=FindOpenSlot(w))==-1) return FALSE; // find an empty slot to make the object name TerFont[obj].InUse=TRUE; TerFont[obj].ObjectType=OBJ_EMBED_INSERT; // object to be inserted TerFont[obj].style=PICT; TerFont[obj].PictType=PICT_METAFILE; TerFont[obj].hMeta=0; // create IOleClientSite and IStorage interfaces for the object if (!TerOlePreCreate(w,obj,&pObjSite,&pObjStg,&OleFmt)) return FALSE; // Create the object result=OleCreate(&ClassId,&IID_IOleObject,OLERENDER_FORMAT,&OleFmt,pObjSite,pObjStg,(LPVOID far *)&(TerFont[obj].pObject)); if (result!=NOERROR || !(TerFont[obj].pObject)) { TerFont[obj].InUse=FALSE; pObjSite->lpVtbl->Release(pObjSite); // release the client site wsprintf(TempString,"Object creation error: %lx",(ULONG)result); return PrintError(w,TempString); } // make advisory connection and display the object TerOlePostCreate(w,obj); // Show the object window if not alredy shown pObject=TerFont[obj].pObject; result=pObject->lpVtbl->DoVerb(pObject,OLEIVERB_SHOW,NULL,pObjSite,0,hTerWnd,NULL); return TRUE; } /****************************************************************************** TerOlePreCreate: This function creates IOleClientSite and IStorage interface needed to create an object. ******************************************************************************/ BOOL TerOlePreCreate(PTERWND w,int obj, LPOLECLIENTSITE far *ppObjSite, LPSTORAGE far *ppObjStg,FORMATETC far *OleFmt) { BYTE ObjName[20]; HRESULT result; // create a new storage for this object StorageId++; wsprintf(ObjName,"TerObj%dId%d",obj,StorageId); result=pDocStorage->lpVtbl->CreateStorage(pDocStorage,StrToOleStr(ObjName,TempString), STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE,0,0,ppObjStg); if (result!=NOERROR || !(*ppObjStg)) { TerFont[obj].InUse=FALSE; wsprintf(TempString,"Error creating object storage: %lx",(ULONG)result); return PrintError(w,TempString); } // create a client site interface for this object if (NULL==((*ppObjSite)=CreateOleClientSite(w,obj,(*ppObjStg)))) { TerFont[obj].InUse=FALSE; return PrintError(w,"Error creating client site!"); } TerFont[obj].pObjSite=(*ppObjSite); // set ole format OleFmt->cfFormat=CF_METAFILEPICT; OleFmt->ptd=NULL; OleFmt->dwAspect=DVASPECT_CONTENT; OleFmt->lindex=-1; OleFmt->tymed=TYMED_MFPICT; return TRUE; } /****************************************************************************** TerOlePostCreate: Make advisory connection and display object ******************************************************************************/ BOOL TerOlePostCreate(PTERWND w,int obj) { BYTE ObjName[129]; LPOLEOBJECT pObject; LPOLECLIENTSITE pObjSite; LPSTRCLIENTSITE pSite; LPVIEWOBJECT pViewObject; HRESULT result; // extract object pointers pObject=TerFont[obj].pObject; pObjSite=TerFont[obj].pObjSite; pSite=(LPSTRCLIENTSITE )pObjSite; // set the client site pObject->lpVtbl->SetClientSite(pObject,pObjSite); // set the object name if (lstrlen(TerArg.file)>0) wsprintf(ObjName,"%s, obj#%d",(LPSTR)TerArg.file,obj); else wsprintf(ObjName,"TerObject#%d",obj); pObject->lpVtbl->SetHostNames(pObject, StrToOleStr(TerArg.file,TempString), StrToOleStr(ObjName,TempString1)); // set the advise link to the pObject pObject->lpVtbl->Advise(pObject,pSite->pObjAdvise,&(pSite->ConnectToken)); // set the advise link to the pViewObject result=pObject->lpVtbl->QueryInterface(pObject,&IID_IViewObject,(LPVOID far *)&pViewObject); if (result!=NOERROR) return PrintError(w,"Error retrieving view object(TerOlePostCreate)"); result=pViewObject->lpVtbl->SetAdvise(pViewObject,DVASPECT_CONTENT,0,pSite->pObjAdvise); if (result!=NOERROR) return PrintError(w,"Error setting the data advise connection(TerOlePostCreate)"); OleSetContainedObject((LPUNKNOWN)pObject,TRUE); // soft lock maintenance function pObjSite->lpVtbl->SaveObject(pObjSite); // save the initial status to the storage return TRUE; } /****************************************************************************** TerInsertDragObject: Insert an ole object inserted using drag/drop. Only the first file in the drag/drop buffer is processed. ******************************************************************************/ BOOL TerInsertDragObject(PTERWND w,HDROP hDrop) { int obj; POINT pt; DWORD lParam; BYTE file[129]; LPOLEOBJECT pObject; LPDATAOBJECT pDataObject; FORMATETC OleFmt; LPSTORAGE pObjStg; LPOLECLIENTSITE pObjSite; STGMEDIUM med; HRESULT result; // Extract the dropped file if (!DragQueryPoint(hDrop,&pt)) return TRUE; DragQueryFile(hDrop,0,file,sizeof(file)-1); // get the first file DragFinish(hDrop); // release the drag buffer // get cursor location at the drag point lParam=pt.y; lParam=lParam<<16; // high word lParam=lParam+pt.x; TerMousePos(w,lParam); CurLine=MouseLine; CurCol=MouseCol; // create the object if ((obj=FindOpenSlot(w))==-1) return FALSE; // find an empty slot to make the object name TerFont[obj].InUse=TRUE; TerFont[obj].style=PICT; TerFont[obj].PictType=PICT_METAFILE; TerFont[obj].hMeta=0; // create IOleClientSite and IStorage interfaces for the object if (!TerOlePreCreate(w,obj,&pObjSite,&pObjStg,&OleFmt)) return FALSE; // Create the object result=OleCreateFromFile(&CLSID_NULL,StrToOleStr(file,TempString),&IID_IOleObject,OLERENDER_FORMAT,&OleFmt,pObjSite,pObjStg,(LPVOID far *)&(TerFont[obj].pObject)); if (result!=NOERROR || !(TerFont[obj].pObject)) { pObjSite->lpVtbl->Release(pObjSite); // release the client site TerFont[obj].InUse=FALSE; wsprintf(TempString,"Object creation error: %lx",(ULONG)result); return PrintError(w,TempString); } pObject=TerFont[obj].pObject; // make advisory connection and display the object TerOlePostCreate(w,obj); // get the IDataObject Interface result=pObject->lpVtbl->QueryInterface(pObject,&IID_IDataObject,(LPVOID far *)&pDataObject); if (result!=NOERROR) return PrintError(w,"Error retrieving data object(TerInsertDragObject)"); // retrieve the presentation data if (NOERROR!=(pDataObject->lpVtbl->GetData(pDataObject,&OleFmt,&med)) || med.tymed!=TYMED_MFPICT) { return PrintError(w,"Error retrieving presentation data(TerInsertDragObject)"); } if (TerCreateMetafile(w,med.u.hGlobal,obj)<0) return FALSE; // extract metafile TerFont[obj].ObjectType=OBJ_EMBED; ReleaseStgMedium(&med); // release data handle TerInsertObjectId(hTerWnd,obj,TRUE); // insert this object into text return TRUE; } /****************************************************************************** TerEditOle: If the current item represents an OLE object, this functions calls the server to update the item. ******************************************************************************/ BOOL TerEditOle(PTERWND w) { int obj; LPOLEOBJECT pObject; // get current font id obj=GetCurCfmt(w,CurLine,CurCol); if (!(TerFont[obj].style&PICT)) return FALSE; if (TerArg.ReadOnly || TerFont[obj].style&PROTECT) return FALSE; // If necessary, convert picture objects to temporary OLE objects if (TerFont[obj].ObjectType==OBJ_NONE) TerCreateTempOle(w,obj); if (TerFont[obj].ObjectType==OBJ_NONE) return FALSE; // run the ole object pObject=TerFont[obj].pObject; pObject->lpVtbl->DoVerb(pObject,OLEIVERB_SHOW,NULL,TerFont[obj].pObjSite,0,hTerWnd,NULL); return TRUE; } /****************************************************************************** TerCreateTempOle: This function creates a temporary ole object from a metafile picture. The temporary metafile object is used to edit picture using MSDRAW. ******************************************************************************/ TerCreateTempOle(PTERWND w,int obj) { HANDLE hMeta; METAHEADER far *hdr; LPWORD pNative; LPBYTE pStr; int len; long far *pLong; long ObjSize,bmWidth,bmHeight,MetaSize; struct StrFont SaveDIBObj,SaveMetaObj; CLSID ClassId; LPOLECLIENTSITE pObjSite; LPSTORAGE pObjStg; FORMATETC OleFmt; if (!(TerFont[obj].style&PICT)) return FALSE; if (TerFont[obj].ObjectType!=OBJ_NONE) return FALSE; // get the class id for MSDRAW program if (NOERROR!=CLSIDFromProgID(StrToOleStr(MSDRAW_CLASS,TempString),&ClassId)) return FALSE; // MS draw program not found // Convert DIB to metafile if necessary if (TerFont[obj].PictType==PICT_DIBITMAP) { SaveDIBObj=TerFont[obj]; // save DIB object if (DIB2Metafile(w,obj)) { SaveMetaObj=TerFont[obj];// save metafile object TerFont[obj]=SaveDIBObj; // restore to delete DeleteTerObject(w,obj); TerFont[obj]=SaveMetaObj;// restore metafile object } } if (TerFont[obj].PictType!=PICT_METAFILE) return FALSE; // Make a native object from the metafile hMeta=TerGetMetaFileBits(TerFont[obj].hMeta); // convert to global handle if (NULL==(hdr=(METAHEADER far *)GlobalLock(hMeta)) ) { MessageBox(hTerWnd,"Error accessing meta file data",NULL,MB_OK); TerFont[obj].ObjectType=OBJ_NONE; // restore to plain picture return FALSE; } MetaSize=hdr->mtSize*2; // calculate the size of the tempporary ole object ObjSize=2*sizeof(long); // ver and indentifier ObjSize+=sizeof(long)+lstrlen(MSDRAW_CLASS)+1; // class id + null terminator ObjSize+=2*sizeof(long); // length of topic and item string ObjSize+=sizeof(long); // length of native data ObjSize+=3*sizeof(WORD); // native data header ObjSize+=MetaSize; // native data bytes ObjSize+=2*sizeof(long); // presentation data, ole ver and id ObjSize+=sizeof(long)+strlen("METAFILEPICT")+1;// format ObjSize+=2*sizeof(long); // width and height ObjSize+=sizeof(long); // size of presentation data ObjSize+=MetaSize; // presentation data bits if ( NULL==(hOleData=GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,ObjSize)) // allocate memory for the text data in our format || NULL==(pOleData=GlobalLock(hOleData)) ){ MessageBox(hTerWnd,"Ran out of memory","TerCreateTempOle",MB_OK); TerFont[obj].ObjectType=OBJ_NONE; // restore to plain picture return FALSE; } // set the object header pLong=(LPLONG)pOleData; *pLong=0x501;pLong++; // ole version number *pLong=2;pLong++; // native data id len=lstrlen(MSDRAW_CLASS); // length of class string *pLong=(len+1);pLong++; // length of class string plus NULL terminator pStr=(LPBYTE)pLong; lstrcpy(pStr,MSDRAW_CLASS); pStr=&(pStr[len]); // NULL not included *pStr=0;pStr++; // add the numm terminator pLong=(LPLONG)pStr; *pLong=0;pLong++; // length of topic string *pLong=0;pLong++; // length of item string *pLong=MetaSize+3*sizeof(WORD); // size of native bits pLong++; // set native data pNative=(LPWORD)pLong; bmHeight=ScrToPointsY(TerFont[obj].bmHeight); // objure height in pointsize bmWidth=ScrToPointsX(TerFont[obj].bmWidth); // objure width in pointsize pNative[0]=MM_ANISOTROPIC; // mapping mode pNative[1]=(WORD)((bmWidth*2500)/72); // width in HIMETRIC pNative[2]=(WORD)((bmHeight*2500)/72); // height in HIMETIC pStr=(LPBYTE)&(pNative[3]); HugeMove(hdr,pStr,MetaSize); // move the rtf data pLong=(LPLONG)&(((char huge *)pStr)[MetaSize]); // advance the pointer // set the presentation data *pLong=0x501;pLong++; // ole version number *pLong=5;pLong++; // presentation data id len=lstrlen("METAFILEPICT"); // length of class string *pLong=(len+1);pLong++; // length of class string plus NULL terminator pStr=(LPBYTE)pLong; lstrcpy(pStr,"METAFILEPICT"); pStr=&(pStr[(int)len]); // NULL not included *pStr=0;pStr++; // add the numm terminator pLong=(LPLONG)pStr; *pLong=pNative[1];pLong++; // width of presentation *pLong=pNative[2];pLong++; // height of presentation *pLong=MetaSize;pLong++; // size of the presentation bits HugeMove(hdr,pLong,MetaSize); // move the rtf data TerFont[obj].hMeta=TerSetMetaFileBits(hMeta); // restore the metafile handle // create an ole object if (!TerOlePreCreate(w,obj,&pObjSite,&pObjStg,&OleFmt)) return FALSE; // copy OLE1 stream data to OLE2 storage OleStream.MaxSize=ObjSize; // object size OleStream.offset=0; // beginning offset in the buffer if (NOERROR!=(OleConvertOLESTREAMToIStorage(&(OleStream.stream),pObjStg,NULL))) { return PrintError(w,"OLE data conversion error(TerCreateTempOle)"); } TerFont[obj].ObjectType=OBJ_EMBED_TEMP; // mark as temporary embedded object if (NOERROR!=(OleLoad(pObjStg,&(IID_IOleObject),pObjSite,(LPVOID far *)&(TerFont[obj].pObject)))) { return PrintError(w,"OLE load error(TerCreateTempOle)"); } TerOlePostCreate(w,obj); // postcreation tasks GlobalUnlock(hOleData); // free the temporary data GlobalFree(hOleData); return TRUE; } /******************************************************************************* TerOleLoad: This function supplies the ole data in the temporary handle (TerFont.hObject). and creates the OLE object. This functions frees the temporary memory handle. *******************************************************************************/ TerOleLoad(PTERWND w,int obj) { FORMATETC OleFmt; LPSTORAGE pObjStg; LPOLECLIENTSITE pObjSite; HRESULT result; LPLONG pLong; CLSID ClassId; if (!TerFont[obj].hObject) return FALSE; hOleData=TerFont[obj].hObject; // initialize the buffer pOleData=NULL; if (NULL==(pOleData=GlobalLock(hOleData)) ){ MessageBox(hTerWnd,"Ran out of memory","TerOleLoad",MB_OK); return FALSE; } // create internal interfaces for the object if (!TerOlePreCreate(w,obj,&pObjSite,&pObjStg,&OleFmt)) return FALSE; // Create the CompObj stream for a link object pLong=(LPLONG)pOleData; if (pLong[1]==1) { // link type object lstrcpy(TempString,(LPSTR)&(pOleData[3*sizeof(LONG)])); // prog id result=CLSIDFromProgID(StrToOleStr(TempString,TempString1),&ClassId); if (NOERROR!=result) return PrintError(w,"OLE class not found in the Registration Database(TerOleLoad)!"); // convert to class id result=WriteClassStg(pObjStg,&ClassId); if (NOERROR!=result) return PrintError(w,"Error writing class id(TerOleLoad)!"); // convert to class id result=WriteFmtUserTypeStg(pObjStg,0,StrToOleStr("",TempString)); if (NOERROR!=result) return PrintError(w,"Error writing user type(TerOleLoad)!"); // convert to class id } // copy OLE1 stream data to OLE2 storage OleStream.MaxSize=TerFont[obj].ObjectSize; // object size OleStream.offset=0; // beginning offset in the buffer result=OleConvertOLESTREAMToIStorage(&(OleStream.stream),pObjStg,NULL); if (result!=NOERROR) return PrintError(w,"OLE data conversion error"); result=OleLoad(pObjStg,&(IID_IOleObject),pObjSite,(LPVOID far *)&(TerFont[obj].pObject)); if (result!=NOERROR || !TerFont[obj].pObject) return PrintError(w,"OLE load error"); // make advisory connection and display the object TerOlePostCreate(w,obj); GlobalUnlock(hOleData); GlobalFree(hOleData); TerFont[obj].hObject=NULL; return TRUE; } /******************************************************************************* TerOleUnload: This function delete the OLE object. *******************************************************************************/ TerOleUnload(PTERWND w,int obj) { LPOLEOBJECT pObject=TerFont[obj].pObject; LPOLECLIENTSITE pObjSite=TerFont[obj].pObjSite; LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE )pObjSite; if (pObject) { pObject->lpVtbl->Unadvise(pObject,pSite->ConnectToken); pObject->lpVtbl->Release(pObject); } // release the IOleClientSite object while(TerFont[obj].pObjSite) { pObjSite=TerFont[obj].pObjSite; pObjSite->lpVtbl->Release(pObjSite); } return TRUE; } /******************************************************************************* TerOleQuerySize: This function returns the size of the specified object storage. *******************************************************************************/ BOOL TerOleQuerySize(PTERWND w, int obj, DWORD far *size) { LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE)TerFont[obj].pObjSite; LPSTORAGE pObjStg=pSite->pObjStg; HRESULT result; BYTE huge * pSaveData; HGLOBAL hSaveData; (*size)=0; hSaveData=hOleData; // save these global variables pSaveData=pOleData; hOleData=NULL; pOleData=0; // set TerOlePut in query mode OleStream.MaxSize=0; // initialize the size output variable OleStream.offset=0; // beginning offset in the buffer result=OleConvertIStorageToOLESTREAM(pObjStg,&(OleStream.stream)); if (result!=NOERROR) { PrintOleError(w,result); wsprintf(TempString,"OLE data conversion error: %lx (TerOleQuerySize)",(DWORD)result); return PrintError(w,TempString); } (*size)=OleStream.MaxSize; // buffer size hOleData=hSaveData; // restore these global variables pOleData=pSaveData; return TRUE; } /******************************************************************************* GetOleStorageData: This function extracts the OLE storage data in a global buffer. This function allocates a new global buffer and leaves it locked. The calling fuction must unlock and free the buffer when done. *******************************************************************************/ GetOleStorageData(PTERWND w,int obj) { LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE)TerFont[obj].pObjSite; LPSTORAGE pObjStg=pSite->pObjStg; HRESULT result; DWORD ObjectSize; // get the data size requirement and allocate memory if (!TerOleQuerySize(w,obj,&ObjectSize) || ObjectSize==0) { MessageBox(hTerWnd,"Error getting object size!","GetOleStorageData",MB_OK); return FALSE; } hOleData=NULL; // initialize the buffer pOleData=NULL; if ( NULL==(hOleData=GlobalAlloc(GMEM_MOVEABLE,ObjectSize)) // allocate memory for the ole data || NULL==(pOleData=GlobalLock(hOleData)) ){ MessageBox(hTerWnd,"Ran out of memory","GetOleStorageData",MB_OK); return FALSE; } // set to object to the global buffer OleStream.MaxSize=ObjectSize; // size of the object to read OleStream.offset=0; // beginning buffer offset result=OleConvertIStorageToOLESTREAM(pObjStg,&(OleStream.stream)); if (result!=NOERROR) { MessageBox(hTerWnd,"Error getting object data","GetOleStorageData",MB_OK); GlobalUnlock(hOleData); GlobalFree(hOleData); return FALSE; } return TRUE; } /******************************************************************************* StrToOleStr: Wait for an ole async operation to be over *******************************************************************************/ LPOLESTR StrToOleStr(LPSTR str,LPSTR OleStr) { #if defined(OLE2ANSI) lstrcpy(OleStr,str); return OleStr; #else int i,len; LPOLESTR str1=(LPOLESTR)OleStr; len=lstrlen(str); for (i=0;i<len;i++) str1[i]=str[i]; str1[i]=0; return str1; #endif } /******************************************************************************* PrintOleError: Print Ole error messages. *******************************************************************************/ PrintOleError(PTERWND w, HRESULT result) { DWORD code=(DWORD)result; char desc[100]; desc[0]=0; if (code==REGDB_E_CLASSNOTREG) lstrcpy(desc,"Class Not Registered"); else if (code==REGDB_E_CLASSNOTREG) lstrcpy(desc,"Share Utility Required"); if (desc[0]!=0) wsprintf(desc,"Error Code: %lx",(DWORD)result); MessageBox(NULL,desc,"OLE Error",MB_OK); return TRUE; } /***************************************************************************** Implementation of IOleClientSite Interface ******************************************************************************/ /***************************************************************************** CreateOleClientSite: This function creates an instance of IOleClientSite interface. The use count for the interface is set to 1. ******************************************************************************/ LPOLECLIENTSITE CreateOleClientSite(PTERWND w, int obj, LPSTORAGE pObjStg) { LPSTRCLIENTSITE pTerSite; LPOLECLIENTSITE pSite; // allocate and inititialize pTerSite if (NULL==(pTerSite=(LPSTRCLIENTSITE )OurAlloc(sizeof(struct StrClientSite)))) return NULL; pTerSite->count=1; // count for the interface pTerSite->w=w; // window pointer for the pSite pTerSite->obj=obj; // object id for the pSite pTerSite->pObjStg=pObjStg; // object IStorage // create IAdviseSink interface pTerSite->pObjAdvise=CreateAdviseSink(w,obj,pObjStg,(LPOLECLIENTSITE)pTerSite); if (!(pTerSite->pObjAdvise)) return NULL; // allocate and intialize the CLIENTSITE virtual functions pSite=(LPOLECLIENTSITE)pTerSite; if (NULL==(pSite->lpVtbl=OurAlloc(sizeof(struct IOleClientSiteVtbl)))) return NULL; if ( NULL==(pSite->lpVtbl->QueryInterface=(LPVOID) MakeProcInstance((FARPROC)IocsQueryInterface,hTerInst)) || NULL==(pSite->lpVtbl->AddRef=(LPVOID) MakeProcInstance((FARPROC)IocsAddRef,hTerInst)) || NULL==(pSite->lpVtbl->Release=(LPVOID) MakeProcInstance((FARPROC)IocsRelease,hTerInst)) || NULL==(pSite->lpVtbl->GetContainer=(LPVOID) MakeProcInstance((FARPROC)IocsGetContainer,hTerInst)) || NULL==(pSite->lpVtbl->OnShowWindow=(LPVOID) MakeProcInstance((FARPROC)IocsOnShowWindow,hTerInst)) || NULL==(pSite->lpVtbl->GetMoniker=(LPVOID) MakeProcInstance((FARPROC)IocsGetMoniker,hTerInst)) || NULL==(pSite->lpVtbl->RequestNewObjectLayout=(LPVOID) MakeProcInstance((FARPROC)IocsRequestNewObjectLayout,hTerInst)) || NULL==(pSite->lpVtbl->SaveObject=(LPVOID) MakeProcInstance((FARPROC)IocsSaveObject,hTerInst)) || NULL==(pSite->lpVtbl->ShowObject=(LPVOID) MakeProcInstance((FARPROC)IocsShowObject,hTerInst)) ){ MessageBox(hTerWnd,"ClientSite Creation Error!",NULL,MB_OK); return NULL; } return pSite; } /***************************************************************************** IocsQueryInterface: Query interface function for IOleClientSite ******************************************************************************/ HRESULT STDMETHODCALLTYPE IocsQueryInterface(LPOLECLIENTSITE this,REFIID riid,LPVOID far *obj) { LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE )this; (*obj)=NULL; // set to NULL if interface not supported if (IsEqualIID(riid,&IID_IUnknown)) (*obj)=this; if (IsEqualIID(riid,&IID_IOleClientSite)) (*obj)=this; if (IsEqualIID(riid,&IID_IAdviseSink)) (*obj)=pSite->pObjAdvise; if (*obj) { LPUNKNOWN far *ppUnk=(LPUNKNOWN far *)obj; (*ppUnk)->lpVtbl->AddRef(*ppUnk); return ResultFromScode(S_OK); } else return ResultFromScode(E_NOINTERFACE); } /***************************************************************************** IocsAddRef: AddRef function for IOleClientSite interface ******************************************************************************/ ULONG STDMETHODCALLTYPE IocsAddRef(LPOLECLIENTSITE this) { LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE )this; pSite->count++; return pSite->count; } /***************************************************************************** IocsRelease: Release function for the IOleClientSite interface ******************************************************************************/ ULONG STDMETHODCALLTYPE IocsRelease(LPOLECLIENTSITE this) { int obj; PTERWND w; LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE )this; w=pSite->w; obj=pSite->obj; pSite->count--; if (pSite->count==0) { // unallocate pSite interface // reduce the ref count for IAdviseSink added during creation if (pSite->pObjAdvise) pSite->pObjAdvise->lpVtbl->Release(pSite->pObjAdvise); #if !defined(WIN32) FreeProcInstance((FARPROC)(this->lpVtbl->QueryInterface)); FreeProcInstance((FARPROC)(this->lpVtbl->AddRef)); FreeProcInstance((FARPROC)(this->lpVtbl->Release)); FreeProcInstance((FARPROC)(this->lpVtbl->GetContainer)); FreeProcInstance((FARPROC)(this->lpVtbl->OnShowWindow)); FreeProcInstance((FARPROC)(this->lpVtbl->GetMoniker)); FreeProcInstance((FARPROC)(this->lpVtbl->RequestNewObjectLayout)); FreeProcInstance((FARPROC)(this->lpVtbl->SaveObject)); FreeProcInstance((FARPROC)(this->lpVtbl->ShowObject)); #endif OurFree(this->lpVtbl); OurFree(this); TerFont[obj].pObjSite=NULL; // object deleted return 0; } return pSite->count; } /***************************************************************************** IocsSaveObject: SaveObject function for the IOleClientSite interface This function brings the data from the IPersistStorage to the IStorage interface. ******************************************************************************/ HRESULT STDMETHODCALLTYPE IocsSaveObject(LPOLECLIENTSITE this) { PTERWND w; LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE )this; LPOLEOBJECT pObject; LPPERSISTSTORAGE lpPS; LPSTORAGE lpStg; HRESULT result; w=pSite->w; // window data pointer pObject=TerFont[pSite->obj].pObject; // object pointer lpStg=pSite->pObjStg; // object storage if (NOERROR!=(result=pObject->lpVtbl->QueryInterface(pObject,&IID_IPersistStorage,(LPVOID far *)&lpPS))) { MessageBox(hTerWnd,"Error retrieving the OLE storage","IocsSaveObject",MB_OK); return result; } if (NOERROR!=(result=OleSave(lpPS,lpStg,TRUE))) { MessageBox(hTerWnd,"Error saving the OLE object","IocsSaveObject",MB_OK); return result; } lpPS->lpVtbl->SaveCompleted(lpPS,NULL); lpPS->lpVtbl->Release(lpPS); // decrement for QueryInterface TerArg.modified++; // file modified return ResultFromScode(S_OK); } /***************************************************************************** Unimplemented functions for the IOleClientSite interface ******************************************************************************/ HRESULT STDMETHODCALLTYPE IocsGetContainer(LPOLECLIENTSITE this,LPOLECONTAINER far * ppContainer) { (*ppContainer)=NULL; return ResultFromScode(E_NOTIMPL); } HRESULT STDMETHODCALLTYPE IocsOnShowWindow(LPOLECLIENTSITE this,BOOL show) { return ResultFromScode(S_OK); } HRESULT STDMETHODCALLTYPE IocsGetMoniker(LPOLECLIENTSITE this,DWORD dwAssign,DWORD dwWhichMoniker,LPMONIKER far * ppmk) { (*ppmk)=NULL; return ResultFromScode(E_NOTIMPL); } HRESULT STDMETHODCALLTYPE IocsRequestNewObjectLayout(LPOLECLIENTSITE this) { return ResultFromScode(E_NOTIMPL); } HRESULT STDMETHODCALLTYPE IocsShowObject(LPOLECLIENTSITE this) { return NOERROR; } /***************************************************************************** Implementation of IAdviseSink Interface ******************************************************************************/ /***************************************************************************** CreateAdviseSink: This function creates an instance of IAdviseSink interface. The use count for the interface is set to 1. ******************************************************************************/ LPADVISESINK CreateAdviseSink(PTERWND w, int obj, LPSTORAGE pObjStg, LPOLECLIENTSITE pObjSite) { LPSTRADVISESINK pTerAdvise; LPADVISESINK pAdvise; // allocate and inititialize pTerSite if (NULL==(pTerAdvise=(LPSTRADVISESINK )OurAlloc(sizeof(struct StrAdviseSink)))) return NULL; pTerAdvise->count=1; // count for the interface pTerAdvise->w=w; // window pointer for the pAdvise pTerAdvise->obj=obj; // object id for the pAdvise pTerAdvise->pObjStg=pObjStg; // object IStorage pTerAdvise->pObjSite=pObjSite; // client site for the object // allocate and intialize the CLIENTSITE virtual functions pAdvise=(LPADVISESINK)pTerAdvise; if (NULL==(pAdvise->lpVtbl=OurAlloc(sizeof(struct IAdviseSinkVtbl)))) return NULL; if ( NULL==(pAdvise->lpVtbl->QueryInterface=(LPVOID) MakeProcInstance((FARPROC)IasQueryInterface,hTerInst)) || NULL==(pAdvise->lpVtbl->AddRef=(LPVOID) MakeProcInstance((FARPROC)IasAddRef,hTerInst)) || NULL==(pAdvise->lpVtbl->Release=(LPVOID) MakeProcInstance((FARPROC)IasRelease,hTerInst)) || NULL==(pAdvise->lpVtbl->OnDataChange=(LPVOID) MakeProcInstance((FARPROC)IasOnDataChange,hTerInst)) || NULL==(pAdvise->lpVtbl->OnViewChange=(LPVOID) MakeProcInstance((FARPROC)IasOnViewChange,hTerInst)) || NULL==(pAdvise->lpVtbl->OnRename=(LPVOID) MakeProcInstance((FARPROC)IasOnRename,hTerInst)) || NULL==(pAdvise->lpVtbl->OnSave=(LPVOID) MakeProcInstance((FARPROC)IasOnSave,hTerInst)) || NULL==(pAdvise->lpVtbl->OnClose=(LPVOID) MakeProcInstance((FARPROC)IasOnClose,hTerInst)) ){ MessageBox(hTerWnd,"AdviseSink Creation Error!",NULL,MB_OK); return NULL; } return pAdvise; } /***************************************************************************** IasQueryInterface: Query interface function for IAdviseSink. This function simply delegates to the IOleClientSite::QueryInterface ******************************************************************************/ HRESULT STDMETHODCALLTYPE IasQueryInterface(LPADVISESINK this,REFIID riid,LPVOID far *obj) { LPSTRADVISESINK pAdvise=(LPSTRADVISESINK )this; LPOLECLIENTSITE pObjSite=pAdvise->pObjSite; return pObjSite->lpVtbl->QueryInterface(pObjSite,riid,obj); } /***************************************************************************** IasAddRef: AddRef function for IAdviseSink interface ******************************************************************************/ ULONG STDMETHODCALLTYPE IasAddRef(LPADVISESINK this) { LPSTRADVISESINK pAdvise=(LPSTRADVISESINK )this; pAdvise->count++; return pAdvise->count; } /***************************************************************************** IasRelease: Release function for the IAdviseSink interface ******************************************************************************/ ULONG STDMETHODCALLTYPE IasRelease(LPADVISESINK this) { LPSTRADVISESINK pAdvise=(LPSTRADVISESINK )this; LPOLECLIENTSITE pObjSite=pAdvise->pObjSite; LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE )pObjSite; pAdvise->count--; if (pAdvise->count==0) { // unallocate pAdvise interface #if !defined(WIN32) FreeProcInstance((FARPROC)(this->lpVtbl->QueryInterface)); FreeProcInstance((FARPROC)(this->lpVtbl->AddRef)); FreeProcInstance((FARPROC)(this->lpVtbl->Release)); FreeProcInstance((FARPROC)(this->lpVtbl->OnDataChange)); FreeProcInstance((FARPROC)(this->lpVtbl->OnViewChange)); FreeProcInstance((FARPROC)(this->lpVtbl->OnRename)); FreeProcInstance((FARPROC)(this->lpVtbl->OnSave)); FreeProcInstance((FARPROC)(this->lpVtbl->OnClose)); #endif OurFree(this->lpVtbl); OurFree(this); // reset the pointer in the IOleClientSite interface if (pSite) pSite->pObjAdvise=NULL; return 0; } return pAdvise->count; } /***************************************************************************** IasOnViewChange: OnViewChange function for the IAdviseSink interface ******************************************************************************/ void STDMETHODCALLTYPE IasOnViewChange(LPADVISESINK this, DWORD dwAspect, LONG index) { LPSTRADVISESINK pAdvise=(LPSTRADVISESINK )this; LPOLECLIENTSITE pObjSite=pAdvise->pObjSite; LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE )pObjSite; int obj,i; LPOLEOBJECT pObject; LPDATAOBJECT pDataObject; PTERWND w; STGMEDIUM med; struct StrFont font; int FontCharWidth[256]; FORMATETC OleFmt; // retrieve the current ole item w=pSite->w; obj=pSite->obj; // item number in the font table pObject=TerFont[obj].pObject; // get the IDataObject Interface if (NOERROR!=(pObject->lpVtbl->QueryInterface(pObject,&IID_IDataObject,(LPVOID far *)&pDataObject))) { PrintError(w,"Error retrieving data object(IasOnViewChange)"); return; } // get the metafile picture representation of the data OleFmt.cfFormat=CF_METAFILEPICT; OleFmt.ptd=NULL; OleFmt.dwAspect=DVASPECT_CONTENT; OleFmt.lindex=-1; OleFmt.tymed=TYMED_MFPICT; if (NOERROR!=(pDataObject->lpVtbl->GetData(pDataObject,&OleFmt,&med)) || med.tymed!=TYMED_MFPICT) { PrintError(w,"Error retrieving presentation data(IasOnViewChange)"); return; } // Incorporate this data into our font table font=TerFont[obj]; // make a copy of the exiting font structure FarMove(TerFont[obj].CharWidth,FontCharWidth,sizeof(FontCharWidth)); InitTerObject(w,obj); // freeup this slot if (TerCreateMetafile(w,(HGLOBAL)(med.u.hGlobal),obj)<0) { TerFont[obj]=font; // restore the previous structure ReleaseStgMedium(&med); // release data handle return; } ReleaseStgMedium(&med); // release data handle // Apply the previous values TerFont[obj].ObjectType=font.ObjectType; TerFont[obj].pObject=font.pObject; TerFont[obj].pObjSite=font.pObjSite; TerFont[obj].ObjectSize=font.ObjectSize; TerFont[obj].AuxId=font.AuxId; TerFont[obj].style=font.style; // Apply the previous size if (TerFont[obj].ObjectType==OBJ_EMBED_INSERT) { // item being inserted TerFont[obj].ObjectType=OBJ_EMBED; TerInsertObjectId(hTerWnd,obj,TRUE); // this is a new object to be inserted } else { TerFont[obj].PictHeight=font.PictHeight; TerFont[obj].PictWidth=font.PictWidth; TerFont[obj].height=font.height; for (i=0;i<256;i++) TerFont[obj].CharWidth[i]=FontCharWidth[i]; XlateSizeForPrt(w,obj); // convert size to printer resolution if (font.hMeta) DeleteMetaFile(font.hMeta); // delete the previous metafile } //** reset the text map as the contents of the picture has changed TerArg.modified++; // file modified for (i=0;i<TotalSegments;i++) DeleteTextSeg(w,i); TotalSegments=0; PaintTer(w); } /***************************************************************************** Unimplemented functions for the IAdviseSink interface ******************************************************************************/ void STDMETHODCALLTYPE IasOnSave(LPADVISESINK this) {} void STDMETHODCALLTYPE IasOnClose(LPADVISESINK this) {} void STDMETHODCALLTYPE IasOnDataChange(LPADVISESINK this, FORMATETC far * fmt, STGMEDIUM far * med) {} void STDMETHODCALLTYPE IasOnRename(LPADVISESINK this, LPMONIKER pmk) {}