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, &current_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