[PATCH 4/4] ole32: Support reading and writing custom clipformats in the data cache.

Robert Shearman rob at codeweavers.com
Mon Dec 4 09:51:15 CST 2006


---
  dlls/ole32/datacache.c |  105 
+++++++++++++++++++++++++++++++++++++++++-------
  1 files changed, 90 insertions(+), 15 deletions(-)
-------------- next part --------------
diff --git a/dlls/ole32/datacache.c b/dlls/ole32/datacache.c
index 01c18f8..81c5951 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,70 @@ 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);
+    }
+    return hr;
+}
+
 /************************************************************************
  * DataCacheEntry_OpenPresStream
  *
@@ -414,8 +481,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)
@@ -586,11 +657,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 +1321,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 +1337,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-patches mailing list