1162 lines
31 KiB
C
1162 lines
31 KiB
C
/*---------------------------------------------------------------------------
|
|
| CDRAG.C
|
|
| This file has the interfaces for the object transferred through the
|
|
| Clipboard or through a Drag-Drop. These interfaces unlike the interfaces
|
|
| implemented in the file OBJ.C transfer the state of the object at
|
|
| Edit->Copy time or Drag-Drop time. The interfaces in OBJ.C transfer the
|
|
| real-time Object Data.
|
|
|
|
|
| Created by: Vij Rajarajan (VijR)
|
|
+---------------------------------------------------------------------------*/
|
|
#define SERVERONLY
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include "mpole.h"
|
|
#include "mplayer.h"
|
|
|
|
#include <malloc.h>
|
|
|
|
#define OLESTDDELIM "!"
|
|
#define STGM_SALL (STGM_READWRITE | STGM_SHARE_EXCLUSIVE)
|
|
|
|
HANDLE GetMetafilePict (VOID);
|
|
SCODE SaveMoniker (LPSTREAM lpstream);
|
|
HANDLE PASCAL GetDib (VOID);
|
|
|
|
HANDLE ghClipData = NULL; /* Holds the data handle at the time of Copy */
|
|
HANDLE ghClipMetafile = NULL; /* to clipboard */
|
|
HANDLE ghClipDib = NULL;
|
|
|
|
/* Global flag to indicate OLE was initialized for drag.
|
|
* This happens on a separate thread from the main window,
|
|
* so we need to initialize and uninitialize independently.
|
|
*/
|
|
BOOL gfOleInitForDrag = FALSE;
|
|
|
|
extern LPDATAOBJECT gpClipboardDataObject;
|
|
|
|
/**************************************************************************
|
|
* CutOrCopyObject
|
|
* Sets the clipboard with the IDataObject interface of the lpdoc
|
|
* object passed as the argument. The function also saves a snapshot of
|
|
* the state of the object in the globals ghClipMetafile, ghClipData,
|
|
* and ghClipDib.
|
|
**************************************************************************/
|
|
void CutOrCopyObj (LPDOC lpdoc)
|
|
{
|
|
LPDATAOBJECT lpDataObj;
|
|
|
|
lpDataObj = (LPDATAOBJECT)CreateClipDragDataObject(lpdoc,TRUE);
|
|
|
|
if (lpDataObj != NULL) {
|
|
if (ghClipData)
|
|
GLOBALFREE(ghClipData);
|
|
if (ghClipMetafile) {
|
|
{
|
|
// note that ghClipMetafile is set deep in PictureFromDib and contains
|
|
// a handle to a windows metafile. Clean this up properly here. There may
|
|
// be other memory/handle leaks caused by this coding of the metafile handle elsewhere.
|
|
// SteveZ
|
|
LPMETAFILEPICT pmfp;
|
|
BOOL bReturn;
|
|
DWORD dw;
|
|
pmfp = (LPMETAFILEPICT)GLOBALLOCK(ghClipMetafile);
|
|
bReturn = DeleteMetaFile(pmfp->hMF);
|
|
if (!bReturn) {
|
|
dw = GetLastError();
|
|
}
|
|
GLOBALUNLOCK(ghClipMetafile);
|
|
}
|
|
GLOBALFREE(ghClipMetafile);
|
|
}
|
|
if (ghClipDib)
|
|
GLOBALFREE(ghClipDib);
|
|
ghClipData = GetLink();
|
|
ghClipMetafile = GetMetafilePict();
|
|
ghClipDib = GetDib();
|
|
OleSetClipboard(lpDataObj);
|
|
IDataObject_Release(lpDataObj);
|
|
gpClipboardDataObject = lpDataObj;
|
|
}
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* CreateClipDragDataObject:
|
|
* This function returns an initialized instance of the CLIPDRAGDATA data
|
|
* structure. fClipData = TRUE if the object is for the clipboard and
|
|
* = FALSE if the object is for Drag-Drop operation.
|
|
**************************************************************************/
|
|
LPCLIPDRAGDATA CreateClipDragDataObject(LPDOC lpdoc, BOOL fClipData)
|
|
{
|
|
LPCLIPDRAGDATA lpclipdragdata;
|
|
|
|
lpclipdragdata = malloc( sizeof(CLIPDRAGDATA) );
|
|
|
|
if (lpclipdragdata == NULL)
|
|
{
|
|
DPF0("Malloc failed in CreateClipDragDataObject\n");
|
|
return NULL;
|
|
}
|
|
|
|
lpclipdragdata->m_IDataObject.lpVtbl = &clipdragVtbl;
|
|
lpclipdragdata->lpClipDragEnum = NULL;
|
|
|
|
lpclipdragdata->m_IDropSource.lpVtbl = &dropsourceVtbl;
|
|
lpclipdragdata->m_IDataObject.lpclipdragdata = lpclipdragdata;
|
|
lpclipdragdata->m_IDropSource.lpclipdragdata = lpclipdragdata;
|
|
lpclipdragdata->lpdoc = lpdoc;
|
|
lpclipdragdata->cRef = 1;
|
|
lpclipdragdata->fClipData = fClipData;
|
|
|
|
return lpclipdragdata;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* DoDrag:
|
|
* Initiates the Drag-Drop operation.
|
|
**************************************************************************/
|
|
void DoDrag(void)
|
|
{
|
|
DWORD dwEffect;
|
|
LPCLIPDRAGDATA lpclipdragdata;
|
|
|
|
if (!InitOLE(&gfOleInitForDrag, NULL))
|
|
{
|
|
DPF0("Initialization of OLE FAILED!! Can't do drag.\n");
|
|
return;
|
|
}
|
|
|
|
lpclipdragdata = CreateClipDragDataObject ((LPDOC)&docMain, FALSE);
|
|
|
|
if (lpclipdragdata)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = (HRESULT)DoDragDrop((IDataObject FAR*)&lpclipdragdata->m_IDataObject,
|
|
(IDropSource FAR*)&lpclipdragdata->m_IDropSource,
|
|
DROPEFFECT_COPY, &dwEffect);
|
|
|
|
DPF("DoDragDrop returned %s\n", hr == S_OK ? "S_OK" : hr == DRAGDROP_S_DROP ? "DRAGDROP_S_DROP" : hr == DRAGDROP_S_CANCEL ? "DRAGDROP_S_CANCEL" : hr == E_OUTOFMEMORY ? "E_OUTOFMEMORY" : hr == E_UNEXPECTED ? "E_UNEXPECTED" : "<?>");
|
|
|
|
IDataObject_Release((IDataObject *)&lpclipdragdata->m_IDataObject);
|
|
}
|
|
}
|
|
|
|
void CleanUpDrag(void)
|
|
{
|
|
if (gfOleInitForDrag)
|
|
{
|
|
DPF("Uninitializing OLE for thread %d\n", GetCurrentThreadId());
|
|
CoDisconnectObject((LPUNKNOWN)&docMain, 0);
|
|
OleUninitialize();
|
|
gfOleInitForDrag = FALSE;
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
* GetObjectDescriptorData:
|
|
* Packages an ObjectDescriptor data structure.
|
|
**************************************************************************/
|
|
HGLOBAL GetObjectDescriptorData(
|
|
CLSID clsid,
|
|
DWORD dwAspect,
|
|
SIZEL sizel,
|
|
POINTL pointl,
|
|
DWORD dwStatus,
|
|
LPTSTR lpszFullUserTypeName,
|
|
LPTSTR lpszSrcOfCopy
|
|
)
|
|
{
|
|
HGLOBAL hMem = NULL;
|
|
IBindCtx FAR *pbc = NULL;
|
|
LPOBJECTDESCRIPTOR lpOD;
|
|
DWORD dwObjectDescSize, dwFullUserTypeNameLen, dwSrcOfCopyLen;
|
|
DWORD Offset;
|
|
|
|
// Get the length of Full User Type Name:
|
|
dwFullUserTypeNameLen = STRING_BYTE_COUNT_NULLOK(lpszFullUserTypeName);
|
|
dwFullUserTypeNameLen *= (sizeof(WCHAR) / sizeof(TCHAR));
|
|
|
|
// Get the Source of Copy string and its length:
|
|
dwSrcOfCopyLen = STRING_BYTE_COUNT_NULLOK(lpszSrcOfCopy);
|
|
dwSrcOfCopyLen *= (sizeof(WCHAR) / sizeof(TCHAR));
|
|
|
|
if (lpszSrcOfCopy == NULL) {
|
|
// No src moniker so use user type name as source string.
|
|
lpszSrcOfCopy = lpszFullUserTypeName;
|
|
dwSrcOfCopyLen = dwFullUserTypeNameLen;
|
|
}
|
|
|
|
// Allocate space for OBJECTDESCRIPTOR and the additional string data
|
|
dwObjectDescSize = sizeof(OBJECTDESCRIPTOR);
|
|
hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
|
|
dwObjectDescSize
|
|
+ dwFullUserTypeNameLen
|
|
+ dwSrcOfCopyLen);
|
|
if (NULL == hMem)
|
|
goto error;
|
|
|
|
lpOD = (LPOBJECTDESCRIPTOR)GLOBALLOCK(hMem);
|
|
|
|
if(!lpOD)
|
|
goto error;
|
|
|
|
// Set offset to copy strings at end of the object descriptor:
|
|
Offset = dwObjectDescSize;
|
|
|
|
// Set the FullUserTypeName offset and copy the string
|
|
if (lpszFullUserTypeName)
|
|
{
|
|
lpOD->dwFullUserTypeName = Offset;
|
|
#ifdef UNICODE
|
|
lstrcpy((LPWSTR)(((LPBYTE)lpOD)+Offset), lpszFullUserTypeName);
|
|
#else
|
|
AnsiToUnicodeString(lpszFullUserTypeName, (LPWSTR)(((LPBYTE)lpOD)+Offset), -1);
|
|
#endif
|
|
Offset += dwFullUserTypeNameLen;
|
|
}
|
|
else lpOD->dwFullUserTypeName = 0; // zero offset indicates that string is not present
|
|
|
|
// Set the SrcOfCopy offset and copy the string
|
|
if (lpszSrcOfCopy)
|
|
{
|
|
lpOD->dwSrcOfCopy = Offset;
|
|
#ifdef UNICODE
|
|
lstrcpy((LPWSTR)(((LPBYTE)lpOD)+Offset), lpszSrcOfCopy);
|
|
#else
|
|
AnsiToUnicodeString(lpszSrcOfCopy, (LPWSTR)(((LPBYTE)lpOD)+Offset), -1);
|
|
#endif
|
|
}
|
|
else lpOD->dwSrcOfCopy = 0; // zero offset indicates that string is not present
|
|
|
|
// Initialize the rest of the OBJECTDESCRIPTOR
|
|
lpOD->cbSize = dwObjectDescSize + dwFullUserTypeNameLen + dwSrcOfCopyLen;
|
|
lpOD->clsid = clsid;
|
|
lpOD->dwDrawAspect = dwAspect;
|
|
lpOD->sizel = sizel;
|
|
lpOD->pointl = pointl;
|
|
lpOD->dwStatus = dwStatus;
|
|
|
|
GLOBALUNLOCK(hMem);
|
|
return hMem;
|
|
|
|
error:
|
|
if (hMem)
|
|
{
|
|
GLOBALUNLOCK(hMem);
|
|
GLOBALFREE(hMem);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
*************** IUnknown INTERFACE INPLEMENTATION.
|
|
**************************************************************************/
|
|
STDMETHODIMP ClipDragUnknownQueryInterface (
|
|
LPCLIPDRAGDATA lpclipdragdata, // data object ptr
|
|
REFIID riidReq, // IID required
|
|
LPVOID FAR * lplpUnk // pre for returning the interface
|
|
)
|
|
{
|
|
if ( IsEqualIID(riidReq, &IID_IDataObject) || IsEqualIID(riidReq, &IID_IUnknown) )
|
|
{
|
|
*lplpUnk = (LPVOID) lpclipdragdata;
|
|
}
|
|
else if ( IsEqualIID(riidReq, &IID_IDropSource))
|
|
{
|
|
*lplpUnk = (LPVOID) &lpclipdragdata->m_IDropSource;
|
|
}
|
|
else
|
|
{
|
|
*lplpUnk = (LPVOID) NULL;
|
|
RETURN_RESULT(E_NOINTERFACE);
|
|
}
|
|
|
|
DPF("ClipDragAddRef: cRef = %d\n", lpclipdragdata->cRef + 1);
|
|
lpclipdragdata->cRef++;
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) ClipDragUnknownAddRef(
|
|
LPCLIPDRAGDATA lpclipdragdata // data object ptr
|
|
)
|
|
{
|
|
DPF("ClipDragAddRef: cRef = %d\n", lpclipdragdata->cRef + 1);
|
|
|
|
return ++lpclipdragdata->cRef;
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) ClipDragUnknownRelease (
|
|
LPCLIPDRAGDATA lpclipdragdata
|
|
)
|
|
{
|
|
DPF("ClipDragRelease: cRef = %d\n", lpclipdragdata->cRef - 1);
|
|
|
|
if ( --lpclipdragdata->cRef != 0 )
|
|
return lpclipdragdata->cRef;
|
|
|
|
free(lpclipdragdata);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
****************** IDataObject INTERFACE IMPLEMENTATION.
|
|
**************************************************************************/
|
|
STDMETHODIMP ClipDragQueryInterface (
|
|
LPDATAOBJECT lpDataObj, // data object ptr
|
|
REFIID riidReq, // IID required
|
|
LPVOID FAR * lplpUnk // pre for returning the interface
|
|
)
|
|
{
|
|
DPF("ClipDragQueryInterface\n");
|
|
|
|
return
|
|
ClipDragUnknownQueryInterface (
|
|
(LPCLIPDRAGDATA) (( struct CDataObject FAR* )lpDataObj)->lpclipdragdata ,
|
|
riidReq,
|
|
lplpUnk
|
|
);
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) ClipDragAddRef(
|
|
LPDATAOBJECT lpDataObj // data object ptr
|
|
)
|
|
{
|
|
return
|
|
ClipDragUnknownAddRef (
|
|
(LPCLIPDRAGDATA) (( struct CDataObject FAR* )lpDataObj)->lpclipdragdata
|
|
);
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) ClipDragRelease (
|
|
LPDATAOBJECT lpDataObj // data object ptr
|
|
)
|
|
{
|
|
return
|
|
ClipDragUnknownRelease (
|
|
(LPCLIPDRAGDATA) (( struct CDataObject FAR* )lpDataObj)->lpclipdragdata
|
|
);
|
|
}
|
|
|
|
|
|
|
|
/* Routines called by ClipDragGetData, one for each format supported:
|
|
*/
|
|
HRESULT ClipDragGetData_EmbedSource(
|
|
LPCLIPDRAGDATA lpclipdragdata,
|
|
LPSTGMEDIUM lpMedium
|
|
);
|
|
HRESULT ClipDragGetData_ObjectDescriptor(
|
|
LPCLIPDRAGDATA lpclipdragdata,
|
|
LPSTGMEDIUM lpMedium
|
|
);
|
|
HRESULT ClipDragGetData_MetafilePict(
|
|
LPCLIPDRAGDATA lpclipdragdata,
|
|
LPSTGMEDIUM lpMedium
|
|
);
|
|
HRESULT ClipDragGetData_DIB(
|
|
LPCLIPDRAGDATA lpclipdragdata,
|
|
LPSTGMEDIUM lpMedium
|
|
);
|
|
|
|
/**************************************************************************
|
|
* ClipDragGetData:
|
|
* Returns the saved snapshot of the Object in the required format,
|
|
* if available. If not, returns the current snapshot. We still write
|
|
* out the OLE1 embedding to maintain backward compatibility.
|
|
**************************************************************************/
|
|
STDMETHODIMP ClipDragGetData (
|
|
LPDATAOBJECT lpDataObj,
|
|
LPFORMATETC lpformatetc,
|
|
LPSTGMEDIUM lpMedium
|
|
)
|
|
{
|
|
LPCLIPDRAGDATA lpclipdragdata;
|
|
SCODE scode;
|
|
STGMEDIUM stgm;
|
|
CLIPFORMAT cfFormat;
|
|
DWORD tymed;
|
|
|
|
DPF("ClipDragGetData\n");
|
|
|
|
if (lpMedium == NULL)
|
|
RETURN_RESULT( E_FAIL);
|
|
|
|
VERIFY_LINDEX(lpformatetc->lindex);
|
|
|
|
memset(&stgm, 0, sizeof stgm);
|
|
|
|
lpclipdragdata = (LPCLIPDRAGDATA) lpDataObj;
|
|
|
|
cfFormat = lpformatetc->cfFormat;
|
|
tymed = lpformatetc->tymed;
|
|
|
|
if ((cfFormat == cfEmbedSource) && (tymed & TYMED_ISTORAGE))
|
|
scode = ClipDragGetData_EmbedSource(lpclipdragdata, &stgm);
|
|
|
|
else if ((cfFormat == cfObjectDescriptor) && (tymed & TYMED_HGLOBAL))
|
|
scode = ClipDragGetData_ObjectDescriptor(lpclipdragdata, &stgm);
|
|
|
|
else if ((cfFormat == CF_METAFILEPICT) && (tymed & TYMED_MFPICT))
|
|
scode = ClipDragGetData_MetafilePict(lpclipdragdata, &stgm);
|
|
|
|
else if ((cfFormat == CF_DIB) && (tymed & TYMED_HGLOBAL))
|
|
scode = ClipDragGetData_DIB(lpclipdragdata, &stgm);
|
|
|
|
else
|
|
scode = DATA_E_FORMATETC;
|
|
|
|
if (scode == S_OK)
|
|
*lpMedium = stgm;
|
|
|
|
RETURN_RESULT(scode);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
BOOL WriteOLE2Class( )
|
|
{
|
|
HKEY hKey;
|
|
TCHAR Data[8];
|
|
DWORD Size;
|
|
BOOL rc = FALSE;
|
|
|
|
if( RegOpenKeyEx( HKEY_CLASSES_ROOT, TEXT( "MPlayer\\Debug" ), 0,
|
|
KEY_READ, &hKey ) == ERROR_SUCCESS )
|
|
{
|
|
if( RegQueryValueEx( hKey, TEXT( "WriteOLE2Class" ), NULL, NULL,
|
|
(LPBYTE)&Data, &Size ) == ERROR_SUCCESS )
|
|
{
|
|
if( Data[0] == TEXT( 'y' ) || Data[0] == TEXT( 'Y' ) )
|
|
rc = TRUE;
|
|
}
|
|
|
|
RegCloseKey( hKey );
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
HRESULT ClipDragGetData_EmbedSource(
|
|
LPCLIPDRAGDATA lpclipdragdata,
|
|
LPSTGMEDIUM lpMedium
|
|
)
|
|
{
|
|
SCODE scode;
|
|
LPSTREAM lpstm = NULL;
|
|
LPWSTR lpszUserType;
|
|
HANDLE hGlobal = NULL;
|
|
DWORD_PTR nNativeSz;
|
|
ULONG cbWritten;
|
|
|
|
scode = GetScode(StgCreateDocfile(NULL, /* Create temporary compound file */
|
|
STGM_CREATE | STGM_SALL | STGM_DELETEONRELEASE,
|
|
0, /* Reserved */
|
|
&lpMedium->pstg));
|
|
|
|
if (scode != S_OK)
|
|
RETURN_RESULT(scode);
|
|
|
|
lpMedium->tymed = TYMED_ISTORAGE;
|
|
lpMedium->pUnkForRelease = NULL;
|
|
|
|
//Mark the Object as OLE1.
|
|
#ifdef UNICODE
|
|
lpszUserType = gachClassRoot;
|
|
#else
|
|
lpszUserType = AllocateUnicodeString(gachClassRoot);
|
|
if (!lpszUserType)
|
|
RETURN_RESULT(E_OUTOFMEMORY);
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
if(WriteOLE2Class())
|
|
{
|
|
DPF("ClipDragGetData_EmbedSource: Writing OLE2 class ID\n");
|
|
scode = GetScode(WriteClassStg(lpMedium->pstg, &CLSID_MPLAYER));
|
|
}
|
|
else
|
|
#endif
|
|
scode = GetScode(WriteClassStg(lpMedium->pstg, &CLSID_OLE1MPLAYER));
|
|
|
|
if (scode != S_OK)
|
|
RETURN_RESULT(scode);
|
|
|
|
scode = GetScode(WriteFmtUserTypeStg(lpMedium->pstg, cfMPlayer, lpszUserType));
|
|
#ifndef UNICODE
|
|
FreeUnicodeString(lpszUserType);
|
|
#endif
|
|
if (scode != S_OK)
|
|
RETURN_RESULT(scode);
|
|
|
|
//Write to \1Ole10Native stream so that this will be readable by OLE1 Mplayer
|
|
scode = GetScode(IStorage_CreateStream(lpMedium->pstg,sz1Ole10Native,
|
|
STGM_CREATE | STGM_SALL,0,0,&lpstm));
|
|
|
|
if (scode != S_OK)
|
|
RETURN_RESULT(scode);
|
|
|
|
//Duplicate the handle we have saved.
|
|
if(lpclipdragdata->fClipData && ghClipData)
|
|
hGlobal = OleDuplicateData(ghClipData, cfEmbedSource, 0);
|
|
else
|
|
hGlobal = GetLink();
|
|
|
|
if (!hGlobal)
|
|
{
|
|
GLOBALFREE(hGlobal);
|
|
RETURN_RESULT(E_OUTOFMEMORY);
|
|
}
|
|
|
|
nNativeSz = GlobalSize(hGlobal);
|
|
lpclipdragdata->lpdoc->native = GLOBALLOCK(hGlobal);
|
|
if(!lpclipdragdata->lpdoc->native)
|
|
{
|
|
GLOBALUNLOCK(hGlobal);
|
|
GLOBALFREE(hGlobal);
|
|
RETURN_RESULT(E_OUTOFMEMORY); /* What's the right error here? */
|
|
}
|
|
|
|
scode = GetScode(IStream_Write(lpstm,&nNativeSz,4,&cbWritten));
|
|
|
|
if (scode != S_OK)
|
|
RETURN_RESULT(scode);
|
|
|
|
scode = GetScode(IStream_Write(lpstm,lpclipdragdata->lpdoc->native,
|
|
(ULONG)nNativeSz,&cbWritten));
|
|
|
|
if (cbWritten != nNativeSz)
|
|
scode = E_FAIL ;
|
|
|
|
IStream_Release(lpstm);
|
|
GLOBALUNLOCK(hGlobal);
|
|
GLOBALFREE(hGlobal);
|
|
lpstm = NULL;
|
|
|
|
RETURN_RESULT(scode);
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
HRESULT ClipDragGetData_ObjectDescriptor(
|
|
LPCLIPDRAGDATA lpclipdragdata,
|
|
LPSTGMEDIUM lpMedium
|
|
)
|
|
{
|
|
SIZEL sizel;
|
|
POINTL pointl;
|
|
TCHAR displayname[256];
|
|
LPTSTR lpszdn = (LPTSTR)displayname;
|
|
HGLOBAL hobjdesc;
|
|
DWORD dwStatus = 0;
|
|
static SZCODE aszDispFormat[] = TEXT("%"TS" : %"TS"");
|
|
|
|
DPF("\n^^^^^^CDGetdata: OBJECTDESC");
|
|
sizel.cx = extWidth;
|
|
sizel.cy = extHeight;
|
|
pointl.x = pointl.y = 0;
|
|
wsprintf(displayname, aszDispFormat, (LPTSTR)gachClassRoot, (LPTSTR)gachWindowTitle);
|
|
|
|
#ifdef DEBUG
|
|
if(WriteOLE2Class())
|
|
{
|
|
DPF("ClipDragGetData_ObjectDescriptor: Getting OLE2 class\n");
|
|
hobjdesc = GetObjectDescriptorData(CLSID_MPLAYER, DVASPECT_CONTENT,
|
|
sizel, pointl, dwStatus, lpszdn, lpszdn);
|
|
}
|
|
else
|
|
#endif
|
|
hobjdesc = GetObjectDescriptorData(CLSID_OLE1MPLAYER, DVASPECT_CONTENT,
|
|
sizel, pointl, dwStatus, lpszdn, lpszdn);
|
|
|
|
if (hobjdesc)
|
|
{
|
|
lpMedium->hGlobal = hobjdesc;
|
|
lpMedium->tymed = TYMED_HGLOBAL;
|
|
lpMedium->pUnkForRelease = NULL;
|
|
return NOERROR;
|
|
}
|
|
|
|
RETURN_RESULT(E_OUTOFMEMORY);
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
HRESULT ClipDragGetData_MetafilePict(
|
|
LPCLIPDRAGDATA lpclipdragdata,
|
|
LPSTGMEDIUM lpMedium
|
|
)
|
|
{
|
|
SCODE scode;
|
|
|
|
lpMedium->tymed = TYMED_MFPICT;
|
|
|
|
if(lpclipdragdata->fClipData && ghClipMetafile)
|
|
lpMedium->hGlobal = OleDuplicateData(ghClipMetafile, CF_METAFILEPICT, 0);
|
|
else
|
|
lpMedium->hGlobal = GetMetafilePict();
|
|
|
|
if (lpMedium->hGlobal == NULL)
|
|
scode = E_OUTOFMEMORY;
|
|
else
|
|
scode = S_OK;
|
|
|
|
lpMedium->pUnkForRelease = NULL;
|
|
|
|
RETURN_RESULT(scode);
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
HRESULT ClipDragGetData_DIB(
|
|
LPCLIPDRAGDATA lpclipdragdata,
|
|
LPSTGMEDIUM lpMedium
|
|
)
|
|
{
|
|
SCODE scode;
|
|
|
|
lpMedium->tymed = TYMED_HGLOBAL;
|
|
|
|
if(lpclipdragdata->fClipData && ghClipDib)
|
|
lpMedium->hGlobal = OleDuplicateData(ghClipDib, CF_DIB, 0);
|
|
else
|
|
/* We must make sure GetDib() happens on the main thread,
|
|
* because otherwise MCI complains.
|
|
*/
|
|
lpMedium->hGlobal = (HANDLE)SendMessage(ghwndApp, WM_GETDIB, 0, 0);
|
|
|
|
if (lpMedium->hGlobal == NULL)
|
|
scode = E_OUTOFMEMORY;
|
|
else
|
|
scode = S_OK;
|
|
|
|
lpMedium->pUnkForRelease = NULL;
|
|
|
|
RETURN_RESULT(scode);
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* ClipDragGetDataHere:
|
|
* Make the embedding by writing into the Stream Mplayer3EmbedSource.
|
|
*
|
|
**************************************************************************/
|
|
STDMETHODIMP ClipDragGetDataHere (
|
|
LPDATAOBJECT lpDataObj,
|
|
LPFORMATETC lpformatetc,
|
|
LPSTGMEDIUM lpMedium
|
|
)
|
|
{
|
|
LPCLIPDRAGDATA lpclipdragdata;
|
|
HANDLE hGlobal = NULL;
|
|
DWORD_PTR nNativeSz;
|
|
LPTSTR lpnative;
|
|
ULONG cbWritten;
|
|
|
|
DPF("ClipDragGetDataHere\n");
|
|
|
|
if (lpMedium == NULL)
|
|
RETURN_RESULT(E_FAIL);
|
|
|
|
VERIFY_LINDEX(lpformatetc->lindex);
|
|
|
|
lpclipdragdata = (LPCLIPDRAGDATA) lpDataObj;
|
|
|
|
if (lpformatetc->cfFormat == cfEmbedSource)
|
|
{
|
|
SCODE scode;
|
|
LPSTREAM lpstm = NULL;
|
|
LPWSTR lpszUserType;
|
|
|
|
if (lpMedium->tymed != TYMED_ISTORAGE)
|
|
RETURN_RESULT(DATA_E_FORMATETC);
|
|
|
|
#ifdef UNICODE
|
|
lpszUserType = gachClassRoot;
|
|
#else
|
|
lpszUserType = AllocateUnicodeString(gachClassRoot);
|
|
if (!lpszUserType)
|
|
RETURN_RESULT(E_OUTOFMEMORY);
|
|
#endif
|
|
//Mark the object as OLE1 MPlayer object for backward compatibility:
|
|
#ifdef DEBUG
|
|
if(WriteOLE2Class())
|
|
{
|
|
DPF("ClipDragGetDataHere: Writing OLE2 class ID\n");
|
|
scode = GetScode(WriteClassStg(lpMedium->pstg, &CLSID_MPLAYER));
|
|
}
|
|
else
|
|
#endif
|
|
scode = GetScode(WriteClassStg(lpMedium->pstg, &CLSID_OLE1MPLAYER));
|
|
|
|
if (scode != S_OK)
|
|
RETURN_RESULT(scode);
|
|
|
|
scode = GetScode(WriteFmtUserTypeStg(lpMedium->pstg, cfMPlayer, lpszUserType));
|
|
#ifndef UNICODE
|
|
FreeUnicodeString(lpszUserType);
|
|
#endif
|
|
if (scode != S_OK)
|
|
RETURN_RESULT(scode);
|
|
|
|
//Write to the \1Ole10Native stream so the object will be readable by OLE1 Mplayer
|
|
if ((scode = GetScode(IStorage_CreateStream(lpMedium->pstg,
|
|
sz1Ole10Native,
|
|
STGM_CREATE | STGM_SALL,
|
|
0, 0, &lpstm))) != S_OK)
|
|
RETURN_RESULT(scode);
|
|
|
|
//Duplicate and give out the handle we have saved.
|
|
if(lpclipdragdata->fClipData && ghClipData)
|
|
hGlobal = OleDuplicateData(ghClipData, cfEmbedSource, 0);
|
|
else
|
|
hGlobal = GetLink();
|
|
|
|
if (!hGlobal)
|
|
{
|
|
RETURN_RESULT(E_OUTOFMEMORY);
|
|
}
|
|
|
|
nNativeSz = GlobalSize(hGlobal);
|
|
lpnative = GLOBALLOCK(hGlobal);
|
|
if (!lpnative)
|
|
{
|
|
GLOBALUNLOCK(hGlobal);
|
|
GLOBALFREE(hGlobal);
|
|
RETURN_RESULT(E_OUTOFMEMORY);
|
|
}
|
|
|
|
scode = GetScode(IStream_Write(lpstm,&nNativeSz,4,&cbWritten));
|
|
|
|
scode = GetScode(IStream_Write(lpstm,lpnative,(ULONG)nNativeSz,&cbWritten));
|
|
if (cbWritten != nNativeSz) scode = E_FAIL ;
|
|
|
|
IStream_Release(lpstm);
|
|
GLOBALUNLOCK(hGlobal);
|
|
GLOBALFREE(hGlobal);
|
|
RETURN_RESULT( scode);
|
|
} else
|
|
RETURN_RESULT(DATA_E_FORMATETC);
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP ClipDragQueryGetData (
|
|
LPDATAOBJECT lpDataObj,
|
|
LPFORMATETC lpformatetc
|
|
)
|
|
{
|
|
DPF("ClipDragQueryGetData\n");
|
|
|
|
if (lpformatetc->cfFormat == cfEmbedSource ||
|
|
lpformatetc->cfFormat == CF_METAFILEPICT ||
|
|
lpformatetc->cfFormat == CF_DIB ||
|
|
lpformatetc->cfFormat == cfObjectDescriptor
|
|
)
|
|
|
|
return NOERROR;
|
|
else
|
|
RETURN_RESULT(DATA_E_FORMATETC);
|
|
}
|
|
|
|
|
|
STDMETHODIMP ClipDragGetCanonicalFormatEtc(
|
|
LPDATAOBJECT lpDataObj,
|
|
LPFORMATETC lpformatetc,
|
|
LPFORMATETC lpformatetcOut
|
|
)
|
|
{
|
|
DPF("ClipDragGetCanonicalFormatEtc\n");
|
|
|
|
RETURN_RESULT(DATA_S_SAMEFORMATETC);
|
|
}
|
|
|
|
|
|
STDMETHODIMP ClipDragSetData (
|
|
LPDATAOBJECT lpDataObj,
|
|
LPFORMATETC lpformatetc,
|
|
LPSTGMEDIUM lpmedium,
|
|
BOOL fRelease
|
|
)
|
|
{
|
|
DPF("ClipDragSetData\n");
|
|
|
|
RETURN_RESULT(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP ClipDragEnumFormatEtc(
|
|
LPDATAOBJECT lpDataObj,
|
|
DWORD dwDirection,
|
|
LPENUMFORMATETC FAR* ppenumFormatEtc
|
|
){
|
|
LPCLIPDRAGENUM lpclipdragenum;
|
|
|
|
if (ppenumFormatEtc != NULL)
|
|
*ppenumFormatEtc = NULL;
|
|
|
|
lpclipdragenum = _fmalloc(sizeof(CLIPDRAGENUM));
|
|
if (lpclipdragenum == NULL)
|
|
RETURN_RESULT(E_OUTOFMEMORY);
|
|
|
|
lpclipdragenum->lpVtbl = &ClipDragEnumVtbl;
|
|
lpclipdragenum->cRef = 1;
|
|
lpclipdragenum->lpClipDragData = (LPCLIPDRAGDATA) lpDataObj;
|
|
lpclipdragenum->cfNext = cfEmbedSource;
|
|
|
|
lpclipdragenum->lpClipDragData->lpClipDragEnum = lpclipdragenum;
|
|
*ppenumFormatEtc = (LPENUMFORMATETC) lpclipdragenum;
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP ClipDragAdvise(
|
|
LPDATAOBJECT LPDATAOBJect,
|
|
FORMATETC FAR* pFormatetc,
|
|
DWORD advf,
|
|
IAdviseSink FAR* pAdvSink,
|
|
DWORD FAR* pdwConnection
|
|
)
|
|
{
|
|
RETURN_RESULT(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP ClipDragUnadvise(
|
|
LPDATAOBJECT LPDATAOBJect,
|
|
DWORD dwConnection
|
|
)
|
|
{
|
|
RETURN_RESULT(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP ClipDragEnumAdvise(
|
|
LPDATAOBJECT LPDATAOBJect,
|
|
LPENUMSTATDATA FAR* ppenumAdvise
|
|
)
|
|
{
|
|
RETURN_RESULT(E_NOTIMPL);
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
**************** IDropSource INTERFACE IMPLEMENTAION.
|
|
**************************************************************************/
|
|
STDMETHODIMP DropSourceQueryInterface (
|
|
LPDROPSOURCE lpdropsource, // data object ptr
|
|
REFIID riidReq, // IID required
|
|
LPVOID FAR * lplpUnk // pre for returning the interface
|
|
)
|
|
{
|
|
return
|
|
ClipDragUnknownQueryInterface (
|
|
(LPCLIPDRAGDATA) ( ( struct CDropSource FAR* )lpdropsource)->lpclipdragdata ,
|
|
riidReq,
|
|
lplpUnk
|
|
);
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) DropSourceAddRef(
|
|
LPDROPSOURCE lpdropsource // data object ptr
|
|
)
|
|
{
|
|
return
|
|
ClipDragUnknownAddRef (
|
|
(LPCLIPDRAGDATA) ( ( struct CDropSource FAR* )lpdropsource)->lpclipdragdata
|
|
);
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) DropSourceRelease (
|
|
LPDROPSOURCE lpdropsource // data object ptr
|
|
)
|
|
{
|
|
return
|
|
ClipDragUnknownRelease (
|
|
(LPCLIPDRAGDATA) ( ( struct CDropSource FAR* )lpdropsource)->lpclipdragdata
|
|
);
|
|
}
|
|
|
|
STDMETHODIMP DropSourceQueryContinueDrag (
|
|
LPDROPSOURCE lpdropsource, // data object ptr
|
|
BOOL fEscapePressed,
|
|
DWORD grfKeyState
|
|
)
|
|
{
|
|
|
|
if (fEscapePressed)
|
|
{
|
|
DPF("DropSourceQueryContinueDrag: fEscapePressed\n");
|
|
RETURN_RESULT( DRAGDROP_S_CANCEL);
|
|
}
|
|
else if (!(grfKeyState & MK_LBUTTON))
|
|
{
|
|
DPF("DropSourceQueryContinueDrag: !(grfKeyState & MK_LBUTTON)\n");
|
|
RETURN_RESULT(DRAGDROP_S_DROP);
|
|
}
|
|
else
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP DropSourceGiveFeedback (
|
|
LPDROPSOURCE lpsropsource, // data object ptr
|
|
DWORD dwEffect
|
|
)
|
|
{
|
|
DPF("DropSourceGiveFeedback\n");
|
|
|
|
RETURN_RESULT(DRAGDROP_S_USEDEFAULTCURSORS);
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
************* IEnumFormatEtc INTERFACE IMPLEMENTATION.
|
|
**************************************************************************/
|
|
STDMETHODIMP ClipDragEnumQueryInterface
|
|
(
|
|
LPENUMFORMATETC lpEnumFormatEtc, // Enumerator object ptr
|
|
REFIID riidReq, // IID required
|
|
LPVOID FAR* lplpUnk // pre for returning the interface
|
|
)
|
|
{
|
|
LPCLIPDRAGENUM lpClipDragEnum;
|
|
|
|
DPF("ClipDragEnumQueryInterface\n");
|
|
|
|
lpClipDragEnum = (LPCLIPDRAGENUM) lpEnumFormatEtc;
|
|
|
|
if (IsEqualIID(riidReq, &IID_IEnumFORMATETC) || IsEqualIID(riidReq, &IID_IUnknown)) {
|
|
*lplpUnk = (LPVOID) lpClipDragEnum;
|
|
lpClipDragEnum->cRef++;
|
|
return NOERROR;
|
|
} else {
|
|
*lplpUnk = (LPVOID) NULL;
|
|
RETURN_RESULT( E_NOINTERFACE);
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) ClipDragEnumAddRef
|
|
(
|
|
LPENUMFORMATETC lpEnumFormatEtc // Enumerator object ptr
|
|
)
|
|
{
|
|
LPCLIPDRAGENUM lpClipDragEnum;
|
|
|
|
lpClipDragEnum = (LPCLIPDRAGENUM) lpEnumFormatEtc;
|
|
|
|
return ++lpClipDragEnum->cRef;
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) ClipDragEnumRelease
|
|
(
|
|
LPENUMFORMATETC lpEnumFormatEtc // Enumerator object ptr
|
|
)
|
|
{
|
|
LPCLIPDRAGENUM lpClipDragEnum;
|
|
|
|
lpClipDragEnum = (LPCLIPDRAGENUM) lpEnumFormatEtc;
|
|
|
|
if (--lpClipDragEnum->cRef != 0)
|
|
return lpClipDragEnum->cRef;
|
|
|
|
// Remove Data object pointer (if one exists) to this
|
|
//
|
|
if (lpClipDragEnum->lpClipDragData != NULL)
|
|
lpClipDragEnum->lpClipDragData->lpClipDragEnum = NULL;
|
|
|
|
_ffree(lpClipDragEnum);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
STDMETHODIMP ClipDragEnumNext
|
|
(
|
|
LPENUMFORMATETC lpEnumFormatEtc, // Enumerator object ptr
|
|
ULONG celt, // Number of items requested
|
|
FORMATETC FAR rgelt[], // Buffer for retuend items
|
|
ULONG FAR* pceltFetched // Number of items returned
|
|
)
|
|
{
|
|
LPCLIPDRAGENUM lpClipDragEnum;
|
|
int ce;
|
|
LPFORMATETC pfe;
|
|
|
|
DPF("ClipDragEnumNext\n");
|
|
|
|
lpClipDragEnum = (LPCLIPDRAGENUM) lpEnumFormatEtc;
|
|
|
|
if (pceltFetched != NULL)
|
|
*pceltFetched = 0;
|
|
|
|
if (lpClipDragEnum->lpClipDragData == NULL) // data object gone
|
|
RETURN_RESULT( E_FAIL);
|
|
|
|
pfe = rgelt;
|
|
pfe->lindex = DEF_LINDEX;
|
|
|
|
|
|
for (ce = (int) celt; ce > 0 && lpClipDragEnum->cfNext != 0; ce--) {
|
|
|
|
if (lpClipDragEnum->cfNext == cfEmbedSource) {
|
|
|
|
pfe->cfFormat = cfEmbedSource;
|
|
pfe->ptd = NULL;
|
|
pfe->dwAspect = DVASPECT_CONTENT;
|
|
pfe->tymed = TYMED_ISTORAGE;
|
|
pfe++;
|
|
|
|
lpClipDragEnum->cfNext = CF_METAFILEPICT;
|
|
}
|
|
else
|
|
if (lpClipDragEnum->cfNext == CF_METAFILEPICT) {
|
|
|
|
pfe->cfFormat = CF_METAFILEPICT;
|
|
pfe->ptd = NULL;
|
|
pfe->dwAspect = DVASPECT_CONTENT;
|
|
pfe->tymed = TYMED_MFPICT;
|
|
pfe++;
|
|
lpClipDragEnum->cfNext = CF_DIB; //0;
|
|
}
|
|
else
|
|
if (lpClipDragEnum->cfNext == CF_DIB) {
|
|
|
|
pfe->cfFormat = CF_DIB;
|
|
pfe->ptd = NULL;
|
|
pfe->dwAspect = DVASPECT_CONTENT;
|
|
pfe->tymed = TYMED_HGLOBAL;
|
|
pfe++;
|
|
lpClipDragEnum->cfNext = cfObjectDescriptor; //0;
|
|
}
|
|
|
|
else
|
|
if (lpClipDragEnum->cfNext == cfObjectDescriptor) {
|
|
|
|
pfe->cfFormat = cfObjectDescriptor;
|
|
pfe->ptd = NULL;
|
|
pfe->dwAspect = DVASPECT_CONTENT;
|
|
pfe->tymed = TYMED_HGLOBAL;
|
|
pfe++;
|
|
lpClipDragEnum->cfNext = 0;
|
|
}
|
|
|
|
}
|
|
|
|
if (pceltFetched != NULL)
|
|
*pceltFetched = celt - ((ULONG) ce) ;
|
|
|
|
RETURN_RESULT( (ce == 0) ? S_OK : S_FALSE);
|
|
}
|
|
|
|
|
|
STDMETHODIMP ClipDragEnumSkip
|
|
(
|
|
LPENUMFORMATETC lpEnumFormatEtc, // Enumerator object ptr
|
|
ULONG celt // Number of elements to skip
|
|
)
|
|
{
|
|
LPCLIPDRAGENUM lpClipDragEnum;
|
|
|
|
DPF("ClipDragEnumSkip\n");
|
|
|
|
lpClipDragEnum = (LPCLIPDRAGENUM) lpEnumFormatEtc;
|
|
|
|
if (lpClipDragEnum->lpClipDragData == NULL) // data object gone
|
|
RETURN_RESULT( E_FAIL);
|
|
|
|
if (lpClipDragEnum->cfNext == cfEmbedSource)
|
|
{
|
|
if (celt == 1)
|
|
lpClipDragEnum->cfNext = CF_METAFILEPICT;
|
|
else if (celt == 2)
|
|
lpClipDragEnum->cfNext = CF_DIB;
|
|
else if (celt == 3)
|
|
lpClipDragEnum->cfNext = cfObjectDescriptor;
|
|
else if (celt > 3)
|
|
goto ReturnFalse;
|
|
}
|
|
else
|
|
if (lpClipDragEnum->cfNext == CF_METAFILEPICT)
|
|
{
|
|
if (celt == 1)
|
|
lpClipDragEnum->cfNext = CF_DIB;
|
|
else if (celt == 2)
|
|
lpClipDragEnum->cfNext = cfObjectDescriptor;
|
|
else if (celt > 2)
|
|
goto ReturnFalse;
|
|
}
|
|
else
|
|
if (lpClipDragEnum->cfNext == CF_DIB)
|
|
{
|
|
if (celt == 1)
|
|
lpClipDragEnum->cfNext = cfObjectDescriptor;
|
|
else if (celt > 1)
|
|
goto ReturnFalse;
|
|
}
|
|
else
|
|
if (lpClipDragEnum->cfNext == cfObjectDescriptor)
|
|
{
|
|
if (celt > 0)
|
|
goto ReturnFalse;
|
|
}
|
|
else
|
|
{
|
|
ReturnFalse:
|
|
RETURN_RESULT(S_FALSE);
|
|
}
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP ClipDragEnumReset
|
|
(
|
|
LPENUMFORMATETC lpEnumFormatEtc // Enumerator object ptr
|
|
)
|
|
{
|
|
LPCLIPDRAGENUM lpClipDragEnum;
|
|
|
|
DPF("ClipDragEnumReset\n");
|
|
|
|
lpClipDragEnum = (LPCLIPDRAGENUM) lpEnumFormatEtc;
|
|
|
|
if (lpClipDragEnum->lpClipDragData == NULL) // data object gone
|
|
RETURN_RESULT( E_FAIL);
|
|
|
|
lpClipDragEnum->cfNext = cfEmbedSource;
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP ClipDragEnumClone
|
|
(
|
|
LPENUMFORMATETC lpEnumFormatEtc, // Enumerator object ptr
|
|
LPENUMFORMATETC FAR* ppenum
|
|
)
|
|
{
|
|
DPF("ClipDragEnumClone\n");
|
|
|
|
if (ppenum != NULL)
|
|
*ppenum = NULL;
|
|
|
|
RETURN_RESULT( E_NOTIMPL);
|
|
}
|