Module: wine Branch: master Commit: e27708f2fd5213cc181e8b40bb331c9a852a9c24 URL: http://source.winehq.org/git/wine.git/?a=commit;h=e27708f2fd5213cc181e8b40bb...
Author: Huw Davies huw@codeweavers.com Date: Tue May 23 13:11:41 2017 +0100
ole32: Create CF_DIB and CF_BITMAP entries when either is cached.
Signed-off-by: Huw Davies huw@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ole32/datacache.c | 36 ++++++++++++-- dlls/ole32/tests/ole2.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 4 deletions(-)
diff --git a/dlls/ole32/datacache.c b/dlls/ole32/datacache.c index 5055c3f..d850a34 100644 --- a/dlls/ole32/datacache.c +++ b/dlls/ole32/datacache.c @@ -2079,6 +2079,7 @@ static HRESULT WINAPI DataCache_Cache( DataCache *This = impl_from_IOleCache2(iface); DataCacheEntry *cache_entry; HRESULT hr; + FORMATETC fmt_cpy;
TRACE("(%p, 0x%x, %p)\n", pformatetc, advf, pdwConnection);
@@ -2087,9 +2088,16 @@ static HRESULT WINAPI DataCache_Cache(
TRACE("pformatetc = %s\n", debugstr_formatetc(pformatetc));
+ fmt_cpy = *pformatetc; /* No need for a deep copy */ + if (fmt_cpy.cfFormat == CF_BITMAP && fmt_cpy.tymed == TYMED_GDI) + { + fmt_cpy.cfFormat = CF_DIB; + fmt_cpy.tymed = TYMED_HGLOBAL; + } + *pdwConnection = 0;
- cache_entry = DataCache_GetEntryForFormatEtc(This, pformatetc); + cache_entry = DataCache_GetEntryForFormatEtc(This, &fmt_cpy); if (cache_entry) { TRACE("found an existing cache entry\n"); @@ -2097,7 +2105,7 @@ static HRESULT WINAPI DataCache_Cache( return CACHE_S_SAMECACHE; }
- hr = DataCache_CreateEntry(This, pformatetc, advf, &cache_entry, FALSE); + hr = DataCache_CreateEntry(This, &fmt_cpy, advf, &cache_entry, FALSE);
if (SUCCEEDED(hr)) { @@ -2134,24 +2142,44 @@ static HRESULT WINAPI DataCache_EnumCache(IOleCache2 *iface, { DataCache *This = impl_from_IOleCache2( iface ); DataCacheEntry *cache_entry; - int i = 0, count = list_count( &This->cache_list ); + int i = 0, count = 0; STATDATA *data; HRESULT hr;
TRACE( "(%p, %p)\n", This, enum_stat );
+ LIST_FOR_EACH_ENTRY( cache_entry, &This->cache_list, DataCacheEntry, entry ) + { + count++; + if (cache_entry->fmtetc.cfFormat == CF_DIB) + count++; + } + data = CoTaskMemAlloc( count * sizeof(*data) ); if (!data) return E_OUTOFMEMORY;
LIST_FOR_EACH_ENTRY( cache_entry, &This->cache_list, DataCacheEntry, entry ) { - if (i == count) break; + if (i == count) goto fail; hr = copy_formatetc( &data[i].formatetc, &cache_entry->fmtetc ); if (FAILED(hr)) goto fail; data[i].advf = cache_entry->advise_flags; data[i].pAdvSink = NULL; data[i].dwConnection = cache_entry->id; i++; + + if (cache_entry->fmtetc.cfFormat == CF_DIB) + { + if (i == count) goto fail; + hr = copy_formatetc( &data[i].formatetc, &cache_entry->fmtetc ); + if (FAILED(hr)) goto fail; + data[i].formatetc.cfFormat = CF_BITMAP; + data[i].formatetc.tymed = TYMED_GDI; + data[i].advf = cache_entry->advise_flags; + data[i].pAdvSink = NULL; + data[i].dwConnection = cache_entry->id; + i++; + } }
hr = EnumSTATDATA_Construct( NULL, 0, i, data, FALSE, enum_stat ); diff --git a/dlls/ole32/tests/ole2.c b/dlls/ole32/tests/ole2.c index 65abb3e..0102ca0 100644 --- a/dlls/ole32/tests/ole2.c +++ b/dlls/ole32/tests/ole2.c @@ -1522,6 +1522,39 @@ static const IUnknownVtbl UnknownVtbl =
static IUnknown unknown = { &UnknownVtbl };
+static void check_enum_cache(IOleCache2 *cache, STATDATA *expect, int num) +{ + IEnumSTATDATA *enum_stat; + STATDATA stat; + HRESULT hr; + + hr = IOleCache2_EnumCache( cache, &enum_stat ); + ok( hr == S_OK, "got %08x\n", hr ); + + while (IEnumSTATDATA_Next(enum_stat, 1, &stat, NULL) == S_OK) + { + ok( stat.formatetc.cfFormat == expect->formatetc.cfFormat, "got %d expect %d\n", + stat.formatetc.cfFormat, expect->formatetc.cfFormat ); + ok( !stat.formatetc.ptd == !expect->formatetc.ptd, "got %p expect %p\n", + stat.formatetc.ptd, expect->formatetc.ptd ); + ok( stat.formatetc.dwAspect == expect->formatetc.dwAspect, "got %d expect %d\n", + stat.formatetc.dwAspect, expect->formatetc.dwAspect ); + ok( stat.formatetc.lindex == expect->formatetc.lindex, "got %d expect %d\n", + stat.formatetc.lindex, expect->formatetc.lindex ); + ok( stat.formatetc.tymed == expect->formatetc.tymed, "got %d expect %d\n", + stat.formatetc.tymed, expect->formatetc.tymed ); + ok( stat.advf == expect->advf, "got %d expect %d\n", stat.advf, expect->advf ); + ok( stat.pAdvSink == 0, "got %p\n", stat.pAdvSink ); + ok( stat.dwConnection == expect->dwConnection, "got %d expect %d\n", stat.dwConnection, expect->dwConnection ); + num--; + expect++; + } + + ok( num == 0, "incorrect number. num %d\n", num ); + + IEnumSTATDATA_Release( enum_stat ); +} + static void test_data_cache(void) { HRESULT hr; @@ -1968,12 +2001,18 @@ static void test_data_cache_dib_contents_stream(int num) IDataObject *data; IViewObject2 *view; IStorage *stg; + IOleCache2 *cache; FORMATETC fmt = {CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; STGMEDIUM med; CLSID cls; SIZEL sz; BYTE *ptr; BITMAPINFOHEADER expect_info; + STATDATA enum_expect[] = + { + {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 }, + {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 }, + };
hr = CreateDataCache( NULL, &CLSID_Picture_Metafile, &IID_IUnknown, (void **)&unk ); ok( SUCCEEDED(hr), "got %08x\n", hr ); @@ -1983,6 +2022,8 @@ static void test_data_cache_dib_contents_stream(int num) ok( SUCCEEDED(hr), "got %08x\n", hr ); hr = IUnknown_QueryInterface( unk, &IID_IViewObject2, (void **)&view ); ok( SUCCEEDED(hr), "got %08x\n", hr ); + hr = IUnknown_QueryInterface( unk, &IID_IOleCache2, (void **)&cache ); + ok( SUCCEEDED(hr), "got %08x\n", hr );
stg = create_storage( num );
@@ -2015,6 +2056,8 @@ static void test_data_cache_dib_contents_stream(int num) GlobalUnlock( U(med).hGlobal ); ReleaseStgMedium( &med );
+ check_enum_cache( cache, enum_expect, 2 ); + hr = IViewObject2_GetExtent( view, DVASPECT_CONTENT, -1, NULL, &sz ); ok( SUCCEEDED(hr), "got %08x\n", hr ); if (num == 0) @@ -2033,12 +2076,98 @@ static void test_data_cache_dib_contents_stream(int num) ReleaseDC( 0, hdc ); }
+ IOleCache2_Release( cache ); IViewObject2_Release( view ); IDataObject_Release( data ); IPersistStorage_Release( persist ); IUnknown_Release( unk ); }
+static void test_data_cache_bitmap(void) +{ + HRESULT hr; + IOleCache2 *cache; + FORMATETC fmt; + DWORD conn; + STATDATA expect[] = + { + {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 0 }, + {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 0 }, + {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 0 }, + {{ CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF }, 0, NULL, 0 } + }; + + hr = CreateDataCache( NULL, &CLSID_NULL, &IID_IOleCache2, (void **)&cache ); + ok( hr == S_OK, "got %08x\n", hr ); + + /* create a dib entry which will also create a bitmap entry too */ + fmt.cfFormat = CF_DIB; + fmt.ptd = NULL; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.tymed = TYMED_HGLOBAL; + + hr = IOleCache2_Cache( cache, &fmt, 0, &conn ); + ok( hr == S_OK, "got %08x\n", hr ); + expect[0].dwConnection = conn; + expect[1].dwConnection = conn; + + check_enum_cache( cache, expect, 2 ); + + /* now try to add a bitmap */ + fmt.cfFormat = CF_BITMAP; + fmt.tymed = TYMED_GDI; + + hr = IOleCache2_Cache( cache, &fmt, 0, &conn ); + ok( hr == CACHE_S_SAMECACHE, "got %08x\n", hr ); + + /* metafile */ + fmt.cfFormat = CF_METAFILEPICT; + fmt.tymed = TYMED_MFPICT; + + hr = IOleCache2_Cache( cache, &fmt, 0, &conn ); + ok( hr == S_OK, "got %08x\n", hr ); + expect[2].dwConnection = conn; + + check_enum_cache( cache, expect, 3); + + /* enhmetafile */ + fmt.cfFormat = CF_ENHMETAFILE; + fmt.tymed = TYMED_ENHMF; + + hr = IOleCache2_Cache( cache, &fmt, 0, &conn ); + ok( hr == S_OK, "got %08x\n", hr ); + expect[3].dwConnection = conn; + + check_enum_cache( cache, expect, 4 ); + + /* uncache everything */ + hr = IOleCache2_Uncache( cache, expect[3].dwConnection ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = IOleCache2_Uncache( cache, expect[2].dwConnection ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = IOleCache2_Uncache( cache, expect[0].dwConnection ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = IOleCache2_Uncache( cache, expect[0].dwConnection ); + ok( hr == OLE_E_NOCONNECTION, "got %08x\n", hr ); + + check_enum_cache( cache, expect, 0 ); + + /* just create a bitmap entry which again adds both dib and bitmap */ + fmt.cfFormat = CF_BITMAP; + fmt.tymed = TYMED_GDI; + + hr = IOleCache2_Cache( cache, &fmt, 0, &conn ); + ok( hr == S_OK, "got %08x\n", hr ); + + expect[0].dwConnection = conn; + expect[1].dwConnection = conn; + + check_enum_cache( cache, expect, 2 ); + + IOleCache2_Release( cache ); +} + static void test_default_handler(void) { HRESULT hr; @@ -2791,6 +2920,7 @@ START_TEST(ole2) test_data_cache(); test_data_cache_dib_contents_stream( 0 ); test_data_cache_dib_contents_stream( 1 ); + test_data_cache_bitmap(); test_default_handler(); test_runnable(); test_OleRun();