Rob Shearman : ole32:
Support reading and writing custom clipformats in the data cache.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Dec 18 05:34:32 CST 2006
Module: wine
Branch: master
Commit: cc30255c8a6ca3c8f04995ab8184cea106dcc0d2
URL: http://source.winehq.org/git/wine.git/?a=commit;h=cc30255c8a6ca3c8f04995ab8184cea106dcc0d2
Author: Rob Shearman <rob at codeweavers.com>
Date: Sun Dec 17 23:44:18 2006 +0000
ole32: Support reading and writing custom clipformats in the data cache.
---
dlls/ole32/datacache.c | 125 +++++++++++++++++++++++++++++++++++++++++------
1 files changed, 109 insertions(+), 16 deletions(-)
diff --git a/dlls/ole32/datacache.c b/dlls/ole32/datacache.c
index 33795f3..249882e 100644
--- a/dlls/ole32/datacache.c
+++ b/dlls/ole32/datacache.c
@@ -67,13 +67,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
*
* This structure represents the header of the \002OlePresXXX stream in
* the OLE object strorage.
- *
- * Most fields are still unknown.
*/
typedef struct PresentationDataHeader
{
- DWORD unknown1; /* -1 */
- DWORD clipformat;
+ /* clipformat:
+ * - standard clipformat:
+ * DWORD length = 0xffffffff;
+ * DWORD cfFormat;
+ * - or custom clipformat:
+ * DWORD length;
+ * CHAR format_name[length]; (null-terminated)
+ */
DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
DVASPECT dvAspect;
DWORD lindex;
@@ -355,7 +359,6 @@ static BOOL DataCache_IsPresentationStre
LPCWSTR name = elem->pwcsName;
return (elem->type == STGTY_STREAM)
- && (elem->cbSize.u.LowPart >= sizeof(PresentationDataHeader))
&& (strlenW(name) == 11)
&& (strncmpW(name, OlePres, 8) == 0)
&& (name[8] >= '0') && (name[8] <= '9')
@@ -363,6 +366,71 @@ static BOOL DataCache_IsPresentationStre
&& (name[10] >= '0') && (name[10] <= '9');
}
+static HRESULT read_clipformat(IStream *stream, CLIPFORMAT *clipformat)
+{
+ DWORD length;
+ HRESULT hr;
+ ULONG read;
+
+ *clipformat = 0;
+
+ hr = IStream_Read(stream, &length, sizeof(length), &read);
+ if (hr != S_OK || read != sizeof(length))
+ return DV_E_CLIPFORMAT;
+ if (length == -1)
+ {
+ DWORD cf;
+ hr = IStream_Read(stream, &cf, sizeof(cf), 0);
+ if (hr != S_OK || read != sizeof(cf))
+ return DV_E_CLIPFORMAT;
+ *clipformat = cf;
+ }
+ else
+ {
+ char *format_name = HeapAlloc(GetProcessHeap(), 0, length);
+ if (!format_name)
+ return E_OUTOFMEMORY;
+ hr = IStream_Read(stream, format_name, length, &read);
+ if (hr != S_OK || read != length || format_name[length - 1] != '\0')
+ {
+ HeapFree(GetProcessHeap(), 0, format_name);
+ return DV_E_CLIPFORMAT;
+ }
+ *clipformat = RegisterClipboardFormatA(format_name);
+ HeapFree(GetProcessHeap(), 0, format_name);
+ }
+ return S_OK;
+}
+
+static HRESULT write_clipformat(IStream *stream, CLIPFORMAT clipformat)
+{
+ DWORD length;
+ HRESULT hr;
+
+ if (clipformat < 0xc000)
+ length = -1;
+ else
+ length = GetClipboardFormatNameA(clipformat, NULL, 0);
+ hr = IStream_Write(stream, &length, sizeof(length), NULL);
+ if (FAILED(hr))
+ return hr;
+ if (clipformat < 0xc000)
+ {
+ DWORD cf = clipformat;
+ hr = IStream_Write(stream, &cf, sizeof(cf), NULL);
+ }
+ else
+ {
+ char *format_name = HeapAlloc(GetProcessHeap(), 0, length);
+ if (!format_name)
+ return E_OUTOFMEMORY;
+ GetClipboardFormatNameA(clipformat, format_name, length);
+ hr = IStream_Write(stream, format_name, length, NULL);
+ HeapFree(GetProcessHeap(), 0, format_name);
+ }
+ return hr;
+}
+
/************************************************************************
* DataCacheEntry_OpenPresStream
*
@@ -414,8 +482,12 @@ static HRESULT DataCacheEntry_OpenPresSt
{
PresentationDataHeader header;
ULONG actual_read;
+ CLIPFORMAT clipformat;
+
+ hr = read_clipformat(pStm, &clipformat);
- hr = IStream_Read(pStm, &header, sizeof(header), &actual_read);
+ if (hr == S_OK)
+ hr = IStream_Read(pStm, &header, sizeof(header), &actual_read);
/* can't use SUCCEEDED(hr): S_FALSE counts as an error */
if (hr == S_OK && actual_read == sizeof(header)
@@ -464,11 +536,14 @@ static HRESULT DataCacheEntry_LoadData(D
{
IStream* presStream = NULL;
HRESULT hres;
+ ULARGE_INTEGER current_pos;
STATSTG streamInfo;
void* metafileBits;
METAFILEPICT *mfpict;
HGLOBAL hmfpict;
PresentationDataHeader header;
+ CLIPFORMAT clipformat;
+ static const LARGE_INTEGER offset_zero;
/*
* Open the presentation stream.
@@ -491,13 +566,27 @@ static HRESULT DataCacheEntry_LoadData(D
* Read the header.
*/
+ hres = read_clipformat(presStream, &clipformat);
+ if (FAILED(hres))
+ {
+ IStream_Release(presStream);
+ return hres;
+ }
+
hres = IStream_Read(
presStream,
&header,
sizeof(PresentationDataHeader),
NULL);
+ if (hres != S_OK)
+ {
+ IStream_Release(presStream);
+ return E_FAIL;
+ }
+
+ hres = IStream_Seek(presStream, offset_zero, STREAM_SEEK_CUR, ¤t_pos);
- streamInfo.cbSize.QuadPart -= sizeof(PresentationDataHeader);
+ streamInfo.cbSize.QuadPart -= current_pos.QuadPart;
hmfpict = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT));
if (!hmfpict)
@@ -586,11 +675,10 @@ static HRESULT DataCacheEntry_Save(DataC
if (FAILED(hr))
return hr;
- /* custom clipformat */
- if (This->data_cf >= 0xc000)
- FIXME("custom clipboard format not serialized properly\n");
- header.unknown1 = -1;
- header.clipformat = This->data_cf;
+ hr = write_clipformat(pres_stream, This->data_cf);
+ if (FAILED(hr))
+ return hr;
+
if (This->fmtetc.ptd)
FIXME("ptd not serialized\n");
header.unknown3 = 4;
@@ -1251,10 +1339,15 @@ static HRESULT WINAPI DataCache_Load(
&pStm);
if (SUCCEEDED(hr))
{
- PresentationDataHeader header;
- ULONG actual_read;
+ PresentationDataHeader header;
+ ULONG actual_read;
+ CLIPFORMAT clipformat;
+
+ hr = read_clipformat(pStm, &clipformat);
- hr = IStream_Read(pStm, &header, sizeof(header), &actual_read);
+ if (hr == S_OK)
+ hr = IStream_Read(pStm, &header, sizeof(header),
+ &actual_read);
/* can't use SUCCEEDED(hr): S_FALSE counts as an error */
if (hr == S_OK && actual_read == sizeof(header))
@@ -1262,7 +1355,7 @@ static HRESULT WINAPI DataCache_Load(
DataCacheEntry *cache_entry;
FORMATETC fmtetc;
- fmtetc.cfFormat = header.clipformat;
+ fmtetc.cfFormat = clipformat;
fmtetc.ptd = NULL; /* FIXME */
fmtetc.dwAspect = header.dvAspect;
fmtetc.lindex = header.lindex;
More information about the wine-cvs
mailing list