Commit 21dbb6c0 authored by Abey George's avatar Abey George Committed by Alexandre Julliard

Implemented OLE clipboard functionality for Embed Source format.

It helps you cut and paste data with Embed Source format between applications. It also implements OleCreateFromData and OleQueryCreateFromData and fixes some bugs in datacache.c.
parent cc279986
......@@ -25,6 +25,7 @@ C_SRCS = \
moniker.c \
ole2.c \
ole2stubs.c \
ole2impl.c \
oleobj.c \
stg_bigblockfile.c \
stg_stream.c \
......
......@@ -2,6 +2,7 @@
* OLE 2 clipboard support
*
* Copyright 1999 Noel Borthwick <noel@macadamian.com>
* Copyright 2000 Abey George <abey@macadamian.com>
*
* NOTES:
* This file contains the implementation for the OLE Clipboard and its
......@@ -51,7 +52,7 @@
#include "winerror.h"
#include "ole2.h"
#include "debugtools.h"
#include "olestd.h"
#define HANDLE_ERROR(err) { hr = err; TRACE("(HRESULT=%lx)\n", (HRESULT)err); goto CLEANUP; }
......@@ -129,6 +130,13 @@ typedef struct
} IEnumFORMATETCImpl;
typedef struct PresentationDataHeader
{
BYTE unknown1[28];
DWORD dwObjectExtentX;
DWORD dwObjectExtentY;
DWORD dwSize;
} PresentationDataHeader;
/*
* The one and only OLEClipbrd object which is created by OLEClipbrd_Initialize()
......@@ -453,7 +461,6 @@ HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
*/
HRESULT WINAPI OleFlushClipboard16(void)
{
return OleFlushClipboard();
}
......@@ -883,6 +890,7 @@ LRESULT CALLBACK OLEClipbrd_WndProc
return 0;
}
#define MAX_CLIPFORMAT_NAME 80
/***********************************************************************
* OLEClipbrd_RenderFormat(LPFORMATETC)
......@@ -892,21 +900,122 @@ LRESULT CALLBACK OLEClipbrd_WndProc
*/
static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
{
STGMEDIUM medium;
STGMEDIUM std;
HGLOBAL hDup;
HRESULT hr = S_OK;
char szFmtName[MAX_CLIPFORMAT_NAME];
ILockBytes *ptrILockBytes = 0;
HGLOBAL hStorage = 0;
GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME);
/* If embed source */
if (!strcmp(szFmtName, CF_EMBEDSOURCE))
{
memset(&std, 0, sizeof(STGMEDIUM));
std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
{
WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%lx)\n", hr);
return hr;
}
if ( FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &medium)) )
if (1) /* check whether the presentation data is already -not- present */
{
FORMATETC fmt2;
STGMEDIUM std2;
METAFILEPICT *mfp = 0;
fmt2.cfFormat = CF_METAFILEPICT;
fmt2.ptd = 0;
fmt2.dwAspect = DVASPECT_CONTENT;
fmt2.lindex = -1;
fmt2.tymed = TYMED_MFPICT;
memset(&std2, 0, sizeof(STGMEDIUM));
std2.tymed = TYMED_MFPICT;
/* Get the metafile picture out of it */
if (!FAILED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
{
mfp = (METAFILEPICT *)GlobalLock(std2.u.hMetaFilePict);
}
if (mfp)
{
OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
IStream *pStream = 0;
void *mfBits;
PresentationDataHeader pdh;
INT nSize;
CLSID clsID;
LPOLESTR strProgID;
CHAR strOleTypeName[51];
BYTE OlePresStreamHeader [] =
{
0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
memset(&pdh, 0, sizeof(PresentationDataHeader));
memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
pdh.dwObjectExtentX = mfp->xExt;
pdh.dwObjectExtentY = mfp->yExt;
pdh.dwSize = nSize;
hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
hr = IStream_Write(pStream, mfBits, nSize, NULL);
IStream_Release(pStream);
HeapFree(GetProcessHeap(), 0, mfBits);
GlobalUnlock(std2.u.hMetaFilePict);
ReadClassStg(std.u.pstg, &clsID);
ProgIDFromCLSID(&clsID, &strProgID);
lstrcpyWtoA(strOleTypeName, strProgID);
OLECONVERT_CreateOleStream(std.u.pstg);
OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
}
}
}
else
{
if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
{
WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr);
return hr;
}
/* To put a copy back on the clipboard */
hStorage = std.u.hGlobal;
}
/*
* Put a copy of the rendered data back on the clipboard
*/
if ( !(hDup = OLEClipbrd_GlobalDupMem(medium.u.hGlobal)) )
if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
HANDLE_ERROR( E_OUTOFMEMORY );
if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
......@@ -917,7 +1026,7 @@ static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pF
CLEANUP:
ReleaseStgMedium(&medium);
ReleaseStgMedium(&std);
return hr;
}
......
......@@ -602,6 +602,7 @@ static HRESULT DataCache_ReadPresentationData(
/*
* Open the stream and read the header.
*/
hres = IStorage_OpenStream(
this->presentationStorage,
streamName,
......@@ -1248,7 +1249,6 @@ static HRESULT WINAPI DataCache_Load(
{
IStorage_AddRef(this->presentationStorage);
}
return S_OK;
}
......@@ -1298,15 +1298,20 @@ static HRESULT WINAPI DataCache_SaveCompleted(
{
TRACE("(%p, %p)\n", iface, pStgNew);
if (pStgNew)
{
/*
* First, make sure we get our hands off any storage we have.
*/
DataCache_HandsOffStorage(iface);
/*
* Then, attach to the new storage.
*/
DataCache_Load(iface, pStgNew);
}
return S_OK;
}
......
/*
* Ole 2 Create functions implementation
*
* Copyright (C) 1999-2000 Abey George
*/
#include "ole2.h"
#include "wingdi.h"
#include "winuser.h"
#include "debugtools.h"
#include "olestd.h"
#include "winreg.h"
DEFAULT_DEBUG_CHANNEL(ole)
#define MAX_CLIPFORMAT_NAME 80
/******************************************************************************
* Function : OleQueryCreateFromData [OLE32.117]
* Author : Abey George
* Checks whether an object can become an embedded object.
* the clipboard or OLE drag and drop.
* Returns : S_OK - Format that supports Embedded object creation are present.
* OLE_E_STATIC - Format that supports static object creation are present.
* S_FALSE - No acceptable format is available.
*/
HRESULT WINAPI OleQueryCreateFromData(LPDATAOBJECT pSrcDataObject)
{
IEnumFORMATETC *pfmt;
FORMATETC fmt;
CHAR szFmtName[MAX_CLIPFORMAT_NAME];
BOOL bFoundStatic = FALSE;
HRESULT hr = IDataObject_EnumFormatEtc(pSrcDataObject, DATADIR_GET, &pfmt);
if (hr == S_OK)
hr = IEnumFORMATETC_Next(pfmt, 1, &fmt, NULL);
while (hr == S_OK)
{
GetClipboardFormatNameA(fmt.cfFormat, szFmtName, MAX_CLIPFORMAT_NAME-1);
/* first, Check for Embedded Object, Embed Source or Filename */
if (!strcmp(szFmtName, CF_EMBEDDEDOBJECT) || !strcmp(szFmtName, CF_EMBEDSOURCE) || !strcmp(szFmtName, CF_FILENAME))
return S_OK;
/* Check for Metafile, Bitmap or DIB */
if (fmt.cfFormat == CF_METAFILEPICT || fmt.cfFormat == CF_BITMAP || fmt.cfFormat == CF_DIB)
bFoundStatic = TRUE;
hr = IEnumFORMATETC_Next(pfmt, 1, &fmt, NULL);
}
/* Found a static format, but no embed format */
if (bFoundStatic)
return OLE_S_STATIC;
return S_FALSE;
}
/******************************************************************************
* Function : OleCreateFromData [OLE32.92]
* Author : Abey George
* Creates an embedded object from data transfer object retrieved from
* the clipboard or OLE drag and drop.
* Returns : S_OK - Embedded object was created successfully.
* OLE_E_STATIC - OLE can create only a static object
* DV_E_FORMATETC - No acceptable format is available (only error return code)
* TODO : CF_FILENAME, CF_EMBEDEDOBJECT formats. Parameter renderopt is currently ignored.
*/
HRESULT WINAPI OleCreateFromData(LPDATAOBJECT pSrcDataObject, REFIID riid,
DWORD renderopt, LPFORMATETC pFormatEtc,
LPOLECLIENTSITE pClientSite, LPSTORAGE pStg,
LPVOID* ppvObj)
{
IEnumFORMATETC *pfmt;
FORMATETC fmt;
CHAR szFmtName[MAX_CLIPFORMAT_NAME];
STGMEDIUM std;
HRESULT hr;
HRESULT hr1;
hr = IDataObject_EnumFormatEtc(pSrcDataObject, DATADIR_GET, &pfmt);
if (hr == S_OK)
{
memset(&std, 0, sizeof(STGMEDIUM));
hr = IEnumFORMATETC_Next(pfmt, 1, &fmt, NULL);
while (hr == S_OK)
{
GetClipboardFormatNameA(fmt.cfFormat, szFmtName, MAX_CLIPFORMAT_NAME-1);
/* first, Check for Embedded Object, Embed Source or Filename */
/* TODO: Currently checks only for Embed Source. */
if (!strcmp(szFmtName, CF_EMBEDSOURCE))
{
std.tymed = TYMED_HGLOBAL;
if ((hr1 = IDataObject_GetData(pSrcDataObject, &fmt, &std)) == S_OK)
{
ILockBytes *ptrILockBytes = 0;
IStorage *pStorage = 0;
IOleObject *pOleObject = 0;
IPersistStorage *pPersistStorage = 0;
CLSID clsID;
/* Create ILock bytes */
hr1 = CreateILockBytesOnHGlobal(std.u.hGlobal, FALSE, &ptrILockBytes);
/* Open storage on the ILock bytes */
if (hr1 == S_OK)
hr1 = StgOpenStorageOnILockBytes(ptrILockBytes, NULL, STGM_SHARE_EXCLUSIVE, NULL, 0, &pStorage);
/* Get Class ID from the opened storage */
if (hr1 == S_OK)
hr1 = ReadClassStg(pStorage, &clsID);
/* Create default handler for Persist storage */
if (hr1 == S_OK)
hr1 = OleCreateDefaultHandler(&clsID, NULL, &IID_IPersistStorage, (LPVOID*)&pPersistStorage);
/* Load the storage to Persist storage */
if (hr1 == S_OK)
hr1 = IPersistStorage_Load(pPersistStorage, pStorage);
/* Query for IOleObject */
if (hr1 == S_OK)
hr1 = IPersistStorage_QueryInterface(pPersistStorage, &IID_IOleObject, (LPVOID*)&pOleObject);
/* Set client site with the IOleObject */
if (hr1 == S_OK)
hr1 = IOleObject_SetClientSite(pOleObject, pClientSite);
IPersistStorage_Release(pPersistStorage);
/* Query for the requested interface */
if (hr1 == S_OK)
hr1 = IPersistStorage_QueryInterface(pPersistStorage, riid, ppvObj);
IPersistStorage_Release(pPersistStorage);
IStorage_Release(pStorage);
if (hr1 == S_OK)
return S_OK;
}
/* Return error */
return DV_E_FORMATETC;
}
hr = IEnumFORMATETC_Next(pfmt, 1, &fmt, NULL);
}
}
return DV_E_FORMATETC;
}
......@@ -2,6 +2,7 @@
* Temporary place for ole2 stubs.
*
* Copyright (C) 1999 Corel Corporation
* Move these functions to dlls/ole32/ole2impl.c when you implement them.
*/
#include "ole2.h"
......@@ -13,19 +14,6 @@
DEFAULT_DEBUG_CHANNEL(ole)
/******************************************************************************
* OleCreateFromData [OLE32.92]
*/
HRESULT WINAPI OleCreateFromData(LPDATAOBJECT pSrcDataObj, REFIID riid,
DWORD renderopt, LPFORMATETC pFormatEtc,
LPOLECLIENTSITE pClientSite, LPSTORAGE pStg,
LPVOID* ppvObj)
{
FIXME("(%p,%p,%li,%p,%p,%p,%p), stub!\n", pSrcDataObj,riid,renderopt,pFormatEtc,pClientSite,pStg,ppvObj);
return DV_E_FORMATETC;
}
/******************************************************************************
* OleCreateLinkToFile [OLE32.96]
*/
HRESULT WINAPI OleCreateLinkToFile(LPCOLESTR lpszFileName, REFIID riid,
......@@ -145,15 +133,6 @@ HGLOBAL WINAPI OleGetIconOfClass(REFCLSID rclsid, LPOLESTR lpszLabel, BOOL fUseT
}
/******************************************************************************
* OleQueryCreateFromData [OLE32.117]
*/
HRESULT WINAPI OleQueryCreateFromData(LPDATAOBJECT pSrcDataObject)
{
FIXME("(%p), stub!\n", pSrcDataObject);
return S_FALSE;
}
/******************************************************************************
* ReadFmtUserTypeStg [OLE32.136]
*/
HRESULT WINAPI ReadFmtUserTypeStg (LPSTORAGE pstg, CLIPFORMAT* pcf, LPOLESTR* lplpszUserType)
......
/*************************************************************************
**
** olestd.h
**
*************************************************************************/
#if !defined( __WINE_OLESTD_H_ )
#define __WINE_OLESTD_H_
#if !defined(__cplusplus) && !defined( __TURBOC__)
#define NONAMELESSUNION /* use strict ANSI standard (for DVOBJ.H) */
#endif
/* Clipboard format strings */
#define CF_EMBEDSOURCE "Embed Source"
#define CF_EMBEDDEDOBJECT "Embedded Object"
#define CF_LINKSOURCE "Link Source"
#define CF_CUSTOMLINKSOURCE "Custom Link Source"
#define CF_OBJECTDESCRIPTOR "Object Descriptor"
#define CF_LINKSRCDESCRIPTOR "Link Source Descriptor"
#define CF_OWNERLINK "OwnerLink"
#define CF_FILENAME "FileName"
#define OleStdQueryOleObjectData(lpformatetc) \
(((lpformatetc)->tymed & TYMED_ISTORAGE) ? \
NOERROR : ResultFromScode(DV_E_FORMATETC))
#define OleStdQueryLinkSourceData(lpformatetc) \
(((lpformatetc)->tymed & TYMED_ISTREAM) ? \
NOERROR : ResultFromScode(DV_E_FORMATETC))
#define OleStdQueryObjectDescriptorData(lpformatetc) \
(((lpformatetc)->tymed & TYMED_HGLOBAL) ? \
NOERROR : ResultFromScode(DV_E_FORMATETC))
#define OleStdQueryFormatMedium(lpformatetc, tymd) \
(((lpformatetc)->tymed & tymd) ? \
NOERROR : ResultFromScode(DV_E_FORMATETC))
/* Make an independent copy of a MetafilePict */
#define OleStdCopyMetafilePict(hpictin, phpictout) \
(*(phpictout) = OleDuplicateData(hpictin,CF_METAFILEPICT,GHND|GMEM_SHARE))
#endif /* __WINE_OLESTD_H_ */
......@@ -5724,9 +5724,10 @@ HRESULT WINAPI OleSaveToStream(IPersistStream *pPStm,IStream *pStm)
if (SUCCEEDED(res))
res=IPersistStream_Save(pPStm,pStm,FALSE);
res=IPersistStream_Save(pPStm,pStm,TRUE);
}
TRACE("Finished Save\n");
return res;
}
......
......@@ -13,6 +13,7 @@
#include "wine/obj_dragdrop.h"
#include "wine/obj_inplace.h"
#include "wine/obj_oleobj.h"
#include "wine/obj_oleview.h"
#ifndef __WINE__
#include "oleidl.h"
#include "oleauto.h"
......
......@@ -1532,6 +1532,7 @@ extern int WIN32_LastError;
#define OLE_E_STATIC 0x8004000B
#define OLE_E_PROMPTSAVECANCELLED 0x8004000C
#define OLE_S_USEREG 0x00040000
#define OLE_S_STATIC 0x00040001
#define DV_E_FORMATETC 0x80040064
#define DV_E_DVASPECT 0x8004006B
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment