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.
1162 lines
31 KiB
1162 lines
31 KiB
/*---------------------------------------------------------------------------
|
|
| 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 <Windows.h>
|
|
#include <shellapi.h>
|
|
|
|
#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);
|
|
}
|
|
|