ole32/tests: Use the available ARRAY_SIZE() macro.
[wine.git] / dlls / ole32 / tests / ole2.c
blob48c9e0cbabdbb927b23848bc83b6e87e1d89292d
1 /*
2 * Object Linking and Embedding Tests
4 * Copyright 2005 Robert Shearman
5 * Copyright 2017 Dmitry Timoshkov
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define COBJMACROS
23 #define CONST_VTABLE
24 #define WIN32_LEAN_AND_MEAN
26 #include <stdarg.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "objbase.h"
32 #include "shlguid.h"
34 #include "wine/test.h"
36 #include "initguid.h"
38 DEFINE_GUID(CLSID_Picture_Metafile,0x315,0,0,0xc0,0,0,0,0,0,0,0x46);
39 DEFINE_GUID(CLSID_Picture_Dib,0x316,0,0,0xc0,0,0,0,0,0,0,0x46);
40 DEFINE_GUID(CLSID_Picture_EnhMetafile,0x319,0,0,0xc0,0,0,0,0,0,0,0x46);
42 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
44 #define DEFINE_EXPECT(func) \
45 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
47 #define SET_EXPECT(func) \
48 expect_ ## func = TRUE
50 #define CHECK_EXPECT2(func) \
51 do { \
52 ok(expect_ ##func, "unexpected call " #func "\n"); \
53 called_ ## func = TRUE; \
54 }while(0)
56 #define CHECK_EXPECT(func) \
57 do { \
58 CHECK_EXPECT2(func); \
59 expect_ ## func = FALSE; \
60 }while(0)
62 #define CHECK_CALLED(func) \
63 do { \
64 ok(called_ ## func, "expected " #func "\n"); \
65 expect_ ## func = called_ ## func = FALSE; \
66 }while(0)
68 DEFINE_EXPECT(Storage_Stat);
69 DEFINE_EXPECT(Storage_OpenStream_CompObj);
70 DEFINE_EXPECT(Storage_OpenStream_OlePres);
71 DEFINE_EXPECT(Storage_SetClass);
72 DEFINE_EXPECT(Storage_CreateStream_CompObj);
73 DEFINE_EXPECT(Storage_CreateStream_OlePres);
74 DEFINE_EXPECT(Storage_OpenStream_Ole);
75 DEFINE_EXPECT(Storage_DestroyElement);
77 static const CLSID *Storage_SetClass_CLSID;
78 static int Storage_DestroyElement_limit;
80 static IPersistStorage OleObjectPersistStg;
81 static IOleCache *cache;
82 static IRunnableObject *runnable;
84 static const CLSID CLSID_WineTestOld =
85 { /* 9474ba1a-258b-490b-bc13-516e9239acd0 */
86 0x9474ba1a,
87 0x258b,
88 0x490b,
89 {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xd0}
92 static const CLSID CLSID_WineTest =
93 { /* 9474ba1a-258b-490b-bc13-516e9239ace0 */
94 0x9474ba1a,
95 0x258b,
96 0x490b,
97 {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xe0}
100 static const IID IID_WineTest =
101 { /* 9474ba1a-258b-490b-bc13-516e9239ace1 */
102 0x9474ba1a,
103 0x258b,
104 0x490b,
105 {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xe1}
108 #define TEST_OPTIONAL 0x1
109 #define TEST_TODO 0x2
111 struct expected_method
113 const char *method;
114 unsigned int flags;
115 FORMATETC fmt;
118 static const struct expected_method *expected_method_list;
119 static FORMATETC *g_expected_fetc = NULL;
121 static BOOL g_showRunnable = TRUE;
122 static BOOL g_isRunning = TRUE;
123 static HRESULT g_GetMiscStatusFailsWith = S_OK;
124 static HRESULT g_QIFailsWith;
126 static UINT cf_test_1, cf_test_2, cf_test_3;
128 static FORMATETC *g_dataobject_fmts;
130 /****************************************************************************
131 * PresentationDataHeader
133 * This structure represents the header of the \002OlePresXXX stream in
134 * the OLE object storage.
136 typedef struct PresentationDataHeader
138 /* clipformat:
139 * - standard clipformat:
140 * DWORD length = 0xffffffff;
141 * DWORD cfFormat;
142 * - or custom clipformat:
143 * DWORD length;
144 * CHAR format_name[length]; (null-terminated)
146 DWORD tdSize; /* This is actually a truncated DVTARGETDEVICE, if tdSize > sizeof(DWORD)
147 then there are tdSize - sizeof(DWORD) more bytes before dvAspect */
148 DVASPECT dvAspect;
149 DWORD lindex;
150 DWORD advf;
151 DWORD unknown7; /* 0 */
152 DWORD dwObjectExtentX;
153 DWORD dwObjectExtentY;
154 DWORD dwSize;
155 } PresentationDataHeader;
157 static void inline check_expected_method_fmt(const char *method_name, const FORMATETC *fmt)
159 trace("%s\n", method_name);
160 ok(expected_method_list->method != NULL, "Extra method %s called\n", method_name);
161 if (!strcmp(expected_method_list->method, "WINE_EXTRA"))
163 todo_wine ok(0, "Too many method calls.\n");
164 return;
166 if (expected_method_list->method)
168 while (expected_method_list->flags & TEST_OPTIONAL &&
169 strcmp(expected_method_list->method, method_name) != 0)
170 expected_method_list++;
171 todo_wine_if (expected_method_list->flags & TEST_TODO)
173 ok(!strcmp(expected_method_list->method, method_name),
174 "Expected %s to be called instead of %s\n",
175 expected_method_list->method, method_name);
176 if (fmt)
178 ok(fmt->cfFormat == expected_method_list->fmt.cfFormat, "got cf %04x vs %04x\n",
179 fmt->cfFormat, expected_method_list->fmt.cfFormat );
180 ok(fmt->dwAspect == expected_method_list->fmt.dwAspect, "got aspect %d vs %d\n",
181 fmt->dwAspect, expected_method_list->fmt.dwAspect );
182 ok(fmt->lindex == expected_method_list->fmt.lindex, "got lindex %d vs %d\n",
183 fmt->lindex, expected_method_list->fmt.lindex );
184 ok(fmt->tymed == expected_method_list->fmt.tymed, "got tymed %d vs %d\n",
185 fmt->tymed, expected_method_list->fmt.tymed );
188 expected_method_list++;
192 #define CHECK_EXPECTED_METHOD(method_name) check_expected_method_fmt(method_name, NULL)
193 #define CHECK_EXPECTED_METHOD_FMT(method_name, fmt) check_expected_method_fmt(method_name, fmt)
195 #define CHECK_NO_EXTRA_METHODS() \
196 do { \
197 while (expected_method_list->flags & TEST_OPTIONAL) \
198 expected_method_list++; \
199 ok(!expected_method_list->method, "Method sequence starting from %s not called\n", expected_method_list->method); \
200 } while (0)
202 /* 2 x 1 x 32 bpp dib. PelsPerMeter = 200x400 */
203 static const BYTE dib[] =
205 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
206 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00,
207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 0xc8, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
213 static void create_dib( STGMEDIUM *med )
215 void *ptr;
217 med->tymed = TYMED_HGLOBAL;
218 U(med)->hGlobal = GlobalAlloc( GMEM_MOVEABLE, sizeof(dib) );
219 ptr = GlobalLock( U(med)->hGlobal );
220 memcpy( ptr, dib, sizeof(dib) );
221 GlobalUnlock( U(med)->hGlobal );
222 med->pUnkForRelease = NULL;
225 static void create_bitmap( STGMEDIUM *med )
227 med->tymed = TYMED_GDI;
228 U(med)->hBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
229 med->pUnkForRelease = NULL;
232 static void create_emf(STGMEDIUM *med)
234 HDC hdc = CreateEnhMetaFileW(NULL, NULL, NULL, NULL);
236 Rectangle(hdc, 0, 0, 150, 300);
237 med->tymed = TYMED_ENHMF;
238 U(med)->hEnhMetaFile = CloseEnhMetaFile(hdc);
239 med->pUnkForRelease = NULL;
242 static void create_mfpict(STGMEDIUM *med)
244 METAFILEPICT *mf;
245 HDC hdc = CreateMetaFileW(NULL);
247 Rectangle(hdc, 0, 0, 100, 200);
249 med->tymed = TYMED_MFPICT;
250 U(med)->hMetaFilePict = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT));
251 mf = GlobalLock(U(med)->hMetaFilePict);
252 mf->mm = MM_ANISOTROPIC;
253 mf->xExt = 100;
254 mf->yExt = 200;
255 mf->hMF = CloseMetaFile(hdc);
256 GlobalUnlock(U(med)->hMetaFilePict);
257 med->pUnkForRelease = NULL;
260 static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, void **ppv)
262 CHECK_EXPECTED_METHOD("OleObject_QueryInterface");
264 *ppv = NULL;
266 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IOleObject))
267 *ppv = iface;
268 else if (IsEqualIID(riid, &IID_IPersistStorage))
269 *ppv = &OleObjectPersistStg;
270 else if (IsEqualIID(riid, &IID_IOleCache))
271 *ppv = cache;
272 else if (IsEqualIID(riid, &IID_IRunnableObject) && g_showRunnable)
273 *ppv = runnable;
274 else if (IsEqualIID(riid, &IID_WineTest))
275 return g_QIFailsWith;
277 if(*ppv) {
278 IUnknown_AddRef((IUnknown*)*ppv);
279 return S_OK;
282 trace("OleObject_QueryInterface: returning E_NOINTERFACE\n");
283 return E_NOINTERFACE;
286 static ULONG WINAPI OleObject_AddRef(IOleObject *iface)
288 CHECK_EXPECTED_METHOD("OleObject_AddRef");
289 return 2;
292 static ULONG WINAPI OleObject_Release(IOleObject *iface)
294 CHECK_EXPECTED_METHOD("OleObject_Release");
295 return 1;
298 static HRESULT WINAPI OleObject_SetClientSite
300 IOleObject *iface,
301 IOleClientSite *pClientSite
304 CHECK_EXPECTED_METHOD("OleObject_SetClientSite");
305 return S_OK;
308 static HRESULT WINAPI OleObject_GetClientSite
310 IOleObject *iface,
311 IOleClientSite **ppClientSite
314 CHECK_EXPECTED_METHOD("OleObject_GetClientSite");
315 return E_NOTIMPL;
318 static HRESULT WINAPI OleObject_SetHostNames
320 IOleObject *iface,
321 LPCOLESTR szContainerApp,
322 LPCOLESTR szContainerObj
325 CHECK_EXPECTED_METHOD("OleObject_SetHostNames");
326 return S_OK;
329 static HRESULT WINAPI OleObject_Close
331 IOleObject *iface,
332 DWORD dwSaveOption
335 CHECK_EXPECTED_METHOD("OleObject_Close");
336 return S_OK;
339 static HRESULT WINAPI OleObject_SetMoniker
341 IOleObject *iface,
342 DWORD dwWhichMoniker,
343 IMoniker *pmk
346 CHECK_EXPECTED_METHOD("OleObject_SetMoniker");
347 return S_OK;
350 static HRESULT WINAPI OleObject_GetMoniker
352 IOleObject *iface,
353 DWORD dwAssign,
354 DWORD dwWhichMoniker,
355 IMoniker **ppmk
358 CHECK_EXPECTED_METHOD("OleObject_GetMoniker");
359 return S_OK;
362 static HRESULT WINAPI OleObject_InitFromData
364 IOleObject *iface,
365 IDataObject *pDataObject,
366 BOOL fCreation,
367 DWORD dwReserved
370 CHECK_EXPECTED_METHOD("OleObject_InitFromData");
371 return S_OK;
374 static HRESULT WINAPI OleObject_GetClipboardData
376 IOleObject *iface,
377 DWORD dwReserved,
378 IDataObject **ppDataObject
381 CHECK_EXPECTED_METHOD("OleObject_GetClipboardData");
382 return E_NOTIMPL;
385 static HRESULT WINAPI OleObject_DoVerb
387 IOleObject *iface,
388 LONG iVerb,
389 LPMSG lpmsg,
390 IOleClientSite *pActiveSite,
391 LONG lindex,
392 HWND hwndParent,
393 LPCRECT lprcPosRect
396 CHECK_EXPECTED_METHOD("OleObject_DoVerb");
397 return S_OK;
400 static HRESULT WINAPI OleObject_EnumVerbs
402 IOleObject *iface,
403 IEnumOLEVERB **ppEnumOleVerb
406 CHECK_EXPECTED_METHOD("OleObject_EnumVerbs");
407 return E_NOTIMPL;
410 static HRESULT WINAPI OleObject_Update
412 IOleObject *iface
415 CHECK_EXPECTED_METHOD("OleObject_Update");
416 return S_OK;
419 static HRESULT WINAPI OleObject_IsUpToDate
421 IOleObject *iface
424 CHECK_EXPECTED_METHOD("OleObject_IsUpToDate");
425 return S_OK;
428 static HRESULT WINAPI OleObject_GetUserClassID
430 IOleObject *iface,
431 CLSID *pClsid
434 CHECK_EXPECTED_METHOD("OleObject_GetUserClassID");
435 return E_NOTIMPL;
438 static HRESULT WINAPI OleObject_GetUserType
440 IOleObject *iface,
441 DWORD dwFormOfType,
442 LPOLESTR *pszUserType
445 CHECK_EXPECTED_METHOD("OleObject_GetUserType");
446 return E_NOTIMPL;
449 static HRESULT WINAPI OleObject_SetExtent
451 IOleObject *iface,
452 DWORD dwDrawAspect,
453 SIZEL *psizel
456 CHECK_EXPECTED_METHOD("OleObject_SetExtent");
457 return S_OK;
460 static HRESULT WINAPI OleObject_GetExtent
462 IOleObject *iface,
463 DWORD dwDrawAspect,
464 SIZEL *psizel
467 CHECK_EXPECTED_METHOD("OleObject_GetExtent");
468 return E_NOTIMPL;
471 static HRESULT WINAPI OleObject_Advise
473 IOleObject *iface,
474 IAdviseSink *pAdvSink,
475 DWORD *pdwConnection
478 CHECK_EXPECTED_METHOD("OleObject_Advise");
479 return S_OK;
482 static HRESULT WINAPI OleObject_Unadvise
484 IOleObject *iface,
485 DWORD dwConnection
488 CHECK_EXPECTED_METHOD("OleObject_Unadvise");
489 return S_OK;
492 static HRESULT WINAPI OleObject_EnumAdvise
494 IOleObject *iface,
495 IEnumSTATDATA **ppenumAdvise
498 CHECK_EXPECTED_METHOD("OleObject_EnumAdvise");
499 return E_NOTIMPL;
502 static HRESULT WINAPI OleObject_GetMiscStatus
504 IOleObject *iface,
505 DWORD aspect,
506 DWORD *pdwStatus
509 CHECK_EXPECTED_METHOD("OleObject_GetMiscStatus");
511 ok(aspect == DVASPECT_CONTENT, "got aspect %d\n", aspect);
513 if (g_GetMiscStatusFailsWith == S_OK)
515 *pdwStatus = OLEMISC_RECOMPOSEONRESIZE;
516 return S_OK;
518 else
520 *pdwStatus = 0x1234;
521 return g_GetMiscStatusFailsWith;
525 static HRESULT WINAPI OleObject_SetColorScheme
527 IOleObject *iface,
528 LOGPALETTE *pLogpal
531 CHECK_EXPECTED_METHOD("OleObject_SetColorScheme");
532 return E_NOTIMPL;
535 static const IOleObjectVtbl OleObjectVtbl =
537 OleObject_QueryInterface,
538 OleObject_AddRef,
539 OleObject_Release,
540 OleObject_SetClientSite,
541 OleObject_GetClientSite,
542 OleObject_SetHostNames,
543 OleObject_Close,
544 OleObject_SetMoniker,
545 OleObject_GetMoniker,
546 OleObject_InitFromData,
547 OleObject_GetClipboardData,
548 OleObject_DoVerb,
549 OleObject_EnumVerbs,
550 OleObject_Update,
551 OleObject_IsUpToDate,
552 OleObject_GetUserClassID,
553 OleObject_GetUserType,
554 OleObject_SetExtent,
555 OleObject_GetExtent,
556 OleObject_Advise,
557 OleObject_Unadvise,
558 OleObject_EnumAdvise,
559 OleObject_GetMiscStatus,
560 OleObject_SetColorScheme
563 static IOleObject OleObject = { &OleObjectVtbl };
565 static HRESULT WINAPI OleObjectPersistStg_QueryInterface(IPersistStorage *iface, REFIID riid, void **ppv)
567 trace("OleObjectPersistStg_QueryInterface\n");
568 return IOleObject_QueryInterface(&OleObject, riid, ppv);
571 static ULONG WINAPI OleObjectPersistStg_AddRef(IPersistStorage *iface)
573 CHECK_EXPECTED_METHOD("OleObjectPersistStg_AddRef");
574 return 2;
577 static ULONG WINAPI OleObjectPersistStg_Release(IPersistStorage *iface)
579 CHECK_EXPECTED_METHOD("OleObjectPersistStg_Release");
580 return 1;
583 static HRESULT WINAPI OleObjectPersistStg_GetClassId(IPersistStorage *iface, CLSID *clsid)
585 CHECK_EXPECTED_METHOD("OleObjectPersistStg_GetClassId");
586 return E_NOTIMPL;
589 static HRESULT WINAPI OleObjectPersistStg_IsDirty
591 IPersistStorage *iface
594 CHECK_EXPECTED_METHOD("OleObjectPersistStg_IsDirty");
595 return S_OK;
598 static HRESULT WINAPI OleObjectPersistStg_InitNew
600 IPersistStorage *iface,
601 IStorage *pStg
604 CHECK_EXPECTED_METHOD("OleObjectPersistStg_InitNew");
605 return S_OK;
608 static HRESULT WINAPI OleObjectPersistStg_Load
610 IPersistStorage *iface,
611 IStorage *pStg
614 CHECK_EXPECTED_METHOD("OleObjectPersistStg_Load");
615 return S_OK;
618 static HRESULT WINAPI OleObjectPersistStg_Save
620 IPersistStorage *iface,
621 IStorage *pStgSave,
622 BOOL fSameAsLoad
625 CHECK_EXPECTED_METHOD("OleObjectPersistStg_Save");
626 return S_OK;
629 static HRESULT WINAPI OleObjectPersistStg_SaveCompleted
631 IPersistStorage *iface,
632 IStorage *pStgNew
635 CHECK_EXPECTED_METHOD("OleObjectPersistStg_SaveCompleted");
636 return S_OK;
639 static HRESULT WINAPI OleObjectPersistStg_HandsOffStorage
641 IPersistStorage *iface
644 CHECK_EXPECTED_METHOD("OleObjectPersistStg_HandsOffStorage");
645 return S_OK;
648 static const IPersistStorageVtbl OleObjectPersistStgVtbl =
650 OleObjectPersistStg_QueryInterface,
651 OleObjectPersistStg_AddRef,
652 OleObjectPersistStg_Release,
653 OleObjectPersistStg_GetClassId,
654 OleObjectPersistStg_IsDirty,
655 OleObjectPersistStg_InitNew,
656 OleObjectPersistStg_Load,
657 OleObjectPersistStg_Save,
658 OleObjectPersistStg_SaveCompleted,
659 OleObjectPersistStg_HandsOffStorage
662 static IPersistStorage OleObjectPersistStg = { &OleObjectPersistStgVtbl };
664 static HRESULT WINAPI OleObjectCache_QueryInterface(IOleCache *iface, REFIID riid, void **ppv)
666 return IOleObject_QueryInterface(&OleObject, riid, ppv);
669 static ULONG WINAPI OleObjectCache_AddRef(IOleCache *iface)
671 CHECK_EXPECTED_METHOD("OleObjectCache_AddRef");
672 return 2;
675 static ULONG WINAPI OleObjectCache_Release(IOleCache *iface)
677 CHECK_EXPECTED_METHOD("OleObjectCache_Release");
678 return 1;
681 static HRESULT WINAPI OleObjectCache_Cache
683 IOleCache *iface,
684 FORMATETC *pformatetc,
685 DWORD advf,
686 DWORD *pdwConnection
689 CHECK_EXPECTED_METHOD("OleObjectCache_Cache");
690 if (g_expected_fetc) {
691 ok(pformatetc != NULL, "pformatetc should not be NULL\n");
692 if (pformatetc) {
693 ok(pformatetc->cfFormat == g_expected_fetc->cfFormat,
694 "cfFormat: %x\n", pformatetc->cfFormat);
695 ok((pformatetc->ptd != NULL) == (g_expected_fetc->ptd != NULL),
696 "ptd: %p\n", pformatetc->ptd);
697 ok(pformatetc->dwAspect == g_expected_fetc->dwAspect,
698 "dwAspect: %x\n", pformatetc->dwAspect);
699 ok(pformatetc->lindex == g_expected_fetc->lindex,
700 "lindex: %x\n", pformatetc->lindex);
701 ok(pformatetc->tymed == g_expected_fetc->tymed,
702 "tymed: %x\n", pformatetc->tymed);
704 } else
705 ok(pformatetc == NULL, "pformatetc should be NULL\n");
706 return S_OK;
709 static HRESULT WINAPI OleObjectCache_Uncache
711 IOleCache *iface,
712 DWORD dwConnection
715 CHECK_EXPECTED_METHOD("OleObjectCache_Uncache");
716 return S_OK;
719 static HRESULT WINAPI OleObjectCache_EnumCache
721 IOleCache *iface,
722 IEnumSTATDATA **ppenumSTATDATA
725 CHECK_EXPECTED_METHOD("OleObjectCache_EnumCache");
726 return S_OK;
730 static HRESULT WINAPI OleObjectCache_InitCache
732 IOleCache *iface,
733 IDataObject *pDataObject
736 CHECK_EXPECTED_METHOD("OleObjectCache_InitCache");
737 return S_OK;
741 static HRESULT WINAPI OleObjectCache_SetData
743 IOleCache *iface,
744 FORMATETC *pformatetc,
745 STGMEDIUM *pmedium,
746 BOOL fRelease
749 CHECK_EXPECTED_METHOD("OleObjectCache_SetData");
750 return S_OK;
754 static const IOleCacheVtbl OleObjectCacheVtbl =
756 OleObjectCache_QueryInterface,
757 OleObjectCache_AddRef,
758 OleObjectCache_Release,
759 OleObjectCache_Cache,
760 OleObjectCache_Uncache,
761 OleObjectCache_EnumCache,
762 OleObjectCache_InitCache,
763 OleObjectCache_SetData
766 static IOleCache OleObjectCache = { &OleObjectCacheVtbl };
768 static HRESULT WINAPI OleObjectCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
770 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
772 *ppv = iface;
773 IClassFactory_AddRef(iface);
774 return S_OK;
776 *ppv = NULL;
777 return E_NOINTERFACE;
780 static ULONG WINAPI OleObjectCF_AddRef(IClassFactory *iface)
782 return 2;
785 static ULONG WINAPI OleObjectCF_Release(IClassFactory *iface)
787 return 1;
790 static HRESULT WINAPI OleObjectCF_CreateInstance(IClassFactory *iface, IUnknown *punkOuter, REFIID riid, void **ppv)
792 return IOleObject_QueryInterface(&OleObject, riid, ppv);
795 static HRESULT WINAPI OleObjectCF_LockServer(IClassFactory *iface, BOOL lock)
797 return S_OK;
800 static const IClassFactoryVtbl OleObjectCFVtbl =
802 OleObjectCF_QueryInterface,
803 OleObjectCF_AddRef,
804 OleObjectCF_Release,
805 OleObjectCF_CreateInstance,
806 OleObjectCF_LockServer
809 static IClassFactory OleObjectCF = { &OleObjectCFVtbl };
811 static HRESULT WINAPI OleObjectRunnable_QueryInterface(IRunnableObject *iface, REFIID riid, void **ppv)
813 return IOleObject_QueryInterface(&OleObject, riid, ppv);
816 static ULONG WINAPI OleObjectRunnable_AddRef(IRunnableObject *iface)
818 CHECK_EXPECTED_METHOD("OleObjectRunnable_AddRef");
819 return 2;
822 static ULONG WINAPI OleObjectRunnable_Release(IRunnableObject *iface)
824 CHECK_EXPECTED_METHOD("OleObjectRunnable_Release");
825 return 1;
828 static HRESULT WINAPI OleObjectRunnable_GetRunningClass(
829 IRunnableObject *iface,
830 LPCLSID lpClsid)
832 CHECK_EXPECTED_METHOD("OleObjectRunnable_GetRunningClass");
833 return E_NOTIMPL;
836 static HRESULT WINAPI OleObjectRunnable_Run(
837 IRunnableObject *iface,
838 LPBINDCTX pbc)
840 CHECK_EXPECTED_METHOD("OleObjectRunnable_Run");
841 return S_OK;
844 static BOOL WINAPI OleObjectRunnable_IsRunning(IRunnableObject *iface)
846 CHECK_EXPECTED_METHOD("OleObjectRunnable_IsRunning");
847 return g_isRunning;
850 static HRESULT WINAPI OleObjectRunnable_LockRunning(
851 IRunnableObject *iface,
852 BOOL fLock,
853 BOOL fLastUnlockCloses)
855 CHECK_EXPECTED_METHOD("OleObjectRunnable_LockRunning");
856 return S_OK;
859 static HRESULT WINAPI OleObjectRunnable_SetContainedObject(
860 IRunnableObject *iface,
861 BOOL fContained)
863 CHECK_EXPECTED_METHOD("OleObjectRunnable_SetContainedObject");
864 return S_OK;
867 static const IRunnableObjectVtbl OleObjectRunnableVtbl =
869 OleObjectRunnable_QueryInterface,
870 OleObjectRunnable_AddRef,
871 OleObjectRunnable_Release,
872 OleObjectRunnable_GetRunningClass,
873 OleObjectRunnable_Run,
874 OleObjectRunnable_IsRunning,
875 OleObjectRunnable_LockRunning,
876 OleObjectRunnable_SetContainedObject
879 static IRunnableObject OleObjectRunnable = { &OleObjectRunnableVtbl };
881 static const CLSID CLSID_Equation3 = {0x0002CE02, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
883 static HRESULT WINAPI viewobject_QueryInterface(IViewObject *iface, REFIID riid, void **obj)
885 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IViewObject))
887 *obj = iface;
888 return S_OK;
891 *obj = NULL;
892 return E_NOINTERFACE;
895 static ULONG WINAPI viewobject_AddRef(IViewObject *iface)
897 return 2;
900 static ULONG WINAPI viewobject_Release(IViewObject *iface)
902 return 1;
905 static HRESULT WINAPI viewobject_Draw(IViewObject *iface, DWORD aspect, LONG index,
906 void *paspect, DVTARGETDEVICE *ptd, HDC hdcTargetDev, HDC hdcDraw,
907 LPCRECTL bounds, LPCRECTL wbounds, BOOL (STDMETHODCALLTYPE *pfnContinue)(ULONG_PTR dwContinue),
908 ULONG_PTR dwContinue)
910 ok(index == -1, "index=%d\n", index);
911 return S_OK;
914 static HRESULT WINAPI viewobject_GetColorSet(IViewObject *iface, DWORD draw_aspect, LONG index,
915 void *aspect, DVTARGETDEVICE *ptd, HDC hicTargetDev, LOGPALETTE **colorset)
917 ok(0, "unexpected call GetColorSet\n");
918 return E_NOTIMPL;
921 static HRESULT WINAPI viewobject_Freeze(IViewObject *iface, DWORD draw_aspect, LONG index,
922 void *aspect, DWORD *freeze)
924 ok(0, "unexpected call Freeze\n");
925 return E_NOTIMPL;
928 static HRESULT WINAPI viewobject_Unfreeze(IViewObject *iface, DWORD freeze)
930 ok(0, "unexpected call Unfreeze\n");
931 return E_NOTIMPL;
934 static HRESULT WINAPI viewobject_SetAdvise(IViewObject *iface, DWORD aspects, DWORD advf, IAdviseSink *sink)
936 ok(0, "unexpected call SetAdvise\n");
937 return E_NOTIMPL;
940 static HRESULT WINAPI viewobject_GetAdvise(IViewObject *iface, DWORD *aspects, DWORD *advf,
941 IAdviseSink **sink)
943 ok(0, "unexpected call GetAdvise\n");
944 return E_NOTIMPL;
947 static const struct IViewObjectVtbl viewobjectvtbl = {
948 viewobject_QueryInterface,
949 viewobject_AddRef,
950 viewobject_Release,
951 viewobject_Draw,
952 viewobject_GetColorSet,
953 viewobject_Freeze,
954 viewobject_Unfreeze,
955 viewobject_SetAdvise,
956 viewobject_GetAdvise
959 static IViewObject viewobject = { &viewobjectvtbl };
961 static void test_OleCreate(IStorage *pStorage)
963 HRESULT hr;
964 IOleObject *pObject;
965 FORMATETC formatetc;
966 static const struct expected_method methods_olerender_none[] =
968 { "OleObject_QueryInterface", 0 },
969 { "OleObject_AddRef", 0 },
970 { "OleObject_QueryInterface", 0 },
971 { "OleObject_AddRef", TEST_OPTIONAL },
972 { "OleObject_Release", TEST_OPTIONAL },
973 { "OleObject_QueryInterface", TEST_OPTIONAL },
974 { "OleObjectPersistStg_AddRef", 0 },
975 { "OleObjectPersistStg_InitNew", 0 },
976 { "OleObjectPersistStg_Release", 0 },
977 { "OleObject_Release", 0 },
978 { "OleObject_Release", TEST_OPTIONAL },
979 { NULL, 0 }
981 static const struct expected_method methods_olerender_draw[] =
983 { "OleObject_QueryInterface", 0 },
984 { "OleObject_AddRef", 0 },
985 { "OleObject_QueryInterface", 0 },
986 { "OleObject_AddRef", TEST_OPTIONAL /* NT4 only */ },
987 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
988 { "OleObject_QueryInterface", TEST_OPTIONAL /* NT4 only */ },
989 { "OleObjectPersistStg_AddRef", 0 },
990 { "OleObjectPersistStg_InitNew", 0 },
991 { "OleObjectPersistStg_Release", 0 },
992 { "OleObject_QueryInterface", 0 },
993 { "OleObjectRunnable_AddRef", 0 },
994 { "OleObjectRunnable_Run", 0 },
995 { "OleObjectRunnable_Release", 0 },
996 { "OleObject_QueryInterface", 0 },
997 { "OleObjectCache_AddRef", 0 },
998 { "OleObjectCache_Cache", 0 },
999 { "OleObjectCache_Release", 0 },
1000 { "OleObject_Release", 0 },
1001 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1002 { NULL, 0 }
1004 static const struct expected_method methods_olerender_draw_with_site[] =
1006 { "OleObject_QueryInterface", 0 },
1007 { "OleObject_AddRef", 0 },
1008 { "OleObject_QueryInterface", 0 },
1009 { "OleObject_AddRef", 0 },
1010 { "OleObject_GetMiscStatus", 0 },
1011 { "OleObject_QueryInterface", 0 },
1012 { "OleObjectPersistStg_AddRef", 0 },
1013 { "OleObjectPersistStg_InitNew", 0 },
1014 { "OleObjectPersistStg_Release", 0 },
1015 { "OleObject_SetClientSite", 0 },
1016 { "OleObject_Release", 0 },
1017 { "OleObject_QueryInterface", 0 },
1018 { "OleObjectRunnable_AddRef", 0 },
1019 { "OleObjectRunnable_Run", 0 },
1020 { "OleObjectRunnable_Release", 0 },
1021 { "OleObject_QueryInterface", 0 },
1022 { "OleObjectCache_AddRef", 0 },
1023 { "OleObjectCache_Cache", 0 },
1024 { "OleObjectCache_Release", 0 },
1025 { "OleObject_Release", 0 },
1026 { NULL, 0 }
1028 static const struct expected_method methods_olerender_format[] =
1030 { "OleObject_QueryInterface", 0 },
1031 { "OleObject_AddRef", 0 },
1032 { "OleObject_QueryInterface", 0 },
1033 { "OleObject_AddRef", 0 },
1034 { "OleObject_GetMiscStatus", 0 },
1035 { "OleObject_QueryInterface", 0 },
1036 { "OleObjectPersistStg_AddRef", 0 },
1037 { "OleObjectPersistStg_InitNew", 0 },
1038 { "OleObjectPersistStg_Release", 0 },
1039 { "OleObject_SetClientSite", 0 },
1040 { "OleObject_Release", 0 },
1041 { "OleObject_QueryInterface", 0 },
1042 { "OleObjectRunnable_AddRef", 0 },
1043 { "OleObjectRunnable_Run", 0 },
1044 { "OleObjectRunnable_Release", 0 },
1045 { "OleObject_QueryInterface", 0 },
1046 { "OleObjectCache_AddRef", 0 },
1047 { "OleObjectCache_Cache", 0 },
1048 { "OleObjectCache_Release", 0 },
1049 { "OleObject_Release", 0 },
1050 { NULL, 0 }
1052 static const struct expected_method methods_olerender_asis[] =
1054 { "OleObject_QueryInterface", 0 },
1055 { "OleObject_AddRef", 0 },
1056 { "OleObject_QueryInterface", 0 },
1057 { "OleObject_AddRef", TEST_OPTIONAL /* NT4 only */ },
1058 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1059 { "OleObject_QueryInterface", TEST_OPTIONAL /* NT4 only */ },
1060 { "OleObjectPersistStg_AddRef", 0 },
1061 { "OleObjectPersistStg_InitNew", 0 },
1062 { "OleObjectPersistStg_Release", 0 },
1063 { "OleObject_Release", 0 },
1064 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1065 { NULL, 0 }
1067 static const struct expected_method methods_olerender_draw_no_runnable[] =
1069 { "OleObject_QueryInterface", 0 },
1070 { "OleObject_AddRef", 0 },
1071 { "OleObject_QueryInterface", 0 },
1072 { "OleObject_AddRef", TEST_OPTIONAL /* NT4 only */ },
1073 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1074 { "OleObject_QueryInterface", TEST_OPTIONAL /* NT4 only */ },
1075 { "OleObjectPersistStg_AddRef", 0 },
1076 { "OleObjectPersistStg_InitNew", 0 },
1077 { "OleObjectPersistStg_Release", 0 },
1078 { "OleObject_QueryInterface", 0 },
1079 { "OleObject_QueryInterface", 0 },
1080 { "OleObjectCache_AddRef", 0 },
1081 { "OleObjectCache_Cache", 0 },
1082 { "OleObjectCache_Release", 0 },
1083 { "OleObject_Release", 0 },
1084 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1085 { NULL, 0 },
1087 static const struct expected_method methods_olerender_draw_no_cache[] =
1089 { "OleObject_QueryInterface", 0 },
1090 { "OleObject_AddRef", 0 },
1091 { "OleObject_QueryInterface", 0 },
1092 { "OleObject_AddRef", TEST_OPTIONAL /* NT4 only */ },
1093 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1094 { "OleObject_QueryInterface", TEST_OPTIONAL /* NT4 only */ },
1095 { "OleObjectPersistStg_AddRef", 0 },
1096 { "OleObjectPersistStg_InitNew", 0 },
1097 { "OleObjectPersistStg_Release", 0 },
1098 { "OleObject_QueryInterface", 0 },
1099 { "OleObjectRunnable_AddRef", 0 },
1100 { "OleObjectRunnable_Run", 0 },
1101 { "OleObjectRunnable_Release", 0 },
1102 { "OleObject_QueryInterface", 0 },
1103 { "OleObject_Release", 0 },
1104 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1105 { NULL, 0 }
1108 g_expected_fetc = &formatetc;
1109 formatetc.cfFormat = 0;
1110 formatetc.ptd = NULL;
1111 formatetc.dwAspect = DVASPECT_CONTENT;
1112 formatetc.lindex = -1;
1113 formatetc.tymed = TYMED_NULL;
1114 runnable = &OleObjectRunnable;
1115 cache = &OleObjectCache;
1116 expected_method_list = methods_olerender_none;
1117 trace("OleCreate with OLERENDER_NONE:\n");
1118 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_NONE, NULL, NULL, pStorage, (void **)&pObject);
1119 ok_ole_success(hr, "OleCreate");
1120 IOleObject_Release(pObject);
1121 CHECK_NO_EXTRA_METHODS();
1123 expected_method_list = methods_olerender_draw;
1124 trace("OleCreate with OLERENDER_DRAW:\n");
1125 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, NULL, pStorage, (void **)&pObject);
1126 ok_ole_success(hr, "OleCreate");
1127 IOleObject_Release(pObject);
1128 CHECK_NO_EXTRA_METHODS();
1130 expected_method_list = methods_olerender_draw_with_site;
1131 trace("OleCreate with OLERENDER_DRAW, with site:\n");
1132 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, (IOleClientSite*)0xdeadbeef, pStorage, (void **)&pObject);
1133 ok_ole_success(hr, "OleCreate");
1134 IOleObject_Release(pObject);
1135 CHECK_NO_EXTRA_METHODS();
1137 /* GetMiscStatus fails */
1138 g_GetMiscStatusFailsWith = 0x8fafefaf;
1139 expected_method_list = methods_olerender_draw_with_site;
1140 trace("OleCreate with OLERENDER_DRAW, with site:\n");
1141 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, (IOleClientSite*)0xdeadbeef, pStorage, (void **)&pObject);
1142 ok_ole_success(hr, "OleCreate");
1143 IOleObject_Release(pObject);
1144 CHECK_NO_EXTRA_METHODS();
1145 g_GetMiscStatusFailsWith = S_OK;
1147 formatetc.cfFormat = CF_TEXT;
1148 formatetc.ptd = NULL;
1149 formatetc.dwAspect = DVASPECT_CONTENT;
1150 formatetc.lindex = -1;
1151 formatetc.tymed = TYMED_HGLOBAL;
1152 expected_method_list = methods_olerender_format;
1153 trace("OleCreate with OLERENDER_FORMAT:\n");
1154 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_FORMAT, &formatetc, (IOleClientSite *)0xdeadbeef, pStorage, (void **)&pObject);
1155 ok(hr == S_OK ||
1156 broken(hr == E_INVALIDARG), /* win2k */
1157 "OleCreate failed with error 0x%08x\n", hr);
1158 if (pObject)
1160 IOleObject_Release(pObject);
1161 CHECK_NO_EXTRA_METHODS();
1164 expected_method_list = methods_olerender_asis;
1165 trace("OleCreate with OLERENDER_ASIS:\n");
1166 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_ASIS, NULL, NULL, pStorage, (void **)&pObject);
1167 ok_ole_success(hr, "OleCreate");
1168 IOleObject_Release(pObject);
1169 CHECK_NO_EXTRA_METHODS();
1171 formatetc.cfFormat = 0;
1172 formatetc.tymed = TYMED_NULL;
1173 runnable = NULL;
1174 expected_method_list = methods_olerender_draw_no_runnable;
1175 trace("OleCreate with OLERENDER_DRAW (no IRunnableObject):\n");
1176 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, NULL, pStorage, (void **)&pObject);
1177 ok_ole_success(hr, "OleCreate");
1178 IOleObject_Release(pObject);
1179 CHECK_NO_EXTRA_METHODS();
1181 runnable = &OleObjectRunnable;
1182 cache = NULL;
1183 expected_method_list = methods_olerender_draw_no_cache;
1184 trace("OleCreate with OLERENDER_DRAW (no IOleCache):\n");
1185 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, NULL, pStorage, (void **)&pObject);
1186 ok_ole_success(hr, "OleCreate");
1187 IOleObject_Release(pObject);
1188 CHECK_NO_EXTRA_METHODS();
1189 trace("end\n");
1190 g_expected_fetc = NULL;
1193 static void test_OleLoad(IStorage *pStorage)
1195 HRESULT hr;
1196 IOleObject *pObject;
1197 DWORD fmt;
1199 static const struct expected_method methods_oleload[] =
1201 { "OleObject_QueryInterface", 0 },
1202 { "OleObject_AddRef", 0 },
1203 { "OleObject_QueryInterface", 0 },
1204 { "OleObject_AddRef", 0 },
1205 { "OleObject_GetMiscStatus", 0 },
1206 { "OleObject_QueryInterface", 0 },
1207 { "OleObjectPersistStg_AddRef", 0 },
1208 { "OleObjectPersistStg_Load", 0 },
1209 { "OleObjectPersistStg_Release", 0 },
1210 { "OleObject_SetClientSite", 0 },
1211 { "OleObject_Release", 0 },
1212 { "OleObject_QueryInterface", 0 },
1213 { "OleObject_GetMiscStatus", 0 },
1214 { "OleObject_Release", 0 },
1215 { NULL, 0 }
1218 /* Test once with IOleObject_GetMiscStatus failing */
1219 expected_method_list = methods_oleload;
1220 g_GetMiscStatusFailsWith = E_FAIL;
1221 trace("OleLoad:\n");
1222 hr = OleLoad(pStorage, &IID_IOleObject, (IOleClientSite *)0xdeadbeef, (void **)&pObject);
1223 ok(hr == S_OK ||
1224 broken(hr == E_INVALIDARG), /* win98 and win2k */
1225 "OleLoad failed with error 0x%08x\n", hr);
1226 if(pObject)
1228 DWORD dwStatus = 0xdeadbeef;
1229 hr = IOleObject_GetMiscStatus(pObject, DVASPECT_CONTENT, &dwStatus);
1230 ok(hr == E_FAIL, "Got 0x%08x\n", hr);
1231 ok(dwStatus == 0x1234, "Got 0x%08x\n", dwStatus);
1233 IOleObject_Release(pObject);
1234 CHECK_NO_EXTRA_METHODS();
1236 g_GetMiscStatusFailsWith = S_OK;
1238 /* Test again, let IOleObject_GetMiscStatus succeed. */
1239 expected_method_list = methods_oleload;
1240 trace("OleLoad:\n");
1241 hr = OleLoad(pStorage, &IID_IOleObject, (IOleClientSite *)0xdeadbeef, (void **)&pObject);
1242 ok(hr == S_OK ||
1243 broken(hr == E_INVALIDARG), /* win98 and win2k */
1244 "OleLoad failed with error 0x%08x\n", hr);
1245 if (pObject)
1247 DWORD dwStatus = 0xdeadbeef;
1248 hr = IOleObject_GetMiscStatus(pObject, DVASPECT_CONTENT, &dwStatus);
1249 ok(hr == S_OK, "Got 0x%08x\n", hr);
1250 ok(dwStatus == 1, "Got 0x%08x\n", dwStatus);
1252 IOleObject_Release(pObject);
1253 CHECK_NO_EXTRA_METHODS();
1256 for (fmt = CF_TEXT; fmt < CF_MAX; fmt++)
1258 static const WCHAR olrepres[] = { 2,'O','l','e','P','r','e','s','0','0','0',0 };
1259 IStorage *stg;
1260 IStream *stream;
1261 IUnknown *obj;
1262 DWORD data, i, data_size;
1263 PresentationDataHeader header;
1264 HDC hdc;
1265 HGDIOBJ hobj;
1266 RECT rc;
1267 char buf[256];
1269 for (i = 0; i < 7; i++)
1271 hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &stg);
1272 ok(hr == S_OK, "StgCreateDocfile error %#x\n", hr);
1274 hr = IStorage_SetClass(stg, &CLSID_WineTest);
1275 ok(hr == S_OK, "SetClass error %#x\n", hr);
1277 hr = IStorage_CreateStream(stg, olrepres, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, &stream);
1278 ok(hr == S_OK, "CreateStream error %#x\n", hr);
1280 data = ~0;
1281 hr = IStream_Write(stream, &data, sizeof(data), NULL);
1282 ok(hr == S_OK, "Write error %#x\n", hr);
1284 data = fmt;
1285 hr = IStream_Write(stream, &data, sizeof(data), NULL);
1286 ok(hr == S_OK, "Write error %#x\n", hr);
1288 switch (fmt)
1290 case CF_BITMAP:
1291 /* FIXME: figure out stream format */
1292 hobj = CreateBitmap(1, 1, 1, 1, NULL);
1293 data_size = GetBitmapBits(hobj, sizeof(buf), buf);
1294 DeleteObject(hobj);
1295 break;
1297 case CF_METAFILEPICT:
1298 case CF_ENHMETAFILE:
1299 hdc = CreateMetaFileA(NULL);
1300 hobj = CloseMetaFile(hdc);
1301 data_size = GetMetaFileBitsEx(hobj, sizeof(buf), buf);
1302 DeleteMetaFile(hobj);
1303 break;
1305 default:
1306 data_size = sizeof(buf);
1307 memset(buf, 'A', sizeof(buf));
1308 break;
1311 header.tdSize = sizeof(header.tdSize);
1312 header.dvAspect = DVASPECT_CONTENT;
1313 header.lindex = -1;
1314 header.advf = 1 << i;
1315 header.unknown7 = 0;
1316 header.dwObjectExtentX = 1;
1317 header.dwObjectExtentY = 1;
1318 header.dwSize = data_size;
1319 hr = IStream_Write(stream, &header, sizeof(header), NULL);
1320 ok(hr == S_OK, "Write error %#x\n", hr);
1322 hr = IStream_Write(stream, buf, data_size, NULL);
1323 ok(hr == S_OK, "Write error %#x\n", hr);
1325 IStream_Release(stream);
1327 hr = OleLoad(stg, &IID_IUnknown, NULL, (void **)&obj);
1328 /* FIXME: figure out stream format */
1329 if (fmt == CF_BITMAP && hr != S_OK)
1331 IStorage_Release(stg);
1332 continue;
1334 ok(hr == S_OK, "OleLoad error %#x: cfFormat = %u, advf = %#x\n", hr, fmt, header.advf);
1336 hdc = CreateCompatibleDC(0);
1337 SetRect(&rc, 0, 0, 100, 100);
1338 hr = OleDraw(obj, DVASPECT_CONTENT, hdc, &rc);
1339 DeleteDC(hdc);
1340 if (fmt == CF_METAFILEPICT)
1341 ok(hr == S_OK, "OleDraw error %#x: cfFormat = %u, advf = %#x\n", hr, fmt, header.advf);
1342 else if (fmt == CF_ENHMETAFILE)
1343 todo_wine
1344 ok(hr == S_OK, "OleDraw error %#x: cfFormat = %u, advf = %#x\n", hr, fmt, header.advf);
1345 else
1346 ok(hr == OLE_E_BLANK || hr == OLE_E_NOTRUNNING || hr == E_FAIL, "OleDraw should fail: %#x, cfFormat = %u, advf = %#x\n", hr, fmt, header.advf);
1348 IUnknown_Release(obj);
1349 IStorage_Release(stg);
1354 static BOOL STDMETHODCALLTYPE draw_continue(ULONG_PTR param)
1356 CHECK_EXPECTED_METHOD("draw_continue");
1357 return TRUE;
1360 static BOOL STDMETHODCALLTYPE draw_continue_false(ULONG_PTR param)
1362 CHECK_EXPECTED_METHOD("draw_continue_false");
1363 return FALSE;
1366 static HRESULT WINAPI AdviseSink_QueryInterface(IAdviseSink *iface, REFIID riid, void **ppv)
1368 if (IsEqualIID(riid, &IID_IAdviseSink) || IsEqualIID(riid, &IID_IUnknown))
1370 *ppv = iface;
1371 IAdviseSink_AddRef(iface);
1372 return S_OK;
1374 *ppv = NULL;
1375 return E_NOINTERFACE;
1378 static ULONG WINAPI AdviseSink_AddRef(IAdviseSink *iface)
1380 return 2;
1383 static ULONG WINAPI AdviseSink_Release(IAdviseSink *iface)
1385 return 1;
1389 static void WINAPI AdviseSink_OnDataChange(
1390 IAdviseSink *iface,
1391 FORMATETC *pFormatetc,
1392 STGMEDIUM *pStgmed)
1394 CHECK_EXPECTED_METHOD("AdviseSink_OnDataChange");
1397 static void WINAPI AdviseSink_OnViewChange(
1398 IAdviseSink *iface,
1399 DWORD dwAspect,
1400 LONG lindex)
1402 CHECK_EXPECTED_METHOD("AdviseSink_OnViewChange");
1405 static void WINAPI AdviseSink_OnRename(
1406 IAdviseSink *iface,
1407 IMoniker *pmk)
1409 CHECK_EXPECTED_METHOD("AdviseSink_OnRename");
1412 static void WINAPI AdviseSink_OnSave(IAdviseSink *iface)
1414 CHECK_EXPECTED_METHOD("AdviseSink_OnSave");
1417 static void WINAPI AdviseSink_OnClose(IAdviseSink *iface)
1419 CHECK_EXPECTED_METHOD("AdviseSink_OnClose");
1422 static const IAdviseSinkVtbl AdviseSinkVtbl =
1424 AdviseSink_QueryInterface,
1425 AdviseSink_AddRef,
1426 AdviseSink_Release,
1427 AdviseSink_OnDataChange,
1428 AdviseSink_OnViewChange,
1429 AdviseSink_OnRename,
1430 AdviseSink_OnSave,
1431 AdviseSink_OnClose
1434 static IAdviseSink AdviseSink = { &AdviseSinkVtbl };
1436 static HRESULT WINAPI DataObject_QueryInterface(
1437 IDataObject* iface,
1438 REFIID riid,
1439 void** ppvObject)
1441 CHECK_EXPECTED_METHOD("DataObject_QueryInterface");
1443 if (IsEqualIID(riid, &IID_IDataObject) || IsEqualIID(riid, &IID_IUnknown))
1445 *ppvObject = iface;
1446 return S_OK;
1448 *ppvObject = NULL;
1449 return S_OK;
1452 static ULONG WINAPI DataObject_AddRef(
1453 IDataObject* iface)
1455 CHECK_EXPECTED_METHOD("DataObject_AddRef");
1456 return 2;
1459 static ULONG WINAPI DataObject_Release(
1460 IDataObject* iface)
1462 CHECK_EXPECTED_METHOD("DataObject_Release");
1463 return 1;
1466 static inline BOOL fmtetc_equal( const FORMATETC *a, const FORMATETC *b )
1468 /* FIXME ptd */
1469 return a->cfFormat == b->cfFormat && a->dwAspect == b->dwAspect &&
1470 a->lindex == b->lindex && a->tymed == b->tymed;
1474 static HRESULT WINAPI DataObject_GetData( IDataObject *iface, FORMATETC *fmt_in,
1475 STGMEDIUM *med )
1477 FORMATETC *fmt;
1479 CHECK_EXPECTED_METHOD_FMT("DataObject_GetData", fmt_in);
1481 for (fmt = g_dataobject_fmts; fmt && fmt->cfFormat != 0; fmt++)
1483 if (fmtetc_equal( fmt_in, fmt ))
1485 switch (fmt->cfFormat)
1487 case CF_DIB:
1488 create_dib( med );
1489 return S_OK;
1490 case CF_BITMAP:
1491 create_bitmap( med );
1492 return S_OK;
1493 default:
1494 trace( "unhandled fmt %d\n", fmt->cfFormat );
1499 return S_FALSE;
1502 static HRESULT WINAPI DataObject_GetDataHere(
1503 IDataObject* iface,
1504 LPFORMATETC pformatetc,
1505 STGMEDIUM* pmedium)
1507 CHECK_EXPECTED_METHOD("DataObject_GetDataHere");
1508 return E_NOTIMPL;
1511 static HRESULT WINAPI DataObject_QueryGetData( IDataObject *iface, FORMATETC *fmt_in )
1513 FORMATETC *fmt;
1515 CHECK_EXPECTED_METHOD_FMT("DataObject_QueryGetData", fmt_in);
1517 for (fmt = g_dataobject_fmts; fmt && fmt->cfFormat != 0; fmt++)
1518 if (fmtetc_equal( fmt_in, fmt )) return S_OK;
1520 return S_FALSE;
1523 static HRESULT WINAPI DataObject_GetCanonicalFormatEtc(
1524 IDataObject* iface,
1525 LPFORMATETC pformatectIn,
1526 LPFORMATETC pformatetcOut)
1528 CHECK_EXPECTED_METHOD("DataObject_GetCanonicalFormatEtc");
1529 return E_NOTIMPL;
1532 static HRESULT WINAPI DataObject_SetData(
1533 IDataObject* iface,
1534 LPFORMATETC pformatetc,
1535 STGMEDIUM* pmedium,
1536 BOOL fRelease)
1538 CHECK_EXPECTED_METHOD("DataObject_SetData");
1539 return E_NOTIMPL;
1542 static HRESULT WINAPI DataObject_EnumFormatEtc(
1543 IDataObject* iface,
1544 DWORD dwDirection,
1545 IEnumFORMATETC** ppenumFormatEtc)
1547 CHECK_EXPECTED_METHOD("DataObject_EnumFormatEtc");
1548 return E_NOTIMPL;
1551 static HRESULT WINAPI DataObject_DAdvise(
1552 IDataObject* iface,
1553 FORMATETC* pformatetc,
1554 DWORD advf,
1555 IAdviseSink* pAdvSink,
1556 DWORD* pdwConnection)
1558 STGMEDIUM stgmedium;
1560 CHECK_EXPECTED_METHOD("DataObject_DAdvise");
1561 *pdwConnection = 1;
1563 if(advf & ADVF_PRIMEFIRST)
1565 ok(pformatetc->cfFormat == cf_test_2, "got %04x\n", pformatetc->cfFormat);
1566 stgmedium.tymed = TYMED_HGLOBAL;
1567 U(stgmedium).hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 4);
1568 stgmedium.pUnkForRelease = NULL;
1569 IAdviseSink_OnDataChange(pAdvSink, pformatetc, &stgmedium);
1572 return S_OK;
1575 static HRESULT WINAPI DataObject_DUnadvise(
1576 IDataObject* iface,
1577 DWORD dwConnection)
1579 CHECK_EXPECTED_METHOD("DataObject_DUnadvise");
1580 return S_OK;
1583 static HRESULT WINAPI DataObject_EnumDAdvise(
1584 IDataObject* iface,
1585 IEnumSTATDATA** ppenumAdvise)
1587 CHECK_EXPECTED_METHOD("DataObject_EnumDAdvise");
1588 return OLE_E_ADVISENOTSUPPORTED;
1591 static IDataObjectVtbl DataObjectVtbl =
1593 DataObject_QueryInterface,
1594 DataObject_AddRef,
1595 DataObject_Release,
1596 DataObject_GetData,
1597 DataObject_GetDataHere,
1598 DataObject_QueryGetData,
1599 DataObject_GetCanonicalFormatEtc,
1600 DataObject_SetData,
1601 DataObject_EnumFormatEtc,
1602 DataObject_DAdvise,
1603 DataObject_DUnadvise,
1604 DataObject_EnumDAdvise
1607 static IDataObject DataObject = { &DataObjectVtbl };
1609 static HRESULT WINAPI Unknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1611 *ppv = NULL;
1612 if (IsEqualIID(riid, &IID_IUnknown)) *ppv = iface;
1613 if (*ppv)
1615 IUnknown_AddRef((IUnknown *)*ppv);
1616 return S_OK;
1618 return E_NOINTERFACE;
1621 static ULONG WINAPI Unknown_AddRef(IUnknown *iface)
1623 return 2;
1626 static ULONG WINAPI Unknown_Release(IUnknown *iface)
1628 return 1;
1631 static const IUnknownVtbl UnknownVtbl =
1633 Unknown_QueryInterface,
1634 Unknown_AddRef,
1635 Unknown_Release
1638 static IUnknown unknown = { &UnknownVtbl };
1640 static void check_enum_cache(IOleCache2 *cache, const STATDATA *expect, int num)
1642 IEnumSTATDATA *enum_stat;
1643 STATDATA stat;
1644 HRESULT hr;
1646 hr = IOleCache2_EnumCache( cache, &enum_stat );
1647 ok( hr == S_OK, "got %08x\n", hr );
1649 while (IEnumSTATDATA_Next(enum_stat, 1, &stat, NULL) == S_OK)
1651 ok( stat.formatetc.cfFormat == expect->formatetc.cfFormat, "got %d expect %d\n",
1652 stat.formatetc.cfFormat, expect->formatetc.cfFormat );
1653 ok( !stat.formatetc.ptd == !expect->formatetc.ptd, "got %p expect %p\n",
1654 stat.formatetc.ptd, expect->formatetc.ptd );
1655 ok( stat.formatetc.dwAspect == expect->formatetc.dwAspect, "got %d expect %d\n",
1656 stat.formatetc.dwAspect, expect->formatetc.dwAspect );
1657 ok( stat.formatetc.lindex == expect->formatetc.lindex, "got %d expect %d\n",
1658 stat.formatetc.lindex, expect->formatetc.lindex );
1659 ok( stat.formatetc.tymed == expect->formatetc.tymed, "got %d expect %d\n",
1660 stat.formatetc.tymed, expect->formatetc.tymed );
1661 ok( stat.advf == expect->advf, "got %d expect %d\n", stat.advf, expect->advf );
1662 ok( stat.pAdvSink == 0, "got %p\n", stat.pAdvSink );
1663 ok( stat.dwConnection == expect->dwConnection, "got %d expect %d\n", stat.dwConnection, expect->dwConnection );
1664 num--;
1665 expect++;
1668 ok( num == 0, "incorrect number. num %d\n", num );
1670 IEnumSTATDATA_Release( enum_stat );
1673 static void test_data_cache(void)
1675 HRESULT hr;
1676 IOleCache2 *pOleCache;
1677 IOleCache *olecache;
1678 IStorage *pStorage;
1679 IUnknown *unk, *unk2;
1680 IPersistStorage *pPS;
1681 IViewObject *pViewObject;
1682 IOleCacheControl *pOleCacheControl;
1683 IDataObject *pCacheDataObject;
1684 FORMATETC fmtetc;
1685 STGMEDIUM stgmedium;
1686 DWORD dwConnection;
1687 DWORD dwFreeze;
1688 RECTL rcBounds;
1689 HDC hdcMem;
1690 CLSID clsid;
1691 char szSystemDir[MAX_PATH];
1692 WCHAR wszPath[MAX_PATH];
1693 static const WCHAR wszShell32[] = {'\\','s','h','e','l','l','3','2','.','d','l','l',0};
1695 static const struct expected_method methods_cacheinitnew[] =
1697 { "AdviseSink_OnViewChange", 0 },
1698 { "AdviseSink_OnViewChange", 0 },
1699 { "draw_continue", 1 },
1700 { "draw_continue_false", 1 },
1701 { "DataObject_DAdvise", 0 },
1702 { "DataObject_DAdvise", 0 },
1703 { "DataObject_DUnadvise", 0 },
1704 { "DataObject_DUnadvise", 0 },
1705 { NULL, 0 }
1707 static const struct expected_method methods_cacheload[] =
1709 { "AdviseSink_OnViewChange", 0 },
1710 { "draw_continue", 1 },
1711 { "draw_continue", 1 },
1712 { "draw_continue", 1 },
1713 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_THUMBNAIL, -1, TYMED_HGLOBAL} },
1714 { "DataObject_GetData", 0, { CF_BITMAP, NULL, DVASPECT_THUMBNAIL, -1, TYMED_GDI} },
1715 { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_ICON, -1, TYMED_MFPICT} },
1716 { NULL, 0 }
1718 static const struct expected_method methods_cachethenrun[] =
1720 { "DataObject_DAdvise", 0 },
1721 { "DataObject_DAdvise", 0 },
1722 { "DataObject_DAdvise", 0 },
1723 { "DataObject_DAdvise", 0 },
1724 { "DataObject_DUnadvise", 0 },
1725 { "DataObject_DUnadvise", 0 },
1726 { "DataObject_DUnadvise", 0 },
1727 { "DataObject_DUnadvise", 0 },
1728 { NULL, 0 }
1731 GetSystemDirectoryA(szSystemDir, ARRAY_SIZE(szSystemDir));
1733 expected_method_list = methods_cacheinitnew;
1735 fmtetc.cfFormat = CF_METAFILEPICT;
1736 fmtetc.dwAspect = DVASPECT_ICON;
1737 fmtetc.lindex = -1;
1738 fmtetc.ptd = NULL;
1739 fmtetc.tymed = TYMED_MFPICT;
1741 hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &pStorage);
1742 ok_ole_success(hr, "StgCreateDocfile");
1744 /* aggregation */
1746 /* requested is not IUnknown */
1747 hr = CreateDataCache(&unknown, &CLSID_NULL, &IID_IOleCache2, (void**)&pOleCache);
1748 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1750 hr = CreateDataCache(&unknown, &CLSID_NULL, &IID_IUnknown, (void**)&unk);
1751 ok(hr == S_OK, "got 0x%08x\n", hr);
1753 hr = IUnknown_QueryInterface(unk, &IID_IOleCache, (void**)&olecache);
1754 ok(hr == S_OK, "got 0x%08x\n", hr);
1755 hr = IUnknown_QueryInterface(unk, &IID_IOleCache2, (void**)&pOleCache);
1756 ok(hr == S_OK, "got 0x%08x\n", hr);
1757 ok(unk != (IUnknown*)olecache, "got %p, expected %p\n", olecache, unk);
1758 ok(unk != (IUnknown*)pOleCache, "got %p, expected %p\n", pOleCache, unk);
1759 IOleCache2_Release(pOleCache);
1760 IOleCache_Release(olecache);
1761 IUnknown_Release(unk);
1763 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IUnknown, (void**)&unk);
1764 ok(hr == S_OK, "got 0x%08x\n", hr);
1765 hr = IUnknown_QueryInterface(unk, &IID_IOleCache, (void**)&olecache);
1766 ok(hr == S_OK, "got 0x%08x\n", hr);
1767 hr = IUnknown_QueryInterface(unk, &IID_IOleCache2, (void**)&pOleCache);
1768 ok(hr == S_OK, "got 0x%08x\n", hr);
1769 hr = IUnknown_QueryInterface(unk, &IID_IUnknown, (void**)&unk2);
1770 ok(hr == S_OK, "got 0x%08x\n", hr);
1771 ok(unk == (IUnknown*)olecache, "got %p, expected %p\n", olecache, unk);
1772 ok(unk == (IUnknown*)pOleCache, "got %p, expected %p\n", pOleCache, unk);
1773 ok(unk == unk2, "got %p, expected %p\n", unk2, unk);
1774 IUnknown_Release(unk2);
1775 IOleCache2_Release(pOleCache);
1776 IOleCache_Release(olecache);
1777 IUnknown_Release(unk);
1779 /* Test with new data */
1781 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IOleCache2, (LPVOID *)&pOleCache);
1782 ok_ole_success(hr, "CreateDataCache");
1784 hr = IOleCache2_QueryInterface(pOleCache, &IID_IPersistStorage, (LPVOID *)&pPS);
1785 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IPersistStorage)");
1786 hr = IOleCache2_QueryInterface(pOleCache, &IID_IViewObject, (LPVOID *)&pViewObject);
1787 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IViewObject)");
1788 hr = IOleCache2_QueryInterface(pOleCache, &IID_IOleCacheControl, (LPVOID *)&pOleCacheControl);
1789 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IOleCacheControl)");
1791 hr = IViewObject_SetAdvise(pViewObject, DVASPECT_ICON, ADVF_PRIMEFIRST, &AdviseSink);
1792 ok_ole_success(hr, "IViewObject_SetAdvise");
1794 hr = IPersistStorage_InitNew(pPS, pStorage);
1795 ok_ole_success(hr, "IPersistStorage_InitNew");
1797 hr = IPersistStorage_IsDirty(pPS);
1798 ok_ole_success(hr, "IPersistStorage_IsDirty");
1800 hr = IPersistStorage_GetClassID(pPS, &clsid);
1801 ok_ole_success(hr, "IPersistStorage_GetClassID");
1802 ok(IsEqualCLSID(&clsid, &IID_NULL), "clsid should be blank\n");
1804 hr = IOleCache2_Uncache(pOleCache, 0xdeadbeef);
1805 ok(hr == OLE_E_NOCONNECTION, "IOleCache_Uncache with invalid value should return OLE_E_NOCONNECTION instead of 0x%x\n", hr);
1807 /* Both tests crash on NT4 and below. StgCreatePropSetStg is only available on w2k and above. */
1808 if (GetProcAddress(GetModuleHandleA("ole32.dll"), "StgCreatePropSetStg"))
1810 hr = IOleCache2_Cache(pOleCache, NULL, 0, &dwConnection);
1811 ok(hr == E_INVALIDARG, "IOleCache_Cache with NULL fmtetc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1813 hr = IOleCache2_Cache(pOleCache, NULL, 0, NULL);
1814 ok(hr == E_INVALIDARG, "IOleCache_Cache with NULL pdwConnection should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1816 else
1818 skip("tests with NULL parameters will crash on NT4 and below\n");
1821 for (fmtetc.cfFormat = CF_TEXT; fmtetc.cfFormat < CF_MAX; fmtetc.cfFormat++)
1823 int i;
1824 fmtetc.dwAspect = DVASPECT_THUMBNAIL;
1825 for (i = 0; i < 7; i++)
1827 fmtetc.tymed = 1 << i;
1828 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1829 if ((fmtetc.cfFormat == CF_METAFILEPICT && fmtetc.tymed == TYMED_MFPICT) ||
1830 (fmtetc.cfFormat == CF_BITMAP && fmtetc.tymed == TYMED_GDI) ||
1831 (fmtetc.cfFormat == CF_DIB && fmtetc.tymed == TYMED_HGLOBAL) ||
1832 (fmtetc.cfFormat == CF_ENHMETAFILE && fmtetc.tymed == TYMED_ENHMF))
1833 ok(hr == S_OK, "IOleCache_Cache cfFormat = %d, tymed = %d should have returned S_OK instead of 0x%08x\n",
1834 fmtetc.cfFormat, fmtetc.tymed, hr);
1835 else if (fmtetc.tymed == TYMED_HGLOBAL)
1836 ok(hr == CACHE_S_FORMATETC_NOTSUPPORTED ||
1837 broken(hr == S_OK && fmtetc.cfFormat == CF_BITMAP) /* Win9x & NT4 */,
1838 "IOleCache_Cache cfFormat = %d, tymed = %d should have returned CACHE_S_FORMATETC_NOTSUPPORTED instead of 0x%08x\n",
1839 fmtetc.cfFormat, fmtetc.tymed, hr);
1840 else
1841 ok(hr == DV_E_TYMED, "IOleCache_Cache cfFormat = %d, tymed = %d should have returned DV_E_TYMED instead of 0x%08x\n",
1842 fmtetc.cfFormat, fmtetc.tymed, hr);
1843 if (SUCCEEDED(hr))
1845 hr = IOleCache2_Uncache(pOleCache, dwConnection);
1846 ok_ole_success(hr, "IOleCache_Uncache");
1851 fmtetc.cfFormat = CF_BITMAP;
1852 fmtetc.dwAspect = DVASPECT_THUMBNAIL;
1853 fmtetc.tymed = TYMED_GDI;
1854 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1855 ok_ole_success(hr, "IOleCache_Cache");
1857 fmtetc.cfFormat = 0;
1858 fmtetc.dwAspect = DVASPECT_ICON;
1859 fmtetc.tymed = TYMED_MFPICT;
1860 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1861 ok_ole_success(hr, "IOleCache_Cache");
1863 MultiByteToWideChar(CP_ACP, 0, szSystemDir, -1, wszPath, ARRAY_SIZE(wszPath));
1864 memcpy(wszPath+lstrlenW(wszPath), wszShell32, sizeof(wszShell32));
1866 fmtetc.cfFormat = CF_METAFILEPICT;
1867 stgmedium.tymed = TYMED_MFPICT;
1868 U(stgmedium).hMetaFilePict = OleMetafilePictFromIconAndLabel(
1869 LoadIconA(NULL, (LPSTR)IDI_APPLICATION), wszPath, wszPath, 0);
1870 stgmedium.pUnkForRelease = NULL;
1872 fmtetc.dwAspect = DVASPECT_CONTENT;
1873 hr = IOleCache2_SetData(pOleCache, &fmtetc, &stgmedium, FALSE);
1874 ok(hr == OLE_E_BLANK, "IOleCache_SetData for aspect not in cache should have return OLE_E_BLANK instead of 0x%08x\n", hr);
1876 fmtetc.dwAspect = DVASPECT_ICON;
1877 hr = IOleCache2_SetData(pOleCache, &fmtetc, &stgmedium, FALSE);
1878 ok_ole_success(hr, "IOleCache_SetData");
1879 ReleaseStgMedium(&stgmedium);
1881 hr = IViewObject_Freeze(pViewObject, DVASPECT_ICON, -1, NULL, &dwFreeze);
1882 todo_wine {
1883 ok_ole_success(hr, "IViewObject_Freeze");
1884 hr = IViewObject_Freeze(pViewObject, DVASPECT_CONTENT, -1, NULL, &dwFreeze);
1885 ok(hr == OLE_E_BLANK, "IViewObject_Freeze with uncached aspect should have returned OLE_E_BLANK instead of 0x%08x\n", hr);
1888 rcBounds.left = 0;
1889 rcBounds.top = 0;
1890 rcBounds.right = 100;
1891 rcBounds.bottom = 100;
1892 hdcMem = CreateCompatibleDC(NULL);
1894 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1895 ok_ole_success(hr, "IViewObject_Draw");
1897 hr = IViewObject_Draw(pViewObject, DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1898 ok(hr == OLE_E_BLANK, "IViewObject_Draw with uncached aspect should have returned OLE_E_BLANK instead of 0x%08x\n", hr);
1900 /* a NULL draw_continue fn ptr */
1901 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, NULL, 0xdeadbeef);
1902 ok_ole_success(hr, "IViewObject_Draw");
1904 /* draw_continue that returns FALSE to abort drawing */
1905 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue_false, 0xdeadbeef);
1906 ok(hr == E_ABORT ||
1907 broken(hr == S_OK), /* win9x may skip the callbacks */
1908 "IViewObject_Draw with draw_continue_false returns 0x%08x\n", hr);
1910 DeleteDC(hdcMem);
1912 hr = IOleCacheControl_OnRun(pOleCacheControl, &DataObject);
1913 ok_ole_success(hr, "IOleCacheControl_OnRun");
1915 hr = IPersistStorage_Save(pPS, pStorage, TRUE);
1916 ok_ole_success(hr, "IPersistStorage_Save");
1918 hr = IPersistStorage_SaveCompleted(pPS, NULL);
1919 ok_ole_success(hr, "IPersistStorage_SaveCompleted");
1921 hr = IPersistStorage_IsDirty(pPS);
1922 ok(hr == S_FALSE, "IPersistStorage_IsDirty should have returned S_FALSE instead of 0x%x\n", hr);
1924 IPersistStorage_Release(pPS);
1925 IViewObject_Release(pViewObject);
1926 IOleCache2_Release(pOleCache);
1927 IOleCacheControl_Release(pOleCacheControl);
1929 CHECK_NO_EXTRA_METHODS();
1931 /* Test with loaded data */
1932 trace("Testing loaded data with CreateDataCache:\n");
1933 expected_method_list = methods_cacheload;
1935 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IOleCache2, (LPVOID *)&pOleCache);
1936 ok_ole_success(hr, "CreateDataCache");
1938 hr = IOleCache2_QueryInterface(pOleCache, &IID_IPersistStorage, (LPVOID *)&pPS);
1939 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IPersistStorage)");
1940 hr = IOleCache2_QueryInterface(pOleCache, &IID_IViewObject, (LPVOID *)&pViewObject);
1941 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IViewObject)");
1943 hr = IViewObject_SetAdvise(pViewObject, DVASPECT_ICON, ADVF_PRIMEFIRST, &AdviseSink);
1944 ok_ole_success(hr, "IViewObject_SetAdvise");
1946 hr = IPersistStorage_Load(pPS, pStorage);
1947 ok_ole_success(hr, "IPersistStorage_Load");
1949 hr = IPersistStorage_IsDirty(pPS);
1950 ok(hr == S_FALSE, "IPersistStorage_IsDirty should have returned S_FALSE instead of 0x%x\n", hr);
1952 fmtetc.cfFormat = 0;
1953 fmtetc.dwAspect = DVASPECT_ICON;
1954 fmtetc.lindex = -1;
1955 fmtetc.ptd = NULL;
1956 fmtetc.tymed = TYMED_MFPICT;
1957 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1958 ok(hr == CACHE_S_SAMECACHE, "IOleCache_Cache with already loaded data format type should return CACHE_S_SAMECACHE instead of 0x%x\n", hr);
1960 rcBounds.left = 0;
1961 rcBounds.top = 0;
1962 rcBounds.right = 100;
1963 rcBounds.bottom = 100;
1964 hdcMem = CreateCompatibleDC(NULL);
1966 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1967 ok_ole_success(hr, "IViewObject_Draw");
1969 hr = IViewObject_Draw(pViewObject, DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1970 ok(hr == OLE_E_BLANK, "IViewObject_Draw with uncached aspect should have returned OLE_E_BLANK instead of 0x%08x\n", hr);
1972 /* unload the cached storage object, causing it to be reloaded */
1973 hr = IOleCache2_DiscardCache(pOleCache, DISCARDCACHE_NOSAVE);
1974 ok_ole_success(hr, "IOleCache2_DiscardCache");
1975 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1976 ok_ole_success(hr, "IViewObject_Draw");
1978 /* unload the cached storage object, but don't allow it to be reloaded */
1979 hr = IPersistStorage_HandsOffStorage(pPS);
1980 ok_ole_success(hr, "IPersistStorage_HandsOffStorage");
1981 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1982 ok_ole_success(hr, "IViewObject_Draw");
1983 hr = IOleCache2_DiscardCache(pOleCache, DISCARDCACHE_NOSAVE);
1984 ok_ole_success(hr, "IOleCache2_DiscardCache");
1985 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1986 ok(hr == OLE_E_BLANK, "IViewObject_Draw with uncached aspect should have returned OLE_E_BLANK instead of 0x%08x\n", hr);
1988 DeleteDC(hdcMem);
1990 hr = IOleCache2_InitCache(pOleCache, &DataObject);
1991 ok(hr == CACHE_E_NOCACHE_UPDATED, "IOleCache_InitCache should have returned CACHE_E_NOCACHE_UPDATED instead of 0x%08x\n", hr);
1993 IPersistStorage_Release(pPS);
1994 IViewObject_Release(pViewObject);
1995 IOleCache2_Release(pOleCache);
1997 CHECK_NO_EXTRA_METHODS();
1999 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IOleCache2, (LPVOID *)&pOleCache);
2000 ok_ole_success(hr, "CreateDataCache");
2002 expected_method_list = methods_cachethenrun;
2004 hr = IOleCache2_QueryInterface(pOleCache, &IID_IDataObject, (LPVOID *)&pCacheDataObject);
2005 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IDataObject)");
2006 hr = IOleCache2_QueryInterface(pOleCache, &IID_IOleCacheControl, (LPVOID *)&pOleCacheControl);
2007 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IOleCacheControl)");
2009 fmtetc.cfFormat = CF_METAFILEPICT;
2010 fmtetc.dwAspect = DVASPECT_CONTENT;
2011 fmtetc.tymed = TYMED_MFPICT;
2013 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
2014 ok_ole_success(hr, "IOleCache_Cache");
2016 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2017 ok(hr == OLE_E_BLANK, "got %08x\n", hr);
2019 fmtetc.cfFormat = cf_test_1;
2020 fmtetc.dwAspect = DVASPECT_CONTENT;
2021 fmtetc.tymed = TYMED_HGLOBAL;
2023 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
2024 ok(hr == CACHE_S_FORMATETC_NOTSUPPORTED, "got %08x\n", hr);
2026 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2027 ok(hr == OLE_E_BLANK, "got %08x\n", hr);
2029 fmtetc.cfFormat = cf_test_2;
2030 hr = IOleCache2_Cache(pOleCache, &fmtetc, ADVF_PRIMEFIRST, &dwConnection);
2031 ok(hr == CACHE_S_FORMATETC_NOTSUPPORTED, "got %08x\n", hr);
2033 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2034 ok(hr == OLE_E_BLANK, "got %08x\n", hr);
2036 hr = IOleCacheControl_OnRun(pOleCacheControl, &DataObject);
2037 ok_ole_success(hr, "IOleCacheControl_OnRun");
2039 fmtetc.cfFormat = cf_test_3;
2040 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
2041 ok(hr == CACHE_S_FORMATETC_NOTSUPPORTED, "got %08x\n", hr);
2043 fmtetc.cfFormat = cf_test_1;
2044 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2045 ok(hr == OLE_E_BLANK, "got %08x\n", hr);
2047 fmtetc.cfFormat = cf_test_2;
2048 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2049 ok(hr == S_OK, "got %08x\n", hr);
2050 ReleaseStgMedium(&stgmedium);
2052 fmtetc.cfFormat = cf_test_3;
2053 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2054 ok(hr == OLE_E_BLANK, "got %08x\n", hr);
2056 IOleCacheControl_Release(pOleCacheControl);
2057 IDataObject_Release(pCacheDataObject);
2058 IOleCache2_Release(pOleCache);
2060 CHECK_NO_EXTRA_METHODS();
2062 IStorage_Release(pStorage);
2065 static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0};
2067 /* 2 x 1 x 32 bpp dib. PelsPerMeter = 200x400 */
2068 static BYTE file_dib[] =
2070 0x42, 0x4d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
2071 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
2072 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00,
2073 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
2074 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00,
2075 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00,
2076 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
2077 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
2080 static IStorage *create_storage( int num )
2082 IStorage *stg;
2083 IStream *stm;
2084 HRESULT hr;
2085 ULONG written;
2087 hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg );
2088 ok( hr == S_OK, "got %08x\n", hr);
2089 hr = IStorage_SetClass( stg, &CLSID_Picture_Dib );
2090 ok( hr == S_OK, "got %08x\n", hr);
2091 hr = IStorage_CreateStream( stg, CONTENTS, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, &stm );
2092 ok( hr == S_OK, "got %08x\n", hr);
2093 if (num == 1) /* Set biXPelsPerMeter = 0 */
2095 file_dib[0x26] = 0;
2096 file_dib[0x27] = 0;
2098 hr = IStream_Write( stm, file_dib, sizeof(file_dib), &written );
2099 ok( hr == S_OK, "got %08x\n", hr);
2100 IStream_Release( stm );
2101 return stg;
2104 static void test_data_cache_dib_contents_stream(int num)
2106 HRESULT hr;
2107 IUnknown *unk;
2108 IPersistStorage *persist;
2109 IDataObject *data;
2110 IViewObject2 *view;
2111 IStorage *stg;
2112 IOleCache2 *cache;
2113 FORMATETC fmt = {CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
2114 STGMEDIUM med;
2115 CLSID cls;
2116 SIZEL sz;
2117 BYTE *ptr;
2118 BITMAPINFOHEADER expect_info;
2119 STATDATA enum_expect[] =
2121 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2122 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 },
2125 hr = CreateDataCache( NULL, &CLSID_Picture_Metafile, &IID_IUnknown, (void **)&unk );
2126 ok( SUCCEEDED(hr), "got %08x\n", hr );
2127 hr = IUnknown_QueryInterface( unk, &IID_IPersistStorage, (void **)&persist );
2128 ok( SUCCEEDED(hr), "got %08x\n", hr );
2129 hr = IUnknown_QueryInterface( unk, &IID_IDataObject, (void **)&data );
2130 ok( SUCCEEDED(hr), "got %08x\n", hr );
2131 hr = IUnknown_QueryInterface( unk, &IID_IViewObject2, (void **)&view );
2132 ok( SUCCEEDED(hr), "got %08x\n", hr );
2133 hr = IUnknown_QueryInterface( unk, &IID_IOleCache2, (void **)&cache );
2134 ok( SUCCEEDED(hr), "got %08x\n", hr );
2136 stg = create_storage( num );
2138 hr = IPersistStorage_Load( persist, stg );
2139 ok( SUCCEEDED(hr), "got %08x\n", hr );
2140 IStorage_Release( stg );
2142 hr = IPersistStorage_GetClassID( persist, &cls );
2143 ok( SUCCEEDED(hr), "got %08x\n", hr );
2144 ok( IsEqualCLSID( &cls, &CLSID_Picture_Dib ), "class id mismatch\n" );
2146 hr = IDataObject_GetData( data, &fmt, &med );
2147 ok( SUCCEEDED(hr), "got %08x\n", hr );
2148 ok( med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed );
2149 ok( GlobalSize( U(med).hGlobal ) >= sizeof(dib) - sizeof(BITMAPFILEHEADER),
2150 "got %lu\n", GlobalSize( U(med).hGlobal ) );
2151 ptr = GlobalLock( U(med).hGlobal );
2153 expect_info = *(BITMAPINFOHEADER *)(file_dib + sizeof(BITMAPFILEHEADER));
2154 if (expect_info.biXPelsPerMeter == 0 || expect_info.biYPelsPerMeter == 0)
2156 HDC hdc = GetDC( 0 );
2157 expect_info.biXPelsPerMeter = MulDiv( GetDeviceCaps( hdc, LOGPIXELSX ), 10000, 254 );
2158 expect_info.biYPelsPerMeter = MulDiv( GetDeviceCaps( hdc, LOGPIXELSY ), 10000, 254 );
2159 ReleaseDC( 0, hdc );
2161 ok( !memcmp( ptr, &expect_info, sizeof(expect_info) ), "mismatch\n" );
2162 ok( !memcmp( ptr + sizeof(expect_info), file_dib + sizeof(BITMAPFILEHEADER) + sizeof(expect_info),
2163 sizeof(file_dib) - sizeof(BITMAPFILEHEADER) - sizeof(expect_info) ), "mismatch\n" );
2164 GlobalUnlock( U(med).hGlobal );
2165 ReleaseStgMedium( &med );
2167 check_enum_cache( cache, enum_expect, 2 );
2169 hr = IViewObject2_GetExtent( view, DVASPECT_CONTENT, -1, NULL, &sz );
2170 ok( SUCCEEDED(hr), "got %08x\n", hr );
2171 if (num == 0)
2173 ok( sz.cx == 1000, "got %d\n", sz.cx );
2174 ok( sz.cy == 250, "got %d\n", sz.cy );
2176 else
2178 HDC hdc = GetDC( 0 );
2179 LONG x = 2 * 2540 / GetDeviceCaps( hdc, LOGPIXELSX );
2180 LONG y = 1 * 2540 / GetDeviceCaps( hdc, LOGPIXELSY );
2181 ok( sz.cx == x, "got %d %d\n", sz.cx, x );
2182 ok( sz.cy == y, "got %d %d\n", sz.cy, y );
2184 ReleaseDC( 0, hdc );
2187 IOleCache2_Release( cache );
2188 IViewObject2_Release( view );
2189 IDataObject_Release( data );
2190 IPersistStorage_Release( persist );
2191 IUnknown_Release( unk );
2194 static void check_bitmap_size( HBITMAP h, int cx, int cy )
2196 BITMAP bm;
2198 GetObjectW( h, sizeof(bm), &bm );
2199 ok( bm.bmWidth == cx, "got %d expect %d\n", bm.bmWidth, cx );
2200 ok( bm.bmHeight == cy, "got %d expect %d\n", bm.bmHeight, cy );
2203 static void check_dib_size( HGLOBAL h, int cx, int cy )
2205 BITMAPINFO *info;
2207 info = GlobalLock( h );
2208 ok( info->bmiHeader.biWidth == cx, "got %d expect %d\n", info->bmiHeader.biWidth, cx );
2209 ok( info->bmiHeader.biHeight == cy, "got %d expect %d\n", info->bmiHeader.biHeight, cy );
2210 GlobalUnlock( h );
2213 static void test_data_cache_cache(void)
2215 HRESULT hr;
2216 IOleCache2 *cache;
2217 IDataObject *data;
2218 FORMATETC fmt;
2219 DWORD conn;
2220 STGMEDIUM med;
2221 STATDATA expect[] =
2223 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 0 },
2224 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 0 },
2225 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 0 },
2226 {{ CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF }, 0, NULL, 0 }
2228 STATDATA view_caching[] =
2230 {{ 0, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF }, 0, NULL, 0 },
2231 {{ 0, 0, DVASPECT_THUMBNAIL, -1, TYMED_HGLOBAL }, 0, NULL, 0 },
2232 {{ 0, 0, DVASPECT_DOCPRINT, -1, TYMED_HGLOBAL }, 0, NULL, 0 },
2233 {{ CF_METAFILEPICT, 0, DVASPECT_ICON, -1, TYMED_MFPICT }, 0, NULL, 0 }
2236 hr = CreateDataCache( NULL, &CLSID_NULL, &IID_IOleCache2, (void **)&cache );
2237 ok( hr == S_OK, "got %08x\n", hr );
2239 /* create a dib entry which will also create a bitmap entry too */
2240 fmt.cfFormat = CF_DIB;
2241 fmt.ptd = NULL;
2242 fmt.dwAspect = DVASPECT_CONTENT;
2243 fmt.lindex = -1;
2244 fmt.tymed = TYMED_HGLOBAL;
2246 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2247 ok( hr == S_OK, "got %08x\n", hr );
2248 ok( conn == 2, "got %d\n", conn );
2249 expect[0].dwConnection = conn;
2250 expect[1].dwConnection = conn;
2252 check_enum_cache( cache, expect, 2 );
2254 /* now try to add a bitmap */
2255 fmt.cfFormat = CF_BITMAP;
2256 fmt.tymed = TYMED_GDI;
2258 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2259 ok( hr == CACHE_S_SAMECACHE, "got %08x\n", hr );
2261 /* metafile */
2262 fmt.cfFormat = CF_METAFILEPICT;
2263 fmt.tymed = TYMED_MFPICT;
2265 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2266 ok( hr == S_OK, "got %08x\n", hr );
2267 ok( conn == 3, "got %d\n", conn );
2268 expect[2].dwConnection = conn;
2270 check_enum_cache( cache, expect, 3);
2272 /* enhmetafile */
2273 fmt.cfFormat = CF_ENHMETAFILE;
2274 fmt.tymed = TYMED_ENHMF;
2276 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2277 ok( hr == S_OK, "got %08x\n", hr );
2278 ok( conn == 4, "got %d\n", conn );
2279 expect[3].dwConnection = conn;
2281 check_enum_cache( cache, expect, 4 );
2283 /* uncache everything */
2284 hr = IOleCache2_Uncache( cache, expect[3].dwConnection );
2285 ok( hr == S_OK, "got %08x\n", hr );
2286 hr = IOleCache2_Uncache( cache, expect[2].dwConnection );
2287 ok( hr == S_OK, "got %08x\n", hr );
2288 hr = IOleCache2_Uncache( cache, expect[0].dwConnection );
2289 ok( hr == S_OK, "got %08x\n", hr );
2290 hr = IOleCache2_Uncache( cache, expect[0].dwConnection );
2291 ok( hr == OLE_E_NOCONNECTION, "got %08x\n", hr );
2293 check_enum_cache( cache, expect, 0 );
2295 /* just create a bitmap entry which again adds both dib and bitmap */
2296 fmt.cfFormat = CF_BITMAP;
2297 fmt.tymed = TYMED_GDI;
2299 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2300 ok( hr == S_OK, "got %08x\n", hr );
2302 expect[0].dwConnection = conn;
2303 expect[1].dwConnection = conn;
2305 check_enum_cache( cache, expect, 2 );
2307 /* Try setting a 1x1 bitmap */
2308 hr = IOleCache2_QueryInterface( cache, &IID_IDataObject, (void **) &data );
2309 ok( hr == S_OK, "got %08x\n", hr );
2311 create_bitmap( &med );
2313 hr = IOleCache2_SetData( cache, &fmt, &med, TRUE );
2314 ok( hr == S_OK, "got %08x\n", hr );
2316 hr = IDataObject_GetData( data, &fmt, &med );
2317 ok( hr == S_OK, "got %08x\n", hr );
2318 ok( med.tymed == TYMED_GDI, "got %d\n", med.tymed );
2319 check_bitmap_size( U(med).hBitmap, 1, 1 );
2320 ReleaseStgMedium( &med );
2322 fmt.cfFormat = CF_DIB;
2323 fmt.tymed = TYMED_HGLOBAL;
2324 hr = IDataObject_GetData( data, &fmt, &med );
2325 ok( hr == S_OK, "got %08x\n", hr );
2326 ok( med.tymed == TYMED_HGLOBAL, "got %d\n", med.tymed );
2327 check_dib_size( U(med).hGlobal, 1, 1 );
2328 ReleaseStgMedium( &med );
2330 /* Now set a 2x1 dib */
2331 fmt.cfFormat = CF_DIB;
2332 fmt.tymed = TYMED_HGLOBAL;
2333 create_dib( &med );
2335 hr = IOleCache2_SetData( cache, &fmt, &med, TRUE );
2336 ok( hr == S_OK, "got %08x\n", hr );
2338 fmt.cfFormat = CF_BITMAP;
2339 fmt.tymed = TYMED_GDI;
2340 hr = IDataObject_GetData( data, &fmt, &med );
2341 ok( hr == S_OK, "got %08x\n", hr );
2342 ok( med.tymed == TYMED_GDI, "got %d\n", med.tymed );
2343 check_bitmap_size( U(med).hBitmap, 2, 1 );
2344 ReleaseStgMedium( &med );
2346 fmt.cfFormat = CF_DIB;
2347 fmt.tymed = TYMED_HGLOBAL;
2348 hr = IDataObject_GetData( data, &fmt, &med );
2349 ok( hr == S_OK, "got %08x\n", hr );
2350 ok( med.tymed == TYMED_HGLOBAL, "got %d\n", med.tymed );
2351 check_dib_size( U(med).hGlobal, 2, 1 );
2352 ReleaseStgMedium( &med );
2354 /* uncache everything */
2355 hr = IOleCache2_Uncache( cache, conn );
2356 ok( hr == S_OK, "got %08x\n", hr );
2358 /* view caching */
2359 fmt.cfFormat = 0;
2360 fmt.tymed = TYMED_ENHMF;
2361 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2362 ok( hr == S_OK, "got %08x\n", hr );
2363 view_caching[0].dwConnection = conn;
2365 fmt.tymed = TYMED_HGLOBAL;
2366 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2367 ok( hr == CACHE_S_SAMECACHE, "got %08x\n", hr );
2369 fmt.dwAspect = DVASPECT_THUMBNAIL;
2370 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2371 ok( hr == S_OK, "got %08x\n", hr );
2372 view_caching[1].dwConnection = conn;
2374 fmt.dwAspect = DVASPECT_DOCPRINT;
2375 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2376 ok( hr == S_OK, "got %08x\n", hr );
2377 view_caching[2].dwConnection = conn;
2379 /* DVASPECT_ICON view cache gets mapped to CF_METAFILEPICT */
2380 fmt.dwAspect = DVASPECT_ICON;
2381 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2382 ok( hr == S_OK, "got %08x\n", hr );
2383 view_caching[3].dwConnection = conn;
2385 check_enum_cache( cache, view_caching, 4 );
2387 /* uncache everything */
2388 hr = IOleCache2_Uncache( cache, view_caching[3].dwConnection );
2389 ok( hr == S_OK, "got %08x\n", hr );
2390 hr = IOleCache2_Uncache( cache, view_caching[2].dwConnection );
2391 ok( hr == S_OK, "got %08x\n", hr );
2392 hr = IOleCache2_Uncache( cache, view_caching[1].dwConnection );
2393 ok( hr == S_OK, "got %08x\n", hr );
2394 hr = IOleCache2_Uncache( cache, view_caching[0].dwConnection );
2395 ok( hr == S_OK, "got %08x\n", hr );
2397 /* Only able to set cfFormat == CF_METAFILEPICT (or == 0, see above) for DVASPECT_ICON */
2398 fmt.dwAspect = DVASPECT_ICON;
2399 fmt.cfFormat = CF_DIB;
2400 fmt.tymed = TYMED_HGLOBAL;
2401 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2402 ok( hr == DV_E_FORMATETC, "got %08x\n", hr );
2403 fmt.cfFormat = CF_BITMAP;
2404 fmt.tymed = TYMED_GDI;
2405 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2406 ok( hr == DV_E_FORMATETC, "got %08x\n", hr );
2407 fmt.cfFormat = CF_ENHMETAFILE;
2408 fmt.tymed = TYMED_ENHMF;
2409 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2410 ok( hr == DV_E_FORMATETC, "got %08x\n", hr );
2411 fmt.cfFormat = CF_METAFILEPICT;
2412 fmt.tymed = TYMED_MFPICT;
2413 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2414 ok( hr == S_OK, "got %08x\n", hr );
2416 /* uncache everything */
2417 hr = IOleCache2_Uncache( cache, conn );
2418 ok( hr == S_OK, "got %08x\n", hr );
2420 /* tymed == 0 */
2421 fmt.cfFormat = CF_ENHMETAFILE;
2422 fmt.dwAspect = DVASPECT_CONTENT;
2423 fmt.tymed = 0;
2424 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2425 ok( hr == DV_E_TYMED, "got %08x\n", hr );
2427 IDataObject_Release( data );
2428 IOleCache2_Release( cache );
2430 /* tests for a static class cache */
2431 hr = CreateDataCache( NULL, &CLSID_Picture_Dib, &IID_IOleCache2, (void **)&cache );
2433 fmt.cfFormat = CF_DIB;
2434 fmt.dwAspect = DVASPECT_CONTENT;
2435 fmt.tymed = TYMED_HGLOBAL;
2436 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2437 ok( hr == CACHE_S_SAMECACHE, "got %08x\n", hr );
2439 /* aspect other than DVASPECT_CONTENT should fail */
2440 fmt.dwAspect = DVASPECT_THUMBNAIL;
2441 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2442 ok( FAILED(hr), "got %08x\n", hr );
2444 fmt.dwAspect = DVASPECT_DOCPRINT;
2445 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2446 ok( FAILED(hr), "got %08x\n", hr );
2448 /* try caching another clip format */
2449 fmt.cfFormat = CF_METAFILEPICT;
2450 fmt.dwAspect = DVASPECT_CONTENT;
2451 fmt.tymed = TYMED_MFPICT;
2452 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2453 ok( FAILED(hr), "got %08x\n", hr );
2455 /* As an exception, it's possible to add an icon aspect */
2456 fmt.cfFormat = CF_METAFILEPICT;
2457 fmt.dwAspect = DVASPECT_ICON;
2458 fmt.tymed = TYMED_MFPICT;
2459 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2460 ok( hr == S_OK, "got %08x\n", hr );
2462 IOleCache2_Release( cache );
2465 /* The CLSID_Picture_ classes automatically create appropriate cache entries */
2466 static void test_data_cache_init(void)
2468 HRESULT hr;
2469 IOleCache2 *cache;
2470 IPersistStorage *persist;
2471 int i;
2472 CLSID clsid;
2473 static const STATDATA enum_expect[] =
2475 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2476 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 },
2477 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 1 },
2478 {{ CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF }, 0, NULL, 1 }
2480 static const struct
2482 const CLSID *clsid;
2483 int enum_start, enum_num;
2484 } data[] =
2486 { &CLSID_NULL, 0, 0 },
2487 { &CLSID_WineTestOld, 0, 0 },
2488 { &CLSID_Picture_Dib, 0, 2 },
2489 { &CLSID_Picture_Metafile, 2, 1 },
2490 { &CLSID_Picture_EnhMetafile, 3, 1 }
2493 for (i = 0; i < ARRAY_SIZE(data); i++)
2495 hr = CreateDataCache( NULL, data[i].clsid, &IID_IOleCache2, (void **)&cache );
2496 ok( hr == S_OK, "got %08x\n", hr );
2498 check_enum_cache( cache, enum_expect + data[i].enum_start , data[i].enum_num );
2500 IOleCache2_QueryInterface( cache, &IID_IPersistStorage, (void **) &persist );
2501 hr = IPersistStorage_GetClassID( persist, &clsid );
2502 ok( hr == S_OK, "got %08x\n", hr );
2503 ok( IsEqualCLSID( &clsid, data[i].clsid ), "class id mismatch %s %s\n", wine_dbgstr_guid( &clsid ),
2504 wine_dbgstr_guid( data[i].clsid ) );
2506 IPersistStorage_Release( persist );
2507 IOleCache2_Release( cache );
2511 static void test_data_cache_initnew(void)
2513 HRESULT hr;
2514 IOleCache2 *cache;
2515 IPersistStorage *persist;
2516 IStorage *stg_dib, *stg_mf, *stg_wine;
2517 CLSID clsid;
2518 static const STATDATA initnew_expect[] =
2520 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2521 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 },
2523 static const STATDATA initnew2_expect[] =
2525 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 1 },
2526 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 2 },
2527 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 2 },
2529 static const STATDATA initnew3_expect[] =
2531 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2532 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 },
2533 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 2 },
2534 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 2 },
2535 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 3 },
2537 static const STATDATA initnew4_expect[] =
2539 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 2 },
2540 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 2 },
2541 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 3 },
2542 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 4 },
2543 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 4 },
2546 hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg_dib );
2547 ok( hr == S_OK, "got %08x\n", hr);
2548 hr = IStorage_SetClass( stg_dib, &CLSID_Picture_Dib );
2549 ok( hr == S_OK, "got %08x\n", hr);
2551 hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg_mf );
2552 ok( hr == S_OK, "got %08x\n", hr);
2553 hr = IStorage_SetClass( stg_mf, &CLSID_Picture_Metafile );
2554 ok( hr == S_OK, "got %08x\n", hr);
2556 hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg_wine );
2557 ok( hr == S_OK, "got %08x\n", hr);
2558 hr = IStorage_SetClass( stg_wine, &CLSID_WineTestOld );
2559 ok( hr == S_OK, "got %08x\n", hr);
2561 hr = CreateDataCache( NULL, &CLSID_WineTestOld, &IID_IOleCache2, (void **)&cache );
2562 ok( hr == S_OK, "got %08x\n", hr );
2563 IOleCache2_QueryInterface( cache, &IID_IPersistStorage, (void **) &persist );
2565 hr = IPersistStorage_InitNew( persist, stg_dib );
2566 ok( hr == S_OK, "got %08x\n", hr);
2568 hr = IPersistStorage_GetClassID( persist, &clsid );
2569 ok( hr == S_OK, "got %08x\n", hr );
2570 ok( IsEqualCLSID( &clsid, &CLSID_Picture_Dib ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2572 check_enum_cache( cache, initnew_expect, 2 );
2574 hr = IPersistStorage_InitNew( persist, stg_mf );
2575 ok( hr == CO_E_ALREADYINITIALIZED, "got %08x\n", hr);
2577 hr = IPersistStorage_HandsOffStorage( persist );
2578 ok( hr == S_OK, "got %08x\n", hr);
2580 hr = IPersistStorage_GetClassID( persist, &clsid );
2581 ok( hr == S_OK, "got %08x\n", hr );
2582 ok( IsEqualCLSID( &clsid, &CLSID_Picture_Dib ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2584 hr = IPersistStorage_InitNew( persist, stg_mf );
2585 ok( hr == S_OK, "got %08x\n", hr);
2587 hr = IPersistStorage_GetClassID( persist, &clsid );
2588 ok( hr == S_OK, "got %08x\n", hr );
2589 ok( IsEqualCLSID( &clsid, &CLSID_Picture_Metafile ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2591 check_enum_cache( cache, initnew2_expect, 3 );
2593 hr = IPersistStorage_HandsOffStorage( persist );
2594 ok( hr == S_OK, "got %08x\n", hr);
2596 hr = IPersistStorage_InitNew( persist, stg_dib );
2597 ok( hr == S_OK, "got %08x\n", hr);
2599 hr = IPersistStorage_GetClassID( persist, &clsid );
2600 ok( hr == S_OK, "got %08x\n", hr );
2601 ok( IsEqualCLSID( &clsid, &CLSID_Picture_Dib ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2603 check_enum_cache( cache, initnew3_expect, 5 );
2605 hr = IPersistStorage_HandsOffStorage( persist );
2606 ok( hr == S_OK, "got %08x\n", hr);
2608 hr = IPersistStorage_InitNew( persist, stg_wine );
2609 ok( hr == S_OK, "got %08x\n", hr);
2611 hr = IPersistStorage_GetClassID( persist, &clsid );
2612 ok( hr == S_OK, "got %08x\n", hr );
2613 ok( IsEqualCLSID( &clsid, &CLSID_WineTestOld ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2615 check_enum_cache( cache, initnew4_expect, 5 );
2617 IStorage_Release( stg_wine );
2618 IStorage_Release( stg_mf );
2619 IStorage_Release( stg_dib );
2621 IPersistStorage_Release( persist );
2622 IOleCache2_Release( cache );
2625 static void test_data_cache_updatecache( void )
2627 HRESULT hr;
2628 IOleCache2 *cache;
2629 FORMATETC fmt;
2630 DWORD conn[4];
2632 static const struct expected_method methods_dib[] =
2634 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2635 { "DataObject_GetData", 0, { CF_BITMAP, NULL, DVASPECT_CONTENT, -1, TYMED_GDI } },
2636 { NULL }
2639 static const struct expected_method methods_dib_emf[] =
2641 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2642 { "DataObject_GetData", 0, { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } },
2643 { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2644 { NULL }
2646 static const struct expected_method methods_dib_wmf[] =
2648 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2649 { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2650 { NULL }
2652 static const struct expected_method methods_viewcache[] =
2654 { "DataObject_QueryGetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2655 { "DataObject_QueryGetData", 0, { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } },
2656 { "DataObject_QueryGetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2657 { "DataObject_QueryGetData", 0, { CF_BITMAP, NULL, DVASPECT_CONTENT, -1, TYMED_GDI } },
2658 { NULL }
2660 static const struct expected_method methods_viewcache_with_dib[] =
2662 { "DataObject_QueryGetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2663 { "DataObject_QueryGetData", 0, { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } },
2664 { "DataObject_QueryGetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2665 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2666 { NULL }
2668 static const struct expected_method methods_flags_all[] =
2670 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2671 { "DataObject_GetData", 0, { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } },
2672 { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2673 { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2674 { NULL }
2676 static const struct expected_method methods_flags_ifblank_1[] =
2678 { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2679 { NULL }
2681 static const struct expected_method methods_flags_ifblank_2[] =
2683 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2684 { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2685 { NULL }
2687 static const struct expected_method methods_flags_normal[] =
2689 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2690 { NULL }
2692 static const struct expected_method methods_initcache[] =
2694 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2695 { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2696 { NULL }
2698 static const struct expected_method methods_empty[] =
2700 { NULL }
2703 static STATDATA view_cache[] =
2705 {{ 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 0 }
2707 static STATDATA view_cache_after_dib[] =
2709 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 0 },
2710 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 0 }
2713 static FORMATETC dib_fmt[] =
2715 { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
2716 { 0 }
2719 hr = CreateDataCache( NULL, &CLSID_WineTestOld, &IID_IOleCache2, (void **)&cache );
2720 ok( hr == S_OK, "got %08x\n", hr );
2722 /* No cache slots */
2723 g_dataobject_fmts = NULL;
2724 expected_method_list = NULL;
2726 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2727 ok( hr == S_OK, "got %08x\n", hr );
2729 /* A dib cache slot */
2730 fmt.cfFormat = CF_DIB;
2731 fmt.ptd = NULL;
2732 fmt.dwAspect = DVASPECT_CONTENT;
2733 fmt.lindex = -1;
2734 fmt.tymed = TYMED_HGLOBAL;
2736 hr = IOleCache2_Cache( cache, &fmt, 0, &conn[0] );
2737 ok( hr == S_OK, "got %08x\n", hr );
2739 expected_method_list = methods_dib;
2741 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2742 ok( hr == CACHE_E_NOCACHE_UPDATED, "got %08x\n", hr );
2744 CHECK_NO_EXTRA_METHODS();
2746 /* Now with a dib available */
2747 g_dataobject_fmts = dib_fmt;
2748 expected_method_list = methods_dib;
2750 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2751 ok( hr == S_OK, "got %08x\n", hr );
2753 /* Add an EMF cache slot */
2754 fmt.cfFormat = CF_ENHMETAFILE;
2755 fmt.ptd = NULL;
2756 fmt.dwAspect = DVASPECT_CONTENT;
2757 fmt.lindex = -1;
2758 fmt.tymed = TYMED_ENHMF;
2760 hr = IOleCache2_Cache( cache, &fmt, 0, &conn[1] );
2761 ok( hr == S_OK, "got %08x\n", hr );
2763 g_dataobject_fmts = dib_fmt;
2764 expected_method_list = methods_dib_emf;
2766 /* Two slots to fill, only the dib will succeed */
2767 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2768 ok( hr == S_OK, "got %08x\n", hr );
2770 CHECK_NO_EXTRA_METHODS();
2772 /* Replace the emf slot with a wmf */
2773 hr = IOleCache2_Uncache( cache, conn[1] );
2774 ok( hr == S_OK, "got %08x\n", hr );
2776 fmt.cfFormat = CF_METAFILEPICT;
2777 fmt.ptd = NULL;
2778 fmt.dwAspect = DVASPECT_CONTENT;
2779 fmt.lindex = -1;
2780 fmt.tymed = TYMED_MFPICT;
2782 hr = IOleCache2_Cache( cache, &fmt, 0, &conn[1] );
2783 ok( hr == S_OK, "got %08x\n", hr );
2785 g_dataobject_fmts = dib_fmt;
2786 expected_method_list = methods_dib_wmf;
2788 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2789 ok( hr == S_OK, "got %08x\n", hr );
2791 hr = IOleCache2_Uncache( cache, conn[1] );
2792 ok( hr == S_OK, "got %08x\n", hr );
2793 hr = IOleCache2_Uncache( cache, conn[0] );
2794 ok( hr == S_OK, "got %08x\n", hr );
2796 /* View caching */
2797 fmt.cfFormat = 0;
2798 fmt.ptd = NULL;
2799 fmt.dwAspect = DVASPECT_CONTENT;
2800 fmt.lindex = -1;
2801 fmt.tymed = TYMED_HGLOBAL;
2803 hr = IOleCache2_Cache( cache, &fmt, 0, &conn[0] );
2804 ok( hr == S_OK, "got %08x\n", hr );
2805 view_cache[0].dwConnection = conn[0];
2807 g_dataobject_fmts = NULL;
2808 expected_method_list = methods_viewcache;
2810 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2811 ok( hr == CACHE_E_NOCACHE_UPDATED, "got %08x\n", hr );
2813 CHECK_NO_EXTRA_METHODS();
2814 check_enum_cache( cache, view_cache, 1 );
2816 g_dataobject_fmts = dib_fmt;
2817 expected_method_list = methods_viewcache_with_dib;
2819 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2820 ok( hr == S_OK, "got %08x\n", hr );
2822 CHECK_NO_EXTRA_METHODS();
2823 view_cache_after_dib[0].dwConnection = view_cache_after_dib[1].dwConnection = view_cache[0].dwConnection;
2824 check_enum_cache( cache, view_cache_after_dib, 2 );
2826 hr = IOleCache2_Uncache( cache, conn[0] );
2827 ok( hr == S_OK, "got %08x\n", hr );
2829 /* Try some different flags */
2831 fmt.cfFormat = CF_DIB;
2832 fmt.ptd = NULL;
2833 fmt.dwAspect = DVASPECT_CONTENT;
2834 fmt.lindex = -1;
2835 fmt.tymed = TYMED_HGLOBAL;
2837 hr = IOleCache2_Cache( cache, &fmt, 0, &conn[0] );
2838 ok( hr == S_OK, "got %08x\n", hr );
2840 fmt.cfFormat = CF_ENHMETAFILE;
2841 fmt.ptd = NULL;
2842 fmt.dwAspect = DVASPECT_CONTENT;
2843 fmt.lindex = -1;
2844 fmt.tymed = TYMED_ENHMF;
2846 hr = IOleCache2_Cache( cache, &fmt, ADVF_NODATA, &conn[1] );
2847 ok( hr == S_OK, "got %08x\n", hr );
2849 fmt.cfFormat = CF_METAFILEPICT;
2850 fmt.ptd = NULL;
2851 fmt.dwAspect = DVASPECT_CONTENT;
2852 fmt.lindex = -1;
2853 fmt.tymed = TYMED_MFPICT;
2855 hr = IOleCache2_Cache( cache, &fmt, ADVFCACHE_ONSAVE, &conn[2] );
2856 ok( hr == S_OK, "got %08x\n", hr );
2858 g_dataobject_fmts = dib_fmt;
2859 expected_method_list = methods_flags_all;
2861 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2863 CHECK_NO_EXTRA_METHODS();
2865 expected_method_list = methods_flags_all;
2867 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2868 ok( hr == S_OK, "got %08x\n", hr );
2870 CHECK_NO_EXTRA_METHODS();
2872 expected_method_list = methods_flags_ifblank_1;
2874 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_IFBLANK , NULL );
2875 ok( hr == S_OK, "got %08x\n", hr );
2877 CHECK_NO_EXTRA_METHODS();
2879 hr = IOleCache2_DiscardCache( cache, DISCARDCACHE_NOSAVE );
2880 ok( hr == S_OK, "got %08x\n", hr );
2882 expected_method_list = methods_flags_ifblank_2;
2884 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_IFBLANK , NULL );
2885 ok( hr == S_OK, "got %08x\n", hr );
2887 CHECK_NO_EXTRA_METHODS();
2889 hr = IOleCache2_DiscardCache( cache, DISCARDCACHE_NOSAVE );
2890 ok( hr == S_OK, "got %08x\n", hr );
2892 expected_method_list = methods_flags_all;
2894 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_IFBLANK | UPDFCACHE_NODATACACHE, NULL );
2895 ok( hr == S_OK, "got %08x\n", hr );
2897 CHECK_NO_EXTRA_METHODS();
2899 expected_method_list = methods_empty;
2901 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ONLYIFBLANK | UPDFCACHE_NORMALCACHE, NULL );
2902 ok( hr == S_OK, "got %08x\n", hr );
2904 CHECK_NO_EXTRA_METHODS();
2906 hr = IOleCache2_DiscardCache( cache, DISCARDCACHE_NOSAVE );
2907 ok( hr == S_OK, "got %08x\n", hr );
2909 expected_method_list = methods_flags_normal;
2911 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ONLYIFBLANK | UPDFCACHE_NORMALCACHE, NULL );
2912 ok( hr == S_OK, "got %08x\n", hr );
2914 CHECK_NO_EXTRA_METHODS();
2916 expected_method_list = methods_initcache;
2918 hr = IOleCache2_InitCache( cache, &DataObject );
2919 ok( hr == S_OK, "got %08x\n", hr );
2921 CHECK_NO_EXTRA_METHODS();
2923 IOleCache2_Release( cache );
2926 static void test_default_handler(void)
2928 HRESULT hr;
2929 IOleObject *pObject;
2930 IRunnableObject *pRunnableObject;
2931 IOleClientSite *pClientSite;
2932 IDataObject *pDataObject;
2933 SIZEL sizel;
2934 DWORD dwStatus;
2935 CLSID clsid;
2936 LPOLESTR pszUserType;
2937 LOGPALETTE palette;
2938 DWORD dwAdvConn;
2939 IMoniker *pMoniker;
2940 FORMATETC fmtetc;
2941 IOleInPlaceObject *pInPlaceObj;
2942 IEnumOLEVERB *pEnumVerbs;
2943 DWORD dwRegister;
2944 static const WCHAR wszUnknown[] = {'U','n','k','n','o','w','n',0};
2945 static const WCHAR wszHostName[] = {'W','i','n','e',' ','T','e','s','t',' ','P','r','o','g','r','a','m',0};
2946 static const WCHAR wszDelim[] = {'!',0};
2948 static const struct expected_method methods_embeddinghelper[] =
2950 { "OleObject_QueryInterface", 0 },
2951 { "OleObject_AddRef", 0 },
2952 { "OleObject_QueryInterface", 0 },
2953 { "OleObject_QueryInterface", TEST_TODO },
2954 { "OleObject_QueryInterface", 0 },
2955 { "OleObject_QueryInterface", 0 },
2956 { "OleObject_QueryInterface", TEST_OPTIONAL }, /* Win95/98/NT4 */
2957 { "OleObject_Release", TEST_TODO },
2958 { "WINE_EXTRA", TEST_OPTIONAL },
2959 { NULL, 0 }
2962 hr = CoCreateInstance(&CLSID_WineTest, NULL, CLSCTX_INPROC_HANDLER, &IID_IOleObject, (void **)&pObject);
2963 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance should have failed with REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2965 hr = OleCreateDefaultHandler(&CLSID_WineTest, NULL, &IID_IOleObject, (void **)&pObject);
2966 ok_ole_success(hr, "OleCreateDefaultHandler");
2968 hr = IOleObject_QueryInterface(pObject, &IID_IOleInPlaceObject, (void **)&pInPlaceObj);
2969 ok(hr == E_NOINTERFACE, "IOleObject_QueryInterface(&IID_IOleInPlaceObject) should return E_NOINTERFACE instead of 0x%08x\n", hr);
2971 hr = IOleObject_Advise(pObject, &AdviseSink, &dwAdvConn);
2972 ok_ole_success(hr, "IOleObject_Advise");
2974 hr = IOleObject_Close(pObject, OLECLOSE_NOSAVE);
2975 ok_ole_success(hr, "IOleObject_Close");
2977 /* FIXME: test IOleObject_EnumAdvise */
2979 hr = IOleObject_EnumVerbs(pObject, &pEnumVerbs);
2980 ok(hr == REGDB_E_CLASSNOTREG, "IOleObject_EnumVerbs should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2982 hr = IOleObject_GetClientSite(pObject, &pClientSite);
2983 ok_ole_success(hr, "IOleObject_GetClientSite");
2985 hr = IOleObject_SetClientSite(pObject, pClientSite);
2986 ok_ole_success(hr, "IOleObject_SetClientSite");
2988 hr = IOleObject_GetClipboardData(pObject, 0, &pDataObject);
2989 ok(hr == OLE_E_NOTRUNNING,
2990 "IOleObject_GetClipboardData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n",
2991 hr);
2993 hr = IOleObject_GetExtent(pObject, DVASPECT_CONTENT, &sizel);
2994 ok(hr == OLE_E_BLANK, "IOleObject_GetExtent should have returned OLE_E_BLANK instead of 0x%08x\n",
2995 hr);
2997 hr = IOleObject_GetMiscStatus(pObject, DVASPECT_CONTENT, &dwStatus);
2998 ok(hr == REGDB_E_CLASSNOTREG, "IOleObject_GetMiscStatus should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
3000 hr = IOleObject_GetUserClassID(pObject, &clsid);
3001 ok_ole_success(hr, "IOleObject_GetUserClassID");
3002 ok(IsEqualCLSID(&clsid, &CLSID_WineTest), "clsid != CLSID_WineTest\n");
3004 hr = IOleObject_GetUserType(pObject, USERCLASSTYPE_FULL, &pszUserType);
3005 todo_wine {
3006 ok_ole_success(hr, "IOleObject_GetUserType");
3007 ok(!lstrcmpW(pszUserType, wszUnknown), "Retrieved user type was wrong\n");
3010 hr = IOleObject_InitFromData(pObject, NULL, TRUE, 0);
3011 ok(hr == OLE_E_NOTRUNNING, "IOleObject_InitFromData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
3013 hr = IOleObject_IsUpToDate(pObject);
3014 ok(hr == OLE_E_NOTRUNNING, "IOleObject_IsUpToDate should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
3016 palette.palNumEntries = 1;
3017 palette.palVersion = 2;
3018 memset(&palette.palPalEntry[0], 0, sizeof(palette.palPalEntry[0]));
3019 hr = IOleObject_SetColorScheme(pObject, &palette);
3020 ok(hr == OLE_E_NOTRUNNING, "IOleObject_SetColorScheme should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
3022 sizel.cx = sizel.cy = 0;
3023 hr = IOleObject_SetExtent(pObject, DVASPECT_CONTENT, &sizel);
3024 ok(hr == OLE_E_NOTRUNNING, "IOleObject_SetExtent should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
3026 hr = IOleObject_SetHostNames(pObject, wszHostName, NULL);
3027 ok_ole_success(hr, "IOleObject_SetHostNames");
3029 hr = CreateItemMoniker(wszDelim, wszHostName, &pMoniker);
3030 ok_ole_success(hr, "CreateItemMoniker");
3031 hr = IOleObject_SetMoniker(pObject, OLEWHICHMK_CONTAINER, pMoniker);
3032 ok_ole_success(hr, "IOleObject_SetMoniker");
3033 IMoniker_Release(pMoniker);
3035 hr = IOleObject_GetMoniker(pObject, OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_CONTAINER, &pMoniker);
3036 ok(hr == E_FAIL, "IOleObject_GetMoniker should have returned E_FAIL instead of 0x%08x\n", hr);
3038 hr = IOleObject_Update(pObject);
3039 todo_wine
3040 ok(hr == REGDB_E_CLASSNOTREG, "IOleObject_Update should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
3042 hr = IOleObject_QueryInterface(pObject, &IID_IDataObject, (void **)&pDataObject);
3043 ok_ole_success(hr, "IOleObject_QueryInterface");
3045 fmtetc.cfFormat = CF_TEXT;
3046 fmtetc.ptd = NULL;
3047 fmtetc.dwAspect = DVASPECT_CONTENT;
3048 fmtetc.lindex = -1;
3049 fmtetc.tymed = TYMED_NULL;
3050 hr = IDataObject_DAdvise(pDataObject, &fmtetc, 0, &AdviseSink, &dwAdvConn);
3051 ok_ole_success(hr, "IDataObject_DAdvise");
3053 fmtetc.cfFormat = CF_ENHMETAFILE;
3054 fmtetc.ptd = NULL;
3055 fmtetc.dwAspect = DVASPECT_CONTENT;
3056 fmtetc.lindex = -1;
3057 fmtetc.tymed = TYMED_ENHMF;
3058 hr = IDataObject_DAdvise(pDataObject, &fmtetc, 0, &AdviseSink, &dwAdvConn);
3059 ok_ole_success(hr, "IDataObject_DAdvise");
3061 fmtetc.cfFormat = CF_ENHMETAFILE;
3062 fmtetc.ptd = NULL;
3063 fmtetc.dwAspect = DVASPECT_CONTENT;
3064 fmtetc.lindex = -1;
3065 fmtetc.tymed = TYMED_ENHMF;
3066 hr = IDataObject_QueryGetData(pDataObject, &fmtetc);
3067 ok(hr == OLE_E_NOTRUNNING, "IDataObject_QueryGetData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
3069 fmtetc.cfFormat = CF_TEXT;
3070 fmtetc.ptd = NULL;
3071 fmtetc.dwAspect = DVASPECT_CONTENT;
3072 fmtetc.lindex = -1;
3073 fmtetc.tymed = TYMED_NULL;
3074 hr = IDataObject_QueryGetData(pDataObject, &fmtetc);
3075 ok(hr == OLE_E_NOTRUNNING, "IDataObject_QueryGetData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
3077 hr = IOleObject_QueryInterface(pObject, &IID_IRunnableObject, (void **)&pRunnableObject);
3078 ok_ole_success(hr, "IOleObject_QueryInterface");
3080 hr = IRunnableObject_SetContainedObject(pRunnableObject, TRUE);
3081 ok_ole_success(hr, "IRunnableObject_SetContainedObject");
3083 hr = IRunnableObject_Run(pRunnableObject, NULL);
3084 ok(hr == REGDB_E_CLASSNOTREG, "IOleObject_Run should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
3086 hr = IOleObject_Close(pObject, OLECLOSE_NOSAVE);
3087 ok_ole_success(hr, "IOleObject_Close");
3089 IRunnableObject_Release(pRunnableObject);
3090 IOleObject_Release(pObject);
3092 /* Test failure propagation from delegate ::QueryInterface */
3093 hr = CoRegisterClassObject(&CLSID_WineTest, (IUnknown*)&OleObjectCF,
3094 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegister);
3095 ok_ole_success(hr, "CoRegisterClassObject");
3096 if(SUCCEEDED(hr))
3098 expected_method_list = methods_embeddinghelper;
3099 hr = OleCreateEmbeddingHelper(&CLSID_WineTest, NULL, EMBDHLP_INPROC_SERVER,
3100 &OleObjectCF, &IID_IOleObject, (void**)&pObject);
3101 ok_ole_success(hr, "OleCreateEmbeddingHelper");
3102 if(SUCCEEDED(hr))
3104 IUnknown *punk;
3106 g_QIFailsWith = E_FAIL;
3107 hr = IOleObject_QueryInterface(pObject, &IID_WineTest, (void**)&punk);
3108 ok(hr == E_FAIL, "Got 0x%08x\n", hr);
3110 g_QIFailsWith = E_NOINTERFACE;
3111 hr = IOleObject_QueryInterface(pObject, &IID_WineTest, (void**)&punk);
3112 ok(hr == E_NOINTERFACE, "Got 0x%08x\n", hr);
3114 g_QIFailsWith = CO_E_OBJNOTCONNECTED;
3115 hr = IOleObject_QueryInterface(pObject, &IID_WineTest, (void**)&punk);
3116 ok(hr == CO_E_OBJNOTCONNECTED, "Got 0x%08x\n", hr);
3118 g_QIFailsWith = 0x87654321;
3119 hr = IOleObject_QueryInterface(pObject, &IID_WineTest, (void**)&punk);
3120 ok(hr == 0x87654321, "Got 0x%08x\n", hr);
3122 IOleObject_Release(pObject);
3125 CHECK_NO_EXTRA_METHODS();
3127 hr = CoRevokeClassObject(dwRegister);
3128 ok_ole_success(hr, "CoRevokeClassObject");
3132 static void test_runnable(void)
3134 static const struct expected_method methods_query_runnable[] =
3136 { "OleObject_QueryInterface", 0 },
3137 { "OleObjectRunnable_AddRef", 0 },
3138 { "OleObjectRunnable_IsRunning", 0 },
3139 { "OleObjectRunnable_Release", 0 },
3140 { NULL, 0 }
3143 static const struct expected_method methods_no_runnable[] =
3145 { "OleObject_QueryInterface", 0 },
3146 { NULL, 0 }
3149 BOOL ret;
3150 IOleObject *object = &OleObject;
3152 /* null argument */
3153 ret = OleIsRunning(NULL);
3154 ok(ret == FALSE, "got %d\n", ret);
3156 expected_method_list = methods_query_runnable;
3157 ret = OleIsRunning(object);
3158 ok(ret == TRUE, "Object should be running\n");
3159 CHECK_NO_EXTRA_METHODS();
3161 g_isRunning = FALSE;
3162 expected_method_list = methods_query_runnable;
3163 ret = OleIsRunning(object);
3164 ok(ret == FALSE, "Object should not be running\n");
3165 CHECK_NO_EXTRA_METHODS();
3167 g_showRunnable = FALSE; /* QueryInterface(IID_IRunnableObject, ...) will fail */
3168 expected_method_list = methods_no_runnable;
3169 ret = OleIsRunning(object);
3170 ok(ret == TRUE, "Object without IRunnableObject should be running\n");
3171 CHECK_NO_EXTRA_METHODS();
3173 g_isRunning = TRUE;
3174 g_showRunnable = TRUE;
3178 static HRESULT WINAPI OleRun_QueryInterface(IRunnableObject *iface, REFIID riid, void **ppv)
3180 *ppv = NULL;
3182 if (IsEqualIID(riid, &IID_IUnknown) ||
3183 IsEqualIID(riid, &IID_IRunnableObject)) {
3184 *ppv = iface;
3187 if (*ppv)
3189 IUnknown_AddRef((IUnknown *)*ppv);
3190 return S_OK;
3193 return E_NOINTERFACE;
3196 static ULONG WINAPI OleRun_AddRef(IRunnableObject *iface)
3198 return 2;
3201 static ULONG WINAPI OleRun_Release(IRunnableObject *iface)
3203 return 1;
3206 static HRESULT WINAPI OleRun_GetRunningClass(IRunnableObject *iface, CLSID *clsid)
3208 ok(0, "unexpected\n");
3209 return E_NOTIMPL;
3212 static HRESULT WINAPI OleRun_Run(IRunnableObject *iface, LPBINDCTX ctx)
3214 ok(ctx == NULL, "got %p\n", ctx);
3215 return 0xdeadc0de;
3218 static BOOL WINAPI OleRun_IsRunning(IRunnableObject *iface)
3220 ok(0, "unexpected\n");
3221 return FALSE;
3224 static HRESULT WINAPI OleRun_LockRunning(IRunnableObject *iface, BOOL lock,
3225 BOOL last_unlock_closes)
3227 ok(0, "unexpected\n");
3228 return E_NOTIMPL;
3231 static HRESULT WINAPI OleRun_SetContainedObject(IRunnableObject *iface, BOOL contained)
3233 ok(0, "unexpected\n");
3234 return E_NOTIMPL;
3237 static const IRunnableObjectVtbl oleruntestvtbl =
3239 OleRun_QueryInterface,
3240 OleRun_AddRef,
3241 OleRun_Release,
3242 OleRun_GetRunningClass,
3243 OleRun_Run,
3244 OleRun_IsRunning,
3245 OleRun_LockRunning,
3246 OleRun_SetContainedObject
3249 static IRunnableObject testrunnable = { &oleruntestvtbl };
3251 static void test_OleRun(void)
3253 HRESULT hr;
3255 /* doesn't support IRunnableObject */
3256 hr = OleRun(&unknown);
3257 ok(hr == S_OK, "OleRun failed 0x%08x\n", hr);
3259 hr = OleRun((IUnknown*)&testrunnable);
3260 ok(hr == 0xdeadc0de, "got 0x%08x\n", hr);
3263 static void test_OleLockRunning(void)
3265 HRESULT hr;
3267 hr = OleLockRunning(&unknown, TRUE, FALSE);
3268 ok(hr == S_OK, "OleLockRunning failed 0x%08x\n", hr);
3271 static void test_OleDraw(void)
3273 HRESULT hr;
3274 RECT rect;
3276 hr = OleDraw((IUnknown*)&viewobject, 0, (HDC)0x1, NULL);
3277 ok(hr == S_OK, "got 0x%08x\n", hr);
3279 hr = OleDraw(NULL, 0, (HDC)0x1, NULL);
3280 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3282 hr = OleDraw(NULL, 0, (HDC)0x1, &rect);
3283 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3286 static const WCHAR olepres0W[] = {2,'O','l','e','P','r','e','s','0','0','0',0};
3287 static const WCHAR comp_objW[] = {1,'C','o','m','p','O','b','j',0};
3288 static IStream *comp_obj_stream;
3289 static IStream *ole_stream;
3290 static IStream *olepres_stream;
3291 static IStream *contents_stream;
3293 static HRESULT WINAPI Storage_QueryInterface(IStorage *iface, REFIID riid, void **ppvObject)
3295 ok(0, "unexpected call to QueryInterface\n");
3296 return E_NOTIMPL;
3299 static ULONG WINAPI Storage_AddRef(IStorage *iface)
3301 ok(0, "unexpected call to AddRef\n");
3302 return 2;
3305 static ULONG WINAPI Storage_Release(IStorage *iface)
3307 ok(0, "unexpected call to Release\n");
3308 return 1;
3311 static HRESULT WINAPI Storage_CreateStream(IStorage *iface, LPCOLESTR pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStream **ppstm)
3313 ULARGE_INTEGER size = {{0}};
3314 LARGE_INTEGER pos = {{0}};
3315 HRESULT hr;
3317 if (!lstrcmpW(pwcsName, comp_objW))
3319 CHECK_EXPECT(Storage_CreateStream_CompObj);
3320 *ppstm = comp_obj_stream;
3322 todo_wine ok(grfMode == (STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
3324 else if (!lstrcmpW(pwcsName, olepres0W))
3326 CHECK_EXPECT(Storage_CreateStream_OlePres);
3327 *ppstm = olepres_stream;
3329 todo_wine ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
3331 else
3333 todo_wine
3334 ok(0, "unexpected stream name %s\n", wine_dbgstr_w(pwcsName));
3335 #if 0 /* FIXME: return NULL once Wine is fixed */
3336 *ppstm = NULL;
3337 return E_NOTIMPL;
3338 #else
3339 *ppstm = contents_stream;
3340 #endif
3343 ok(!reserved1, "reserved1 = %x\n", reserved1);
3344 ok(!reserved2, "reserved2 = %x\n", reserved2);
3345 ok(!!ppstm, "ppstm = NULL\n");
3347 IStream_AddRef(*ppstm);
3348 hr = IStream_Seek(*ppstm, pos, STREAM_SEEK_SET, NULL);
3349 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3350 hr = IStream_SetSize(*ppstm, size);
3351 ok(hr == S_OK, "IStream_SetSize returned %x\n", hr);
3352 return S_OK;
3355 static HRESULT WINAPI Storage_OpenStream(IStorage *iface, LPCOLESTR pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream **ppstm)
3357 static const WCHAR ole1W[] = {1,'O','l','e',0};
3359 LARGE_INTEGER pos = {{0}};
3360 HRESULT hr;
3362 ok(!reserved1, "reserved1 = %p\n", reserved1);
3363 ok(!reserved2, "reserved2 = %x\n", reserved2);
3364 ok(!!ppstm, "ppstm = NULL\n");
3366 if(!lstrcmpW(pwcsName, comp_objW)) {
3367 CHECK_EXPECT2(Storage_OpenStream_CompObj);
3368 ok(grfMode == STGM_SHARE_EXCLUSIVE, "grfMode = %x\n", grfMode);
3370 *ppstm = comp_obj_stream;
3371 IStream_AddRef(comp_obj_stream);
3372 hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL);
3373 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3374 return S_OK;
3375 }else if(!lstrcmpW(pwcsName, ole1W)) {
3376 CHECK_EXPECT(Storage_OpenStream_Ole);
3378 if (!ole_stream)
3380 ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READ), "grfMode = %x\n", grfMode);
3382 *ppstm = NULL;
3383 return STG_E_FILENOTFOUND;
3386 ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
3388 *ppstm = ole_stream;
3389 IStream_AddRef(ole_stream);
3390 hr = IStream_Seek(ole_stream, pos, STREAM_SEEK_SET, NULL);
3391 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3392 return S_OK;
3394 }else if(!lstrcmpW(pwcsName, olepres0W)) {
3395 CHECK_EXPECT(Storage_OpenStream_OlePres);
3396 ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
3398 *ppstm = olepres_stream;
3399 IStream_AddRef(olepres_stream);
3400 hr = IStream_Seek(olepres_stream, pos, STREAM_SEEK_SET, NULL);
3401 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3402 return S_OK;
3405 ok(0, "unexpected call to OpenStream: %s\n", wine_dbgstr_w(pwcsName));
3406 return E_NOTIMPL;
3409 static HRESULT WINAPI Storage_CreateStorage(IStorage *iface, LPCOLESTR pwcsName, DWORD grfMode, DWORD dwStgFmt, DWORD reserved2, IStorage **ppstg)
3411 ok(0, "unexpected call to CreateStorage\n");
3412 return E_NOTIMPL;
3415 static HRESULT WINAPI Storage_OpenStorage(IStorage *iface, LPCOLESTR pwcsName, IStorage *pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage **ppstg)
3417 ok(0, "unexpected call to OpenStorage\n");
3418 return E_NOTIMPL;
3421 static HRESULT WINAPI Storage_CopyTo(IStorage *iface, DWORD ciidExclude, const IID *rgiidExclude, SNB snbExclude, IStorage *pstgDest)
3423 ok(0, "unexpected call to CopyTo\n");
3424 return E_NOTIMPL;
3427 static HRESULT WINAPI Storage_MoveElementTo(IStorage *iface, LPCOLESTR pwcsName, IStorage *pstgDest, LPCOLESTR pwcsNewName, DWORD grfFlags)
3429 ok(0, "unexpected call to MoveElementTo\n");
3430 return E_NOTIMPL;
3433 static HRESULT WINAPI Storage_Commit(IStorage *iface, DWORD grfCommitFlags)
3435 ok(0, "unexpected call to Commit\n");
3436 return E_NOTIMPL;
3439 static HRESULT WINAPI Storage_Revert(IStorage *iface)
3441 ok(0, "unexpected call to Revert\n");
3442 return E_NOTIMPL;
3445 static HRESULT WINAPI Storage_EnumElements(IStorage *iface, DWORD reserved1, void *reserved2, DWORD reserved3, IEnumSTATSTG **ppenum)
3447 ok(0, "unexpected call to EnumElements\n");
3448 return E_NOTIMPL;
3451 static HRESULT WINAPI Storage_DestroyElement(IStorage *iface, LPCOLESTR pwcsName)
3453 char name[32];
3454 int stream_n, cmp;
3456 CHECK_EXPECT2(Storage_DestroyElement);
3457 cmp = CompareStringW(LOCALE_NEUTRAL, 0, pwcsName, 8, olepres0W, 8);
3458 ok(cmp == CSTR_EQUAL,
3459 "unexpected call to DestroyElement(%s)\n", wine_dbgstr_w(pwcsName));
3461 WideCharToMultiByte(CP_ACP, 0, pwcsName, -1, name, sizeof(name), NULL, NULL);
3462 stream_n = atol(name + 8);
3463 if (stream_n <= Storage_DestroyElement_limit)
3464 return S_OK;
3466 return STG_E_FILENOTFOUND;
3469 static HRESULT WINAPI Storage_RenameElement(IStorage *iface, LPCOLESTR pwcsOldName, LPCOLESTR pwcsNewName)
3471 ok(0, "unexpected call to RenameElement\n");
3472 return E_NOTIMPL;
3475 static HRESULT WINAPI Storage_SetElementTimes(IStorage *iface, LPCOLESTR pwcsName, const FILETIME *pctime, const FILETIME *patime, const FILETIME *pmtime)
3477 ok(0, "unexpected call to SetElementTimes\n");
3478 return E_NOTIMPL;
3481 static HRESULT WINAPI Storage_SetClass(IStorage *iface, REFCLSID clsid)
3483 CHECK_EXPECT(Storage_SetClass);
3484 ok(IsEqualIID(clsid, Storage_SetClass_CLSID), "expected %s, got %s\n",
3485 wine_dbgstr_guid(Storage_SetClass_CLSID), wine_dbgstr_guid(clsid));
3486 return S_OK;
3489 static HRESULT WINAPI Storage_SetStateBits(IStorage *iface, DWORD grfStateBits, DWORD grfMask)
3491 ok(0, "unexpected call to SetStateBits\n");
3492 return E_NOTIMPL;
3495 static HRESULT WINAPI Storage_Stat(IStorage *iface, STATSTG *pstatstg, DWORD grfStatFlag)
3497 CHECK_EXPECT2(Storage_Stat);
3498 ok(pstatstg != NULL, "pstatstg = NULL\n");
3499 ok(grfStatFlag == STATFLAG_NONAME, "grfStatFlag = %x\n", grfStatFlag);
3501 memset(pstatstg, 0, sizeof(STATSTG));
3502 pstatstg->type = STGTY_STORAGE;
3503 pstatstg->clsid = CLSID_WineTestOld;
3504 return S_OK;
3507 static IStorageVtbl StorageVtbl =
3509 Storage_QueryInterface,
3510 Storage_AddRef,
3511 Storage_Release,
3512 Storage_CreateStream,
3513 Storage_OpenStream,
3514 Storage_CreateStorage,
3515 Storage_OpenStorage,
3516 Storage_CopyTo,
3517 Storage_MoveElementTo,
3518 Storage_Commit,
3519 Storage_Revert,
3520 Storage_EnumElements,
3521 Storage_DestroyElement,
3522 Storage_RenameElement,
3523 Storage_SetElementTimes,
3524 Storage_SetClass,
3525 Storage_SetStateBits,
3526 Storage_Stat
3529 static IStorage Storage = { &StorageVtbl };
3531 static void test_OleDoAutoConvert(void)
3533 static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0};
3534 static struct {
3535 DWORD reserved1;
3536 DWORD version;
3537 DWORD reserved2[5];
3538 DWORD ansi_user_type_len;
3539 DWORD ansi_clipboard_format_len;
3540 DWORD reserved3;
3541 DWORD unicode_marker;
3542 DWORD unicode_user_type_len;
3543 DWORD unicode_clipboard_format_len;
3544 DWORD reserved4;
3545 } comp_obj_data;
3546 static struct {
3547 DWORD version;
3548 DWORD flags;
3549 DWORD link_update_option;
3550 DWORD reserved1;
3551 DWORD reserved_moniker_stream_size;
3552 DWORD relative_source_moniker_stream_size;
3553 DWORD absolute_source_moniker_stream_size;
3554 DWORD clsid_indicator;
3555 CLSID clsid;
3556 DWORD reserved_display_name;
3557 DWORD reserved2;
3558 DWORD local_update_time;
3559 DWORD local_check_update_time;
3560 DWORD remote_update_time;
3561 } ole_data;
3563 LARGE_INTEGER pos = {{0}};
3564 WCHAR buf[39+6];
3565 DWORD i, ret;
3566 HKEY root;
3567 CLSID clsid;
3568 HRESULT hr;
3570 hr = CreateStreamOnHGlobal(NULL, TRUE, &comp_obj_stream);
3571 ok(hr == S_OK, "CreateStreamOnHGlobal returned %x\n", hr);
3572 hr = IStream_Write(comp_obj_stream, (char*)&comp_obj_data, sizeof(comp_obj_data), NULL);
3573 ok(hr == S_OK, "IStream_Write returned %x\n", hr);
3575 hr = CreateStreamOnHGlobal(NULL, TRUE, &ole_stream);
3576 ok(hr == S_OK, "CreateStreamOnHGlobal returned %x\n", hr);
3577 hr = IStream_Write(ole_stream, (char*)&ole_data, sizeof(ole_data), NULL);
3578 ok(hr == S_OK, "IStream_Write returned %x\n", hr);
3580 clsid = IID_WineTest;
3581 hr = OleDoAutoConvert(NULL, &clsid);
3582 ok(hr == E_INVALIDARG, "OleDoAutoConvert returned %x\n", hr);
3583 ok(IsEqualIID(&clsid, &IID_NULL), "clsid = %s\n", wine_dbgstr_guid(&clsid));
3585 if(0) /* crashes on Win7 */
3586 OleDoAutoConvert(&Storage, NULL);
3588 clsid = IID_WineTest;
3589 SET_EXPECT(Storage_Stat);
3590 hr = OleDoAutoConvert(&Storage, &clsid);
3591 ok(hr == REGDB_E_CLASSNOTREG, "OleDoAutoConvert returned %x\n", hr);
3592 CHECK_CALLED(Storage_Stat);
3593 ok(IsEqualIID(&clsid, &CLSID_WineTestOld), "clsid = %s\n", wine_dbgstr_guid(&clsid));
3595 lstrcpyW(buf, clsidW);
3596 StringFromGUID2(&CLSID_WineTestOld, buf+6, 39);
3598 ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, buf, 0, NULL, 0,
3599 KEY_READ | KEY_WRITE | KEY_CREATE_SUB_KEY, NULL, &root, NULL);
3600 if(ret != ERROR_SUCCESS) {
3601 win_skip("not enough permissions to create CLSID key (%u)\n", ret);
3602 return;
3605 clsid = IID_WineTest;
3606 SET_EXPECT(Storage_Stat);
3607 hr = OleDoAutoConvert(&Storage, &clsid);
3608 ok(hr == REGDB_E_KEYMISSING, "OleDoAutoConvert returned %x\n", hr);
3609 CHECK_CALLED(Storage_Stat);
3610 ok(IsEqualIID(&clsid, &CLSID_WineTestOld), "clsid = %s\n", wine_dbgstr_guid(&clsid));
3612 hr = OleSetAutoConvert(&CLSID_WineTestOld, &CLSID_WineTest);
3613 ok_ole_success(hr, "OleSetAutoConvert");
3615 hr = OleGetAutoConvert(&CLSID_WineTestOld, &clsid);
3616 ok_ole_success(hr, "OleGetAutoConvert");
3617 ok(IsEqualIID(&clsid, &CLSID_WineTest), "incorrect clsid: %s\n", wine_dbgstr_guid(&clsid));
3619 clsid = IID_WineTest;
3620 SET_EXPECT(Storage_Stat);
3621 SET_EXPECT(Storage_OpenStream_CompObj);
3622 SET_EXPECT(Storage_SetClass);
3623 SET_EXPECT(Storage_CreateStream_CompObj);
3624 SET_EXPECT(Storage_OpenStream_Ole);
3625 hr = OleDoAutoConvert(&Storage, &clsid);
3626 ok(hr == S_OK, "OleDoAutoConvert returned %x\n", hr);
3627 CHECK_CALLED(Storage_Stat);
3628 CHECK_CALLED(Storage_OpenStream_CompObj);
3629 CHECK_CALLED(Storage_SetClass);
3630 CHECK_CALLED(Storage_CreateStream_CompObj);
3631 CHECK_CALLED(Storage_OpenStream_Ole);
3632 ok(IsEqualIID(&clsid, &CLSID_WineTest), "clsid = %s\n", wine_dbgstr_guid(&clsid));
3634 hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL);
3635 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3636 hr = IStream_Read(comp_obj_stream, &comp_obj_data, sizeof(comp_obj_data), NULL);
3637 ok(hr == S_OK, "IStream_Read returned %x\n", hr);
3638 ok(comp_obj_data.reserved1 == 0xfffe0001, "reserved1 = %x\n", comp_obj_data.reserved1);
3639 ok(comp_obj_data.version == 0xa03, "version = %x\n", comp_obj_data.version);
3640 ok(comp_obj_data.reserved2[0] == -1, "reserved2[0] = %x\n", comp_obj_data.reserved2[0]);
3641 ok(IsEqualIID(comp_obj_data.reserved2+1, &CLSID_WineTestOld), "reserved2 = %s\n", wine_dbgstr_guid((CLSID*)(comp_obj_data.reserved2+1)));
3642 ok(!comp_obj_data.ansi_user_type_len, "ansi_user_type_len = %d\n", comp_obj_data.ansi_user_type_len);
3643 ok(!comp_obj_data.ansi_clipboard_format_len, "ansi_clipboard_format_len = %d\n", comp_obj_data.ansi_clipboard_format_len);
3644 ok(!comp_obj_data.reserved3, "reserved3 = %x\n", comp_obj_data.reserved3);
3645 ok(comp_obj_data.unicode_marker == 0x71b239f4, "unicode_marker = %x\n", comp_obj_data.unicode_marker);
3646 ok(!comp_obj_data.unicode_user_type_len, "unicode_user_type_len = %d\n", comp_obj_data.unicode_user_type_len);
3647 ok(!comp_obj_data.unicode_clipboard_format_len, "unicode_clipboard_format_len = %d\n", comp_obj_data.unicode_clipboard_format_len);
3648 ok(!comp_obj_data.reserved4, "reserved4 %d\n", comp_obj_data.reserved4);
3650 hr = IStream_Seek(ole_stream, pos, STREAM_SEEK_SET, NULL);
3651 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3652 hr = IStream_Read(ole_stream, &ole_data, sizeof(ole_data), NULL);
3653 ok(hr == S_OK, "IStream_Read returned %x\n", hr);
3654 ok(ole_data.version == 0, "version = %x\n", ole_data.version);
3655 ok(ole_data.flags == 4, "flags = %x\n", ole_data.flags);
3656 for(i=2; i<sizeof(ole_data)/sizeof(DWORD); i++)
3657 ok(((DWORD*)&ole_data)[i] == 0, "ole_data[%d] = %x\n", i, ((DWORD*)&ole_data)[i]);
3659 SET_EXPECT(Storage_OpenStream_Ole);
3660 hr = SetConvertStg(&Storage, TRUE);
3661 ok(hr == S_OK, "SetConvertStg returned %x\n", hr);
3662 CHECK_CALLED(Storage_OpenStream_Ole);
3664 SET_EXPECT(Storage_OpenStream_CompObj);
3665 SET_EXPECT(Storage_Stat);
3666 SET_EXPECT(Storage_CreateStream_CompObj);
3667 hr = WriteFmtUserTypeStg(&Storage, 0, NULL);
3668 ok(hr == S_OK, "WriteFmtUserTypeStg returned %x\n", hr);
3669 todo_wine CHECK_CALLED(Storage_OpenStream_CompObj);
3670 CHECK_CALLED(Storage_Stat);
3671 CHECK_CALLED(Storage_CreateStream_CompObj);
3672 hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL);
3673 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3674 hr = IStream_Read(comp_obj_stream, &comp_obj_data, sizeof(comp_obj_data), NULL);
3675 ok(hr == S_OK, "IStream_Read returned %x\n", hr);
3676 ok(comp_obj_data.reserved1 == 0xfffe0001, "reserved1 = %x\n", comp_obj_data.reserved1);
3677 ok(comp_obj_data.version == 0xa03, "version = %x\n", comp_obj_data.version);
3678 ok(comp_obj_data.reserved2[0] == -1, "reserved2[0] = %x\n", comp_obj_data.reserved2[0]);
3679 ok(IsEqualIID(comp_obj_data.reserved2+1, &CLSID_WineTestOld), "reserved2 = %s\n", wine_dbgstr_guid((CLSID*)(comp_obj_data.reserved2+1)));
3680 ok(!comp_obj_data.ansi_user_type_len, "ansi_user_type_len = %d\n", comp_obj_data.ansi_user_type_len);
3681 ok(!comp_obj_data.ansi_clipboard_format_len, "ansi_clipboard_format_len = %d\n", comp_obj_data.ansi_clipboard_format_len);
3682 ok(!comp_obj_data.reserved3, "reserved3 = %x\n", comp_obj_data.reserved3);
3683 ok(comp_obj_data.unicode_marker == 0x71b239f4, "unicode_marker = %x\n", comp_obj_data.unicode_marker);
3684 ok(!comp_obj_data.unicode_user_type_len, "unicode_user_type_len = %d\n", comp_obj_data.unicode_user_type_len);
3685 ok(!comp_obj_data.unicode_clipboard_format_len, "unicode_clipboard_format_len = %d\n", comp_obj_data.unicode_clipboard_format_len);
3686 ok(!comp_obj_data.reserved4, "reserved4 %d\n", comp_obj_data.reserved4);
3688 ret = IStream_Release(comp_obj_stream);
3689 ok(!ret, "comp_obj_stream was not freed\n");
3690 ret = IStream_Release(ole_stream);
3691 ok(!ret, "ole_stream was not freed\n");
3693 ret = RegDeleteKeyA(root, "AutoConvertTo");
3694 ok(ret == ERROR_SUCCESS, "RegDeleteKey error %u\n", ret);
3695 ret = RegDeleteKeyA(root, "");
3696 ok(ret == ERROR_SUCCESS, "RegDeleteKey error %u\n", ret);
3697 RegCloseKey(root);
3700 /* 1x1 pixel bmp */
3701 static const unsigned char bmpimage[] =
3703 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,
3704 0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
3705 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
3706 0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
3707 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,
3708 0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
3709 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,
3710 0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
3711 0x00,0x00
3714 static const unsigned char mf_blank_bits[] =
3716 0x01,0x00,0x09,0x00,0x00,0x03,0x0c,0x00,
3717 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
3718 0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00
3721 static void test_data_cache_save(void)
3723 static const WCHAR contentsW[] = { 'C','o','n','t','e','n','t','s',0 };
3724 HRESULT hr;
3725 ILockBytes *ilb;
3726 IStorage *doc;
3727 IStream *stm;
3728 IOleCache2 *cache;
3729 IPersistStorage *stg;
3730 DWORD clipformat[2];
3731 PresentationDataHeader hdr;
3733 hr = CreateILockBytesOnHGlobal(0, TRUE, &ilb);
3734 ok(hr == S_OK, "unexpected %#x\n", hr);
3735 hr = StgCreateDocfileOnILockBytes(ilb, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &doc);
3736 ok(hr == S_OK, "unexpected %#x\n", hr);
3738 ILockBytes_Release(ilb);
3740 hr = IStorage_SetClass(doc, &CLSID_WineTest);
3741 ok(hr == S_OK, "unexpected %#x\n", hr);
3743 hr = IStorage_CreateStream(doc, contentsW, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3744 ok(hr == S_OK, "unexpected %#x\n", hr);
3745 hr = IStream_Write(stm, bmpimage, sizeof(bmpimage), NULL);
3746 ok(hr == S_OK, "unexpected %#x\n", hr);
3747 IStream_Release(stm);
3749 hr = IStorage_CreateStream(doc, olepres0W, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3750 ok(hr == S_OK, "unexpected %#x\n", hr);
3752 clipformat[0] = -1;
3753 clipformat[1] = CF_METAFILEPICT;
3754 hr = IStream_Write(stm, clipformat, sizeof(clipformat), NULL);
3755 ok(hr == S_OK, "unexpected %#x\n", hr);
3757 hdr.tdSize = sizeof(hdr.tdSize);
3758 hdr.dvAspect = DVASPECT_CONTENT;
3759 hdr.lindex = -1;
3760 hdr.advf = ADVF_PRIMEFIRST;
3761 hdr.unknown7 = 0;
3762 hdr.dwObjectExtentX = 0;
3763 hdr.dwObjectExtentY = 0;
3764 hdr.dwSize = sizeof(mf_blank_bits);
3765 hr = IStream_Write(stm, &hdr, sizeof(hdr), NULL);
3766 ok(hr == S_OK, "unexpected %#x\n", hr);
3767 hr = IStream_Write(stm, mf_blank_bits, sizeof(mf_blank_bits), NULL);
3768 ok(hr == S_OK, "unexpected %#x\n", hr);
3770 IStream_Release(stm);
3772 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IUnknown, (void **)&cache);
3773 ok(hr == S_OK, "unexpected %#x\n", hr);
3774 hr = IOleCache2_QueryInterface(cache, &IID_IPersistStorage, (void **)&stg);
3775 ok(hr == S_OK, "unexpected %#x\n", hr);
3776 hr = IPersistStorage_Load(stg, doc);
3777 ok(hr == S_OK, "unexpected %#x\n", hr);
3779 IStorage_Release(doc);
3781 hr = IPersistStorage_IsDirty(stg);
3782 ok(hr == S_FALSE, "unexpected %#x\n", hr);
3784 ole_stream = NULL;
3785 hr = CreateStreamOnHGlobal(NULL, TRUE, &olepres_stream);
3786 ok(hr == S_OK, "unexpected %#x\n", hr);
3788 /* FIXME: remove this stream once Wine is fixed */
3789 hr = CreateStreamOnHGlobal(NULL, TRUE, &contents_stream);
3790 ok(hr == S_OK, "unexpected %#x\n", hr);
3792 SET_EXPECT(Storage_CreateStream_OlePres);
3793 SET_EXPECT(Storage_OpenStream_OlePres);
3794 SET_EXPECT(Storage_OpenStream_Ole);
3795 SET_EXPECT(Storage_DestroyElement);
3796 Storage_DestroyElement_limit = 50;
3797 Storage_SetClass_CLSID = &CLSID_NULL;
3798 trace("IPersistStorage_Save:\n");
3799 hr = IPersistStorage_Save(stg, &Storage, FALSE);
3800 ok(hr == S_OK, "unexpected %#x\n", hr);
3801 CHECK_CALLED(Storage_CreateStream_OlePres);
3802 todo_wine
3803 CHECK_CALLED(Storage_OpenStream_OlePres);
3804 todo_wine
3805 CHECK_CALLED(Storage_OpenStream_Ole);
3806 todo_wine
3807 CHECK_CALLED(Storage_DestroyElement);
3809 IStream_Release(olepres_stream);
3810 IStream_Release(contents_stream);
3812 IPersistStorage_Release(stg);
3813 IOleCache2_Release(cache);
3816 #define MAX_STREAM 16
3818 struct stream_def
3820 const char *name;
3821 int cf;
3822 DVASPECT dvAspect;
3823 ADVF advf;
3824 const void *data;
3825 size_t data_size;
3828 struct storage_def
3830 const CLSID *clsid;
3831 int stream_count;
3832 struct stream_def stream[MAX_STREAM];
3835 static const struct storage_def stg_def_0 =
3837 &CLSID_NULL, 1,
3838 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) }}
3840 static const struct storage_def stg_def_0_saved =
3842 &CLSID_NULL, 0, {{ 0 }}
3844 static const struct storage_def stg_def_1 =
3846 &CLSID_NULL, 2,
3847 {{ "Contents", -1, 0, 0, NULL, 0 },
3848 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3850 static const struct storage_def stg_def_1_saved =
3852 &CLSID_NULL, 1,
3853 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3855 static const struct storage_def stg_def_2 =
3857 &CLSID_ManualResetEvent, 2,
3858 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3859 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3861 static const struct storage_def stg_def_2_saved =
3863 &CLSID_NULL, 1,
3864 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3866 static const struct storage_def stg_def_3 =
3868 &CLSID_NULL, 5,
3869 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3870 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3871 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3872 { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
3873 { "MyStream", -1, 0, 0, "Hello World!", 13 }}
3875 static const struct storage_def stg_def_3_saved =
3877 &CLSID_NULL, 3,
3878 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3879 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3880 { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) }}
3882 static const struct storage_def stg_def_4 =
3884 &CLSID_Picture_EnhMetafile, 5,
3885 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3886 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3887 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3888 { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
3889 { "MyStream", -1, 0, 0, "Hello World!", 13 }}
3891 static const struct storage_def stg_def_4_saved =
3893 &CLSID_NULL, 1,
3894 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3896 static const struct storage_def stg_def_5 =
3898 &CLSID_Picture_Dib, 5,
3899 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3900 { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
3901 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3902 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3903 { "MyStream", -1, 0, 0, "Hello World!", 13 }}
3905 static const struct storage_def stg_def_5_saved =
3907 &CLSID_NULL, 1,
3908 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3910 static const struct storage_def stg_def_6 =
3912 &CLSID_Picture_Metafile, 5,
3913 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3914 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3915 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3916 { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
3917 { "MyStream", -1, 0, 0, "Hello World!", 13 }}
3919 static const struct storage_def stg_def_6_saved =
3921 &CLSID_NULL, 1,
3922 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3924 static const struct storage_def stg_def_7 =
3926 &CLSID_Picture_Dib, 1,
3927 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) }}
3929 static const struct storage_def stg_def_7_saved =
3931 &CLSID_NULL, 0, {{ 0 }}
3933 static const struct storage_def stg_def_8 =
3935 &CLSID_Picture_Metafile, 1,
3936 {{ "Contents", -1, 0, 0, mf_blank_bits, sizeof(mf_blank_bits) }}
3938 static const struct storage_def stg_def_8_saved =
3940 &CLSID_NULL, 0, {{ 0 }}
3942 static const struct storage_def stg_def_9 =
3944 &CLSID_Picture_EnhMetafile, 1,
3945 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) }}
3947 static const struct storage_def stg_def_9_saved =
3949 &CLSID_NULL, 0, {{ 0 }}
3952 static int read_clipformat(IStream *stream)
3954 HRESULT hr;
3955 ULONG bytes;
3956 int length, clipformat = -2;
3958 hr = IStream_Read(stream, &length, sizeof(length), &bytes);
3959 if (hr != S_OK || bytes != sizeof(length))
3960 return -2;
3961 if (length == 0)
3962 return 0;
3963 if (length == -1)
3965 hr = IStream_Read(stream, &clipformat, sizeof(clipformat), &bytes);
3966 if (hr != S_OK || bytes != sizeof(clipformat))
3967 return -2;
3969 else
3970 ok(0, "unhandled clipformat length %d\n", length);
3972 return clipformat;
3975 static void check_storage_contents(IStorage *stg, const struct storage_def *stg_def,
3976 int *enumerated_streams, int *matched_streams)
3978 HRESULT hr;
3979 IEnumSTATSTG *enumstg;
3980 IStream *stream;
3981 STATSTG stat;
3982 int i, seen_stream[MAX_STREAM] = { 0 };
3984 if (winetest_debug > 1)
3985 trace("check_storage_contents:\n=============================================\n");
3987 *enumerated_streams = 0;
3988 *matched_streams = 0;
3990 hr = IStorage_Stat(stg, &stat, STATFLAG_NONAME);
3991 ok(hr == S_OK, "unexpected %#x\n", hr);
3992 ok(IsEqualCLSID(stg_def->clsid, &stat.clsid), "expected %s, got %s\n",
3993 wine_dbgstr_guid(stg_def->clsid), wine_dbgstr_guid(&stat.clsid));
3995 hr = IStorage_EnumElements(stg, 0, NULL, 0, &enumstg);
3996 ok(hr == S_OK, "unexpected %#x\n", hr);
3998 for (;;)
4000 ULONG bytes;
4001 int clipformat = -1;
4002 PresentationDataHeader header;
4003 char name[32];
4004 BYTE data[1024];
4006 memset(&header, 0, sizeof(header));
4008 hr = IEnumSTATSTG_Next(enumstg, 1, &stat, NULL);
4009 if(hr == S_FALSE) break;
4010 ok(hr == S_OK, "unexpected %#x\n", hr);
4012 if (winetest_debug > 1)
4013 trace("name %s, type %u, size %d, clsid %s\n",
4014 wine_dbgstr_w(stat.pwcsName), stat.type, stat.cbSize.u.LowPart, wine_dbgstr_guid(&stat.clsid));
4016 ok(stat.type == STGTY_STREAM, "unexpected %#x\n", stat.type);
4018 WideCharToMultiByte(CP_ACP, 0, stat.pwcsName, -1, name, sizeof(name), NULL, NULL);
4020 hr = IStorage_OpenStream(stg, stat.pwcsName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream);
4021 ok(hr == S_OK, "unexpected %#x\n", hr);
4023 if (!memcmp(name, "\2OlePres", 8))
4025 ULONG header_size = sizeof(header);
4027 clipformat = read_clipformat(stream);
4029 if (clipformat == 0) /* view cache */
4030 header_size = FIELD_OFFSET(PresentationDataHeader, unknown7);
4032 hr = IStream_Read(stream, &header, header_size, &bytes);
4033 ok(hr == S_OK, "unexpected %#x\n", hr);
4034 ok(bytes == header_size, "read %u bytes, expected %u\n", bytes, header_size);
4036 if (winetest_debug > 1)
4037 trace("header: tdSize %#x, dvAspect %#x, lindex %#x, advf %#x, unknown7 %#x, dwObjectExtentX %#x, dwObjectExtentY %#x, dwSize %#x\n",
4038 header.tdSize, header.dvAspect, header.lindex, header.advf, header.unknown7,
4039 header.dwObjectExtentX, header.dwObjectExtentY, header.dwSize);
4042 memset(data, 0, sizeof(data));
4043 hr = IStream_Read(stream, data, sizeof(data), &bytes);
4044 ok(hr == S_OK, "unexpected %#x\n", hr);
4045 if (winetest_debug > 1)
4046 trace("stream data (%u bytes): %02x %02x %02x %02x\n", bytes, data[0], data[1], data[2], data[3]);
4048 for (i = 0; i < stg_def->stream_count; i++)
4050 if (seen_stream[i]) continue;
4052 if (winetest_debug > 1)
4053 trace("%s/%s, %d/%d, %d/%d, %d/%d\n",
4054 stg_def->stream[i].name, name,
4055 stg_def->stream[i].cf, clipformat,
4056 stg_def->stream[i].dvAspect, header.dvAspect,
4057 stg_def->stream[i].advf, header.advf);
4059 if (!strcmp(stg_def->stream[i].name, name) &&
4060 stg_def->stream[i].cf == clipformat &&
4061 stg_def->stream[i].dvAspect == header.dvAspect &&
4062 stg_def->stream[i].advf == header.advf &&
4063 stg_def->stream[i].data_size <= bytes &&
4064 (!stg_def->stream[i].data_size ||
4065 (!memcmp(stg_def->stream[i].data, data, min(stg_def->stream[i].data_size, bytes)))))
4067 if (winetest_debug > 1)
4068 trace("stream %d matches def stream %d\n", *enumerated_streams, i);
4069 seen_stream[i] = 1;
4070 *matched_streams += 1;
4074 CoTaskMemFree(stat.pwcsName);
4075 IStream_Release(stream);
4077 *enumerated_streams += 1;
4081 static HRESULT stgmedium_cmp(const STGMEDIUM *med1, STGMEDIUM *med2)
4083 BYTE *data1, *data2;
4084 ULONG datasize1, datasize2;
4086 if (med1->tymed != med2->tymed)
4087 return E_FAIL;
4089 if (med1->tymed == TYMED_MFPICT)
4091 METAFILEPICT *mfpict1 = GlobalLock(U(med1)->hMetaFilePict);
4092 METAFILEPICT *mfpict2 = GlobalLock(U(med2)->hMetaFilePict);
4094 datasize1 = GetMetaFileBitsEx(mfpict1->hMF, 0, NULL);
4095 datasize2 = GetMetaFileBitsEx(mfpict2->hMF, 0, NULL);
4096 if (datasize1 == datasize2)
4098 data1 = HeapAlloc(GetProcessHeap(), 0, datasize1);
4099 data2 = HeapAlloc(GetProcessHeap(), 0, datasize2);
4100 GetMetaFileBitsEx(mfpict1->hMF, datasize1, data1);
4101 GetMetaFileBitsEx(mfpict2->hMF, datasize2, data2);
4103 else return E_FAIL;
4105 else if (med1->tymed == TYMED_ENHMF)
4107 datasize1 = GetEnhMetaFileBits(med1->hEnhMetaFile, 0, NULL);
4108 datasize2 = GetEnhMetaFileBits(med2->hEnhMetaFile, 0, NULL);
4109 if (datasize1 == datasize2)
4111 data1 = HeapAlloc(GetProcessHeap(), 0, datasize1);
4112 data2 = HeapAlloc(GetProcessHeap(), 0, datasize2);
4113 GetEnhMetaFileBits(med1->hEnhMetaFile, datasize1, data1);
4114 GetEnhMetaFileBits(med2->hEnhMetaFile, datasize2, data2);
4116 else return E_FAIL;
4118 else if (med1->tymed == TYMED_HGLOBAL)
4120 datasize1 = GlobalSize(med1->hGlobal);
4121 datasize2 = GlobalSize(med2->hGlobal);
4123 if (datasize1 == datasize2)
4125 data1 = GlobalLock(med1->hGlobal);
4126 data2 = GlobalLock(med2->hGlobal);
4128 else
4129 return E_FAIL;
4131 else
4132 return E_NOTIMPL;
4134 if (memcmp(data1, data2, datasize1) != 0)
4135 return E_FAIL;
4137 if (med1->tymed == TYMED_HGLOBAL)
4139 GlobalUnlock(U(med1)->hGlobal);
4140 GlobalUnlock(U(med2)->hGlobal);
4142 else if (med1->tymed == TYMED_MFPICT)
4144 HeapFree(GetProcessHeap(), 0, data1);
4145 HeapFree(GetProcessHeap(), 0, data2);
4146 GlobalUnlock(U(med1)->hMetaFilePict);
4147 GlobalUnlock(U(med2)->hMetaFilePict);
4149 else
4151 HeapFree(GetProcessHeap(), 0, data1);
4152 HeapFree(GetProcessHeap(), 0, data2);
4155 return S_OK;
4158 static IStorage *create_storage_from_def(const struct storage_def *stg_def)
4160 HRESULT hr;
4161 IStorage *stg;
4162 IStream *stm;
4163 int i;
4165 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &stg);
4166 ok(hr == S_OK, "unexpected %#x\n", hr);
4168 hr = IStorage_SetClass(stg, stg_def->clsid);
4169 ok(hr == S_OK, "unexpected %#x\n", hr);
4171 for (i = 0; i < stg_def->stream_count; i++)
4173 WCHAR name[32];
4175 MultiByteToWideChar(CP_ACP, 0, stg_def->stream[i].name, -1, name, 32);
4176 hr = IStorage_CreateStream(stg, name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
4177 ok(hr == S_OK, "unexpected %#x\n", hr);
4179 if (stg_def->stream[i].cf != -1)
4181 int clipformat[2];
4182 PresentationDataHeader hdr;
4184 if (stg_def->stream[i].cf)
4186 clipformat[0] = -1;
4187 clipformat[1] = stg_def->stream[i].cf;
4188 hr = IStream_Write(stm, clipformat, sizeof(clipformat), NULL);
4190 else
4192 clipformat[0] = 0;
4193 hr = IStream_Write(stm, &clipformat[0], sizeof(clipformat[0]), NULL);
4195 ok(hr == S_OK, "unexpected %#x\n", hr);
4197 hdr.tdSize = sizeof(hdr.tdSize);
4198 hdr.dvAspect = stg_def->stream[i].dvAspect;
4199 hdr.lindex = -1;
4200 hdr.advf = stg_def->stream[i].advf;
4201 hdr.unknown7 = 0;
4202 hdr.dwObjectExtentX = 0;
4203 hdr.dwObjectExtentY = 0;
4204 hdr.dwSize = stg_def->stream[i].data_size;
4205 hr = IStream_Write(stm, &hdr, sizeof(hdr), NULL);
4206 ok(hr == S_OK, "unexpected %#x\n", hr);
4209 if (stg_def->stream[i].data_size)
4211 hr = IStream_Write(stm, stg_def->stream[i].data, stg_def->stream[i].data_size, NULL);
4212 ok(hr == S_OK, "unexpected %#x\n", hr);
4215 IStream_Release(stm);
4218 return stg;
4221 static const BYTE dib_inf[] =
4223 0x42, 0x4d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
4224 0x00, 0x00, 0x36, 0x00, 0x00, 0x00
4227 static const BYTE mf_rec[] =
4229 0xd7, 0xcd, 0xc6, 0x9a, 0x00, 0x00, 0x00, 0x00,
4230 0x00, 0x00, 0x16, 0x00, 0x2d, 0x00, 0x40, 0x02,
4231 0x00, 0x00, 0x00, 0x00, 0x6a, 0x55
4234 static void get_stgdef(struct storage_def *stg_def, CLIPFORMAT cf, STGMEDIUM *stg_med, int stm_idx)
4236 BYTE *data;
4237 int data_size;
4238 METAFILEPICT *mfpict;
4239 HDC hdc;
4241 switch (cf)
4243 case CF_DIB:
4244 data_size = sizeof(dib);
4245 if (!strcmp(stg_def->stream[stm_idx].name, "CONTENTS"))
4247 data_size += sizeof(dib_inf);
4248 data = HeapAlloc(GetProcessHeap(), 0, data_size);
4249 memcpy(data, dib_inf, sizeof(dib_inf));
4250 memcpy(data + sizeof(dib_inf), dib, sizeof(dib));
4252 else
4254 data = HeapAlloc(GetProcessHeap(), 0, data_size);
4255 memcpy(data, dib, sizeof(dib));
4257 stg_def->stream[stm_idx].data = data;
4258 stg_def->stream[stm_idx].data_size = data_size;
4259 break;
4260 case CF_METAFILEPICT:
4261 mfpict = GlobalLock(U(stg_med)->hMetaFilePict);
4262 data_size = GetMetaFileBitsEx(mfpict->hMF, 0, NULL);
4263 if (!strcmp(stg_def->stream[stm_idx].name, "CONTENTS"))
4265 data = HeapAlloc(GetProcessHeap(), 0, data_size + sizeof(mf_rec));
4266 memcpy(data, mf_rec, sizeof(mf_rec));
4267 GetMetaFileBitsEx(mfpict->hMF, data_size, data + sizeof(mf_rec));
4268 data_size += sizeof(mf_rec);
4270 else
4272 data = HeapAlloc(GetProcessHeap(), 0, data_size);
4273 GetMetaFileBitsEx(mfpict->hMF, data_size, data);
4275 GlobalUnlock(U(stg_med)->hMetaFilePict);
4276 stg_def->stream[stm_idx].data_size = data_size;
4277 stg_def->stream[stm_idx].data = data;
4278 break;
4279 case CF_ENHMETAFILE:
4280 if (!strcmp(stg_def->stream[stm_idx].name, "CONTENTS"))
4282 data_size = GetEnhMetaFileBits(U(stg_med)->hEnhMetaFile, 0, NULL);
4283 data = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) + sizeof(ENHMETAHEADER) + data_size);
4284 *((DWORD *)data) = sizeof(ENHMETAHEADER);
4285 GetEnhMetaFileBits(U(stg_med)->hEnhMetaFile, data_size, data + sizeof(DWORD) + sizeof(ENHMETAHEADER));
4286 memcpy(data + sizeof(DWORD), data + sizeof(DWORD) + sizeof(ENHMETAHEADER), sizeof(ENHMETAHEADER));
4287 data_size += sizeof(DWORD) + sizeof(ENHMETAHEADER);
4289 else
4291 hdc = GetDC(NULL);
4292 data_size = GetWinMetaFileBits(U(stg_med)->hEnhMetaFile, 0, NULL, MM_ANISOTROPIC, hdc);
4293 data = HeapAlloc(GetProcessHeap(), 0, data_size);
4294 GetWinMetaFileBits(U(stg_med)->hEnhMetaFile, data_size, data, MM_ANISOTROPIC, hdc);
4295 ReleaseDC(NULL, hdc);
4297 stg_def->stream[stm_idx].data_size = data_size;
4298 stg_def->stream[stm_idx].data = data;
4299 break;
4303 static void get_stgmedium(CLIPFORMAT cfFormat, STGMEDIUM *stgmedium)
4305 switch (cfFormat)
4307 case CF_DIB:
4308 create_dib(stgmedium);
4309 break;
4310 case CF_METAFILEPICT:
4311 create_mfpict(stgmedium);
4312 break;
4313 case CF_ENHMETAFILE:
4314 create_emf(stgmedium);
4315 break;
4316 default:
4317 ok(0, "cf %x not implemented\n", cfFormat);
4321 #define MAX_FMTS 5
4322 static void test_data_cache_save_data(void)
4324 HRESULT hr;
4325 STGMEDIUM stgmed;
4326 ILockBytes *ilb;
4327 IStorage *doc;
4328 IOleCache2 *cache;
4329 IPersistStorage *persist;
4330 IDataObject *odata;
4331 int enumerated_streams, matched_streams, i;
4332 DWORD dummy;
4333 STGMEDIUM stgmeds[MAX_FMTS];
4334 struct tests_data_cache
4336 FORMATETC fmts[MAX_FMTS];
4337 int num_fmts, num_set;
4338 const CLSID *clsid;
4339 struct storage_def stg_def;
4342 static struct tests_data_cache *pdata, data[] =
4346 { CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
4347 { CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT },
4348 { CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF },
4349 { 0, 0, DVASPECT_DOCPRINT, -1, TYMED_HGLOBAL },
4351 4, 3, &CLSID_WineTest,
4353 &CLSID_WineTestOld, 4, { { "\2OlePres000", CF_DIB, DVASPECT_CONTENT, 0, NULL, 0 },
4354 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, 0, NULL, 0 },
4355 { "\2OlePres002", CF_ENHMETAFILE, DVASPECT_CONTENT, 0, NULL, 0 },
4356 { "\2OlePres003", 0, DVASPECT_DOCPRINT, 0, NULL, 0 } }
4359 /* without setting data */
4362 { CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
4363 { CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT },
4364 { CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF },
4366 3, 0, &CLSID_WineTest,
4368 &CLSID_WineTestOld, 3, { { "\2OlePres000", CF_DIB, DVASPECT_CONTENT, 0, NULL, 0 },
4369 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, 0, NULL, 0 },
4370 { "\2OlePres002", CF_ENHMETAFILE, DVASPECT_CONTENT, 0, NULL, 0 } }
4373 /* static picture clsids */
4376 { CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
4378 1, 1, &CLSID_Picture_Dib,
4380 &CLSID_WineTestOld, 1, { { "CONTENTS", -1, 0, 0, NULL, 0 } }
4385 { CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT },
4387 1, 1, &CLSID_Picture_Metafile,
4389 &CLSID_WineTestOld, 1, { { "CONTENTS", -1, 0, 0, NULL, 0 } }
4394 { CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF },
4396 1, 1, &CLSID_Picture_EnhMetafile,
4398 &CLSID_WineTestOld, 1, { { "CONTENTS", -1, 0, 0, NULL, 0 } }
4401 /* static picture clsids without setting any data */
4404 { CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
4406 1, 0, &CLSID_Picture_Dib,
4408 &CLSID_WineTestOld, 1, { { "CONTENTS", -1, 0, 0, NULL, 0 } }
4413 { CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT },
4415 1, 0, &CLSID_Picture_Metafile,
4417 &CLSID_WineTestOld, 1, { { "CONTENTS", -1, 0, 0, NULL, 0 } }
4422 { CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF },
4424 1, 0, &CLSID_Picture_EnhMetafile,
4426 &CLSID_WineTestOld, 1, { { "CONTENTS", -1, 0, 0, NULL, 0 } }
4431 { 0 }
4436 /* test _Save after caching directly through _Cache + _SetData */
4437 for (pdata = data; pdata->clsid != NULL; pdata++)
4439 hr = CreateDataCache(NULL, pdata->clsid, &IID_IOleCache2, (void **)&cache);
4440 ok(hr == S_OK, "unexpected %#x\n", hr);
4442 for (i = 0; i < pdata->num_fmts; i++)
4444 hr = IOleCache2_Cache(cache, &pdata->fmts[i], 0, &dummy);
4445 ok(SUCCEEDED(hr), "unexpected %#x\n", hr);
4446 if (i < pdata->num_set)
4448 get_stgmedium(pdata->fmts[i].cfFormat, &stgmeds[i]);
4449 get_stgdef(&pdata->stg_def, pdata->fmts[i].cfFormat, &stgmeds[i], i);
4450 hr = IOleCache2_SetData(cache, &pdata->fmts[i], &stgmeds[i], FALSE);
4451 ok(hr == S_OK, "unexpected %#x\n", hr);
4455 /* create Storage in memory where we'll save cache */
4456 hr = CreateILockBytesOnHGlobal(0, TRUE, &ilb);
4457 ok(hr == S_OK, "unexpected %#x\n", hr);
4458 hr = StgCreateDocfileOnILockBytes(ilb, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &doc);
4459 ok(hr == S_OK, "unexpected %#x\n", hr);
4460 ILockBytes_Release(ilb);
4461 hr = IStorage_SetClass(doc, &CLSID_WineTestOld);
4462 ok(hr == S_OK, "unexpected %#x\n", hr);
4464 hr = IOleCache2_QueryInterface(cache, &IID_IPersistStorage, (void **)&persist);
4465 ok(hr == S_OK, "unexpected %#x\n", hr);
4467 /* cache entries are dirty. test saving them to stg */
4468 trace("IPersistStorage_Save:\n");
4469 hr = IPersistStorage_Save(persist, doc, FALSE);
4470 ok(hr == S_OK, "unexpected %#x\n", hr);
4472 hr = IPersistStorage_IsDirty(persist);
4473 ok(hr == S_OK, "unexpected %#x\n", hr);
4475 check_storage_contents(doc, &pdata->stg_def, &enumerated_streams, &matched_streams);
4476 ok(enumerated_streams == matched_streams, "enumerated %d != matched %d\n",
4477 enumerated_streams, matched_streams);
4478 ok(enumerated_streams == pdata->stg_def.stream_count, "created %d != def streams %d\n",
4479 enumerated_streams, pdata->stg_def.stream_count);
4481 IPersistStorage_Release(persist);
4482 IOleCache2_Release(cache);
4484 /* now test _Load/_GetData using the storage we used for _Save */
4485 hr = CreateDataCache(NULL, pdata->clsid, &IID_IOleCache2, (void **)&cache);
4486 ok(hr == S_OK, "unexpected %#x\n", hr);
4487 hr = IOleCache2_QueryInterface(cache, &IID_IPersistStorage, (void **)&persist);
4488 ok(hr == S_OK, "unexpected %#x\n", hr);
4490 hr = IStorage_SetClass(doc, pdata->clsid);
4491 ok(hr == S_OK, "unexpected %#x\n", hr);
4492 trace("IPersistStorage_Load\n");
4493 hr = IPersistStorage_Load(persist, doc);
4494 ok(hr == S_OK, "unexpected %#x\n", hr);
4496 hr = IOleCache2_QueryInterface(cache, &IID_IDataObject, (void **)&odata);
4497 ok(hr == S_OK, "unexpected %#x\n", hr);
4498 for (i = 0; i < pdata->num_set; i++)
4500 hr = IDataObject_GetData(odata, &pdata->fmts[i], &stgmed);
4501 ok(hr == S_OK, "unexpected %#x\n", hr);
4503 hr = stgmedium_cmp(&stgmeds[i], &stgmed);
4504 ok(hr == S_OK, "unexpected %#x\n", hr);
4505 ReleaseStgMedium(&stgmed);
4506 ReleaseStgMedium(&stgmeds[i]);
4509 IDataObject_Release(odata);
4510 IPersistStorage_Release(persist);
4511 IStorage_Release(doc);
4512 IOleCache2_Release(cache);
4513 for (i = 0; i < pdata->num_set; i++)
4514 HeapFree(GetProcessHeap(), 0, (void *)pdata->stg_def.stream[i].data);
4519 static void test_data_cache_contents(void)
4521 HRESULT hr;
4522 IStorage *doc1, *doc2;
4523 IOleCache2 *cache;
4524 IPersistStorage *stg;
4525 int i, enumerated_streams, matched_streams;
4526 static const struct
4528 const struct storage_def *in;
4529 const struct storage_def *out;
4530 } test_data[] =
4532 { &stg_def_0, &stg_def_0_saved },
4533 { &stg_def_1, &stg_def_1_saved },
4534 { &stg_def_2, &stg_def_2_saved },
4535 { &stg_def_3, &stg_def_3_saved },
4536 { &stg_def_4, &stg_def_4_saved },
4537 { &stg_def_5, &stg_def_5_saved },
4538 { &stg_def_6, &stg_def_6_saved },
4539 { &stg_def_7, &stg_def_7_saved },
4540 { &stg_def_8, &stg_def_8_saved },
4541 { &stg_def_9, &stg_def_9_saved },
4544 for (i = 0; i < ARRAY_SIZE(test_data); i++)
4546 if (winetest_debug > 1)
4547 trace("start testing storage def %d\n", i);
4549 doc1 = create_storage_from_def(test_data[i].in);
4550 if (!doc1) continue;
4552 enumerated_streams = matched_streams = -1;
4553 check_storage_contents(doc1, test_data[i].in, &enumerated_streams, &matched_streams);
4554 ok(enumerated_streams == matched_streams, "%d in: enumerated %d != matched %d\n", i,
4555 enumerated_streams, matched_streams);
4556 ok(enumerated_streams == test_data[i].in->stream_count, "%d: created %d != def streams %d\n", i,
4557 enumerated_streams, test_data[i].in->stream_count);
4559 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IUnknown, (void **)&cache);
4560 ok(hr == S_OK, "unexpected %#x\n", hr);
4561 hr = IOleCache2_QueryInterface(cache, &IID_IPersistStorage, (void **)&stg);
4562 ok(hr == S_OK, "unexpected %#x\n", hr);
4563 hr = IPersistStorage_Load(stg, doc1);
4564 ok(hr == S_OK, "unexpected %#x\n", hr);
4566 IStorage_Release(doc1);
4568 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &doc2);
4569 ok(hr == S_OK, "unexpected %#x\n", hr);
4571 hr = IPersistStorage_IsDirty(stg);
4572 ok(hr == S_FALSE, "%d: unexpected %#x\n", i, hr);
4574 hr = IPersistStorage_Save(stg, doc2, FALSE);
4575 ok(hr == S_OK, "unexpected %#x\n", hr);
4577 IPersistStorage_Release(stg);
4579 enumerated_streams = matched_streams = -1;
4580 check_storage_contents(doc2, test_data[i].out, &enumerated_streams, &matched_streams);
4581 todo_wine_if(!(test_data[i].in == &stg_def_0 || test_data[i].in == &stg_def_1 || test_data[i].in == &stg_def_2))
4582 ok(enumerated_streams == matched_streams, "%d out: enumerated %d != matched %d\n", i,
4583 enumerated_streams, matched_streams);
4584 todo_wine_if(!(test_data[i].in == &stg_def_0 || test_data[i].in == &stg_def_4 || test_data[i].in == &stg_def_5
4585 || test_data[i].in == &stg_def_6))
4586 ok(enumerated_streams == test_data[i].out->stream_count, "%d: saved streams %d != def streams %d\n", i,
4587 enumerated_streams, test_data[i].out->stream_count);
4589 IStorage_Release(doc2);
4591 if (winetest_debug > 1)
4592 trace("done testing storage def %d\n", i);
4596 START_TEST(ole2)
4598 DWORD dwRegister;
4599 IStorage *pStorage;
4600 STATSTG statstg;
4601 HRESULT hr;
4603 cf_test_1 = RegisterClipboardFormatA("cf_winetest_1");
4604 cf_test_2 = RegisterClipboardFormatA("cf_winetest_2");
4605 cf_test_3 = RegisterClipboardFormatA("cf_winetest_3");
4607 CoInitialize(NULL);
4609 hr = CoRegisterClassObject(&CLSID_Equation3, (IUnknown *)&OleObjectCF, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegister);
4610 ok_ole_success(hr, "CoRegisterClassObject");
4612 hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &pStorage);
4613 ok_ole_success(hr, "StgCreateDocfile");
4615 test_OleCreate(pStorage);
4617 hr = IStorage_Stat(pStorage, &statstg, STATFLAG_NONAME);
4618 ok_ole_success(hr, "IStorage_Stat");
4619 ok(IsEqualCLSID(&CLSID_Equation3, &statstg.clsid), "Wrong CLSID in storage\n");
4621 test_OleLoad(pStorage);
4623 IStorage_Release(pStorage);
4625 hr = CoRevokeClassObject(dwRegister);
4626 ok_ole_success(hr, "CoRevokeClassObject");
4628 Storage_SetClass_CLSID = &CLSID_WineTest;
4630 test_data_cache();
4631 test_data_cache_dib_contents_stream( 0 );
4632 test_data_cache_dib_contents_stream( 1 );
4633 test_data_cache_cache();
4634 test_data_cache_init();
4635 test_data_cache_initnew();
4636 test_data_cache_updatecache();
4637 test_default_handler();
4638 test_runnable();
4639 test_OleRun();
4640 test_OleLockRunning();
4641 test_OleDraw();
4642 test_OleDoAutoConvert();
4643 test_data_cache_save();
4644 test_data_cache_save_data();
4645 test_data_cache_contents();
4647 CoUninitialize();