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.
diff --git a/dlls/ole32/Makefile.in b/dlls/ole32/Makefile.in
index 7143249..907bc62 100644
--- a/dlls/ole32/Makefile.in
+++ b/dlls/ole32/Makefile.in
@@ -25,6 +25,7 @@
moniker.c \
ole2.c \
ole2stubs.c \
+ ole2impl.c \
oleobj.c \
stg_bigblockfile.c \
stg_stream.c \
diff --git a/dlls/ole32/clipboard.c b/dlls/ole32/clipboard.c
index e6ed9ef..c4269ee 100644
--- a/dlls/ole32/clipboard.c
+++ b/dlls/ole32/clipboard.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 @@
} 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 OleFlushClipboard16(void)
-
{
return OleFlushClipboard();
}
@@ -883,6 +890,7 @@
return 0;
}
+#define MAX_CLIPFORMAT_NAME 80
/***********************************************************************
* OLEClipbrd_RenderFormat(LPFORMATETC)
@@ -892,21 +900,122 @@
*/
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 (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);
- if ( FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &medium)) )
+ 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 @@
CLEANUP:
- ReleaseStgMedium(&medium);
+ ReleaseStgMedium(&std);
return hr;
}
diff --git a/dlls/ole32/datacache.c b/dlls/ole32/datacache.c
index 0458929..53f4486 100644
--- a/dlls/ole32/datacache.c
+++ b/dlls/ole32/datacache.c
@@ -602,6 +602,7 @@
/*
* Open the stream and read the header.
*/
+
hres = IStorage_OpenStream(
this->presentationStorage,
streamName,
@@ -1248,7 +1249,6 @@
{
IStorage_AddRef(this->presentationStorage);
}
-
return S_OK;
}
@@ -1298,15 +1298,20 @@
{
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;
}
diff --git a/dlls/ole32/ole2impl.c b/dlls/ole32/ole2impl.c
new file mode 100644
index 0000000..9e165ba
--- /dev/null
+++ b/dlls/ole32/ole2impl.c
@@ -0,0 +1,173 @@
+/*
+ * 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;
+}
+
diff --git a/dlls/ole32/ole2stubs.c b/dlls/ole32/ole2stubs.c
index 620f4f9..0c6c663 100644
--- a/dlls/ole32/ole2stubs.c
+++ b/dlls/ole32/ole2stubs.c
@@ -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 @@
}
/******************************************************************************
- * 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)
diff --git a/dlls/ole32/olestd.h b/dlls/ole32/olestd.h
new file mode 100644
index 0000000..e250b21
--- /dev/null
+++ b/dlls/ole32/olestd.h
@@ -0,0 +1,44 @@
+/*************************************************************************
+**
+** 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_ */
diff --git a/dlls/ole32/storage32.c b/dlls/ole32/storage32.c
index aa1b2be..f5b701e 100644
--- a/dlls/ole32/storage32.c
+++ b/dlls/ole32/storage32.c
@@ -5724,9 +5724,10 @@
if (SUCCEEDED(res))
- res=IPersistStream_Save(pPStm,pStm,FALSE);
+ res=IPersistStream_Save(pPStm,pStm,TRUE);
}
+ TRACE("Finished Save\n");
return res;
}
diff --git a/include/ole2.h b/include/ole2.h
index 3651a98..f89ef2f 100644
--- a/include/ole2.h
+++ b/include/ole2.h
@@ -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"
diff --git a/include/winerror.h b/include/winerror.h
index bf93b34..0c78792 100644
--- a/include/winerror.h
+++ b/include/winerror.h
@@ -1532,6 +1532,7 @@
#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