/*--------------------------------------------------------------------------- | OBJ.C | This file has the IUnknown, IOleObject, IStdMarshalInfo and IDataObject | interfaces of the OLE2 object (docMain). it also has other helper functions | | Created By: Vij Rajarajan (VijR) +---------------------------------------------------------------------------*/ #define SERVERONLY #include #include #include "mpole.h" #include "mplayer.h" extern int FAR PASCAL ReallyDoVerb (LPDOC, LONG, LPMSG, LPOLECLIENTSITE, BOOL, BOOL); extern BOOL FindRealFileName(LPTSTR szFile, int iLen); // static functions. HANDLE PASCAL GetDib (VOID); HANDLE GetMetafilePict (VOID); HANDLE GetMPlayerIcon(void); extern void FAR PASCAL SetEmbeddedObjectFlag(BOOL flag); extern HPALETTE CopyPalette(HPALETTE hpal); extern HBITMAP FAR PASCAL BitmapMCI(void); extern HPALETTE FAR PASCAL PaletteMCI(void); extern void DoInPlaceDeactivate(LPDOC lpdoc); HANDLE FAR PASCAL PictureFromDib(HANDLE hdib, HPALETTE hpal); HANDLE FAR PASCAL DibFromBitmap(HBITMAP hbm, HPALETTE hpal); void FAR PASCAL DitherMCI(HANDLE hdib, HPALETTE hpal); /* GetMetafilePict * --------------- * * RETURNS: A handle to the object's data in metafile format. */ HANDLE GetMetafilePict ( ) { HPALETTE hpal; HANDLE hdib; HANDLE hmfp; HDC hdc; DPF("GetMetafilePict called on thread %d\n", GetCurrentThreadId()); hdib = (HANDLE)SendMessage(ghwndApp, WM_GETDIB, 0, 0); /* If we're dithered, don't use a palette */ hdc = GetDC(NULL); if ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) && (gwOptions & OPT_DITHER)) hpal = NULL; else hpal = PaletteMCI(); if (hpal) hpal = CopyPalette(hpal); ReleaseDC(NULL, hdc); hmfp = PictureFromDib(hdib, hpal); if (hpal) DeleteObject(hpal); GLOBALFREE(hdib); return hmfp; } /************************************************************************** //## Somebody wants a dib (OLE) ***************************************************************************/ HANDLE PASCAL GetDib( VOID ) { HBITMAP hbm; HPALETTE hpal; HANDLE hdib; HDC hdc; DPF("GetDib\n"); hbm = BitmapMCI(); hpal = PaletteMCI(); hdib = DibFromBitmap(hbm, hpal); // // if we are on a palette device. possibly dither to the VGA colors // for apps that dont deal with palettes! // hdc = GetDC(NULL); if ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) && (gwOptions & OPT_DITHER)) { DitherMCI(hdib, hpal); hpal = NULL; // no longer working with a palette } ReleaseDC(NULL, hdc); if (hbm) DeleteObject(hbm); return hdib; } /************************************************************************** * GetMPlayerIcon: This function extracts the our Icon and gives it out * as a Metafile incase the client wants DVASPECT_ICON ***************************************************************************/ HANDLE GetMPlayerIcon (void) { HICON hicon; HDC hdc; HANDLE hmfp = NULL; LPMETAFILEPICT pmfp=NULL; static int cxIcon = 0; static int cyIcon = 0; static int cxIconHiMetric = 0; static int cyIconHiMetric = 0; hicon = GetIconForCurrentDevice(GI_LARGE, IDI_DDEFAULT); if ((HICON)1==hicon || NULL==hicon) return NULL; if (!(hmfp = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(METAFILEPICT)))) return NULL; pmfp = (METAFILEPICT FAR*) GLOBALLOCK (hmfp); if (0==cxIcon) { // In units of pixels cxIcon = GetSystemMetrics (SM_CXICON); cyIcon = GetSystemMetrics (SM_CYICON); // In units of .01 millimeter cxIconHiMetric = cxIcon * HIMETRIC_PER_INCH / giXppli; cyIconHiMetric = cyIcon * HIMETRIC_PER_INCH / giYppli;; } pmfp->mm = MM_ANISOTROPIC; pmfp->xExt = cxIconHiMetric; pmfp->yExt = cyIconHiMetric; hdc = CreateMetaFile (NULL); SetWindowOrgEx (hdc, 0, 0, NULL); SetWindowExtEx (hdc, cxIcon, cyIcon, NULL); DrawIcon (hdc, 0, 0, hicon); pmfp->hMF = CloseMetaFile (hdc); GLOBALUNLOCK (hmfp); if (NULL == pmfp->hMF) { GLOBALFREE (hmfp); return NULL; } return hmfp; } #ifdef DEBUG #define DBG_CHECK_GUID(guid) \ if (IsEqualIID(&guid, riidReq)) \ return #guid LPSTR DbgGetIIDString(REFIID riidReq) { static CHAR UnknownIID[64]; DBG_CHECK_GUID(IID_IUnknown); DBG_CHECK_GUID(IID_IClassFactory); DBG_CHECK_GUID(IID_IMalloc); DBG_CHECK_GUID(IID_IMarshal); DBG_CHECK_GUID(IID_IRpcChannel); DBG_CHECK_GUID(IID_IRpcStub); DBG_CHECK_GUID(IID_IStubManager); DBG_CHECK_GUID(IID_IRpcProxy); DBG_CHECK_GUID(IID_IProxyManager); DBG_CHECK_GUID(IID_IPSFactory); DBG_CHECK_GUID(IID_ILockBytes); DBG_CHECK_GUID(IID_IStorage); DBG_CHECK_GUID(IID_IStream); DBG_CHECK_GUID(IID_IEnumSTATSTG); DBG_CHECK_GUID(IID_IBindCtx); DBG_CHECK_GUID(IID_IMoniker); DBG_CHECK_GUID(IID_IRunningObjectTable); DBG_CHECK_GUID(IID_IInternalMoniker); DBG_CHECK_GUID(IID_IRootStorage); DBG_CHECK_GUID(IID_IDfReserved1); DBG_CHECK_GUID(IID_IDfReserved2); DBG_CHECK_GUID(IID_IDfReserved3); DBG_CHECK_GUID(IID_IMessageFilter); DBG_CHECK_GUID(CLSID_StdMarshal); DBG_CHECK_GUID(IID_IStdMarshalInfo); DBG_CHECK_GUID(IID_IExternalConnection); DBG_CHECK_GUID(IID_IEnumUnknown); DBG_CHECK_GUID(IID_IEnumString); DBG_CHECK_GUID(IID_IEnumMoniker); DBG_CHECK_GUID(IID_IEnumFORMATETC); DBG_CHECK_GUID(IID_IEnumOLEVERB); DBG_CHECK_GUID(IID_IEnumSTATDATA); DBG_CHECK_GUID(IID_IEnumGeneric); DBG_CHECK_GUID(IID_IEnumHolder); DBG_CHECK_GUID(IID_IEnumCallback); DBG_CHECK_GUID(IID_IPersistStream); DBG_CHECK_GUID(IID_IPersistStorage); DBG_CHECK_GUID(IID_IPersistFile); DBG_CHECK_GUID(IID_IPersist); DBG_CHECK_GUID(IID_IViewObject); DBG_CHECK_GUID(IID_IDataObject); DBG_CHECK_GUID(IID_IAdviseSink); DBG_CHECK_GUID(IID_IDataAdviseHolder); DBG_CHECK_GUID(IID_IOleAdviseHolder); DBG_CHECK_GUID(IID_IOleObject); DBG_CHECK_GUID(IID_IOleInPlaceObject); DBG_CHECK_GUID(IID_IOleWindow); DBG_CHECK_GUID(IID_IOleInPlaceUIWindow); DBG_CHECK_GUID(IID_IOleInPlaceFrame); DBG_CHECK_GUID(IID_IOleInPlaceActiveObject); DBG_CHECK_GUID(IID_IOleClientSite); DBG_CHECK_GUID(IID_IOleInPlaceSite); DBG_CHECK_GUID(IID_IParseDisplayName); DBG_CHECK_GUID(IID_IOleContainer); DBG_CHECK_GUID(IID_IOleItemContainer); DBG_CHECK_GUID(IID_IOleLink); DBG_CHECK_GUID(IID_IOleCache); DBG_CHECK_GUID(IID_IOleManager); DBG_CHECK_GUID(IID_IOlePresObj); DBG_CHECK_GUID(IID_IDropSource); DBG_CHECK_GUID(IID_IDropTarget); DBG_CHECK_GUID(IID_IDebug); DBG_CHECK_GUID(IID_IDebugStream); DBG_CHECK_GUID(IID_IAdviseSink2); DBG_CHECK_GUID(IID_IRunnableObject); DBG_CHECK_GUID(IID_IViewObject2); DBG_CHECK_GUID(IID_IOleCache2); DBG_CHECK_GUID(IID_IOleCacheControl); wsprintfA(UnknownIID, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", riidReq->Data1, riidReq->Data2, riidReq->Data3, riidReq->Data4[0], riidReq->Data4[1], riidReq->Data4[2], riidReq->Data4[3], riidReq->Data4[4], riidReq->Data4[5], riidReq->Data4[6], riidReq->Data4[7]); return UnknownIID; } #endif /************************************************************************** ***************** IUnknown INTERFACE IMPLEMENTATION. **************************************************************************/ STDMETHODIMP UnkQueryInterface( LPUNKNOWN lpUnkObj, // Unknown object ptr REFIID riidReq, // IID required LPVOID FAR * lplpUnk // pre for returning the interface ) { LPDOC lpdoc; lpdoc = ((struct COleObjectImpl FAR*)lpUnkObj)->lpdoc; DPF1("QueryInterface( %s )\n", DbgGetIIDString(riidReq)); if (IsEqualIID(riidReq, &IID_IOleObject)) { *lplpUnk = (LPVOID) &lpdoc->m_Ole; lpdoc->cRef++; return NOERROR; } else if (IsEqualIID(riidReq, &IID_IDataObject)) { *lplpUnk = (LPVOID) &lpdoc->m_Data; lpdoc->cRef++; return NOERROR; } else if (IsEqualIID(riidReq, &IID_IUnknown)) { *lplpUnk = (LPVOID) &lpdoc->m_Ole; lpdoc->cRef++; return NOERROR; } else if (IsEqualIID(riidReq, &IID_IPersist) || IsEqualIID(riidReq, &IID_IPersistStorage)) { *lplpUnk = (LPVOID) &lpdoc->m_PersistStorage; lpdoc->cRef++; return NOERROR; } else if (IsEqualIID(riidReq, &IID_IPersistFile)) { *lplpUnk = (LPVOID) &lpdoc->m_PersistFile; lpdoc->cRef++; return NOERROR; } else if (IsEqualIID(riidReq, &IID_IOleWindow) || IsEqualIID(riidReq, &IID_IOleInPlaceObject)) { *lplpUnk = (LPVOID) &lpdoc->m_InPlace; lpdoc->cRef++; return NOERROR; } else if (IsEqualIID(riidReq, &IID_IOleInPlaceActiveObject)) { *lplpUnk = (LPVOID) &lpdoc->m_IPActive; lpdoc->cRef++; return NOERROR; } else { *lplpUnk = (LPVOID) NULL; DPF1("E_NOINTERFACE\n"); RETURN_RESULT(E_NOINTERFACE); } } STDMETHODIMP_(ULONG) UnkAddRef(LPUNKNOWN lpUnkObj) { LPDOC lpdoc; lpdoc = ((struct COleObjectImpl FAR*)lpUnkObj)->lpdoc; return ++lpdoc->cRef; } STDMETHODIMP_(ULONG) UnkRelease (LPUNKNOWN lpUnkObj) { LPDOC lpdoc; lpdoc = ((struct COleObjectImpl FAR*)lpUnkObj)->lpdoc; if (--lpdoc->cRef == 0) { DPF1("\n**^*^*^*^*^*^*^*^*^*^*^*^*Refcnt OK\n"); if (!(gfOle2IPPlaying || gfOle2IPEditing) && srvrMain.cLock == 0) PostCloseMessage(); return 0; } return lpdoc->cRef; } /************************************************************************** ************* IOleObject INTERFACE IMPLEMENTATION **************************************************************************/ //delegate to the common IUnknown Implemenation. STDMETHODIMP OleObjQueryInterface( LPOLEOBJECT lpOleObj, // ole object ptr REFIID riidReq, // IID required LPVOID FAR * lplpUnk // pre for returning the interface ) { return( UnkQueryInterface((LPUNKNOWN)lpOleObj, riidReq, lplpUnk)); } STDMETHODIMP_(ULONG) OleObjAddRef( LPOLEOBJECT lpOleObj // ole object ptr ) { return UnkAddRef((LPUNKNOWN) lpOleObj); } STDMETHODIMP_(ULONG) OleObjRelease ( LPOLEOBJECT lpOleObj // ole object ptr ) { LPDOC lpdoc; lpdoc = ((struct COleObjectImpl FAR*)lpOleObj)->lpdoc; return UnkRelease((LPUNKNOWN) lpOleObj); } //Save the Client site pointer. STDMETHODIMP OleObjSetClientSite( LPOLEOBJECT lpOleObj, LPOLECLIENTSITE lpclientSite ) { LPDOC lpdoc; DPF("OleObjSetClientSite\n"); lpdoc = ((struct COleObjectImpl FAR*)lpOleObj)->lpdoc; if (lpdoc->lpoleclient) IOleClientSite_Release(lpdoc->lpoleclient); lpdoc->lpoleclient = (LPOLECLIENTSITE) lpclientSite; // OLE2NOTE: to be able to hold onto clientSite pointer, we must AddRef it if (lpclientSite) IOleClientSite_AddRef(lpclientSite); return NOERROR; } STDMETHODIMP OleObjGetClientSite ( LPOLEOBJECT lpOleObj, LPOLECLIENTSITE FAR* lplpclientSite ) { DPF("OleObjGetClientSite\n"); return NOERROR; } /* CheckIfInPPViewer * * Hack to stop PowerPoint viewer from crashing when we're trying to play in place. * * PP Viewer was written under the assumption that Media Player was not a full-blown * OLE2 server. Much of the code was stubbed out to make the Viewer small. * Unfortunately this means it crashes when certain calls are made for in-place * activation. These are the problem interface methods: * * OnInPlaceActivate/Deactivate * OnUIActivate/Deactivate * OnPosRectChange * * If we're in PP Viewer we simply do not make these calls. * * We detect that we're in PP Viewer by finding the parent of the window whose * handle is passed to DoVerb. The window handle passed in to DoVerb is of * "ppSlideShowWin" class, which is the same as in PP Slide Show, which works * correctly. However its parent's class is "PP4VDialog" (as distinct from * "PPApplicationClass"). So, if we find this class name, set a global flag * to test before making the troublesome calls. * * Andrew Bell (andrewbe) 11 May 1995 * */ STATICFN void CheckIfInPPViewer(HWND hwndParent) { HWND hwndGrandParent; TCHAR ClassName[256]; gfInPPViewer = FALSE; if (hwndParent) { hwndGrandParent = GetParent(hwndParent); if (hwndGrandParent) { if (GetClassName(hwndGrandParent, ClassName, CHAR_COUNT(ClassName)) > 0) { if (lstrcmp(ClassName, TEXT("PP4VDialog")) == 0) { DPF0("Detected that we're in PP Viewer\n"); gfInPPViewer = TRUE; } } } } } //delegate to ReallyDoVerb. STDMETHODIMP OleObjDoVerb( LPOLEOBJECT lpOleObj, LONG lVerb, LPMSG lpmsg, LPOLECLIENTSITE pActiveSite, LONG lindex, HWND hwndParent, LPCRECT lprcPosRect ) { LPDOC lpdoc = ((struct COleObjectImpl FAR*)lpOleObj)->lpdoc; DPF("OleObjDoVerb\n"); CheckIfInPPViewer(hwndParent); RETURN_RESULT( ReallyDoVerb(lpdoc, lVerb, lpmsg, pActiveSite, TRUE, TRUE)); } STDMETHODIMP OleObjEnumVerbs( LPOLEOBJECT lpOleObj, IEnumOLEVERB FAR* FAR* lplpenumOleVerb ) { DPF("OleObjEnumVerbs\n"); *lplpenumOleVerb = NULL; RETURN_RESULT( OLE_S_USEREG); //Use the reg db. } STDMETHODIMP OleObjUpdate(LPOLEOBJECT lpOleObj) { DPF("OleObjUpdate\n"); // we can't contain links so there is nothing to update return NOERROR; } STDMETHODIMP OleObjIsUpToDate(LPOLEOBJECT lpOleObj) { DPF("OleObjIsUpToDate\n"); // we can't contain links so there is nothing to update return NOERROR; } /* From OLE2HELP.HLP: GetUserClassID returns the CLSID as the user knows it. For embedded objects, this is always the CLSID that is persistently stored and is returned by IPersist::GetClassID. For linked objects, this is the CLSID of the last bound link source. If a Treat As operation is taking place, this is the CLSID of the application being emulated (also the CLSID that will be written into storage). I can't follow the logic here. What if it's an embedded object and a Treat As operation? However, AlexGo tells me that my IOleObject interfaces should return the OLE2 Class ID. */ STDMETHODIMP OleObjGetUserClassID (LPOLEOBJECT lpOleObj, CLSID FAR* pClsid) { DPF1("OleObjGetUserClassID\n"); *pClsid = gClsID; return NOERROR; } /************************************************************************** * Set our UserTypeName to "Media Clip" **************************************************************************/ STDMETHODIMP OleObjGetUserType (LPOLEOBJECT lpOleObj, DWORD dwFormOfType, LPWSTR FAR* pszUserType) { LPMALLOC lpMalloc; LPWSTR lpstr; int clen; DPF1("OleObjGetUserType\n"); *pszUserType = NULL; if(CoGetMalloc(MEMCTX_TASK,&lpMalloc) != 0) RETURN_RESULT(E_OUTOFMEMORY); clen = STRING_BYTE_COUNT(gachClassRoot); #ifndef UNICODE clen *= (sizeof(WCHAR) / sizeof(CHAR)); #endif lpstr = IMalloc_Alloc(lpMalloc, clen); IMalloc_Release(lpMalloc); #ifdef UNICODE lstrcpy(lpstr,gachClassRoot); #else AnsiToUnicodeString(gachClassRoot, lpstr, -1); #endif /* UNICODE */ *pszUserType = lpstr; return NOERROR; } /************************************************************************** * Get the name of the client and set the title. **************************************************************************/ STDMETHODIMP OleObjSetHostNames ( LPOLEOBJECT lpOleObj, LPCWSTR lpszClientAppW, LPCWSTR lpszClientObjW ) { LPDOC lpdoc; LPTSTR lpszClientApp; LPTSTR lpszClientObj; DPF1("OleObjSetHostNames\n"); #ifdef UNICODE lpszClientApp = (LPTSTR)lpszClientAppW; lpszClientObj = (LPTSTR)lpszClientObjW; #else lpszClientApp = AllocateAnsiString(lpszClientAppW); lpszClientObj = AllocateAnsiString(lpszClientObjW); if( !lpszClientApp || !lpszClientObj ) RETURN_RESULT(E_OUTOFMEMORY); #endif /* UNICODE */ lpdoc = ((struct COleObjectImpl FAR*)lpOleObj)->lpdoc; // object is embedded. lpdoc->doctype = doctypeEmbedded; if (lpszClientObj == NULL) lpszClientObj = lpszClientApp; SetTitle(lpdoc, lpszClientObj); SetMPlayerIcon(); lstrcpy (szClient, lpszClientApp); if (lpszClientObj) { LPTSTR lpszFileName = FileName(lpszClientObj); if (lpszFileName) lstrcpy (szClientDoc, lpszFileName); } // this is the only time we know the object will be an embedding SetEmbeddedObjectFlag(TRUE); #ifndef UNICODE FreeAnsiString(lpszClientApp); FreeAnsiString(lpszClientObj); #endif /* NOT UNICODE */ return NOERROR; } /************************************************************************** * The client closed the object. The server will now shut down. **************************************************************************/ STDMETHODIMP OleObjClose ( LPOLEOBJECT lpOleObj, DWORD dwSaveOptions ) { LPDOC lpdoc; DPF1("OleObjClose\n"); lpdoc = ((struct COleObjectImpl FAR*)lpOleObj)->lpdoc; /* Hack to stop PowerPoint crashing: * * Win95 bug #19848: Crash saving PowerPoint with out-of-place mplayer * * If we don't call IOleClientSite::SaveObject() at this point, * PowerPoint will crash under certain circumstances. * * This is an extract from mail I received from TuanN, the PPT dev: * * The fundamental problem is that PP expects to receive the * IAdviseSink::SaveObject() as a result of calling IOleObject::Close(). * Since the Media Player did not send that notficiation in this test case, * PP tries to perform an Undo operation during the ensuing OnClose() * notification and thus erroneously destroys the embedded object. * The reason we throw away the object is because PP thinks that this * object is still virgin (no OnViewChange). Please refer to SaveObject(), * OnClose() in CtCommon.cpp and slide\sextern.c for more info. In the test * case, during OnClose(), the "revert" state is TRUE, PP will do a * Ex_REVERTED operation (stack calls: SClosePicts, SClear, * SSaveforUndo--> object deleted). * * AndrewBe, 6 December 1994 */ if (lpdoc->lpoleclient) IOleClientSite_SaveObject(lpdoc->lpoleclient); DoInPlaceDeactivate(lpdoc); SendDocMsg(lpdoc,OLE_CLOSED); DestroyDoc(lpdoc); ExitApplication(); //CoDisconnectObject((LPUNKNOWN)lpdoc, NULL); SendMessage(ghwndApp, WM_COMMAND, (WPARAM)IDM_EXIT, 0L); return NOERROR; } STDMETHODIMP OleObjSetMoniker(LPOLEOBJECT lpOleObj, DWORD dwWhichMoniker, LPMONIKER pmk) { DPF("OleObjSetMoniker\n"); return NOERROR; } STDMETHODIMP OleObjGetMoniker(LPOLEOBJECT lpOleObj, DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER FAR* lplpmk) { LPDOC lpdoc; DPF("OleObjGetMoniker\n"); *lplpmk = NULL; lpdoc = ((struct COleObjectImpl FAR*)lpOleObj)->lpdoc; if (lpdoc->lpoleclient != NULL) { return( IOleClientSite_GetMoniker(lpdoc->lpoleclient, dwAssign, dwWhichMoniker, lplpmk)); } else if (lpdoc->doctype == doctypeFromFile) { // use file moniker WCHAR sz[cchFilenameMax]; if (GlobalGetAtomNameW(lpdoc->aDocName, sz, CHAR_COUNT(sz)) == 0) RETURN_RESULT( E_FAIL); return( (HRESULT)CreateFileMoniker(sz, lplpmk)); } else RETURN_RESULT( E_FAIL); } STDMETHODIMP OleObjInitFromData ( LPOLEOBJECT lpOleObj, LPDATAOBJECT lpDataObj, BOOL fCreation, DWORD dwReserved ) { DPF("OleObjInitFromData - E_NOTIMPL\n"); RETURN_RESULT( E_NOTIMPL); } STDMETHODIMP OleObjGetClipboardData ( LPOLEOBJECT lpOleObj, DWORD dwReserved, LPDATAOBJECT FAR* lplpDataObj ) { DPF("OleObjGetClipboardData - E_NOTIMPL\n"); RETURN_RESULT( E_NOTIMPL); } STDMETHODIMP OleObjSetExtent( LPOLEOBJECT lpOleObj, DWORD dwAspect, LPSIZEL lpsizel) { DPF("OleObjSetExtent\n"); #ifdef LATER gscaleInitXY[SCALE_X].denom = lpsizel->cx; gscaleInitXY[SCALE_Y].denom = lpsizel->cy; #endif return NOERROR; } //Get the object extent from the Metafile. GetMetafilePict saves the extents // in extWidth and extHeight STDMETHODIMP OleObjGetExtent( LPOLEOBJECT lpOleObj, DWORD dwAspect, LPSIZEL lpSizel) { HGLOBAL hTmpMF; LPDOC lpdoc; DPF("OleObjGetExtent\n"); lpdoc = ((struct COleObjectImpl FAR*)lpOleObj)->lpdoc; if((dwAspect & (DVASPECT_CONTENT | DVASPECT_DOCPRINT)) == 0) RETURN_RESULT( E_INVALIDARG); // There may be a potential memory leak here -- hTmpMF contains a handle to a // metafile that must be deleted. See code in cdrag.c. // Not changed here at this time since I do not want to break anything. // SteveZ hTmpMF = GetMetafilePict(); GLOBALUNLOCK(hTmpMF); GLOBALFREE(hTmpMF); lpSizel->cx = extWidth; lpSizel->cy = extHeight; return NOERROR; } STDMETHODIMP OleObjAdvise(LPOLEOBJECT lpOleObj, LPADVISESINK lpAdvSink, LPDWORD lpdwConnection) { LPDOC lpdoc; DPF("OleObjAdvise\n"); lpdoc = ((struct COleObjectImpl FAR*)lpOleObj)->lpdoc; if (lpdoc->lpoaholder == NULL && CreateOleAdviseHolder(&lpdoc->lpoaholder) != S_OK) RETURN_RESULT( E_OUTOFMEMORY); return( IOleAdviseHolder_Advise(lpdoc->lpoaholder, lpAdvSink, lpdwConnection)); } STDMETHODIMP OleObjUnadvise(LPOLEOBJECT lpOleObj, DWORD dwConnection) { LPDOC lpdoc; DPF("OleObjUnadvise\n"); lpdoc = ((struct COleObjectImpl FAR*)lpOleObj)->lpdoc; if (lpdoc->lpoaholder == NULL) RETURN_RESULT( E_FAIL); return( IOleAdviseHolder_Unadvise(lpdoc->lpoaholder, dwConnection)); } STDMETHODIMP OleObjEnumAdvise(LPOLEOBJECT lpOleObj, LPENUMSTATDATA FAR* lplpenumAdvise) { LPDOC lpdoc; DPF("OleObjEnumAdvise\n"); lpdoc = ((struct COleObjectImpl FAR*)lpOleObj)->lpdoc; if (lpdoc->lpoaholder == NULL) RETURN_RESULT( E_FAIL); return(IOleAdviseHolder_EnumAdvise(lpdoc->lpoaholder, lplpenumAdvise)); } STDMETHODIMP OleObjGetMiscStatus (LPOLEOBJECT lpOleObj, DWORD dwAspect, DWORD FAR* pdwStatus) { DPF("OleObjGetMiscStatus\n"); RETURN_RESULT( OLE_S_USEREG); } STDMETHODIMP OleObjSetColorScheme(LPOLEOBJECT lpOleObj, LPLOGPALETTE lpLogPal) { DPF("OleObjSetColorScheme\n"); return NOERROR; } STDMETHODIMP OleObjLockObject(LPOLEOBJECT lpOleObj, BOOL fLock) { LPDOC lpdoc; DPF("OleObjLockObject\n"); lpdoc = ((struct COleObjectImpl FAR*)lpOleObj)->lpdoc; if (fLock) lpdoc->cLock++; else { if (!lpdoc->cLock) RETURN_RESULT( E_FAIL); if (--lpdoc->cLock == 0) OleObjClose(lpOleObj, OLECLOSE_SAVEIFDIRTY); return NOERROR; } return NOERROR; } /************************************************************************** ************* IDataObject INTERFACE IMPLEMENTATION. **************************************************************************/ //Delegate to the common IUnknown implementation. STDMETHODIMP DataObjQueryInterface ( LPDATAOBJECT lpDataObj, // data object ptr REFIID riidReq, // IID required LPVOID FAR * lplpUnk // pre for returning the interface ) { return( UnkQueryInterface((LPUNKNOWN)lpDataObj, riidReq, lplpUnk)); } STDMETHODIMP_(ULONG) DataObjAddRef( LPDATAOBJECT lpDataObj // data object ptr ) { return UnkAddRef((LPUNKNOWN) lpDataObj); } STDMETHODIMP_(ULONG) DataObjRelease ( LPDATAOBJECT lpDataObj // data object ptr ) { LPDOC lpdoc; lpdoc = ((struct CDataObjectImpl FAR*)lpDataObj)->lpdoc; return UnkRelease((LPUNKNOWN) lpDataObj); } /************************************************************************** * DataObjGetData: * Provides the data for METAFILE and DIB formats. **************************************************************************/ STDMETHODIMP DataObjGetData ( LPDATAOBJECT lpDataObj, LPFORMATETC lpformatetc, LPSTGMEDIUM lpMedium ) { LPDOC lpdoc; DPF1("DataObjGetData\n"); if (lpMedium == NULL) RETURN_RESULT( E_FAIL); // null out in case of error lpMedium->tymed = TYMED_NULL; lpMedium->pUnkForRelease = NULL; lpMedium->hGlobal = NULL; lpdoc = ((struct CDataObjectImpl FAR*)lpDataObj)->lpdoc; VERIFY_LINDEX(lpformatetc->lindex); if (lpformatetc->dwAspect == DVASPECT_ICON) { if (lpformatetc->cfFormat != CF_METAFILEPICT) RETURN_RESULT( DATA_E_FORMATETC); } else { if (!(lpformatetc->dwAspect & (DVASPECT_CONTENT | DVASPECT_DOCPRINT))) RETURN_RESULT( DATA_E_FORMATETC); // we support only these 2 aspects } if (lpMedium->tymed != TYMED_NULL) // all the other formats we only give out in our own global block RETURN_RESULT( DATA_E_FORMATETC); lpMedium->tymed = TYMED_HGLOBAL; if (lpformatetc->cfFormat == CF_METAFILEPICT) { lpMedium->tymed = TYMED_MFPICT; DPF1("Before getmeta\n"); if (lpformatetc->dwAspect == DVASPECT_ICON) lpMedium->hGlobal = GetMPlayerIcon (); else lpMedium->hGlobal = GetMetafilePict (); DPF1("After getmeta\n"); if (!lpMedium->hGlobal) RETURN_RESULT( E_OUTOFMEMORY); #ifdef DEBUG if (__iDebugLevel >= 1) { /* Useful check to validate what we're passing back to the container. */ if (OpenClipboard(ghwndApp)) { EmptyClipboard(); SetClipboardData(CF_METAFILEPICT, lpMedium->hGlobal); CloseClipboard(); } } #endif return NOERROR; } if (lpformatetc->cfFormat == CF_DIB) { lpMedium->tymed = TYMED_HGLOBAL; lpMedium->hGlobal = (HANDLE)GetDib(); if (!(lpMedium->hGlobal)) RETURN_RESULT( E_OUTOFMEMORY); #ifdef DEBUG if (__iDebugLevel >= 1) { /* Useful check to validate what we're passing back to the container. */ if (OpenClipboard(ghwndApp)) { EmptyClipboard(); SetClipboardData(CF_DIB, lpMedium->hGlobal); CloseClipboard(); } } #endif return NOERROR; } RETURN_RESULT( DATA_E_FORMATETC); } STDMETHODIMP DataObjGetDataHere ( LPDATAOBJECT lpDataObj, LPFORMATETC lpformatetc, LPSTGMEDIUM lpMedium ) { RETURN_RESULT( E_NOTIMPL); } STDMETHODIMP DataObjQueryGetData ( LPDATAOBJECT lpDataObj, LPFORMATETC lpformatetc ) { // this is only a query if ((lpformatetc->cfFormat == CF_METAFILEPICT) && (lpformatetc->tymed & TYMED_MFPICT)) return NOERROR; if ((lpformatetc->cfFormat == CF_DIB) && (lpformatetc->tymed & TYMED_HGLOBAL)) return NOERROR; RETURN_RESULT( DATA_E_FORMATETC); } STDMETHODIMP DataObjGetCanonicalFormatEtc( LPDATAOBJECT lpDataObj, LPFORMATETC lpformatetc, LPFORMATETC lpformatetcOut ) { RETURN_RESULT(DATA_S_SAMEFORMATETC); } STDMETHODIMP DataObjEnumFormatEtc( LPDATAOBJECT lpDataObj, DWORD dwDirection, LPENUMFORMATETC FAR* lplpenumFormatEtc ) { *lplpenumFormatEtc = NULL; RETURN_RESULT( OLE_S_USEREG); } STDMETHODIMP DataObjAdvise(LPDATAOBJECT lpDataObject, FORMATETC FAR* pFormatetc, DWORD advf, IAdviseSink FAR* pAdvSink, DWORD FAR* pdwConnection) { LPDOC lpdoc; lpdoc = ((struct CDataObjectImpl FAR*)lpDataObject)->lpdoc; VERIFY_LINDEX(pFormatetc->lindex); if (pFormatetc->cfFormat == 0 && pFormatetc->dwAspect == -1 && pFormatetc->ptd == NULL && pFormatetc->tymed == -1) // wild card advise; don't check ; else if (DataObjQueryGetData(lpDataObject, pFormatetc) != S_OK) RETURN_RESULT( DATA_E_FORMATETC); if (lpdoc->lpdaholder == NULL && CreateDataAdviseHolder(&lpdoc->lpdaholder) != S_OK) RETURN_RESULT( E_OUTOFMEMORY); return( IDataAdviseHolder_Advise(lpdoc->lpdaholder, lpDataObject, pFormatetc, advf, pAdvSink, pdwConnection)); } STDMETHODIMP DataObjUnadvise(LPDATAOBJECT lpDataObject, DWORD dwConnection) { LPDOC lpdoc; lpdoc = ((struct CDataObjectImpl FAR*)lpDataObject)->lpdoc; if (lpdoc->lpdaholder == NULL) // no one registered RETURN_RESULT( E_INVALIDARG); return( IDataAdviseHolder_Unadvise(lpdoc->lpdaholder, dwConnection)); } STDMETHODIMP DataObjEnumAdvise(LPDATAOBJECT lpDataObject, LPENUMSTATDATA FAR* ppenumAdvise) { LPDOC lpdoc; lpdoc = ((struct CDataObjectImpl FAR*)lpDataObject)->lpdoc; if (lpdoc->lpdaholder == NULL) RETURN_RESULT( E_FAIL); return( IDataAdviseHolder_EnumAdvise(lpdoc->lpdaholder, ppenumAdvise)); } /************************************************************************** * DataObjSetData: * This should never be called.!! The data is actually fed through * IPersistStorage. **************************************************************************/ STDMETHODIMP DataObjSetData ( LPDATAOBJECT lpDataObj, LPFORMATETC lpformatetc, LPSTGMEDIUM lpmedium, BOOL fRelease ) { LPVOID lpMem; LPSTR lpnative; LPDOC lpdoc = ((struct CDataObjectImpl FAR *)lpDataObj)->lpdoc; DPF1("*DOSETDATA"); if(lpformatetc->cfFormat !=cfNative) RETURN_RESULT(DATA_E_FORMATETC); lpMem = GLOBALLOCK(lpmedium->hGlobal); if (lpMem) { SCODE scode; lpnative = lpMem; scode = ItemSetData((LPBYTE)lpnative); if(scode == S_OK) fDocChanged = FALSE; GLOBALUNLOCK(lpmedium->hGlobal); RETURN_RESULT(scode); } RETURN_RESULT(E_OUTOFMEMORY); }