[PATCH 5/6] ole32: Implement IOleCache2_UpdateCache().
Huw Davies <[email protected]>
| Newsgroups | gmane.comp.emulators.wine.patches |
|---|---|
| Message-ID | <[email protected]> |
Signed-off-by: Huw Davies <[email protected]> --- dlls/ole32/datacache.c | 141 ++++++++++++-- dlls/ole32/tests/ole2.c | 480 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 540 insertions(+), 81 deletions(-) diff --git a/dlls/ole32/datacache.c b/dlls/ole32/datacache.c index 7a19a171e5..2c5e45134e 100644 --- a/dlls/ole32/datacache.c +++ b/dlls/ole32/datacache.c @@ -961,12 +961,33 @@ static HBITMAP synthesize_bitmap( HGLOBAL dib ) return ret; } +static HENHMETAFILE synthesize_emf( HMETAFILEPICT data ) +{ + METAFILEPICT *pict; + HENHMETAFILE emf = 0; + UINT size; + void *bits; + + if (!(pict = GlobalLock( data ))) return 0; + + size = GetMetaFileBitsEx( pict->hMF, 0, NULL ); + if ((bits = HeapAlloc( GetProcessHeap(), 0, size ))) + { + GetMetaFileBitsEx( pict->hMF, size, bits ); + emf = SetWinMetaFileBits( size, bits, NULL, pict ); + HeapFree( GetProcessHeap(), 0, bits ); + } + + GlobalUnlock( data ); + return emf; +} + static HRESULT DataCacheEntry_SetData(DataCacheEntry *cache_entry, const FORMATETC *formatetc, STGMEDIUM *stgmedium, BOOL fRelease) { - STGMEDIUM dib_copy; + STGMEDIUM copy; if ((!cache_entry->fmtetc.cfFormat && !formatetc->cfFormat) || (cache_entry->fmtetc.tymed == TYMED_NULL && formatetc->tymed == TYMED_NULL) || @@ -981,11 +1002,19 @@ static HRESULT DataCacheEntry_SetData(DataCacheEntry *cache_entry, if (formatetc->cfFormat == CF_BITMAP) { - dib_copy.tymed = TYMED_HGLOBAL; - dib_copy.u.hGlobal = synthesize_dib( stgmedium->u.hBitmap ); - dib_copy.pUnkForRelease = NULL; + copy.tymed = TYMED_HGLOBAL; + copy.u.hGlobal = synthesize_dib( stgmedium->u.hBitmap ); + copy.pUnkForRelease = NULL; + if (fRelease) ReleaseStgMedium(stgmedium); + stgmedium = © + fRelease = TRUE; + } + else if (formatetc->cfFormat == CF_METAFILEPICT && cache_entry->fmtetc.cfFormat == CF_ENHMETAFILE) + { + copy.tymed = TYMED_ENHMF; + copy.u.hEnhMetaFile = synthesize_emf( stgmedium->u.hMetaFilePict ); if (fRelease) ReleaseStgMedium(stgmedium); - stgmedium = &dib_copy; + stgmedium = © fRelease = TRUE; } @@ -2381,14 +2410,102 @@ static HRESULT WINAPI DataCache_IOleCache2_SetData( return OLE_E_BLANK; } -static HRESULT WINAPI DataCache_UpdateCache( - IOleCache2* iface, - LPDATAOBJECT pDataObject, - DWORD grfUpdf, - LPVOID pReserved) +static BOOL entry_updateable( DataCacheEntry *entry, DWORD mode ) { - FIXME("(%p, 0x%x, %p): stub\n", pDataObject, grfUpdf, pReserved); - return E_NOTIMPL; + BOOL is_blank = entry->stgmedium.tymed == TYMED_NULL; + + if ((mode & UPDFCACHE_ONLYIFBLANK) && !is_blank) return FALSE; + + if ((mode & UPDFCACHE_NODATACACHE) && (entry->advise_flags & ADVF_NODATA)) return TRUE; + if ((mode & UPDFCACHE_ONSAVECACHE) && (entry->advise_flags & ADVFCACHE_ONSAVE)) return TRUE; + if ((mode & UPDFCACHE_ONSTOPCACHE) && (entry->advise_flags & ADVF_DATAONSTOP)) return TRUE; + if ((mode & UPDFCACHE_NORMALCACHE) && (entry->advise_flags == 0)) return TRUE; + if ((mode & UPDFCACHE_IFBLANK) && (is_blank && !(entry->advise_flags & ADVF_NODATA))) return TRUE; + + return FALSE; +} + +static HRESULT WINAPI DataCache_UpdateCache( IOleCache2 *iface, IDataObject *data, + DWORD mode, void *reserved ) +{ + DataCache *This = impl_from_IOleCache2(iface); + DataCacheEntry *cache_entry; + STGMEDIUM med; + HRESULT hr = S_OK; + CLIPFORMAT view_list[] = { CF_METAFILEPICT, CF_ENHMETAFILE, CF_DIB, CF_BITMAP }; + FORMATETC fmt; + int i, slots = 0; + BOOL done_one = FALSE; + + TRACE( "(%p %p %08x %p)\n", iface, data, mode, reserved ); + + LIST_FOR_EACH_ENTRY( cache_entry, &This->cache_list, DataCacheEntry, entry ) + { + slots++; + + if (!entry_updateable( cache_entry, mode )) + { + done_one = TRUE; + continue; + } + + fmt = cache_entry->fmtetc; + + if (fmt.cfFormat) + { + hr = IDataObject_GetData( data, &fmt, &med ); + if (hr != S_OK && fmt.cfFormat == CF_DIB) + { + fmt.cfFormat = CF_BITMAP; + fmt.tymed = TYMED_GDI; + hr = IDataObject_GetData( data, &fmt, &med ); + } + if (hr != S_OK && fmt.cfFormat == CF_ENHMETAFILE) + { + fmt.cfFormat = CF_METAFILEPICT; + fmt.tymed = TYMED_MFPICT; + hr = IDataObject_GetData( data, &fmt, &med ); + } + if (hr == S_OK) + { + hr = DataCacheEntry_SetData( cache_entry, &fmt, &med, TRUE ); + if (hr != S_OK) ReleaseStgMedium( &med ); + else done_one = TRUE; + } + } + else + { + for (i = 0; i < sizeof(view_list) / sizeof(view_list[0]); i++) + { + fmt.cfFormat = view_list[i]; + fmt.tymed = tymed_from_cf( fmt.cfFormat ); + hr = IDataObject_QueryGetData( data, &fmt ); + if (hr == S_OK) + { + hr = IDataObject_GetData( data, &fmt, &med ); + if (hr == S_OK) + { + if (fmt.cfFormat == CF_BITMAP) + { + cache_entry->fmtetc.cfFormat = CF_DIB; + cache_entry->fmtetc.tymed = TYMED_HGLOBAL; + } + else + { + cache_entry->fmtetc.cfFormat = fmt.cfFormat; + cache_entry->fmtetc.tymed = fmt.tymed; + } + hr = DataCacheEntry_SetData( cache_entry, &fmt, &med, TRUE ); + if (hr != S_OK) ReleaseStgMedium( &med ); + else done_one = TRUE; + break; + } + } + } + } + } + + return (!slots || done_one) ? S_OK : CACHE_E_NOCACHE_UPDATED; } static HRESULT WINAPI DataCache_DiscardCache( diff --git a/dlls/ole32/tests/ole2.c b/dlls/ole32/tests/ole2.c index aaee6773d8..9b96570999 100644 --- a/dlls/ole32/tests/ole2.c +++ b/dlls/ole32/tests/ole2.c @@ -112,6 +112,7 @@ struct expected_method { const char *method; unsigned int flags; + FORMATETC fmt; }; static const struct expected_method *expected_method_list; @@ -124,6 +125,8 @@ static HRESULT g_QIFailsWith; static UINT cf_test_1, cf_test_2, cf_test_3; +static FORMATETC *g_dataobject_fmts; + /**************************************************************************** * PresentationDataHeader * @@ -150,27 +153,43 @@ typedef struct PresentationDataHeader DWORD dwSize; } PresentationDataHeader; -#define CHECK_EXPECTED_METHOD(method_name) \ - do { \ - trace("%s\n", method_name); \ - ok(expected_method_list->method != NULL, "Extra method %s called\n", method_name); \ - if (!strcmp(expected_method_list->method, "WINE_EXTRA")) \ - { \ - todo_wine ok(0, "Too many method calls.\n"); \ - break; \ - } \ - if (expected_method_list->method) \ - { \ - while (expected_method_list->flags & TEST_OPTIONAL && \ - strcmp(expected_method_list->method, method_name) != 0) \ - expected_method_list++; \ - todo_wine_if (expected_method_list->flags & TEST_TODO) \ - ok(!strcmp(expected_method_list->method, method_name), \ - "Expected %s to be called instead of %s\n", \ - expected_method_list->method, method_name); \ - expected_method_list++; \ - } \ - } while(0) +static void inline check_expected_method_fmt(const char *method_name, const FORMATETC *fmt) +{ + trace("%s\n", method_name); + ok(expected_method_list->method != NULL, "Extra method %s called\n", method_name); + if (!strcmp(expected_method_list->method, "WINE_EXTRA")) + { + todo_wine ok(0, "Too many method calls.\n"); + return; + } + if (expected_method_list->method) + { + while (expected_method_list->flags & TEST_OPTIONAL && + strcmp(expected_method_list->method, method_name) != 0) + expected_method_list++; + todo_wine_if (expected_method_list->flags & TEST_TODO) + { + ok(!strcmp(expected_method_list->method, method_name), + "Expected %s to be called instead of %s\n", + expected_method_list->method, method_name); + if (fmt) + { + ok(fmt->cfFormat == expected_method_list->fmt.cfFormat, "got cf %04x vs %04x\n", + fmt->cfFormat, expected_method_list->fmt.cfFormat ); + ok(fmt->dwAspect == expected_method_list->fmt.dwAspect, "got aspect %d vs %d\n", + fmt->dwAspect, expected_method_list->fmt.dwAspect ); + ok(fmt->lindex == expected_method_list->fmt.lindex, "got lindex %d vs %d\n", + fmt->lindex, expected_method_list->fmt.lindex ); + ok(fmt->tymed == expected_method_list->fmt.tymed, "got tymed %d vs %d\n", + fmt->tymed, expected_method_list->fmt.tymed ); + } + } + expected_method_list++; + } +} + +#define CHECK_EXPECTED_METHOD(method_name) check_expected_method_fmt(method_name, NULL) +#define CHECK_EXPECTED_METHOD_FMT(method_name, fmt) check_expected_method_fmt(method_name, fmt) #define CHECK_NO_EXTRA_METHODS() \ do { \ @@ -179,6 +198,41 @@ typedef struct PresentationDataHeader ok(!expected_method_list->method, "Method sequence starting from %s not called\n", expected_method_list->method); \ } while (0) +/* 2 x 1 x 32 bpp dib. PelsPerMeter = 200x400 */ +static BYTE dib[] = +{ + 0x42, 0x4d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, + + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, + 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static void create_dib( STGMEDIUM *med ) +{ + void *ptr; + + med->tymed = TYMED_HGLOBAL; + U(med)->hGlobal = GlobalAlloc( GMEM_MOVEABLE, sizeof(dib) - sizeof(BITMAPFILEHEADER) ); + ptr = GlobalLock( U(med)->hGlobal ); + memcpy( ptr, dib + sizeof(BITMAPFILEHEADER), sizeof(dib) - sizeof(BITMAPFILEHEADER) ); + GlobalUnlock( U(med)->hGlobal ); + med->pUnkForRelease = NULL; +} + +static void create_bitmap( STGMEDIUM *med ) +{ + med->tymed = TYMED_GDI; + U(med)->hBitmap = CreateBitmap( 1, 1, 1, 1, NULL ); + med->pUnkForRelease = NULL; +} + static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, void **ppv) { CHECK_EXPECTED_METHOD("OleObject_QueryInterface"); @@ -1385,13 +1439,40 @@ static ULONG WINAPI DataObject_Release( return 1; } -static HRESULT WINAPI DataObject_GetData( - IDataObject* iface, - LPFORMATETC pformatetcIn, - STGMEDIUM* pmedium) +static inline BOOL fmtetc_equal( const FORMATETC *a, const FORMATETC *b ) { - CHECK_EXPECTED_METHOD("DataObject_GetData"); - return E_NOTIMPL; + /* FIXME ptd */ + return a->cfFormat == b->cfFormat && a->dwAspect == b->dwAspect && + a->lindex == b->lindex && a->tymed == b->tymed; + +} + +static HRESULT WINAPI DataObject_GetData( IDataObject *iface, FORMATETC *fmt_in, + STGMEDIUM *med ) +{ + FORMATETC *fmt; + + CHECK_EXPECTED_METHOD_FMT("DataObject_GetData", fmt_in); + + for (fmt = g_dataobject_fmts; fmt && fmt->cfFormat != 0; fmt++) + { + if (fmtetc_equal( fmt_in, fmt )) + { + switch (fmt->cfFormat) + { + case CF_DIB: + create_dib( med ); + return S_OK; + case CF_BITMAP: + create_bitmap( med ); + return S_OK; + default: + trace( "unhandled fmt %d\n", fmt->cfFormat ); + } + } + } + + return S_FALSE; } static HRESULT WINAPI DataObject_GetDataHere( @@ -1403,12 +1484,16 @@ static HRESULT WINAPI DataObject_GetDataHere( return E_NOTIMPL; } -static HRESULT WINAPI DataObject_QueryGetData( - IDataObject* iface, - LPFORMATETC pformatetc) +static HRESULT WINAPI DataObject_QueryGetData( IDataObject *iface, FORMATETC *fmt_in ) { - CHECK_EXPECTED_METHOD("DataObject_QueryGetData"); - return S_OK; + FORMATETC *fmt; + + CHECK_EXPECTED_METHOD_FMT("DataObject_QueryGetData", fmt_in); + + for (fmt = g_dataobject_fmts; fmt && fmt->cfFormat != 0; fmt++) + if (fmtetc_equal( fmt_in, fmt )) return S_OK; + + return S_FALSE; } static HRESULT WINAPI DataObject_GetCanonicalFormatEtc( @@ -1601,9 +1686,9 @@ static void test_data_cache(void) { "draw_continue", 1 }, { "draw_continue", 1 }, { "draw_continue", 1 }, - { "DataObject_GetData", 0 }, - { "DataObject_GetData", 0 }, - { "DataObject_GetData", 0 }, + { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_THUMBNAIL, -1, TYMED_HGLOBAL} }, + { "DataObject_GetData", 0, { CF_BITMAP, NULL, DVASPECT_THUMBNAIL, -1, TYMED_GDI} }, + { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_ICON, -1, TYMED_MFPICT} }, { NULL, 0 } }; static const struct expected_method methods_cachethenrun[] = @@ -1611,7 +1696,6 @@ static void test_data_cache(void) { "DataObject_DAdvise", 0 }, { "DataObject_DAdvise", 0 }, { "DataObject_DAdvise", 0 }, - { "DataObject_QueryGetData", 1 }, /* called by win9x and nt4 */ { "DataObject_DAdvise", 0 }, { "DataObject_DUnadvise", 0 }, { "DataObject_DUnadvise", 0 }, @@ -1961,22 +2045,6 @@ static void test_data_cache(void) static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0}; -/* 2 x 1 x 32 bpp dib. PelsPerMeter = 200x400 */ -static BYTE dib[] = -{ - 0x42, 0x4d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, - - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, - 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -}; - static IStorage *create_storage( int num ) { IStorage *stg; @@ -2001,18 +2069,6 @@ static IStorage *create_storage( int num ) return stg; } -static HGLOBAL create_dib( void ) -{ - HGLOBAL h; - void *ptr; - - h = GlobalAlloc( GMEM_MOVEABLE, sizeof(dib) - sizeof(BITMAPFILEHEADER) ); - ptr = GlobalLock( h ); - memcpy( ptr, dib + sizeof(BITMAPFILEHEADER), sizeof(dib) - sizeof(BITMAPFILEHEADER) ); - GlobalUnlock( h ); - return h; -} - static void test_data_cache_dib_contents_stream(int num) { HRESULT hr; @@ -2220,9 +2276,7 @@ static void test_data_cache_cache(void) hr = IOleCache2_QueryInterface( cache, &IID_IDataObject, (void **) &data ); ok( hr == S_OK, "got %08x\n", hr ); - med.tymed = TYMED_GDI; - U(med).hBitmap = CreateBitmap( 1, 1, 1, 1, NULL ); - med.pUnkForRelease = NULL; + create_bitmap( &med ); hr = IOleCache2_SetData( cache, &fmt, &med, TRUE ); ok( hr == S_OK, "got %08x\n", hr ); @@ -2244,8 +2298,7 @@ static void test_data_cache_cache(void) /* Now set a 2x1 dib */ fmt.cfFormat = CF_DIB; fmt.tymed = TYMED_HGLOBAL; - med.tymed = TYMED_HGLOBAL; - U(med).hGlobal = create_dib(); + create_dib( &med ); hr = IOleCache2_SetData( cache, &fmt, &med, TRUE ); ok( hr == S_OK, "got %08x\n", hr ); @@ -2503,6 +2556,294 @@ static void test_data_cache_initnew(void) IOleCache2_Release( cache ); } +static void test_data_cache_updatecache( void ) +{ + HRESULT hr; + IOleCache2 *cache; + FORMATETC fmt; + DWORD conn[4]; + + static const struct expected_method methods_dib[] = + { + { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } }, + { "DataObject_GetData", 0, { CF_BITMAP, NULL, DVASPECT_CONTENT, -1, TYMED_GDI } }, + { NULL } + }; + + static const struct expected_method methods_dib_emf[] = + { + { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } }, + { "DataObject_GetData", 0, { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } }, + { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } }, + { NULL } + }; + static const struct expected_method methods_dib_wmf[] = + { + { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } }, + { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } }, + { NULL } + }; + static const struct expected_method methods_viewcache[] = + { + { "DataObject_QueryGetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } }, + { "DataObject_QueryGetData", 0, { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } }, + { "DataObject_QueryGetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } }, + { "DataObject_QueryGetData", 0, { CF_BITMAP, NULL, DVASPECT_CONTENT, -1, TYMED_GDI } }, + { NULL } + }; + static const struct expected_method methods_viewcache_with_dib[] = + { + { "DataObject_QueryGetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } }, + { "DataObject_QueryGetData", 0, { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } }, + { "DataObject_QueryGetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } }, + { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } }, + { NULL } + }; + static const struct expected_method methods_flags_all[] = + { + { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } }, + { "DataObject_GetData", 0, { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } }, + { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } }, + { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } }, + { NULL } + }; + static const struct expected_method methods_flags_ifblank_1[] = + { + { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } }, + { NULL } + }; + static const struct expected_method methods_flags_ifblank_2[] = + { + { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } }, + { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } }, + { NULL } + }; + static const struct expected_method methods_flags_normal[] = + { + { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } }, + { NULL } + }; + static const struct expected_method methods_empty[] = + { + { NULL } + }; + + static STATDATA view_cache[] = + { + {{ 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 0 } + }; + static STATDATA view_cache_after_dib[] = + { + {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 0 }, + {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 0 } + }; + + static FORMATETC dib_fmt[] = + { + { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, + { 0 } + }; + + hr = CreateDataCache( NULL, &CLSID_WineTestOld, &IID_IOleCache2, (void **)&cache ); + ok( hr == S_OK, "got %08x\n", hr ); + + /* No cache slots */ + g_dataobject_fmts = NULL; + expected_method_list = NULL; + + hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + /* A dib cache slot */ + 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[0] ); + ok( hr == S_OK, "got %08x\n", hr ); + + expected_method_list = methods_dib; + + hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL ); + ok( hr == CACHE_E_NOCACHE_UPDATED, "got %08x\n", hr ); + + CHECK_NO_EXTRA_METHODS(); + + /* Now with a dib available */ + g_dataobject_fmts = dib_fmt; + expected_method_list = methods_dib; + + hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + /* Add an EMF cache slot */ + fmt.cfFormat = CF_ENHMETAFILE; + fmt.ptd = NULL; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.tymed = TYMED_ENHMF; + + hr = IOleCache2_Cache( cache, &fmt, 0, &conn[1] ); + ok( hr == S_OK, "got %08x\n", hr ); + + g_dataobject_fmts = dib_fmt; + expected_method_list = methods_dib_emf; + + /* Two slots to fill, only the dib will succeed */ + hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + CHECK_NO_EXTRA_METHODS(); + + /* Replace the emf slot with a wmf */ + hr = IOleCache2_Uncache( cache, conn[1] ); + ok( hr == S_OK, "got %08x\n", hr ); + + fmt.cfFormat = CF_METAFILEPICT; + fmt.ptd = NULL; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.tymed = TYMED_MFPICT; + + hr = IOleCache2_Cache( cache, &fmt, 0, &conn[1] ); + ok( hr == S_OK, "got %08x\n", hr ); + + g_dataobject_fmts = dib_fmt; + expected_method_list = methods_dib_wmf; + + hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = IOleCache2_Uncache( cache, conn[1] ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = IOleCache2_Uncache( cache, conn[0] ); + ok( hr == S_OK, "got %08x\n", hr ); + + /* View caching */ + fmt.cfFormat = 0; + fmt.ptd = NULL; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.tymed = TYMED_HGLOBAL; + + hr = IOleCache2_Cache( cache, &fmt, 0, &conn[0] ); + ok( hr == S_OK, "got %08x\n", hr ); + view_cache[0].dwConnection = conn[0]; + + g_dataobject_fmts = NULL; + expected_method_list = methods_viewcache; + + hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL ); + ok( hr == CACHE_E_NOCACHE_UPDATED, "got %08x\n", hr ); + + CHECK_NO_EXTRA_METHODS(); + check_enum_cache( cache, view_cache, 1 ); + + g_dataobject_fmts = dib_fmt; + expected_method_list = methods_viewcache_with_dib; + + hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + CHECK_NO_EXTRA_METHODS(); + view_cache_after_dib[0].dwConnection = view_cache_after_dib[1].dwConnection = view_cache[0].dwConnection; + check_enum_cache( cache, view_cache_after_dib, 2 ); + + hr = IOleCache2_Uncache( cache, conn[0] ); + ok( hr == S_OK, "got %08x\n", hr ); + + /* Try some different flags */ + + 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[0] ); + ok( hr == S_OK, "got %08x\n", hr ); + + fmt.cfFormat = CF_ENHMETAFILE; + fmt.ptd = NULL; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.tymed = TYMED_ENHMF; + + hr = IOleCache2_Cache( cache, &fmt, ADVF_NODATA, &conn[1] ); + ok( hr == S_OK, "got %08x\n", hr ); + + fmt.cfFormat = CF_METAFILEPICT; + fmt.ptd = NULL; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.tymed = TYMED_MFPICT; + + hr = IOleCache2_Cache( cache, &fmt, ADVFCACHE_ONSAVE, &conn[2] ); + ok( hr == S_OK, "got %08x\n", hr ); + + g_dataobject_fmts = dib_fmt; + expected_method_list = methods_flags_all; + + hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL ); + + CHECK_NO_EXTRA_METHODS(); + + expected_method_list = methods_flags_all; + + hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + CHECK_NO_EXTRA_METHODS(); + + expected_method_list = methods_flags_ifblank_1; + + hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_IFBLANK , NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + CHECK_NO_EXTRA_METHODS(); + + hr = IOleCache2_DiscardCache( cache, DISCARDCACHE_NOSAVE ); + ok( hr == S_OK, "got %08x\n", hr ); + + expected_method_list = methods_flags_ifblank_2; + + hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_IFBLANK , NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + CHECK_NO_EXTRA_METHODS(); + + hr = IOleCache2_DiscardCache( cache, DISCARDCACHE_NOSAVE ); + ok( hr == S_OK, "got %08x\n", hr ); + + expected_method_list = methods_flags_all; + + hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_IFBLANK | UPDFCACHE_NODATACACHE, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + CHECK_NO_EXTRA_METHODS(); + + expected_method_list = methods_empty; + + hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ONLYIFBLANK | UPDFCACHE_NORMALCACHE, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + CHECK_NO_EXTRA_METHODS(); + + hr = IOleCache2_DiscardCache( cache, DISCARDCACHE_NOSAVE ); + ok( hr == S_OK, "got %08x\n", hr ); + + expected_method_list = methods_flags_normal; + + hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ONLYIFBLANK | UPDFCACHE_NORMALCACHE, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + CHECK_NO_EXTRA_METHODS(); + + IOleCache2_Release( cache ); +} + static void test_default_handler(void) { HRESULT hr; @@ -3833,6 +4174,7 @@ START_TEST(ole2) test_data_cache_cache(); test_data_cache_init(); test_data_cache_initnew(); + test_data_cache_updatecache(); test_default_handler(); test_runnable(); test_OleRun(); -- 2.12.0