[PATCH 1/5] ole32: Refactor OLE's data cache Save implementation.

Sergio Gómez Del Real sdelreal at codeweavers.com
Wed Dec 6 09:52:23 CST 2017


Signed-off-by: Sergio Gómez Del Real <sdelreal at codeweavers.com>
---
 dlls/ole32/datacache.c | 239 ++++++++++++++++++++++++-------------------------
 1 file changed, 119 insertions(+), 120 deletions(-)

diff --git a/dlls/ole32/datacache.c b/dlls/ole32/datacache.c
index c550c75cd3..f46f71215d 100644
--- a/dlls/ole32/datacache.c
+++ b/dlls/ole32/datacache.c
@@ -775,16 +775,118 @@ static HRESULT DataCacheEntry_LoadData(DataCacheEntry *cache_entry)
     return hr;
 }
 
-static HRESULT DataCacheEntry_CreateStream(DataCacheEntry *cache_entry,
-                                           IStorage *storage, IStream **stream)
+static void init_stream_header(DataCacheEntry *entry, PresentationDataHeader *header)
 {
-    WCHAR wszName[] = {2,'O','l','e','P','r','e','s',
+    if (entry->fmtetc.ptd)
+        FIXME("ptd not serialized\n");
+    header->tdSize = sizeof(header->tdSize);
+    header->dvAspect = entry->fmtetc.dwAspect;
+    header->lindex = entry->fmtetc.lindex;
+    header->advf = entry->advise_flags;
+    header->unknown7 = 0;
+    header->dwObjectExtentX = 0;
+    header->dwObjectExtentY = 0;
+    header->dwSize = 0;
+}
+
+static HRESULT save_dib(DataCacheEntry *entry, BOOL contents, IStream *stream)
+{
+    HRESULT hr = S_OK;
+    int data_size = GlobalSize(entry->stgmedium.u.hGlobal);
+    BITMAPINFO *bmi = GlobalLock(entry->stgmedium.u.hGlobal);
+
+    if (!contents)
+    {
+        PresentationDataHeader header;
+
+        init_stream_header(entry, &header);
+        hr = write_clipformat(stream, entry->fmtetc.cfFormat);
+        if (FAILED(hr)) goto end;
+        if (data_size)
+        {
+            header.dwSize = data_size;
+            /* Size in units of 0.01mm (ie. MM_HIMETRIC) */
+            if (bmi->bmiHeader.biXPelsPerMeter != 0 && bmi->bmiHeader.biYPelsPerMeter != 0)
+            {
+                header.dwObjectExtentX = MulDiv(bmi->bmiHeader.biWidth, 100000, bmi->bmiHeader.biXPelsPerMeter);
+                header.dwObjectExtentY = MulDiv(bmi->bmiHeader.biHeight, 100000, bmi->bmiHeader.biYPelsPerMeter);
+            }
+            else
+            {
+                HDC hdc = GetDC(0);
+                header.dwObjectExtentX = MulDiv(bmi->bmiHeader.biWidth, 2540, GetDeviceCaps(hdc, LOGPIXELSX));
+                header.dwObjectExtentY = MulDiv(bmi->bmiHeader.biHeight, 2540, GetDeviceCaps(hdc, LOGPIXELSY));
+                ReleaseDC(0, hdc);
+            }
+        }
+        hr = IStream_Write(stream, &header, sizeof(PresentationDataHeader), NULL);
+        if (hr == S_OK && data_size)
+            hr = IStream_Write(stream, bmi, data_size, NULL);
+    }
+
+end:
+    if (bmi) GlobalUnlock(entry->stgmedium.u.hGlobal);
+    return hr;
+}
+
+static HRESULT save_mfpict(DataCacheEntry *entry, BOOL contents, IStream *stream)
+{
+    HRESULT hr = S_OK;
+    int data_size = 0;
+    void *data = NULL;
+    METAFILEPICT *mfpict = NULL;
+
+    if (!contents)
+    {
+        PresentationDataHeader header;
+
+        init_stream_header(entry, &header);
+        hr = write_clipformat(stream, entry->fmtetc.cfFormat);
+        if (FAILED(hr)) return hr;
+        if (entry->stgmedium.tymed != TYMED_NULL)
+        {
+            mfpict = GlobalLock(entry->stgmedium.u.hMetaFilePict);
+            if (!mfpict)
+                return DV_E_STGMEDIUM;
+            data_size = GetMetaFileBitsEx(mfpict->hMF, 0, NULL);
+            header.dwObjectExtentX = mfpict->xExt;
+            header.dwObjectExtentY = mfpict->yExt;
+            header.dwSize = data_size;
+            data = HeapAlloc(GetProcessHeap(), 0, header.dwSize);
+            if (!data)
+            {
+                GlobalUnlock(entry->stgmedium.u.hMetaFilePict);
+                return E_OUTOFMEMORY;
+            }
+            GetMetaFileBitsEx(mfpict->hMF, header.dwSize, data);
+            GlobalUnlock(entry->stgmedium.u.hMetaFilePict);
+        }
+        hr = IStream_Write(stream, &header, sizeof(PresentationDataHeader), NULL);
+        if (hr == S_OK && data_size)
+            hr = IStream_Write(stream, data, data_size, NULL);
+        HeapFree(GetProcessHeap(), 0, data);
+    }
+
+    return hr;
+}
+
+static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0};
+
+static HRESULT create_stream(DataCacheEntry *cache_entry, IStorage *storage,
+                             BOOL contents, IStream **stream)
+{
+    WCHAR pres[] = {2,'O','l','e','P','r','e','s',
         '0' + (cache_entry->stream_number / 100) % 10,
         '0' + (cache_entry->stream_number / 10) % 10,
         '0' + cache_entry->stream_number % 10, 0};
+    const WCHAR *name;
 
-    /* FIXME: cache the created stream in This? */
-    return IStorage_CreateStream(storage, wszName,
+    if (contents)
+        name = CONTENTS;
+    else
+        name = pres;
+
+    return IStorage_CreateStream(storage, name,
                                  STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
                                  0, 0, stream);
 }
@@ -792,130 +894,29 @@ static HRESULT DataCacheEntry_CreateStream(DataCacheEntry *cache_entry,
 static HRESULT DataCacheEntry_Save(DataCacheEntry *cache_entry, IStorage *storage,
                                    BOOL same_as_load)
 {
-    PresentationDataHeader header;
     HRESULT hr;
-    IStream *pres_stream;
-    void *data = NULL;
+    IStream *stream;
+    BOOL contents = (cache_entry->id == 1);
 
     TRACE("stream_number = %d, fmtetc = %s\n", cache_entry->stream_number, debugstr_formatetc(&cache_entry->fmtetc));
 
-    hr = DataCacheEntry_CreateStream(cache_entry, storage, &pres_stream);
+    hr = create_stream(cache_entry, storage, contents, &stream);
     if (FAILED(hr))
         return hr;
 
-    hr = write_clipformat(pres_stream, cache_entry->fmtetc.cfFormat);
-    if (FAILED(hr))
-        return hr;
-
-    if (cache_entry->fmtetc.ptd)
-        FIXME("ptd not serialized\n");
-    header.tdSize = sizeof(header.tdSize);
-    header.dvAspect = cache_entry->fmtetc.dwAspect;
-    header.lindex = cache_entry->fmtetc.lindex;
-    header.advf = cache_entry->advise_flags;
-    header.unknown7 = 0;
-    header.dwObjectExtentX = 0;
-    header.dwObjectExtentY = 0;
-    header.dwSize = 0;
-
-    /* size the data */
-    switch (cache_entry->fmtetc.cfFormat)
-    {
-        case CF_METAFILEPICT:
-        {
-            if (cache_entry->stgmedium.tymed != TYMED_NULL)
-            {
-                const METAFILEPICT *mfpict = GlobalLock(cache_entry->stgmedium.u.hMetaFilePict);
-                if (!mfpict)
-                {
-                    IStream_Release(pres_stream);
-                    return DV_E_STGMEDIUM;
-                }
-                header.dwObjectExtentX = mfpict->xExt;
-                header.dwObjectExtentY = mfpict->yExt;
-                header.dwSize = GetMetaFileBitsEx(mfpict->hMF, 0, NULL);
-                GlobalUnlock(cache_entry->stgmedium.u.hMetaFilePict);
-            }
-            break;
-        }
-        case CF_DIB:
-        {
-            header.dwSize = GlobalSize(cache_entry->stgmedium.u.hGlobal);
-            if (header.dwSize)
-            {
-                const BITMAPINFO *bmi = GlobalLock(cache_entry->stgmedium.u.hGlobal);
-                /* Size in units of 0.01mm (ie. MM_HIMETRIC) */
-                if (bmi->bmiHeader.biXPelsPerMeter != 0 && bmi->bmiHeader.biYPelsPerMeter != 0)
-                {
-                    header.dwObjectExtentX = MulDiv( bmi->bmiHeader.biWidth, 100000, bmi->bmiHeader.biXPelsPerMeter );
-                    header.dwObjectExtentY = MulDiv( bmi->bmiHeader.biHeight, 100000, bmi->bmiHeader.biYPelsPerMeter );
-                }
-                else
-                {
-                    HDC hdc = GetDC(0);
-                    header.dwObjectExtentX = MulDiv( bmi->bmiHeader.biWidth, 2540, GetDeviceCaps(hdc, LOGPIXELSX) );
-                    header.dwObjectExtentY = MulDiv( bmi->bmiHeader.biHeight, 2540, GetDeviceCaps(hdc, LOGPIXELSY) );
-                    ReleaseDC(0, hdc);
-                }
-                GlobalUnlock(cache_entry->stgmedium.u.hGlobal);
-            }
-            break;
-        }
-        default:
-            break;
-    }
-
-    /*
-     * Write the header.
-     */
-    hr = IStream_Write(pres_stream, &header, sizeof(PresentationDataHeader),
-                       NULL);
-    if (FAILED(hr))
-    {
-        IStream_Release(pres_stream);
-        return hr;
-    }
-
-    /* get the data */
     switch (cache_entry->fmtetc.cfFormat)
     {
-        case CF_METAFILEPICT:
-        {
-            if (cache_entry->stgmedium.tymed != TYMED_NULL)
-            {
-                const METAFILEPICT *mfpict = GlobalLock(cache_entry->stgmedium.u.hMetaFilePict);
-                if (!mfpict)
-                {
-                    IStream_Release(pres_stream);
-                    return DV_E_STGMEDIUM;
-                }
-                if (header.dwSize)
-                {
-                    data = HeapAlloc(GetProcessHeap(), 0, header.dwSize);
-                    GetMetaFileBitsEx(mfpict->hMF, header.dwSize, data);
-                    GlobalUnlock(cache_entry->stgmedium.u.hMetaFilePict);
-                    if (data)
-                    {
-                        hr = IStream_Write(pres_stream, data, header.dwSize, NULL);
-                        HeapFree(GetProcessHeap(), 0, data);
-                    }
-                }
-            }
-            break;
-        }
-        case CF_DIB:
-        {
-            data = GlobalLock(cache_entry->stgmedium.u.hGlobal);
-            if (header.dwSize)
-                hr = IStream_Write(pres_stream, data, header.dwSize, NULL);
-            GlobalUnlock(cache_entry->stgmedium.u.hGlobal);
-            break;
-        }
-        default:
-            break;
+    case CF_DIB:
+        hr = save_dib(cache_entry, contents, stream);
+        break;
+    case CF_METAFILEPICT:
+        hr = save_mfpict(cache_entry, contents, stream);
+        break;
+    default:
+        FIXME("got unsupported clipboard format %x\n", cache_entry->fmtetc.cfFormat);
     }
 
-    IStream_Release(pres_stream);
+    IStream_Release(stream);
     return hr;
 }
 
@@ -1651,8 +1652,6 @@ static HRESULT parse_contents_stream( DataCache *This, IStorage *stg, IStream *s
     return add_cache_entry( This, fmt, 0, stm, contents_stream );
 }
 
-static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0};
-
 /************************************************************************
  * DataCache_Load (IPersistStorage)
  *
-- 
2.14.1




More information about the wine-devel mailing list