ole32: A presentation cache for DVASPECT_ICON must have format CF_METAFILEPICT.
[wine.git] / dlls / ole32 / tests / ole2.c
blob4f72622da168d58c0657b4fd4a87bfe5fb8a0a8f
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;
117 static const struct expected_method *expected_method_list;
118 static FORMATETC *g_expected_fetc = NULL;
120 static BOOL g_showRunnable = TRUE;
121 static BOOL g_isRunning = TRUE;
122 static HRESULT g_GetMiscStatusFailsWith = S_OK;
123 static HRESULT g_QIFailsWith;
125 static UINT cf_test_1, cf_test_2, cf_test_3;
127 /****************************************************************************
128 * PresentationDataHeader
130 * This structure represents the header of the \002OlePresXXX stream in
131 * the OLE object storage.
133 typedef struct PresentationDataHeader
135 /* clipformat:
136 * - standard clipformat:
137 * DWORD length = 0xffffffff;
138 * DWORD cfFormat;
139 * - or custom clipformat:
140 * DWORD length;
141 * CHAR format_name[length]; (null-terminated)
143 DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
144 DVASPECT dvAspect;
145 DWORD lindex;
146 DWORD advf;
147 DWORD unknown7; /* 0 */
148 DWORD dwObjectExtentX;
149 DWORD dwObjectExtentY;
150 DWORD dwSize;
151 } PresentationDataHeader;
153 #define CHECK_EXPECTED_METHOD(method_name) \
154 do { \
155 trace("%s\n", method_name); \
156 ok(expected_method_list->method != NULL, "Extra method %s called\n", method_name); \
157 if (!strcmp(expected_method_list->method, "WINE_EXTRA")) \
159 todo_wine ok(0, "Too many method calls.\n"); \
160 break; \
162 if (expected_method_list->method) \
164 while (expected_method_list->flags & TEST_OPTIONAL && \
165 strcmp(expected_method_list->method, method_name) != 0) \
166 expected_method_list++; \
167 todo_wine_if (expected_method_list->flags & TEST_TODO) \
168 ok(!strcmp(expected_method_list->method, method_name), \
169 "Expected %s to be called instead of %s\n", \
170 expected_method_list->method, method_name); \
171 expected_method_list++; \
173 } while(0)
175 #define CHECK_NO_EXTRA_METHODS() \
176 do { \
177 while (expected_method_list->flags & TEST_OPTIONAL) \
178 expected_method_list++; \
179 ok(!expected_method_list->method, "Method sequence starting from %s not called\n", expected_method_list->method); \
180 } while (0)
182 static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, void **ppv)
184 CHECK_EXPECTED_METHOD("OleObject_QueryInterface");
186 *ppv = NULL;
188 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IOleObject))
189 *ppv = iface;
190 else if (IsEqualIID(riid, &IID_IPersistStorage))
191 *ppv = &OleObjectPersistStg;
192 else if (IsEqualIID(riid, &IID_IOleCache))
193 *ppv = cache;
194 else if (IsEqualIID(riid, &IID_IRunnableObject) && g_showRunnable)
195 *ppv = runnable;
196 else if (IsEqualIID(riid, &IID_WineTest))
197 return g_QIFailsWith;
199 if(*ppv) {
200 IUnknown_AddRef((IUnknown*)*ppv);
201 return S_OK;
204 trace("OleObject_QueryInterface: returning E_NOINTERFACE\n");
205 return E_NOINTERFACE;
208 static ULONG WINAPI OleObject_AddRef(IOleObject *iface)
210 CHECK_EXPECTED_METHOD("OleObject_AddRef");
211 return 2;
214 static ULONG WINAPI OleObject_Release(IOleObject *iface)
216 CHECK_EXPECTED_METHOD("OleObject_Release");
217 return 1;
220 static HRESULT WINAPI OleObject_SetClientSite
222 IOleObject *iface,
223 IOleClientSite *pClientSite
226 CHECK_EXPECTED_METHOD("OleObject_SetClientSite");
227 return S_OK;
230 static HRESULT WINAPI OleObject_GetClientSite
232 IOleObject *iface,
233 IOleClientSite **ppClientSite
236 CHECK_EXPECTED_METHOD("OleObject_GetClientSite");
237 return E_NOTIMPL;
240 static HRESULT WINAPI OleObject_SetHostNames
242 IOleObject *iface,
243 LPCOLESTR szContainerApp,
244 LPCOLESTR szContainerObj
247 CHECK_EXPECTED_METHOD("OleObject_SetHostNames");
248 return S_OK;
251 static HRESULT WINAPI OleObject_Close
253 IOleObject *iface,
254 DWORD dwSaveOption
257 CHECK_EXPECTED_METHOD("OleObject_Close");
258 return S_OK;
261 static HRESULT WINAPI OleObject_SetMoniker
263 IOleObject *iface,
264 DWORD dwWhichMoniker,
265 IMoniker *pmk
268 CHECK_EXPECTED_METHOD("OleObject_SetMoniker");
269 return S_OK;
272 static HRESULT WINAPI OleObject_GetMoniker
274 IOleObject *iface,
275 DWORD dwAssign,
276 DWORD dwWhichMoniker,
277 IMoniker **ppmk
280 CHECK_EXPECTED_METHOD("OleObject_GetMoniker");
281 return S_OK;
284 static HRESULT WINAPI OleObject_InitFromData
286 IOleObject *iface,
287 IDataObject *pDataObject,
288 BOOL fCreation,
289 DWORD dwReserved
292 CHECK_EXPECTED_METHOD("OleObject_InitFromData");
293 return S_OK;
296 static HRESULT WINAPI OleObject_GetClipboardData
298 IOleObject *iface,
299 DWORD dwReserved,
300 IDataObject **ppDataObject
303 CHECK_EXPECTED_METHOD("OleObject_GetClipboardData");
304 return E_NOTIMPL;
307 static HRESULT WINAPI OleObject_DoVerb
309 IOleObject *iface,
310 LONG iVerb,
311 LPMSG lpmsg,
312 IOleClientSite *pActiveSite,
313 LONG lindex,
314 HWND hwndParent,
315 LPCRECT lprcPosRect
318 CHECK_EXPECTED_METHOD("OleObject_DoVerb");
319 return S_OK;
322 static HRESULT WINAPI OleObject_EnumVerbs
324 IOleObject *iface,
325 IEnumOLEVERB **ppEnumOleVerb
328 CHECK_EXPECTED_METHOD("OleObject_EnumVerbs");
329 return E_NOTIMPL;
332 static HRESULT WINAPI OleObject_Update
334 IOleObject *iface
337 CHECK_EXPECTED_METHOD("OleObject_Update");
338 return S_OK;
341 static HRESULT WINAPI OleObject_IsUpToDate
343 IOleObject *iface
346 CHECK_EXPECTED_METHOD("OleObject_IsUpToDate");
347 return S_OK;
350 static HRESULT WINAPI OleObject_GetUserClassID
352 IOleObject *iface,
353 CLSID *pClsid
356 CHECK_EXPECTED_METHOD("OleObject_GetUserClassID");
357 return E_NOTIMPL;
360 static HRESULT WINAPI OleObject_GetUserType
362 IOleObject *iface,
363 DWORD dwFormOfType,
364 LPOLESTR *pszUserType
367 CHECK_EXPECTED_METHOD("OleObject_GetUserType");
368 return E_NOTIMPL;
371 static HRESULT WINAPI OleObject_SetExtent
373 IOleObject *iface,
374 DWORD dwDrawAspect,
375 SIZEL *psizel
378 CHECK_EXPECTED_METHOD("OleObject_SetExtent");
379 return S_OK;
382 static HRESULT WINAPI OleObject_GetExtent
384 IOleObject *iface,
385 DWORD dwDrawAspect,
386 SIZEL *psizel
389 CHECK_EXPECTED_METHOD("OleObject_GetExtent");
390 return E_NOTIMPL;
393 static HRESULT WINAPI OleObject_Advise
395 IOleObject *iface,
396 IAdviseSink *pAdvSink,
397 DWORD *pdwConnection
400 CHECK_EXPECTED_METHOD("OleObject_Advise");
401 return S_OK;
404 static HRESULT WINAPI OleObject_Unadvise
406 IOleObject *iface,
407 DWORD dwConnection
410 CHECK_EXPECTED_METHOD("OleObject_Unadvise");
411 return S_OK;
414 static HRESULT WINAPI OleObject_EnumAdvise
416 IOleObject *iface,
417 IEnumSTATDATA **ppenumAdvise
420 CHECK_EXPECTED_METHOD("OleObject_EnumAdvise");
421 return E_NOTIMPL;
424 static HRESULT WINAPI OleObject_GetMiscStatus
426 IOleObject *iface,
427 DWORD aspect,
428 DWORD *pdwStatus
431 CHECK_EXPECTED_METHOD("OleObject_GetMiscStatus");
433 ok(aspect == DVASPECT_CONTENT, "got aspect %d\n", aspect);
435 if (g_GetMiscStatusFailsWith == S_OK)
437 *pdwStatus = OLEMISC_RECOMPOSEONRESIZE;
438 return S_OK;
440 else
442 *pdwStatus = 0x1234;
443 return g_GetMiscStatusFailsWith;
447 static HRESULT WINAPI OleObject_SetColorScheme
449 IOleObject *iface,
450 LOGPALETTE *pLogpal
453 CHECK_EXPECTED_METHOD("OleObject_SetColorScheme");
454 return E_NOTIMPL;
457 static const IOleObjectVtbl OleObjectVtbl =
459 OleObject_QueryInterface,
460 OleObject_AddRef,
461 OleObject_Release,
462 OleObject_SetClientSite,
463 OleObject_GetClientSite,
464 OleObject_SetHostNames,
465 OleObject_Close,
466 OleObject_SetMoniker,
467 OleObject_GetMoniker,
468 OleObject_InitFromData,
469 OleObject_GetClipboardData,
470 OleObject_DoVerb,
471 OleObject_EnumVerbs,
472 OleObject_Update,
473 OleObject_IsUpToDate,
474 OleObject_GetUserClassID,
475 OleObject_GetUserType,
476 OleObject_SetExtent,
477 OleObject_GetExtent,
478 OleObject_Advise,
479 OleObject_Unadvise,
480 OleObject_EnumAdvise,
481 OleObject_GetMiscStatus,
482 OleObject_SetColorScheme
485 static IOleObject OleObject = { &OleObjectVtbl };
487 static HRESULT WINAPI OleObjectPersistStg_QueryInterface(IPersistStorage *iface, REFIID riid, void **ppv)
489 trace("OleObjectPersistStg_QueryInterface\n");
490 return IOleObject_QueryInterface(&OleObject, riid, ppv);
493 static ULONG WINAPI OleObjectPersistStg_AddRef(IPersistStorage *iface)
495 CHECK_EXPECTED_METHOD("OleObjectPersistStg_AddRef");
496 return 2;
499 static ULONG WINAPI OleObjectPersistStg_Release(IPersistStorage *iface)
501 CHECK_EXPECTED_METHOD("OleObjectPersistStg_Release");
502 return 1;
505 static HRESULT WINAPI OleObjectPersistStg_GetClassId(IPersistStorage *iface, CLSID *clsid)
507 CHECK_EXPECTED_METHOD("OleObjectPersistStg_GetClassId");
508 return E_NOTIMPL;
511 static HRESULT WINAPI OleObjectPersistStg_IsDirty
513 IPersistStorage *iface
516 CHECK_EXPECTED_METHOD("OleObjectPersistStg_IsDirty");
517 return S_OK;
520 static HRESULT WINAPI OleObjectPersistStg_InitNew
522 IPersistStorage *iface,
523 IStorage *pStg
526 CHECK_EXPECTED_METHOD("OleObjectPersistStg_InitNew");
527 return S_OK;
530 static HRESULT WINAPI OleObjectPersistStg_Load
532 IPersistStorage *iface,
533 IStorage *pStg
536 CHECK_EXPECTED_METHOD("OleObjectPersistStg_Load");
537 return S_OK;
540 static HRESULT WINAPI OleObjectPersistStg_Save
542 IPersistStorage *iface,
543 IStorage *pStgSave,
544 BOOL fSameAsLoad
547 CHECK_EXPECTED_METHOD("OleObjectPersistStg_Save");
548 return S_OK;
551 static HRESULT WINAPI OleObjectPersistStg_SaveCompleted
553 IPersistStorage *iface,
554 IStorage *pStgNew
557 CHECK_EXPECTED_METHOD("OleObjectPersistStg_SaveCompleted");
558 return S_OK;
561 static HRESULT WINAPI OleObjectPersistStg_HandsOffStorage
563 IPersistStorage *iface
566 CHECK_EXPECTED_METHOD("OleObjectPersistStg_HandsOffStorage");
567 return S_OK;
570 static const IPersistStorageVtbl OleObjectPersistStgVtbl =
572 OleObjectPersistStg_QueryInterface,
573 OleObjectPersistStg_AddRef,
574 OleObjectPersistStg_Release,
575 OleObjectPersistStg_GetClassId,
576 OleObjectPersistStg_IsDirty,
577 OleObjectPersistStg_InitNew,
578 OleObjectPersistStg_Load,
579 OleObjectPersistStg_Save,
580 OleObjectPersistStg_SaveCompleted,
581 OleObjectPersistStg_HandsOffStorage
584 static IPersistStorage OleObjectPersistStg = { &OleObjectPersistStgVtbl };
586 static HRESULT WINAPI OleObjectCache_QueryInterface(IOleCache *iface, REFIID riid, void **ppv)
588 return IOleObject_QueryInterface(&OleObject, riid, ppv);
591 static ULONG WINAPI OleObjectCache_AddRef(IOleCache *iface)
593 CHECK_EXPECTED_METHOD("OleObjectCache_AddRef");
594 return 2;
597 static ULONG WINAPI OleObjectCache_Release(IOleCache *iface)
599 CHECK_EXPECTED_METHOD("OleObjectCache_Release");
600 return 1;
603 static HRESULT WINAPI OleObjectCache_Cache
605 IOleCache *iface,
606 FORMATETC *pformatetc,
607 DWORD advf,
608 DWORD *pdwConnection
611 CHECK_EXPECTED_METHOD("OleObjectCache_Cache");
612 if (g_expected_fetc) {
613 ok(pformatetc != NULL, "pformatetc should not be NULL\n");
614 if (pformatetc) {
615 ok(pformatetc->cfFormat == g_expected_fetc->cfFormat,
616 "cfFormat: %x\n", pformatetc->cfFormat);
617 ok((pformatetc->ptd != NULL) == (g_expected_fetc->ptd != NULL),
618 "ptd: %p\n", pformatetc->ptd);
619 ok(pformatetc->dwAspect == g_expected_fetc->dwAspect,
620 "dwAspect: %x\n", pformatetc->dwAspect);
621 ok(pformatetc->lindex == g_expected_fetc->lindex,
622 "lindex: %x\n", pformatetc->lindex);
623 ok(pformatetc->tymed == g_expected_fetc->tymed,
624 "tymed: %x\n", pformatetc->tymed);
626 } else
627 ok(pformatetc == NULL, "pformatetc should be NULL\n");
628 return S_OK;
631 static HRESULT WINAPI OleObjectCache_Uncache
633 IOleCache *iface,
634 DWORD dwConnection
637 CHECK_EXPECTED_METHOD("OleObjectCache_Uncache");
638 return S_OK;
641 static HRESULT WINAPI OleObjectCache_EnumCache
643 IOleCache *iface,
644 IEnumSTATDATA **ppenumSTATDATA
647 CHECK_EXPECTED_METHOD("OleObjectCache_EnumCache");
648 return S_OK;
652 static HRESULT WINAPI OleObjectCache_InitCache
654 IOleCache *iface,
655 IDataObject *pDataObject
658 CHECK_EXPECTED_METHOD("OleObjectCache_InitCache");
659 return S_OK;
663 static HRESULT WINAPI OleObjectCache_SetData
665 IOleCache *iface,
666 FORMATETC *pformatetc,
667 STGMEDIUM *pmedium,
668 BOOL fRelease
671 CHECK_EXPECTED_METHOD("OleObjectCache_SetData");
672 return S_OK;
676 static const IOleCacheVtbl OleObjectCacheVtbl =
678 OleObjectCache_QueryInterface,
679 OleObjectCache_AddRef,
680 OleObjectCache_Release,
681 OleObjectCache_Cache,
682 OleObjectCache_Uncache,
683 OleObjectCache_EnumCache,
684 OleObjectCache_InitCache,
685 OleObjectCache_SetData
688 static IOleCache OleObjectCache = { &OleObjectCacheVtbl };
690 static HRESULT WINAPI OleObjectCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
692 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
694 *ppv = iface;
695 IClassFactory_AddRef(iface);
696 return S_OK;
698 *ppv = NULL;
699 return E_NOINTERFACE;
702 static ULONG WINAPI OleObjectCF_AddRef(IClassFactory *iface)
704 return 2;
707 static ULONG WINAPI OleObjectCF_Release(IClassFactory *iface)
709 return 1;
712 static HRESULT WINAPI OleObjectCF_CreateInstance(IClassFactory *iface, IUnknown *punkOuter, REFIID riid, void **ppv)
714 return IOleObject_QueryInterface(&OleObject, riid, ppv);
717 static HRESULT WINAPI OleObjectCF_LockServer(IClassFactory *iface, BOOL lock)
719 return S_OK;
722 static const IClassFactoryVtbl OleObjectCFVtbl =
724 OleObjectCF_QueryInterface,
725 OleObjectCF_AddRef,
726 OleObjectCF_Release,
727 OleObjectCF_CreateInstance,
728 OleObjectCF_LockServer
731 static IClassFactory OleObjectCF = { &OleObjectCFVtbl };
733 static HRESULT WINAPI OleObjectRunnable_QueryInterface(IRunnableObject *iface, REFIID riid, void **ppv)
735 return IOleObject_QueryInterface(&OleObject, riid, ppv);
738 static ULONG WINAPI OleObjectRunnable_AddRef(IRunnableObject *iface)
740 CHECK_EXPECTED_METHOD("OleObjectRunnable_AddRef");
741 return 2;
744 static ULONG WINAPI OleObjectRunnable_Release(IRunnableObject *iface)
746 CHECK_EXPECTED_METHOD("OleObjectRunnable_Release");
747 return 1;
750 static HRESULT WINAPI OleObjectRunnable_GetRunningClass(
751 IRunnableObject *iface,
752 LPCLSID lpClsid)
754 CHECK_EXPECTED_METHOD("OleObjectRunnable_GetRunningClass");
755 return E_NOTIMPL;
758 static HRESULT WINAPI OleObjectRunnable_Run(
759 IRunnableObject *iface,
760 LPBINDCTX pbc)
762 CHECK_EXPECTED_METHOD("OleObjectRunnable_Run");
763 return S_OK;
766 static BOOL WINAPI OleObjectRunnable_IsRunning(IRunnableObject *iface)
768 CHECK_EXPECTED_METHOD("OleObjectRunnable_IsRunning");
769 return g_isRunning;
772 static HRESULT WINAPI OleObjectRunnable_LockRunning(
773 IRunnableObject *iface,
774 BOOL fLock,
775 BOOL fLastUnlockCloses)
777 CHECK_EXPECTED_METHOD("OleObjectRunnable_LockRunning");
778 return S_OK;
781 static HRESULT WINAPI OleObjectRunnable_SetContainedObject(
782 IRunnableObject *iface,
783 BOOL fContained)
785 CHECK_EXPECTED_METHOD("OleObjectRunnable_SetContainedObject");
786 return S_OK;
789 static const IRunnableObjectVtbl OleObjectRunnableVtbl =
791 OleObjectRunnable_QueryInterface,
792 OleObjectRunnable_AddRef,
793 OleObjectRunnable_Release,
794 OleObjectRunnable_GetRunningClass,
795 OleObjectRunnable_Run,
796 OleObjectRunnable_IsRunning,
797 OleObjectRunnable_LockRunning,
798 OleObjectRunnable_SetContainedObject
801 static IRunnableObject OleObjectRunnable = { &OleObjectRunnableVtbl };
803 static const CLSID CLSID_Equation3 = {0x0002CE02, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
805 static HRESULT WINAPI viewobject_QueryInterface(IViewObject *iface, REFIID riid, void **obj)
807 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IViewObject))
809 *obj = iface;
810 return S_OK;
813 *obj = NULL;
814 return E_NOINTERFACE;
817 static ULONG WINAPI viewobject_AddRef(IViewObject *iface)
819 return 2;
822 static ULONG WINAPI viewobject_Release(IViewObject *iface)
824 return 1;
827 static HRESULT WINAPI viewobject_Draw(IViewObject *iface, DWORD aspect, LONG index,
828 void *paspect, DVTARGETDEVICE *ptd, HDC hdcTargetDev, HDC hdcDraw,
829 LPCRECTL bounds, LPCRECTL wbounds, BOOL (STDMETHODCALLTYPE *pfnContinue)(ULONG_PTR dwContinue),
830 ULONG_PTR dwContinue)
832 ok(index == -1, "index=%d\n", index);
833 return S_OK;
836 static HRESULT WINAPI viewobject_GetColorSet(IViewObject *iface, DWORD draw_aspect, LONG index,
837 void *aspect, DVTARGETDEVICE *ptd, HDC hicTargetDev, LOGPALETTE **colorset)
839 ok(0, "unexpected call GetColorSet\n");
840 return E_NOTIMPL;
843 static HRESULT WINAPI viewobject_Freeze(IViewObject *iface, DWORD draw_aspect, LONG index,
844 void *aspect, DWORD *freeze)
846 ok(0, "unexpected call Freeze\n");
847 return E_NOTIMPL;
850 static HRESULT WINAPI viewobject_Unfreeze(IViewObject *iface, DWORD freeze)
852 ok(0, "unexpected call Unfreeze\n");
853 return E_NOTIMPL;
856 static HRESULT WINAPI viewobject_SetAdvise(IViewObject *iface, DWORD aspects, DWORD advf, IAdviseSink *sink)
858 ok(0, "unexpected call SetAdvise\n");
859 return E_NOTIMPL;
862 static HRESULT WINAPI viewobject_GetAdvise(IViewObject *iface, DWORD *aspects, DWORD *advf,
863 IAdviseSink **sink)
865 ok(0, "unexpected call GetAdvise\n");
866 return E_NOTIMPL;
869 static const struct IViewObjectVtbl viewobjectvtbl = {
870 viewobject_QueryInterface,
871 viewobject_AddRef,
872 viewobject_Release,
873 viewobject_Draw,
874 viewobject_GetColorSet,
875 viewobject_Freeze,
876 viewobject_Unfreeze,
877 viewobject_SetAdvise,
878 viewobject_GetAdvise
881 static IViewObject viewobject = { &viewobjectvtbl };
883 static void test_OleCreate(IStorage *pStorage)
885 HRESULT hr;
886 IOleObject *pObject;
887 FORMATETC formatetc;
888 static const struct expected_method methods_olerender_none[] =
890 { "OleObject_QueryInterface", 0 },
891 { "OleObject_AddRef", 0 },
892 { "OleObject_QueryInterface", 0 },
893 { "OleObject_AddRef", TEST_OPTIONAL },
894 { "OleObject_Release", TEST_OPTIONAL },
895 { "OleObject_QueryInterface", TEST_OPTIONAL },
896 { "OleObjectPersistStg_AddRef", 0 },
897 { "OleObjectPersistStg_InitNew", 0 },
898 { "OleObjectPersistStg_Release", 0 },
899 { "OleObject_Release", 0 },
900 { "OleObject_Release", TEST_OPTIONAL },
901 { NULL, 0 }
903 static const struct expected_method methods_olerender_draw[] =
905 { "OleObject_QueryInterface", 0 },
906 { "OleObject_AddRef", 0 },
907 { "OleObject_QueryInterface", 0 },
908 { "OleObject_AddRef", TEST_OPTIONAL /* NT4 only */ },
909 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
910 { "OleObject_QueryInterface", TEST_OPTIONAL /* NT4 only */ },
911 { "OleObjectPersistStg_AddRef", 0 },
912 { "OleObjectPersistStg_InitNew", 0 },
913 { "OleObjectPersistStg_Release", 0 },
914 { "OleObject_QueryInterface", 0 },
915 { "OleObjectRunnable_AddRef", 0 },
916 { "OleObjectRunnable_Run", 0 },
917 { "OleObjectRunnable_Release", 0 },
918 { "OleObject_QueryInterface", 0 },
919 { "OleObjectCache_AddRef", 0 },
920 { "OleObjectCache_Cache", 0 },
921 { "OleObjectCache_Release", 0 },
922 { "OleObject_Release", 0 },
923 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
924 { NULL, 0 }
926 static const struct expected_method methods_olerender_draw_with_site[] =
928 { "OleObject_QueryInterface", 0 },
929 { "OleObject_AddRef", 0 },
930 { "OleObject_QueryInterface", 0 },
931 { "OleObject_AddRef", 0 },
932 { "OleObject_GetMiscStatus", 0 },
933 { "OleObject_QueryInterface", 0 },
934 { "OleObjectPersistStg_AddRef", 0 },
935 { "OleObjectPersistStg_InitNew", 0 },
936 { "OleObjectPersistStg_Release", 0 },
937 { "OleObject_SetClientSite", 0 },
938 { "OleObject_Release", 0 },
939 { "OleObject_QueryInterface", 0 },
940 { "OleObjectRunnable_AddRef", 0 },
941 { "OleObjectRunnable_Run", 0 },
942 { "OleObjectRunnable_Release", 0 },
943 { "OleObject_QueryInterface", 0 },
944 { "OleObjectCache_AddRef", 0 },
945 { "OleObjectCache_Cache", 0 },
946 { "OleObjectCache_Release", 0 },
947 { "OleObject_Release", 0 },
948 { NULL, 0 }
950 static const struct expected_method methods_olerender_format[] =
952 { "OleObject_QueryInterface", 0 },
953 { "OleObject_AddRef", 0 },
954 { "OleObject_QueryInterface", 0 },
955 { "OleObject_AddRef", 0 },
956 { "OleObject_GetMiscStatus", 0 },
957 { "OleObject_QueryInterface", 0 },
958 { "OleObjectPersistStg_AddRef", 0 },
959 { "OleObjectPersistStg_InitNew", 0 },
960 { "OleObjectPersistStg_Release", 0 },
961 { "OleObject_SetClientSite", 0 },
962 { "OleObject_Release", 0 },
963 { "OleObject_QueryInterface", 0 },
964 { "OleObjectRunnable_AddRef", 0 },
965 { "OleObjectRunnable_Run", 0 },
966 { "OleObjectRunnable_Release", 0 },
967 { "OleObject_QueryInterface", 0 },
968 { "OleObjectCache_AddRef", 0 },
969 { "OleObjectCache_Cache", 0 },
970 { "OleObjectCache_Release", 0 },
971 { "OleObject_Release", 0 },
972 { NULL, 0 }
974 static const struct expected_method methods_olerender_asis[] =
976 { "OleObject_QueryInterface", 0 },
977 { "OleObject_AddRef", 0 },
978 { "OleObject_QueryInterface", 0 },
979 { "OleObject_AddRef", TEST_OPTIONAL /* NT4 only */ },
980 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
981 { "OleObject_QueryInterface", TEST_OPTIONAL /* NT4 only */ },
982 { "OleObjectPersistStg_AddRef", 0 },
983 { "OleObjectPersistStg_InitNew", 0 },
984 { "OleObjectPersistStg_Release", 0 },
985 { "OleObject_Release", 0 },
986 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
987 { NULL, 0 }
989 static const struct expected_method methods_olerender_draw_no_runnable[] =
991 { "OleObject_QueryInterface", 0 },
992 { "OleObject_AddRef", 0 },
993 { "OleObject_QueryInterface", 0 },
994 { "OleObject_AddRef", TEST_OPTIONAL /* NT4 only */ },
995 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
996 { "OleObject_QueryInterface", TEST_OPTIONAL /* NT4 only */ },
997 { "OleObjectPersistStg_AddRef", 0 },
998 { "OleObjectPersistStg_InitNew", 0 },
999 { "OleObjectPersistStg_Release", 0 },
1000 { "OleObject_QueryInterface", 0 },
1001 { "OleObject_QueryInterface", 0 },
1002 { "OleObjectCache_AddRef", 0 },
1003 { "OleObjectCache_Cache", 0 },
1004 { "OleObjectCache_Release", 0 },
1005 { "OleObject_Release", 0 },
1006 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1007 { NULL, 0 },
1009 static const struct expected_method methods_olerender_draw_no_cache[] =
1011 { "OleObject_QueryInterface", 0 },
1012 { "OleObject_AddRef", 0 },
1013 { "OleObject_QueryInterface", 0 },
1014 { "OleObject_AddRef", TEST_OPTIONAL /* NT4 only */ },
1015 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1016 { "OleObject_QueryInterface", TEST_OPTIONAL /* NT4 only */ },
1017 { "OleObjectPersistStg_AddRef", 0 },
1018 { "OleObjectPersistStg_InitNew", 0 },
1019 { "OleObjectPersistStg_Release", 0 },
1020 { "OleObject_QueryInterface", 0 },
1021 { "OleObjectRunnable_AddRef", 0 },
1022 { "OleObjectRunnable_Run", 0 },
1023 { "OleObjectRunnable_Release", 0 },
1024 { "OleObject_QueryInterface", 0 },
1025 { "OleObject_Release", 0 },
1026 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1027 { NULL, 0 }
1030 g_expected_fetc = &formatetc;
1031 formatetc.cfFormat = 0;
1032 formatetc.ptd = NULL;
1033 formatetc.dwAspect = DVASPECT_CONTENT;
1034 formatetc.lindex = -1;
1035 formatetc.tymed = TYMED_NULL;
1036 runnable = &OleObjectRunnable;
1037 cache = &OleObjectCache;
1038 expected_method_list = methods_olerender_none;
1039 trace("OleCreate with OLERENDER_NONE:\n");
1040 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_NONE, NULL, NULL, pStorage, (void **)&pObject);
1041 ok_ole_success(hr, "OleCreate");
1042 IOleObject_Release(pObject);
1043 CHECK_NO_EXTRA_METHODS();
1045 expected_method_list = methods_olerender_draw;
1046 trace("OleCreate with OLERENDER_DRAW:\n");
1047 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, NULL, pStorage, (void **)&pObject);
1048 ok_ole_success(hr, "OleCreate");
1049 IOleObject_Release(pObject);
1050 CHECK_NO_EXTRA_METHODS();
1052 expected_method_list = methods_olerender_draw_with_site;
1053 trace("OleCreate with OLERENDER_DRAW, with site:\n");
1054 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, (IOleClientSite*)0xdeadbeef, pStorage, (void **)&pObject);
1055 ok_ole_success(hr, "OleCreate");
1056 IOleObject_Release(pObject);
1057 CHECK_NO_EXTRA_METHODS();
1059 /* GetMiscStatus fails */
1060 g_GetMiscStatusFailsWith = 0x8fafefaf;
1061 expected_method_list = methods_olerender_draw_with_site;
1062 trace("OleCreate with OLERENDER_DRAW, with site:\n");
1063 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, (IOleClientSite*)0xdeadbeef, pStorage, (void **)&pObject);
1064 ok_ole_success(hr, "OleCreate");
1065 IOleObject_Release(pObject);
1066 CHECK_NO_EXTRA_METHODS();
1067 g_GetMiscStatusFailsWith = S_OK;
1069 formatetc.cfFormat = CF_TEXT;
1070 formatetc.ptd = NULL;
1071 formatetc.dwAspect = DVASPECT_CONTENT;
1072 formatetc.lindex = -1;
1073 formatetc.tymed = TYMED_HGLOBAL;
1074 expected_method_list = methods_olerender_format;
1075 trace("OleCreate with OLERENDER_FORMAT:\n");
1076 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_FORMAT, &formatetc, (IOleClientSite *)0xdeadbeef, pStorage, (void **)&pObject);
1077 ok(hr == S_OK ||
1078 broken(hr == E_INVALIDARG), /* win2k */
1079 "OleCreate failed with error 0x%08x\n", hr);
1080 if (pObject)
1082 IOleObject_Release(pObject);
1083 CHECK_NO_EXTRA_METHODS();
1086 expected_method_list = methods_olerender_asis;
1087 trace("OleCreate with OLERENDER_ASIS:\n");
1088 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_ASIS, NULL, NULL, pStorage, (void **)&pObject);
1089 ok_ole_success(hr, "OleCreate");
1090 IOleObject_Release(pObject);
1091 CHECK_NO_EXTRA_METHODS();
1093 formatetc.cfFormat = 0;
1094 formatetc.tymed = TYMED_NULL;
1095 runnable = NULL;
1096 expected_method_list = methods_olerender_draw_no_runnable;
1097 trace("OleCreate with OLERENDER_DRAW (no IRunnableObject):\n");
1098 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, NULL, pStorage, (void **)&pObject);
1099 ok_ole_success(hr, "OleCreate");
1100 IOleObject_Release(pObject);
1101 CHECK_NO_EXTRA_METHODS();
1103 runnable = &OleObjectRunnable;
1104 cache = NULL;
1105 expected_method_list = methods_olerender_draw_no_cache;
1106 trace("OleCreate with OLERENDER_DRAW (no IOleCache):\n");
1107 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, NULL, pStorage, (void **)&pObject);
1108 ok_ole_success(hr, "OleCreate");
1109 IOleObject_Release(pObject);
1110 CHECK_NO_EXTRA_METHODS();
1111 trace("end\n");
1112 g_expected_fetc = NULL;
1115 static void test_OleLoad(IStorage *pStorage)
1117 HRESULT hr;
1118 IOleObject *pObject;
1119 DWORD fmt;
1121 static const struct expected_method methods_oleload[] =
1123 { "OleObject_QueryInterface", 0 },
1124 { "OleObject_AddRef", 0 },
1125 { "OleObject_QueryInterface", 0 },
1126 { "OleObject_AddRef", 0 },
1127 { "OleObject_GetMiscStatus", 0 },
1128 { "OleObject_QueryInterface", 0 },
1129 { "OleObjectPersistStg_AddRef", 0 },
1130 { "OleObjectPersistStg_Load", 0 },
1131 { "OleObjectPersistStg_Release", 0 },
1132 { "OleObject_SetClientSite", 0 },
1133 { "OleObject_Release", 0 },
1134 { "OleObject_QueryInterface", 0 },
1135 { "OleObject_GetMiscStatus", 0 },
1136 { "OleObject_Release", 0 },
1137 { NULL, 0 }
1140 /* Test once with IOleObject_GetMiscStatus failing */
1141 expected_method_list = methods_oleload;
1142 g_GetMiscStatusFailsWith = E_FAIL;
1143 trace("OleLoad:\n");
1144 hr = OleLoad(pStorage, &IID_IOleObject, (IOleClientSite *)0xdeadbeef, (void **)&pObject);
1145 ok(hr == S_OK ||
1146 broken(hr == E_INVALIDARG), /* win98 and win2k */
1147 "OleLoad failed with error 0x%08x\n", hr);
1148 if(pObject)
1150 DWORD dwStatus = 0xdeadbeef;
1151 hr = IOleObject_GetMiscStatus(pObject, DVASPECT_CONTENT, &dwStatus);
1152 ok(hr == E_FAIL, "Got 0x%08x\n", hr);
1153 ok(dwStatus == 0x1234, "Got 0x%08x\n", dwStatus);
1155 IOleObject_Release(pObject);
1156 CHECK_NO_EXTRA_METHODS();
1158 g_GetMiscStatusFailsWith = S_OK;
1160 /* Test again, let IOleObject_GetMiscStatus succeed. */
1161 expected_method_list = methods_oleload;
1162 trace("OleLoad:\n");
1163 hr = OleLoad(pStorage, &IID_IOleObject, (IOleClientSite *)0xdeadbeef, (void **)&pObject);
1164 ok(hr == S_OK ||
1165 broken(hr == E_INVALIDARG), /* win98 and win2k */
1166 "OleLoad failed with error 0x%08x\n", hr);
1167 if (pObject)
1169 DWORD dwStatus = 0xdeadbeef;
1170 hr = IOleObject_GetMiscStatus(pObject, DVASPECT_CONTENT, &dwStatus);
1171 ok(hr == S_OK, "Got 0x%08x\n", hr);
1172 ok(dwStatus == 1, "Got 0x%08x\n", dwStatus);
1174 IOleObject_Release(pObject);
1175 CHECK_NO_EXTRA_METHODS();
1178 for (fmt = CF_TEXT; fmt < CF_MAX; fmt++)
1180 static const WCHAR olrepres[] = { 2,'O','l','e','P','r','e','s','0','0','0',0 };
1181 IStorage *stg;
1182 IStream *stream;
1183 IUnknown *obj;
1184 DWORD data, i, data_size;
1185 PresentationDataHeader header;
1186 HDC hdc;
1187 HGDIOBJ hobj;
1188 RECT rc;
1189 char buf[256];
1191 for (i = 0; i < 7; i++)
1193 hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &stg);
1194 ok(hr == S_OK, "StgCreateDocfile error %#x\n", hr);
1196 hr = IStorage_SetClass(stg, &CLSID_WineTest);
1197 ok(hr == S_OK, "SetClass error %#x\n", hr);
1199 hr = IStorage_CreateStream(stg, olrepres, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, &stream);
1200 ok(hr == S_OK, "CreateStream error %#x\n", hr);
1202 data = ~0;
1203 hr = IStream_Write(stream, &data, sizeof(data), NULL);
1204 ok(hr == S_OK, "Write error %#x\n", hr);
1206 data = fmt;
1207 hr = IStream_Write(stream, &data, sizeof(data), NULL);
1208 ok(hr == S_OK, "Write error %#x\n", hr);
1210 switch (fmt)
1212 case CF_BITMAP:
1213 /* FIXME: figure out stream format */
1214 hobj = CreateBitmap(1, 1, 1, 1, NULL);
1215 data_size = GetBitmapBits(hobj, sizeof(buf), buf);
1216 DeleteObject(hobj);
1217 break;
1219 case CF_METAFILEPICT:
1220 case CF_ENHMETAFILE:
1221 hdc = CreateMetaFileA(NULL);
1222 hobj = CloseMetaFile(hdc);
1223 data_size = GetMetaFileBitsEx(hobj, sizeof(buf), buf);
1224 DeleteMetaFile(hobj);
1225 break;
1227 default:
1228 data_size = sizeof(buf);
1229 memset(buf, 'A', sizeof(buf));
1230 break;
1233 header.unknown3 = 4;
1234 header.dvAspect = DVASPECT_CONTENT;
1235 header.lindex = -1;
1236 header.advf = 1 << i;
1237 header.unknown7 = 0;
1238 header.dwObjectExtentX = 1;
1239 header.dwObjectExtentY = 1;
1240 header.dwSize = data_size;
1241 hr = IStream_Write(stream, &header, sizeof(header), NULL);
1242 ok(hr == S_OK, "Write error %#x\n", hr);
1244 hr = IStream_Write(stream, buf, data_size, NULL);
1245 ok(hr == S_OK, "Write error %#x\n", hr);
1247 IStream_Release(stream);
1249 hr = OleLoad(stg, &IID_IUnknown, NULL, (void **)&obj);
1250 /* FIXME: figure out stream format */
1251 if (fmt == CF_BITMAP && hr != S_OK)
1253 IStorage_Release(stg);
1254 continue;
1256 ok(hr == S_OK, "OleLoad error %#x: cfFormat = %u, advf = %#x\n", hr, fmt, header.advf);
1258 hdc = CreateCompatibleDC(0);
1259 SetRect(&rc, 0, 0, 100, 100);
1260 hr = OleDraw(obj, DVASPECT_CONTENT, hdc, &rc);
1261 DeleteDC(hdc);
1262 if (fmt == CF_METAFILEPICT)
1263 ok(hr == S_OK, "OleDraw error %#x: cfFormat = %u, advf = %#x\n", hr, fmt, header.advf);
1264 else if (fmt == CF_ENHMETAFILE)
1265 todo_wine
1266 ok(hr == S_OK, "OleDraw error %#x: cfFormat = %u, advf = %#x\n", hr, fmt, header.advf);
1267 else
1268 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);
1270 IUnknown_Release(obj);
1271 IStorage_Release(stg);
1276 static BOOL STDMETHODCALLTYPE draw_continue(ULONG_PTR param)
1278 CHECK_EXPECTED_METHOD("draw_continue");
1279 return TRUE;
1282 static BOOL STDMETHODCALLTYPE draw_continue_false(ULONG_PTR param)
1284 CHECK_EXPECTED_METHOD("draw_continue_false");
1285 return FALSE;
1288 static HRESULT WINAPI AdviseSink_QueryInterface(IAdviseSink *iface, REFIID riid, void **ppv)
1290 if (IsEqualIID(riid, &IID_IAdviseSink) || IsEqualIID(riid, &IID_IUnknown))
1292 *ppv = iface;
1293 IAdviseSink_AddRef(iface);
1294 return S_OK;
1296 *ppv = NULL;
1297 return E_NOINTERFACE;
1300 static ULONG WINAPI AdviseSink_AddRef(IAdviseSink *iface)
1302 return 2;
1305 static ULONG WINAPI AdviseSink_Release(IAdviseSink *iface)
1307 return 1;
1311 static void WINAPI AdviseSink_OnDataChange(
1312 IAdviseSink *iface,
1313 FORMATETC *pFormatetc,
1314 STGMEDIUM *pStgmed)
1316 CHECK_EXPECTED_METHOD("AdviseSink_OnDataChange");
1319 static void WINAPI AdviseSink_OnViewChange(
1320 IAdviseSink *iface,
1321 DWORD dwAspect,
1322 LONG lindex)
1324 CHECK_EXPECTED_METHOD("AdviseSink_OnViewChange");
1327 static void WINAPI AdviseSink_OnRename(
1328 IAdviseSink *iface,
1329 IMoniker *pmk)
1331 CHECK_EXPECTED_METHOD("AdviseSink_OnRename");
1334 static void WINAPI AdviseSink_OnSave(IAdviseSink *iface)
1336 CHECK_EXPECTED_METHOD("AdviseSink_OnSave");
1339 static void WINAPI AdviseSink_OnClose(IAdviseSink *iface)
1341 CHECK_EXPECTED_METHOD("AdviseSink_OnClose");
1344 static const IAdviseSinkVtbl AdviseSinkVtbl =
1346 AdviseSink_QueryInterface,
1347 AdviseSink_AddRef,
1348 AdviseSink_Release,
1349 AdviseSink_OnDataChange,
1350 AdviseSink_OnViewChange,
1351 AdviseSink_OnRename,
1352 AdviseSink_OnSave,
1353 AdviseSink_OnClose
1356 static IAdviseSink AdviseSink = { &AdviseSinkVtbl };
1358 static HRESULT WINAPI DataObject_QueryInterface(
1359 IDataObject* iface,
1360 REFIID riid,
1361 void** ppvObject)
1363 CHECK_EXPECTED_METHOD("DataObject_QueryInterface");
1365 if (IsEqualIID(riid, &IID_IDataObject) || IsEqualIID(riid, &IID_IUnknown))
1367 *ppvObject = iface;
1368 return S_OK;
1370 *ppvObject = NULL;
1371 return S_OK;
1374 static ULONG WINAPI DataObject_AddRef(
1375 IDataObject* iface)
1377 CHECK_EXPECTED_METHOD("DataObject_AddRef");
1378 return 2;
1381 static ULONG WINAPI DataObject_Release(
1382 IDataObject* iface)
1384 CHECK_EXPECTED_METHOD("DataObject_Release");
1385 return 1;
1388 static HRESULT WINAPI DataObject_GetData(
1389 IDataObject* iface,
1390 LPFORMATETC pformatetcIn,
1391 STGMEDIUM* pmedium)
1393 CHECK_EXPECTED_METHOD("DataObject_GetData");
1394 return E_NOTIMPL;
1397 static HRESULT WINAPI DataObject_GetDataHere(
1398 IDataObject* iface,
1399 LPFORMATETC pformatetc,
1400 STGMEDIUM* pmedium)
1402 CHECK_EXPECTED_METHOD("DataObject_GetDataHere");
1403 return E_NOTIMPL;
1406 static HRESULT WINAPI DataObject_QueryGetData(
1407 IDataObject* iface,
1408 LPFORMATETC pformatetc)
1410 CHECK_EXPECTED_METHOD("DataObject_QueryGetData");
1411 return S_OK;
1414 static HRESULT WINAPI DataObject_GetCanonicalFormatEtc(
1415 IDataObject* iface,
1416 LPFORMATETC pformatectIn,
1417 LPFORMATETC pformatetcOut)
1419 CHECK_EXPECTED_METHOD("DataObject_GetCanonicalFormatEtc");
1420 return E_NOTIMPL;
1423 static HRESULT WINAPI DataObject_SetData(
1424 IDataObject* iface,
1425 LPFORMATETC pformatetc,
1426 STGMEDIUM* pmedium,
1427 BOOL fRelease)
1429 CHECK_EXPECTED_METHOD("DataObject_SetData");
1430 return E_NOTIMPL;
1433 static HRESULT WINAPI DataObject_EnumFormatEtc(
1434 IDataObject* iface,
1435 DWORD dwDirection,
1436 IEnumFORMATETC** ppenumFormatEtc)
1438 CHECK_EXPECTED_METHOD("DataObject_EnumFormatEtc");
1439 return E_NOTIMPL;
1442 static HRESULT WINAPI DataObject_DAdvise(
1443 IDataObject* iface,
1444 FORMATETC* pformatetc,
1445 DWORD advf,
1446 IAdviseSink* pAdvSink,
1447 DWORD* pdwConnection)
1449 STGMEDIUM stgmedium;
1451 CHECK_EXPECTED_METHOD("DataObject_DAdvise");
1452 *pdwConnection = 1;
1454 if(advf & ADVF_PRIMEFIRST)
1456 ok(pformatetc->cfFormat == cf_test_2, "got %04x\n", pformatetc->cfFormat);
1457 stgmedium.tymed = TYMED_HGLOBAL;
1458 U(stgmedium).hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 4);
1459 stgmedium.pUnkForRelease = NULL;
1460 IAdviseSink_OnDataChange(pAdvSink, pformatetc, &stgmedium);
1463 return S_OK;
1466 static HRESULT WINAPI DataObject_DUnadvise(
1467 IDataObject* iface,
1468 DWORD dwConnection)
1470 CHECK_EXPECTED_METHOD("DataObject_DUnadvise");
1471 return S_OK;
1474 static HRESULT WINAPI DataObject_EnumDAdvise(
1475 IDataObject* iface,
1476 IEnumSTATDATA** ppenumAdvise)
1478 CHECK_EXPECTED_METHOD("DataObject_EnumDAdvise");
1479 return OLE_E_ADVISENOTSUPPORTED;
1482 static IDataObjectVtbl DataObjectVtbl =
1484 DataObject_QueryInterface,
1485 DataObject_AddRef,
1486 DataObject_Release,
1487 DataObject_GetData,
1488 DataObject_GetDataHere,
1489 DataObject_QueryGetData,
1490 DataObject_GetCanonicalFormatEtc,
1491 DataObject_SetData,
1492 DataObject_EnumFormatEtc,
1493 DataObject_DAdvise,
1494 DataObject_DUnadvise,
1495 DataObject_EnumDAdvise
1498 static IDataObject DataObject = { &DataObjectVtbl };
1500 static HRESULT WINAPI Unknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1502 *ppv = NULL;
1503 if (IsEqualIID(riid, &IID_IUnknown)) *ppv = iface;
1504 if (*ppv)
1506 IUnknown_AddRef((IUnknown *)*ppv);
1507 return S_OK;
1509 return E_NOINTERFACE;
1512 static ULONG WINAPI Unknown_AddRef(IUnknown *iface)
1514 return 2;
1517 static ULONG WINAPI Unknown_Release(IUnknown *iface)
1519 return 1;
1522 static const IUnknownVtbl UnknownVtbl =
1524 Unknown_QueryInterface,
1525 Unknown_AddRef,
1526 Unknown_Release
1529 static IUnknown unknown = { &UnknownVtbl };
1531 static void check_enum_cache(IOleCache2 *cache, const STATDATA *expect, int num)
1533 IEnumSTATDATA *enum_stat;
1534 STATDATA stat;
1535 HRESULT hr;
1537 hr = IOleCache2_EnumCache( cache, &enum_stat );
1538 ok( hr == S_OK, "got %08x\n", hr );
1540 while (IEnumSTATDATA_Next(enum_stat, 1, &stat, NULL) == S_OK)
1542 ok( stat.formatetc.cfFormat == expect->formatetc.cfFormat, "got %d expect %d\n",
1543 stat.formatetc.cfFormat, expect->formatetc.cfFormat );
1544 ok( !stat.formatetc.ptd == !expect->formatetc.ptd, "got %p expect %p\n",
1545 stat.formatetc.ptd, expect->formatetc.ptd );
1546 ok( stat.formatetc.dwAspect == expect->formatetc.dwAspect, "got %d expect %d\n",
1547 stat.formatetc.dwAspect, expect->formatetc.dwAspect );
1548 ok( stat.formatetc.lindex == expect->formatetc.lindex, "got %d expect %d\n",
1549 stat.formatetc.lindex, expect->formatetc.lindex );
1550 ok( stat.formatetc.tymed == expect->formatetc.tymed, "got %d expect %d\n",
1551 stat.formatetc.tymed, expect->formatetc.tymed );
1552 ok( stat.advf == expect->advf, "got %d expect %d\n", stat.advf, expect->advf );
1553 ok( stat.pAdvSink == 0, "got %p\n", stat.pAdvSink );
1554 ok( stat.dwConnection == expect->dwConnection, "got %d expect %d\n", stat.dwConnection, expect->dwConnection );
1555 num--;
1556 expect++;
1559 ok( num == 0, "incorrect number. num %d\n", num );
1561 IEnumSTATDATA_Release( enum_stat );
1564 static void test_data_cache(void)
1566 HRESULT hr;
1567 IOleCache2 *pOleCache;
1568 IOleCache *olecache;
1569 IStorage *pStorage;
1570 IUnknown *unk, *unk2;
1571 IPersistStorage *pPS;
1572 IViewObject *pViewObject;
1573 IOleCacheControl *pOleCacheControl;
1574 IDataObject *pCacheDataObject;
1575 FORMATETC fmtetc;
1576 STGMEDIUM stgmedium;
1577 DWORD dwConnection;
1578 DWORD dwFreeze;
1579 RECTL rcBounds;
1580 HDC hdcMem;
1581 CLSID clsid;
1582 char szSystemDir[MAX_PATH];
1583 WCHAR wszPath[MAX_PATH];
1584 static const WCHAR wszShell32[] = {'\\','s','h','e','l','l','3','2','.','d','l','l',0};
1586 static const struct expected_method methods_cacheinitnew[] =
1588 { "AdviseSink_OnViewChange", 0 },
1589 { "AdviseSink_OnViewChange", 0 },
1590 { "draw_continue", 1 },
1591 { "draw_continue_false", 1 },
1592 { "DataObject_DAdvise", 0 },
1593 { "DataObject_DAdvise", 0 },
1594 { "DataObject_DUnadvise", 0 },
1595 { "DataObject_DUnadvise", 0 },
1596 { NULL, 0 }
1598 static const struct expected_method methods_cacheload[] =
1600 { "AdviseSink_OnViewChange", 0 },
1601 { "draw_continue", 1 },
1602 { "draw_continue", 1 },
1603 { "draw_continue", 1 },
1604 { "DataObject_GetData", 0 },
1605 { "DataObject_GetData", 0 },
1606 { "DataObject_GetData", 0 },
1607 { NULL, 0 }
1609 static const struct expected_method methods_cachethenrun[] =
1611 { "DataObject_DAdvise", 0 },
1612 { "DataObject_DAdvise", 0 },
1613 { "DataObject_DAdvise", 0 },
1614 { "DataObject_QueryGetData", 1 }, /* called by win9x and nt4 */
1615 { "DataObject_DAdvise", 0 },
1616 { "DataObject_DUnadvise", 0 },
1617 { "DataObject_DUnadvise", 0 },
1618 { "DataObject_DUnadvise", 0 },
1619 { "DataObject_DUnadvise", 0 },
1620 { NULL, 0 }
1623 GetSystemDirectoryA(szSystemDir, sizeof(szSystemDir)/sizeof(szSystemDir[0]));
1625 expected_method_list = methods_cacheinitnew;
1627 fmtetc.cfFormat = CF_METAFILEPICT;
1628 fmtetc.dwAspect = DVASPECT_ICON;
1629 fmtetc.lindex = -1;
1630 fmtetc.ptd = NULL;
1631 fmtetc.tymed = TYMED_MFPICT;
1633 hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &pStorage);
1634 ok_ole_success(hr, "StgCreateDocfile");
1636 /* aggregation */
1638 /* requested is not IUnknown */
1639 hr = CreateDataCache(&unknown, &CLSID_NULL, &IID_IOleCache2, (void**)&pOleCache);
1640 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1642 hr = CreateDataCache(&unknown, &CLSID_NULL, &IID_IUnknown, (void**)&unk);
1643 ok(hr == S_OK, "got 0x%08x\n", hr);
1645 hr = IUnknown_QueryInterface(unk, &IID_IOleCache, (void**)&olecache);
1646 ok(hr == S_OK, "got 0x%08x\n", hr);
1647 hr = IUnknown_QueryInterface(unk, &IID_IOleCache2, (void**)&pOleCache);
1648 ok(hr == S_OK, "got 0x%08x\n", hr);
1649 ok(unk != (IUnknown*)olecache, "got %p, expected %p\n", olecache, unk);
1650 ok(unk != (IUnknown*)pOleCache, "got %p, expected %p\n", pOleCache, unk);
1651 IOleCache2_Release(pOleCache);
1652 IOleCache_Release(olecache);
1653 IUnknown_Release(unk);
1655 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IUnknown, (void**)&unk);
1656 ok(hr == S_OK, "got 0x%08x\n", hr);
1657 hr = IUnknown_QueryInterface(unk, &IID_IOleCache, (void**)&olecache);
1658 ok(hr == S_OK, "got 0x%08x\n", hr);
1659 hr = IUnknown_QueryInterface(unk, &IID_IOleCache2, (void**)&pOleCache);
1660 ok(hr == S_OK, "got 0x%08x\n", hr);
1661 hr = IUnknown_QueryInterface(unk, &IID_IUnknown, (void**)&unk2);
1662 ok(hr == S_OK, "got 0x%08x\n", hr);
1663 ok(unk == (IUnknown*)olecache, "got %p, expected %p\n", olecache, unk);
1664 ok(unk == (IUnknown*)pOleCache, "got %p, expected %p\n", pOleCache, unk);
1665 ok(unk == unk2, "got %p, expected %p\n", unk2, unk);
1666 IUnknown_Release(unk2);
1667 IOleCache2_Release(pOleCache);
1668 IOleCache_Release(olecache);
1669 IUnknown_Release(unk);
1671 /* Test with new data */
1673 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IOleCache2, (LPVOID *)&pOleCache);
1674 ok_ole_success(hr, "CreateDataCache");
1676 hr = IOleCache2_QueryInterface(pOleCache, &IID_IPersistStorage, (LPVOID *)&pPS);
1677 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IPersistStorage)");
1678 hr = IOleCache2_QueryInterface(pOleCache, &IID_IViewObject, (LPVOID *)&pViewObject);
1679 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IViewObject)");
1680 hr = IOleCache2_QueryInterface(pOleCache, &IID_IOleCacheControl, (LPVOID *)&pOleCacheControl);
1681 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IOleCacheControl)");
1683 hr = IViewObject_SetAdvise(pViewObject, DVASPECT_ICON, ADVF_PRIMEFIRST, &AdviseSink);
1684 ok_ole_success(hr, "IViewObject_SetAdvise");
1686 hr = IPersistStorage_InitNew(pPS, pStorage);
1687 ok_ole_success(hr, "IPersistStorage_InitNew");
1689 hr = IPersistStorage_IsDirty(pPS);
1690 ok_ole_success(hr, "IPersistStorage_IsDirty");
1692 hr = IPersistStorage_GetClassID(pPS, &clsid);
1693 ok_ole_success(hr, "IPersistStorage_GetClassID");
1694 ok(IsEqualCLSID(&clsid, &IID_NULL), "clsid should be blank\n");
1696 hr = IOleCache2_Uncache(pOleCache, 0xdeadbeef);
1697 ok(hr == OLE_E_NOCONNECTION, "IOleCache_Uncache with invalid value should return OLE_E_NOCONNECTION instead of 0x%x\n", hr);
1699 /* Both tests crash on NT4 and below. StgCreatePropSetStg is only available on w2k and above. */
1700 if (GetProcAddress(GetModuleHandleA("ole32.dll"), "StgCreatePropSetStg"))
1702 hr = IOleCache2_Cache(pOleCache, NULL, 0, &dwConnection);
1703 ok(hr == E_INVALIDARG, "IOleCache_Cache with NULL fmtetc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1705 hr = IOleCache2_Cache(pOleCache, NULL, 0, NULL);
1706 ok(hr == E_INVALIDARG, "IOleCache_Cache with NULL pdwConnection should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1708 else
1710 skip("tests with NULL parameters will crash on NT4 and below\n");
1713 for (fmtetc.cfFormat = CF_TEXT; fmtetc.cfFormat < CF_MAX; fmtetc.cfFormat++)
1715 int i;
1716 fmtetc.dwAspect = DVASPECT_THUMBNAIL;
1717 for (i = 0; i < 7; i++)
1719 fmtetc.tymed = 1 << i;
1720 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1721 if ((fmtetc.cfFormat == CF_METAFILEPICT && fmtetc.tymed == TYMED_MFPICT) ||
1722 (fmtetc.cfFormat == CF_BITMAP && fmtetc.tymed == TYMED_GDI) ||
1723 (fmtetc.cfFormat == CF_DIB && fmtetc.tymed == TYMED_HGLOBAL) ||
1724 (fmtetc.cfFormat == CF_ENHMETAFILE && fmtetc.tymed == TYMED_ENHMF))
1725 ok(hr == S_OK, "IOleCache_Cache cfFormat = %d, tymed = %d should have returned S_OK instead of 0x%08x\n",
1726 fmtetc.cfFormat, fmtetc.tymed, hr);
1727 else if (fmtetc.tymed == TYMED_HGLOBAL)
1728 ok(hr == CACHE_S_FORMATETC_NOTSUPPORTED ||
1729 broken(hr == S_OK && fmtetc.cfFormat == CF_BITMAP) /* Win9x & NT4 */,
1730 "IOleCache_Cache cfFormat = %d, tymed = %d should have returned CACHE_S_FORMATETC_NOTSUPPORTED instead of 0x%08x\n",
1731 fmtetc.cfFormat, fmtetc.tymed, hr);
1732 else
1733 ok(hr == DV_E_TYMED, "IOleCache_Cache cfFormat = %d, tymed = %d should have returned DV_E_TYMED instead of 0x%08x\n",
1734 fmtetc.cfFormat, fmtetc.tymed, hr);
1735 if (SUCCEEDED(hr))
1737 hr = IOleCache2_Uncache(pOleCache, dwConnection);
1738 ok_ole_success(hr, "IOleCache_Uncache");
1743 fmtetc.cfFormat = CF_BITMAP;
1744 fmtetc.dwAspect = DVASPECT_THUMBNAIL;
1745 fmtetc.tymed = TYMED_GDI;
1746 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1747 ok_ole_success(hr, "IOleCache_Cache");
1749 fmtetc.cfFormat = 0;
1750 fmtetc.dwAspect = DVASPECT_ICON;
1751 fmtetc.tymed = TYMED_MFPICT;
1752 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1753 ok_ole_success(hr, "IOleCache_Cache");
1755 MultiByteToWideChar(CP_ACP, 0, szSystemDir, -1, wszPath, sizeof(wszPath)/sizeof(wszPath[0]));
1756 memcpy(wszPath+lstrlenW(wszPath), wszShell32, sizeof(wszShell32));
1758 fmtetc.cfFormat = CF_METAFILEPICT;
1759 stgmedium.tymed = TYMED_MFPICT;
1760 U(stgmedium).hMetaFilePict = OleMetafilePictFromIconAndLabel(
1761 LoadIconA(NULL, (LPSTR)IDI_APPLICATION), wszPath, wszPath, 0);
1762 stgmedium.pUnkForRelease = NULL;
1764 fmtetc.dwAspect = DVASPECT_CONTENT;
1765 hr = IOleCache2_SetData(pOleCache, &fmtetc, &stgmedium, FALSE);
1766 ok(hr == OLE_E_BLANK, "IOleCache_SetData for aspect not in cache should have return OLE_E_BLANK instead of 0x%08x\n", hr);
1768 fmtetc.dwAspect = DVASPECT_ICON;
1769 hr = IOleCache2_SetData(pOleCache, &fmtetc, &stgmedium, FALSE);
1770 ok_ole_success(hr, "IOleCache_SetData");
1771 ReleaseStgMedium(&stgmedium);
1773 hr = IViewObject_Freeze(pViewObject, DVASPECT_ICON, -1, NULL, &dwFreeze);
1774 todo_wine {
1775 ok_ole_success(hr, "IViewObject_Freeze");
1776 hr = IViewObject_Freeze(pViewObject, DVASPECT_CONTENT, -1, NULL, &dwFreeze);
1777 ok(hr == OLE_E_BLANK, "IViewObject_Freeze with uncached aspect should have returned OLE_E_BLANK instead of 0x%08x\n", hr);
1780 rcBounds.left = 0;
1781 rcBounds.top = 0;
1782 rcBounds.right = 100;
1783 rcBounds.bottom = 100;
1784 hdcMem = CreateCompatibleDC(NULL);
1786 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1787 ok_ole_success(hr, "IViewObject_Draw");
1789 hr = IViewObject_Draw(pViewObject, DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1790 ok(hr == OLE_E_BLANK, "IViewObject_Draw with uncached aspect should have returned OLE_E_BLANK instead of 0x%08x\n", hr);
1792 /* a NULL draw_continue fn ptr */
1793 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, NULL, 0xdeadbeef);
1794 ok_ole_success(hr, "IViewObject_Draw");
1796 /* draw_continue that returns FALSE to abort drawing */
1797 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue_false, 0xdeadbeef);
1798 ok(hr == E_ABORT ||
1799 broken(hr == S_OK), /* win9x may skip the callbacks */
1800 "IViewObject_Draw with draw_continue_false returns 0x%08x\n", hr);
1802 DeleteDC(hdcMem);
1804 hr = IOleCacheControl_OnRun(pOleCacheControl, &DataObject);
1805 ok_ole_success(hr, "IOleCacheControl_OnRun");
1807 hr = IPersistStorage_Save(pPS, pStorage, TRUE);
1808 ok_ole_success(hr, "IPersistStorage_Save");
1810 hr = IPersistStorage_SaveCompleted(pPS, NULL);
1811 ok_ole_success(hr, "IPersistStorage_SaveCompleted");
1813 hr = IPersistStorage_IsDirty(pPS);
1814 ok(hr == S_FALSE, "IPersistStorage_IsDirty should have returned S_FALSE instead of 0x%x\n", hr);
1816 IPersistStorage_Release(pPS);
1817 IViewObject_Release(pViewObject);
1818 IOleCache2_Release(pOleCache);
1819 IOleCacheControl_Release(pOleCacheControl);
1821 CHECK_NO_EXTRA_METHODS();
1823 /* Test with loaded data */
1824 trace("Testing loaded data with CreateDataCache:\n");
1825 expected_method_list = methods_cacheload;
1827 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IOleCache2, (LPVOID *)&pOleCache);
1828 ok_ole_success(hr, "CreateDataCache");
1830 hr = IOleCache2_QueryInterface(pOleCache, &IID_IPersistStorage, (LPVOID *)&pPS);
1831 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IPersistStorage)");
1832 hr = IOleCache2_QueryInterface(pOleCache, &IID_IViewObject, (LPVOID *)&pViewObject);
1833 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IViewObject)");
1835 hr = IViewObject_SetAdvise(pViewObject, DVASPECT_ICON, ADVF_PRIMEFIRST, &AdviseSink);
1836 ok_ole_success(hr, "IViewObject_SetAdvise");
1838 hr = IPersistStorage_Load(pPS, pStorage);
1839 ok_ole_success(hr, "IPersistStorage_Load");
1841 hr = IPersistStorage_IsDirty(pPS);
1842 ok(hr == S_FALSE, "IPersistStorage_IsDirty should have returned S_FALSE instead of 0x%x\n", hr);
1844 fmtetc.cfFormat = 0;
1845 fmtetc.dwAspect = DVASPECT_ICON;
1846 fmtetc.lindex = -1;
1847 fmtetc.ptd = NULL;
1848 fmtetc.tymed = TYMED_MFPICT;
1849 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1850 ok(hr == CACHE_S_SAMECACHE, "IOleCache_Cache with already loaded data format type should return CACHE_S_SAMECACHE instead of 0x%x\n", hr);
1852 rcBounds.left = 0;
1853 rcBounds.top = 0;
1854 rcBounds.right = 100;
1855 rcBounds.bottom = 100;
1856 hdcMem = CreateCompatibleDC(NULL);
1858 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1859 ok_ole_success(hr, "IViewObject_Draw");
1861 hr = IViewObject_Draw(pViewObject, DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1862 ok(hr == OLE_E_BLANK, "IViewObject_Draw with uncached aspect should have returned OLE_E_BLANK instead of 0x%08x\n", hr);
1864 /* unload the cached storage object, causing it to be reloaded */
1865 hr = IOleCache2_DiscardCache(pOleCache, DISCARDCACHE_NOSAVE);
1866 ok_ole_success(hr, "IOleCache2_DiscardCache");
1867 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1868 ok_ole_success(hr, "IViewObject_Draw");
1870 /* unload the cached storage object, but don't allow it to be reloaded */
1871 hr = IPersistStorage_HandsOffStorage(pPS);
1872 ok_ole_success(hr, "IPersistStorage_HandsOffStorage");
1873 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1874 ok_ole_success(hr, "IViewObject_Draw");
1875 hr = IOleCache2_DiscardCache(pOleCache, DISCARDCACHE_NOSAVE);
1876 ok_ole_success(hr, "IOleCache2_DiscardCache");
1877 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1878 ok(hr == OLE_E_BLANK, "IViewObject_Draw with uncached aspect should have returned OLE_E_BLANK instead of 0x%08x\n", hr);
1880 DeleteDC(hdcMem);
1882 todo_wine {
1883 hr = IOleCache2_InitCache(pOleCache, &DataObject);
1884 ok(hr == CACHE_E_NOCACHE_UPDATED, "IOleCache_InitCache should have returned CACHE_E_NOCACHE_UPDATED instead of 0x%08x\n", hr);
1887 IPersistStorage_Release(pPS);
1888 IViewObject_Release(pViewObject);
1889 IOleCache2_Release(pOleCache);
1891 todo_wine {
1892 CHECK_NO_EXTRA_METHODS();
1895 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IOleCache2, (LPVOID *)&pOleCache);
1896 ok_ole_success(hr, "CreateDataCache");
1898 expected_method_list = methods_cachethenrun;
1900 hr = IOleCache2_QueryInterface(pOleCache, &IID_IDataObject, (LPVOID *)&pCacheDataObject);
1901 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IDataObject)");
1902 hr = IOleCache2_QueryInterface(pOleCache, &IID_IOleCacheControl, (LPVOID *)&pOleCacheControl);
1903 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IOleCacheControl)");
1905 fmtetc.cfFormat = CF_METAFILEPICT;
1906 fmtetc.dwAspect = DVASPECT_CONTENT;
1907 fmtetc.tymed = TYMED_MFPICT;
1909 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1910 ok_ole_success(hr, "IOleCache_Cache");
1912 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
1913 ok(hr == OLE_E_BLANK, "got %08x\n", hr);
1915 fmtetc.cfFormat = cf_test_1;
1916 fmtetc.dwAspect = DVASPECT_CONTENT;
1917 fmtetc.tymed = TYMED_HGLOBAL;
1919 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1920 ok(hr == CACHE_S_FORMATETC_NOTSUPPORTED, "got %08x\n", hr);
1922 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
1923 ok(hr == OLE_E_BLANK, "got %08x\n", hr);
1925 fmtetc.cfFormat = cf_test_2;
1926 hr = IOleCache2_Cache(pOleCache, &fmtetc, ADVF_PRIMEFIRST, &dwConnection);
1927 ok(hr == CACHE_S_FORMATETC_NOTSUPPORTED, "got %08x\n", hr);
1929 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
1930 ok(hr == OLE_E_BLANK, "got %08x\n", hr);
1932 hr = IOleCacheControl_OnRun(pOleCacheControl, &DataObject);
1933 ok_ole_success(hr, "IOleCacheControl_OnRun");
1935 fmtetc.cfFormat = cf_test_3;
1936 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1937 ok(hr == CACHE_S_FORMATETC_NOTSUPPORTED, "got %08x\n", hr);
1939 fmtetc.cfFormat = cf_test_1;
1940 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
1941 ok(hr == OLE_E_BLANK, "got %08x\n", hr);
1943 fmtetc.cfFormat = cf_test_2;
1944 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
1945 ok(hr == S_OK, "got %08x\n", hr);
1946 ReleaseStgMedium(&stgmedium);
1948 fmtetc.cfFormat = cf_test_3;
1949 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
1950 ok(hr == OLE_E_BLANK, "got %08x\n", hr);
1952 IOleCacheControl_Release(pOleCacheControl);
1953 IDataObject_Release(pCacheDataObject);
1954 IOleCache2_Release(pOleCache);
1956 CHECK_NO_EXTRA_METHODS();
1958 IStorage_Release(pStorage);
1962 static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0};
1964 /* 2 x 1 x 32 bpp dib. PelsPerMeter = 200x400 */
1965 static BYTE dib[] =
1967 0x42, 0x4d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
1968 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
1970 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00,
1971 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
1973 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00,
1974 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00,
1976 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
1977 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
1980 static IStorage *create_storage( int num )
1982 IStorage *stg;
1983 IStream *stm;
1984 HRESULT hr;
1985 ULONG written;
1987 hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg );
1988 ok( hr == S_OK, "got %08x\n", hr);
1989 hr = IStorage_SetClass( stg, &CLSID_Picture_Dib );
1990 ok( hr == S_OK, "got %08x\n", hr);
1991 hr = IStorage_CreateStream( stg, CONTENTS, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, &stm );
1992 ok( hr == S_OK, "got %08x\n", hr);
1993 if (num == 1) /* Set biXPelsPerMeter = 0 */
1995 dib[0x26] = 0;
1996 dib[0x27] = 0;
1998 hr = IStream_Write( stm, dib, sizeof(dib), &written );
1999 ok( hr == S_OK, "got %08x\n", hr);
2000 IStream_Release( stm );
2001 return stg;
2004 static HGLOBAL create_dib( void )
2006 HGLOBAL h;
2007 void *ptr;
2009 h = GlobalAlloc( GMEM_MOVEABLE, sizeof(dib) - sizeof(BITMAPFILEHEADER) );
2010 ptr = GlobalLock( h );
2011 memcpy( ptr, dib + sizeof(BITMAPFILEHEADER), sizeof(dib) - sizeof(BITMAPFILEHEADER) );
2012 GlobalUnlock( h );
2013 return h;
2016 static void test_data_cache_dib_contents_stream(int num)
2018 HRESULT hr;
2019 IUnknown *unk;
2020 IPersistStorage *persist;
2021 IDataObject *data;
2022 IViewObject2 *view;
2023 IStorage *stg;
2024 IOleCache2 *cache;
2025 FORMATETC fmt = {CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
2026 STGMEDIUM med;
2027 CLSID cls;
2028 SIZEL sz;
2029 BYTE *ptr;
2030 BITMAPINFOHEADER expect_info;
2031 STATDATA enum_expect[] =
2033 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2034 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 },
2037 hr = CreateDataCache( NULL, &CLSID_Picture_Metafile, &IID_IUnknown, (void **)&unk );
2038 ok( SUCCEEDED(hr), "got %08x\n", hr );
2039 hr = IUnknown_QueryInterface( unk, &IID_IPersistStorage, (void **)&persist );
2040 ok( SUCCEEDED(hr), "got %08x\n", hr );
2041 hr = IUnknown_QueryInterface( unk, &IID_IDataObject, (void **)&data );
2042 ok( SUCCEEDED(hr), "got %08x\n", hr );
2043 hr = IUnknown_QueryInterface( unk, &IID_IViewObject2, (void **)&view );
2044 ok( SUCCEEDED(hr), "got %08x\n", hr );
2045 hr = IUnknown_QueryInterface( unk, &IID_IOleCache2, (void **)&cache );
2046 ok( SUCCEEDED(hr), "got %08x\n", hr );
2048 stg = create_storage( num );
2050 hr = IPersistStorage_Load( persist, stg );
2051 ok( SUCCEEDED(hr), "got %08x\n", hr );
2052 IStorage_Release( stg );
2054 hr = IPersistStorage_GetClassID( persist, &cls );
2055 ok( SUCCEEDED(hr), "got %08x\n", hr );
2056 ok( IsEqualCLSID( &cls, &CLSID_Picture_Dib ), "class id mismatch\n" );
2058 hr = IDataObject_GetData( data, &fmt, &med );
2059 ok( SUCCEEDED(hr), "got %08x\n", hr );
2060 ok( med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed );
2061 ok( GlobalSize( U(med).hGlobal ) >= sizeof(dib) - sizeof(BITMAPFILEHEADER),
2062 "got %lu\n", GlobalSize( U(med).hGlobal ) );
2063 ptr = GlobalLock( U(med).hGlobal );
2065 expect_info = *(BITMAPINFOHEADER *)(dib + sizeof(BITMAPFILEHEADER));
2066 if (expect_info.biXPelsPerMeter == 0 || expect_info.biYPelsPerMeter == 0)
2068 HDC hdc = GetDC( 0 );
2069 expect_info.biXPelsPerMeter = MulDiv( GetDeviceCaps( hdc, LOGPIXELSX ), 10000, 254 );
2070 expect_info.biYPelsPerMeter = MulDiv( GetDeviceCaps( hdc, LOGPIXELSY ), 10000, 254 );
2071 ReleaseDC( 0, hdc );
2073 ok( !memcmp( ptr, &expect_info, sizeof(expect_info) ), "mismatch\n" );
2074 ok( !memcmp( ptr + sizeof(expect_info), dib + sizeof(BITMAPFILEHEADER) + sizeof(expect_info),
2075 sizeof(dib) - sizeof(BITMAPFILEHEADER) - sizeof(expect_info) ), "mismatch\n" );
2076 GlobalUnlock( U(med).hGlobal );
2077 ReleaseStgMedium( &med );
2079 check_enum_cache( cache, enum_expect, 2 );
2081 hr = IViewObject2_GetExtent( view, DVASPECT_CONTENT, -1, NULL, &sz );
2082 ok( SUCCEEDED(hr), "got %08x\n", hr );
2083 if (num == 0)
2085 ok( sz.cx == 1000, "got %d\n", sz.cx );
2086 ok( sz.cy == 250, "got %d\n", sz.cy );
2088 else
2090 HDC hdc = GetDC( 0 );
2091 LONG x = 2 * 2540 / GetDeviceCaps( hdc, LOGPIXELSX );
2092 LONG y = 1 * 2540 / GetDeviceCaps( hdc, LOGPIXELSY );
2093 ok( sz.cx == x, "got %d %d\n", sz.cx, x );
2094 ok( sz.cy == y, "got %d %d\n", sz.cy, y );
2096 ReleaseDC( 0, hdc );
2099 IOleCache2_Release( cache );
2100 IViewObject2_Release( view );
2101 IDataObject_Release( data );
2102 IPersistStorage_Release( persist );
2103 IUnknown_Release( unk );
2106 static void check_bitmap_size( HBITMAP h, int cx, int cy )
2108 BITMAP bm;
2110 GetObjectW( h, sizeof(bm), &bm );
2111 ok( bm.bmWidth == cx, "got %d expect %d\n", bm.bmWidth, cx );
2112 ok( bm.bmHeight == cy, "got %d expect %d\n", bm.bmHeight, cy );
2115 static void check_dib_size( HGLOBAL h, int cx, int cy )
2117 BITMAPINFO *info;
2119 info = GlobalLock( h );
2120 ok( info->bmiHeader.biWidth == cx, "got %d expect %d\n", info->bmiHeader.biWidth, cx );
2121 ok( info->bmiHeader.biHeight == cy, "got %d expect %d\n", info->bmiHeader.biHeight, cy );
2122 GlobalUnlock( h );
2125 static void test_data_cache_cache(void)
2127 HRESULT hr;
2128 IOleCache2 *cache;
2129 IDataObject *data;
2130 FORMATETC fmt;
2131 DWORD conn;
2132 STGMEDIUM med;
2133 STATDATA expect[] =
2135 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 0 },
2136 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 0 },
2137 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 0 },
2138 {{ CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF }, 0, NULL, 0 }
2140 STATDATA view_caching[] =
2142 {{ 0, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF }, 0, NULL, 0 },
2143 {{ 0, 0, DVASPECT_THUMBNAIL, -1, TYMED_HGLOBAL }, 0, NULL, 0 },
2144 {{ 0, 0, DVASPECT_DOCPRINT, -1, TYMED_HGLOBAL }, 0, NULL, 0 },
2145 {{ CF_METAFILEPICT, 0, DVASPECT_ICON, -1, TYMED_MFPICT }, 0, NULL, 0 }
2148 hr = CreateDataCache( NULL, &CLSID_NULL, &IID_IOleCache2, (void **)&cache );
2149 ok( hr == S_OK, "got %08x\n", hr );
2151 /* create a dib entry which will also create a bitmap entry too */
2152 fmt.cfFormat = CF_DIB;
2153 fmt.ptd = NULL;
2154 fmt.dwAspect = DVASPECT_CONTENT;
2155 fmt.lindex = -1;
2156 fmt.tymed = TYMED_HGLOBAL;
2158 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2159 ok( hr == S_OK, "got %08x\n", hr );
2160 ok( conn == 2, "got %d\n", conn );
2161 expect[0].dwConnection = conn;
2162 expect[1].dwConnection = conn;
2164 check_enum_cache( cache, expect, 2 );
2166 /* now try to add a bitmap */
2167 fmt.cfFormat = CF_BITMAP;
2168 fmt.tymed = TYMED_GDI;
2170 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2171 ok( hr == CACHE_S_SAMECACHE, "got %08x\n", hr );
2173 /* metafile */
2174 fmt.cfFormat = CF_METAFILEPICT;
2175 fmt.tymed = TYMED_MFPICT;
2177 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2178 ok( hr == S_OK, "got %08x\n", hr );
2179 ok( conn == 3, "got %d\n", conn );
2180 expect[2].dwConnection = conn;
2182 check_enum_cache( cache, expect, 3);
2184 /* enhmetafile */
2185 fmt.cfFormat = CF_ENHMETAFILE;
2186 fmt.tymed = TYMED_ENHMF;
2188 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2189 ok( hr == S_OK, "got %08x\n", hr );
2190 ok( conn == 4, "got %d\n", conn );
2191 expect[3].dwConnection = conn;
2193 check_enum_cache( cache, expect, 4 );
2195 /* uncache everything */
2196 hr = IOleCache2_Uncache( cache, expect[3].dwConnection );
2197 ok( hr == S_OK, "got %08x\n", hr );
2198 hr = IOleCache2_Uncache( cache, expect[2].dwConnection );
2199 ok( hr == S_OK, "got %08x\n", hr );
2200 hr = IOleCache2_Uncache( cache, expect[0].dwConnection );
2201 ok( hr == S_OK, "got %08x\n", hr );
2202 hr = IOleCache2_Uncache( cache, expect[0].dwConnection );
2203 ok( hr == OLE_E_NOCONNECTION, "got %08x\n", hr );
2205 check_enum_cache( cache, expect, 0 );
2207 /* just create a bitmap entry which again adds both dib and bitmap */
2208 fmt.cfFormat = CF_BITMAP;
2209 fmt.tymed = TYMED_GDI;
2211 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2212 ok( hr == S_OK, "got %08x\n", hr );
2214 expect[0].dwConnection = conn;
2215 expect[1].dwConnection = conn;
2217 check_enum_cache( cache, expect, 2 );
2219 /* Try setting a 1x1 bitmap */
2220 hr = IOleCache2_QueryInterface( cache, &IID_IDataObject, (void **) &data );
2221 ok( hr == S_OK, "got %08x\n", hr );
2223 med.tymed = TYMED_GDI;
2224 U(med).hBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
2225 med.pUnkForRelease = NULL;
2227 hr = IOleCache2_SetData( cache, &fmt, &med, TRUE );
2228 ok( hr == S_OK, "got %08x\n", hr );
2230 hr = IDataObject_GetData( data, &fmt, &med );
2231 ok( hr == S_OK, "got %08x\n", hr );
2232 ok( med.tymed == TYMED_GDI, "got %d\n", med.tymed );
2233 check_bitmap_size( U(med).hBitmap, 1, 1 );
2234 ReleaseStgMedium( &med );
2236 fmt.cfFormat = CF_DIB;
2237 fmt.tymed = TYMED_HGLOBAL;
2238 hr = IDataObject_GetData( data, &fmt, &med );
2239 ok( hr == S_OK, "got %08x\n", hr );
2240 ok( med.tymed == TYMED_HGLOBAL, "got %d\n", med.tymed );
2241 check_dib_size( U(med).hGlobal, 1, 1 );
2242 ReleaseStgMedium( &med );
2244 /* Now set a 2x1 dib */
2245 fmt.cfFormat = CF_DIB;
2246 fmt.tymed = TYMED_HGLOBAL;
2247 med.tymed = TYMED_HGLOBAL;
2248 U(med).hGlobal = create_dib();
2250 hr = IOleCache2_SetData( cache, &fmt, &med, TRUE );
2251 ok( hr == S_OK, "got %08x\n", hr );
2253 fmt.cfFormat = CF_BITMAP;
2254 fmt.tymed = TYMED_GDI;
2255 hr = IDataObject_GetData( data, &fmt, &med );
2256 ok( hr == S_OK, "got %08x\n", hr );
2257 ok( med.tymed == TYMED_GDI, "got %d\n", med.tymed );
2258 check_bitmap_size( U(med).hBitmap, 2, 1 );
2259 ReleaseStgMedium( &med );
2261 fmt.cfFormat = CF_DIB;
2262 fmt.tymed = TYMED_HGLOBAL;
2263 hr = IDataObject_GetData( data, &fmt, &med );
2264 ok( hr == S_OK, "got %08x\n", hr );
2265 ok( med.tymed == TYMED_HGLOBAL, "got %d\n", med.tymed );
2266 check_dib_size( U(med).hGlobal, 2, 1 );
2267 ReleaseStgMedium( &med );
2269 /* uncache everything */
2270 hr = IOleCache2_Uncache( cache, conn );
2271 ok( hr == S_OK, "got %08x\n", hr );
2273 /* view caching */
2274 fmt.cfFormat = 0;
2275 fmt.tymed = TYMED_ENHMF;
2276 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2277 ok( hr == S_OK, "got %08x\n", hr );
2278 view_caching[0].dwConnection = conn;
2280 fmt.tymed = TYMED_HGLOBAL;
2281 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2282 ok( hr == CACHE_S_SAMECACHE, "got %08x\n", hr );
2284 fmt.dwAspect = DVASPECT_THUMBNAIL;
2285 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2286 ok( hr == S_OK, "got %08x\n", hr );
2287 view_caching[1].dwConnection = conn;
2289 fmt.dwAspect = DVASPECT_DOCPRINT;
2290 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2291 ok( hr == S_OK, "got %08x\n", hr );
2292 view_caching[2].dwConnection = conn;
2294 /* DVASPECT_ICON view cache gets mapped to CF_METAFILEPICT */
2295 fmt.dwAspect = DVASPECT_ICON;
2296 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2297 ok( hr == S_OK, "got %08x\n", hr );
2298 view_caching[3].dwConnection = conn;
2300 check_enum_cache( cache, view_caching, 4 );
2302 /* uncache everything */
2303 hr = IOleCache2_Uncache( cache, view_caching[3].dwConnection );
2304 ok( hr == S_OK, "got %08x\n", hr );
2305 hr = IOleCache2_Uncache( cache, view_caching[2].dwConnection );
2306 ok( hr == S_OK, "got %08x\n", hr );
2307 hr = IOleCache2_Uncache( cache, view_caching[1].dwConnection );
2308 ok( hr == S_OK, "got %08x\n", hr );
2309 hr = IOleCache2_Uncache( cache, view_caching[0].dwConnection );
2310 ok( hr == S_OK, "got %08x\n", hr );
2312 /* Only able to set cfFormat == CF_METAFILEPICT (or == 0, see above) for DVASPECT_ICON */
2313 fmt.dwAspect = DVASPECT_ICON;
2314 fmt.cfFormat = CF_DIB;
2315 fmt.tymed = TYMED_HGLOBAL;
2316 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2317 ok( hr == DV_E_FORMATETC, "got %08x\n", hr );
2318 fmt.cfFormat = CF_BITMAP;
2319 fmt.tymed = TYMED_GDI;
2320 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2321 ok( hr == DV_E_FORMATETC, "got %08x\n", hr );
2322 fmt.cfFormat = CF_ENHMETAFILE;
2323 fmt.tymed = TYMED_ENHMF;
2324 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2325 ok( hr == DV_E_FORMATETC, "got %08x\n", hr );
2326 fmt.cfFormat = CF_METAFILEPICT;
2327 fmt.tymed = TYMED_MFPICT;
2328 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2329 ok( hr == S_OK, "got %08x\n", hr );
2331 /* uncache everything */
2332 hr = IOleCache2_Uncache( cache, conn );
2333 ok( hr == S_OK, "got %08x\n", hr );
2335 IDataObject_Release( data );
2336 IOleCache2_Release( cache );
2339 /* The CLSID_Picture_ classes automatically create appropriate cache entries */
2340 static void test_data_cache_init(void)
2342 HRESULT hr;
2343 IOleCache2 *cache;
2344 IPersistStorage *persist;
2345 int i;
2346 CLSID clsid;
2347 static const STATDATA enum_expect[] =
2349 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2350 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 },
2351 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 1 },
2352 {{ CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF }, 0, NULL, 1 }
2354 static const struct
2356 const CLSID *clsid;
2357 int enum_start, enum_num;
2358 } data[] =
2360 { &CLSID_NULL, 0, 0 },
2361 { &CLSID_WineTestOld, 0, 0 },
2362 { &CLSID_Picture_Dib, 0, 2 },
2363 { &CLSID_Picture_Metafile, 2, 1 },
2364 { &CLSID_Picture_EnhMetafile, 3, 1 }
2367 for (i = 0; i < sizeof(data) / sizeof(data[0]); i++)
2369 hr = CreateDataCache( NULL, data[i].clsid, &IID_IOleCache2, (void **)&cache );
2370 ok( hr == S_OK, "got %08x\n", hr );
2372 check_enum_cache( cache, enum_expect + data[i].enum_start , data[i].enum_num );
2374 IOleCache2_QueryInterface( cache, &IID_IPersistStorage, (void **) &persist );
2375 hr = IPersistStorage_GetClassID( persist, &clsid );
2376 ok( hr == S_OK, "got %08x\n", hr );
2377 ok( IsEqualCLSID( &clsid, data[i].clsid ), "class id mismatch %s %s\n", wine_dbgstr_guid( &clsid ),
2378 wine_dbgstr_guid( data[i].clsid ) );
2380 IPersistStorage_Release( persist );
2381 IOleCache2_Release( cache );
2385 static void test_data_cache_initnew(void)
2387 HRESULT hr;
2388 IOleCache2 *cache;
2389 IPersistStorage *persist;
2390 IStorage *stg_dib, *stg_mf, *stg_wine;
2391 CLSID clsid;
2392 static const STATDATA initnew_expect[] =
2394 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2395 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 },
2397 static const STATDATA initnew2_expect[] =
2399 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 1 },
2400 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 2 },
2401 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 2 },
2403 static const STATDATA initnew3_expect[] =
2405 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2406 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 },
2407 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 2 },
2408 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 2 },
2409 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 3 },
2411 static const STATDATA initnew4_expect[] =
2413 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 2 },
2414 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 2 },
2415 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 3 },
2416 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 4 },
2417 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 4 },
2420 hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg_dib );
2421 ok( hr == S_OK, "got %08x\n", hr);
2422 hr = IStorage_SetClass( stg_dib, &CLSID_Picture_Dib );
2423 ok( hr == S_OK, "got %08x\n", hr);
2425 hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg_mf );
2426 ok( hr == S_OK, "got %08x\n", hr);
2427 hr = IStorage_SetClass( stg_mf, &CLSID_Picture_Metafile );
2428 ok( hr == S_OK, "got %08x\n", hr);
2430 hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg_wine );
2431 ok( hr == S_OK, "got %08x\n", hr);
2432 hr = IStorage_SetClass( stg_wine, &CLSID_WineTestOld );
2433 ok( hr == S_OK, "got %08x\n", hr);
2435 hr = CreateDataCache( NULL, &CLSID_WineTestOld, &IID_IOleCache2, (void **)&cache );
2436 ok( hr == S_OK, "got %08x\n", hr );
2437 IOleCache2_QueryInterface( cache, &IID_IPersistStorage, (void **) &persist );
2439 hr = IPersistStorage_InitNew( persist, stg_dib );
2440 ok( hr == S_OK, "got %08x\n", hr);
2442 hr = IPersistStorage_GetClassID( persist, &clsid );
2443 ok( hr == S_OK, "got %08x\n", hr );
2444 ok( IsEqualCLSID( &clsid, &CLSID_Picture_Dib ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2446 check_enum_cache( cache, initnew_expect, 2 );
2448 hr = IPersistStorage_InitNew( persist, stg_mf );
2449 ok( hr == CO_E_ALREADYINITIALIZED, "got %08x\n", hr);
2451 hr = IPersistStorage_HandsOffStorage( persist );
2452 ok( hr == S_OK, "got %08x\n", hr);
2454 hr = IPersistStorage_GetClassID( persist, &clsid );
2455 ok( hr == S_OK, "got %08x\n", hr );
2456 ok( IsEqualCLSID( &clsid, &CLSID_Picture_Dib ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2458 hr = IPersistStorage_InitNew( persist, stg_mf );
2459 ok( hr == S_OK, "got %08x\n", hr);
2461 hr = IPersistStorage_GetClassID( persist, &clsid );
2462 ok( hr == S_OK, "got %08x\n", hr );
2463 ok( IsEqualCLSID( &clsid, &CLSID_Picture_Metafile ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2465 check_enum_cache( cache, initnew2_expect, 3 );
2467 hr = IPersistStorage_HandsOffStorage( persist );
2468 ok( hr == S_OK, "got %08x\n", hr);
2470 hr = IPersistStorage_InitNew( persist, stg_dib );
2471 ok( hr == S_OK, "got %08x\n", hr);
2473 hr = IPersistStorage_GetClassID( persist, &clsid );
2474 ok( hr == S_OK, "got %08x\n", hr );
2475 ok( IsEqualCLSID( &clsid, &CLSID_Picture_Dib ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2477 check_enum_cache( cache, initnew3_expect, 5 );
2479 hr = IPersistStorage_HandsOffStorage( persist );
2480 ok( hr == S_OK, "got %08x\n", hr);
2482 hr = IPersistStorage_InitNew( persist, stg_wine );
2483 ok( hr == S_OK, "got %08x\n", hr);
2485 hr = IPersistStorage_GetClassID( persist, &clsid );
2486 ok( hr == S_OK, "got %08x\n", hr );
2487 ok( IsEqualCLSID( &clsid, &CLSID_WineTestOld ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2489 check_enum_cache( cache, initnew4_expect, 5 );
2491 IStorage_Release( stg_wine );
2492 IStorage_Release( stg_mf );
2493 IStorage_Release( stg_dib );
2495 IPersistStorage_Release( persist );
2496 IOleCache2_Release( cache );
2499 static void test_default_handler(void)
2501 HRESULT hr;
2502 IOleObject *pObject;
2503 IRunnableObject *pRunnableObject;
2504 IOleClientSite *pClientSite;
2505 IDataObject *pDataObject;
2506 SIZEL sizel;
2507 DWORD dwStatus;
2508 CLSID clsid;
2509 LPOLESTR pszUserType;
2510 LOGPALETTE palette;
2511 DWORD dwAdvConn;
2512 IMoniker *pMoniker;
2513 FORMATETC fmtetc;
2514 IOleInPlaceObject *pInPlaceObj;
2515 IEnumOLEVERB *pEnumVerbs;
2516 DWORD dwRegister;
2517 static const WCHAR wszUnknown[] = {'U','n','k','n','o','w','n',0};
2518 static const WCHAR wszHostName[] = {'W','i','n','e',' ','T','e','s','t',' ','P','r','o','g','r','a','m',0};
2519 static const WCHAR wszDelim[] = {'!',0};
2521 static const struct expected_method methods_embeddinghelper[] =
2523 { "OleObject_QueryInterface", 0 },
2524 { "OleObject_AddRef", 0 },
2525 { "OleObject_QueryInterface", 0 },
2526 { "OleObject_QueryInterface", TEST_TODO },
2527 { "OleObject_QueryInterface", 0 },
2528 { "OleObject_QueryInterface", 0 },
2529 { "OleObject_QueryInterface", TEST_OPTIONAL }, /* Win95/98/NT4 */
2530 { "OleObject_Release", TEST_TODO },
2531 { "WINE_EXTRA", TEST_OPTIONAL },
2532 { NULL, 0 }
2535 hr = CoCreateInstance(&CLSID_WineTest, NULL, CLSCTX_INPROC_HANDLER, &IID_IOleObject, (void **)&pObject);
2536 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance should have failed with REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2538 hr = OleCreateDefaultHandler(&CLSID_WineTest, NULL, &IID_IOleObject, (void **)&pObject);
2539 ok_ole_success(hr, "OleCreateDefaultHandler");
2541 hr = IOleObject_QueryInterface(pObject, &IID_IOleInPlaceObject, (void **)&pInPlaceObj);
2542 ok(hr == E_NOINTERFACE, "IOleObject_QueryInterface(&IID_IOleInPlaceObject) should return E_NOINTERFACE instead of 0x%08x\n", hr);
2544 hr = IOleObject_Advise(pObject, &AdviseSink, &dwAdvConn);
2545 ok_ole_success(hr, "IOleObject_Advise");
2547 hr = IOleObject_Close(pObject, OLECLOSE_NOSAVE);
2548 ok_ole_success(hr, "IOleObject_Close");
2550 /* FIXME: test IOleObject_EnumAdvise */
2552 hr = IOleObject_EnumVerbs(pObject, &pEnumVerbs);
2553 ok(hr == REGDB_E_CLASSNOTREG, "IOleObject_EnumVerbs should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2555 hr = IOleObject_GetClientSite(pObject, &pClientSite);
2556 ok_ole_success(hr, "IOleObject_GetClientSite");
2558 hr = IOleObject_SetClientSite(pObject, pClientSite);
2559 ok_ole_success(hr, "IOleObject_SetClientSite");
2561 hr = IOleObject_GetClipboardData(pObject, 0, &pDataObject);
2562 ok(hr == OLE_E_NOTRUNNING,
2563 "IOleObject_GetClipboardData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n",
2564 hr);
2566 hr = IOleObject_GetExtent(pObject, DVASPECT_CONTENT, &sizel);
2567 ok(hr == OLE_E_BLANK, "IOleObject_GetExtent should have returned OLE_E_BLANK instead of 0x%08x\n",
2568 hr);
2570 hr = IOleObject_GetMiscStatus(pObject, DVASPECT_CONTENT, &dwStatus);
2571 ok(hr == REGDB_E_CLASSNOTREG, "IOleObject_GetMiscStatus should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2573 hr = IOleObject_GetUserClassID(pObject, &clsid);
2574 ok_ole_success(hr, "IOleObject_GetUserClassID");
2575 ok(IsEqualCLSID(&clsid, &CLSID_WineTest), "clsid != CLSID_WineTest\n");
2577 hr = IOleObject_GetUserType(pObject, USERCLASSTYPE_FULL, &pszUserType);
2578 todo_wine {
2579 ok_ole_success(hr, "IOleObject_GetUserType");
2580 ok(!lstrcmpW(pszUserType, wszUnknown), "Retrieved user type was wrong\n");
2583 hr = IOleObject_InitFromData(pObject, NULL, TRUE, 0);
2584 ok(hr == OLE_E_NOTRUNNING, "IOleObject_InitFromData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
2586 hr = IOleObject_IsUpToDate(pObject);
2587 ok(hr == OLE_E_NOTRUNNING, "IOleObject_IsUpToDate should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
2589 palette.palNumEntries = 1;
2590 palette.palVersion = 2;
2591 memset(&palette.palPalEntry[0], 0, sizeof(palette.palPalEntry[0]));
2592 hr = IOleObject_SetColorScheme(pObject, &palette);
2593 ok(hr == OLE_E_NOTRUNNING, "IOleObject_SetColorScheme should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
2595 sizel.cx = sizel.cy = 0;
2596 hr = IOleObject_SetExtent(pObject, DVASPECT_CONTENT, &sizel);
2597 ok(hr == OLE_E_NOTRUNNING, "IOleObject_SetExtent should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
2599 hr = IOleObject_SetHostNames(pObject, wszHostName, NULL);
2600 ok_ole_success(hr, "IOleObject_SetHostNames");
2602 hr = CreateItemMoniker(wszDelim, wszHostName, &pMoniker);
2603 ok_ole_success(hr, "CreateItemMoniker");
2604 hr = IOleObject_SetMoniker(pObject, OLEWHICHMK_CONTAINER, pMoniker);
2605 ok_ole_success(hr, "IOleObject_SetMoniker");
2606 IMoniker_Release(pMoniker);
2608 hr = IOleObject_GetMoniker(pObject, OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_CONTAINER, &pMoniker);
2609 ok(hr == E_FAIL, "IOleObject_GetMoniker should have returned E_FAIL instead of 0x%08x\n", hr);
2611 hr = IOleObject_Update(pObject);
2612 todo_wine
2613 ok(hr == REGDB_E_CLASSNOTREG, "IOleObject_Update should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2615 hr = IOleObject_QueryInterface(pObject, &IID_IDataObject, (void **)&pDataObject);
2616 ok_ole_success(hr, "IOleObject_QueryInterface");
2618 fmtetc.cfFormat = CF_TEXT;
2619 fmtetc.ptd = NULL;
2620 fmtetc.dwAspect = DVASPECT_CONTENT;
2621 fmtetc.lindex = -1;
2622 fmtetc.tymed = TYMED_NULL;
2623 hr = IDataObject_DAdvise(pDataObject, &fmtetc, 0, &AdviseSink, &dwAdvConn);
2624 ok_ole_success(hr, "IDataObject_DAdvise");
2626 fmtetc.cfFormat = CF_ENHMETAFILE;
2627 fmtetc.ptd = NULL;
2628 fmtetc.dwAspect = DVASPECT_CONTENT;
2629 fmtetc.lindex = -1;
2630 fmtetc.tymed = TYMED_ENHMF;
2631 hr = IDataObject_DAdvise(pDataObject, &fmtetc, 0, &AdviseSink, &dwAdvConn);
2632 ok_ole_success(hr, "IDataObject_DAdvise");
2634 fmtetc.cfFormat = CF_ENHMETAFILE;
2635 fmtetc.ptd = NULL;
2636 fmtetc.dwAspect = DVASPECT_CONTENT;
2637 fmtetc.lindex = -1;
2638 fmtetc.tymed = TYMED_ENHMF;
2639 hr = IDataObject_QueryGetData(pDataObject, &fmtetc);
2640 ok(hr == OLE_E_NOTRUNNING, "IDataObject_QueryGetData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
2642 fmtetc.cfFormat = CF_TEXT;
2643 fmtetc.ptd = NULL;
2644 fmtetc.dwAspect = DVASPECT_CONTENT;
2645 fmtetc.lindex = -1;
2646 fmtetc.tymed = TYMED_NULL;
2647 hr = IDataObject_QueryGetData(pDataObject, &fmtetc);
2648 ok(hr == OLE_E_NOTRUNNING, "IDataObject_QueryGetData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
2650 hr = IOleObject_QueryInterface(pObject, &IID_IRunnableObject, (void **)&pRunnableObject);
2651 ok_ole_success(hr, "IOleObject_QueryInterface");
2653 hr = IRunnableObject_SetContainedObject(pRunnableObject, TRUE);
2654 ok_ole_success(hr, "IRunnableObject_SetContainedObject");
2656 hr = IRunnableObject_Run(pRunnableObject, NULL);
2657 ok(hr == REGDB_E_CLASSNOTREG, "IOleObject_Run should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2659 hr = IOleObject_Close(pObject, OLECLOSE_NOSAVE);
2660 ok_ole_success(hr, "IOleObject_Close");
2662 IRunnableObject_Release(pRunnableObject);
2663 IOleObject_Release(pObject);
2665 /* Test failure propagation from delegate ::QueryInterface */
2666 hr = CoRegisterClassObject(&CLSID_WineTest, (IUnknown*)&OleObjectCF,
2667 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegister);
2668 ok_ole_success(hr, "CoRegisterClassObject");
2669 if(SUCCEEDED(hr))
2671 expected_method_list = methods_embeddinghelper;
2672 hr = OleCreateEmbeddingHelper(&CLSID_WineTest, NULL, EMBDHLP_INPROC_SERVER,
2673 &OleObjectCF, &IID_IOleObject, (void**)&pObject);
2674 ok_ole_success(hr, "OleCreateEmbeddingHelper");
2675 if(SUCCEEDED(hr))
2677 IUnknown *punk;
2679 g_QIFailsWith = E_FAIL;
2680 hr = IOleObject_QueryInterface(pObject, &IID_WineTest, (void**)&punk);
2681 ok(hr == E_FAIL, "Got 0x%08x\n", hr);
2683 g_QIFailsWith = E_NOINTERFACE;
2684 hr = IOleObject_QueryInterface(pObject, &IID_WineTest, (void**)&punk);
2685 ok(hr == E_NOINTERFACE, "Got 0x%08x\n", hr);
2687 g_QIFailsWith = CO_E_OBJNOTCONNECTED;
2688 hr = IOleObject_QueryInterface(pObject, &IID_WineTest, (void**)&punk);
2689 ok(hr == CO_E_OBJNOTCONNECTED, "Got 0x%08x\n", hr);
2691 g_QIFailsWith = 0x87654321;
2692 hr = IOleObject_QueryInterface(pObject, &IID_WineTest, (void**)&punk);
2693 ok(hr == 0x87654321, "Got 0x%08x\n", hr);
2695 IOleObject_Release(pObject);
2698 CHECK_NO_EXTRA_METHODS();
2700 hr = CoRevokeClassObject(dwRegister);
2701 ok_ole_success(hr, "CoRevokeClassObject");
2705 static void test_runnable(void)
2707 static const struct expected_method methods_query_runnable[] =
2709 { "OleObject_QueryInterface", 0 },
2710 { "OleObjectRunnable_AddRef", 0 },
2711 { "OleObjectRunnable_IsRunning", 0 },
2712 { "OleObjectRunnable_Release", 0 },
2713 { NULL, 0 }
2716 static const struct expected_method methods_no_runnable[] =
2718 { "OleObject_QueryInterface", 0 },
2719 { NULL, 0 }
2722 BOOL ret;
2723 IOleObject *object = &OleObject;
2725 /* null argument */
2726 ret = OleIsRunning(NULL);
2727 ok(ret == FALSE, "got %d\n", ret);
2729 expected_method_list = methods_query_runnable;
2730 ret = OleIsRunning(object);
2731 ok(ret == TRUE, "Object should be running\n");
2732 CHECK_NO_EXTRA_METHODS();
2734 g_isRunning = FALSE;
2735 expected_method_list = methods_query_runnable;
2736 ret = OleIsRunning(object);
2737 ok(ret == FALSE, "Object should not be running\n");
2738 CHECK_NO_EXTRA_METHODS();
2740 g_showRunnable = FALSE; /* QueryInterface(IID_IRunnableObject, ...) will fail */
2741 expected_method_list = methods_no_runnable;
2742 ret = OleIsRunning(object);
2743 ok(ret == TRUE, "Object without IRunnableObject should be running\n");
2744 CHECK_NO_EXTRA_METHODS();
2746 g_isRunning = TRUE;
2747 g_showRunnable = TRUE;
2751 static HRESULT WINAPI OleRun_QueryInterface(IRunnableObject *iface, REFIID riid, void **ppv)
2753 *ppv = NULL;
2755 if (IsEqualIID(riid, &IID_IUnknown) ||
2756 IsEqualIID(riid, &IID_IRunnableObject)) {
2757 *ppv = iface;
2760 if (*ppv)
2762 IUnknown_AddRef((IUnknown *)*ppv);
2763 return S_OK;
2766 return E_NOINTERFACE;
2769 static ULONG WINAPI OleRun_AddRef(IRunnableObject *iface)
2771 return 2;
2774 static ULONG WINAPI OleRun_Release(IRunnableObject *iface)
2776 return 1;
2779 static HRESULT WINAPI OleRun_GetRunningClass(IRunnableObject *iface, CLSID *clsid)
2781 ok(0, "unexpected\n");
2782 return E_NOTIMPL;
2785 static HRESULT WINAPI OleRun_Run(IRunnableObject *iface, LPBINDCTX ctx)
2787 ok(ctx == NULL, "got %p\n", ctx);
2788 return 0xdeadc0de;
2791 static BOOL WINAPI OleRun_IsRunning(IRunnableObject *iface)
2793 ok(0, "unexpected\n");
2794 return FALSE;
2797 static HRESULT WINAPI OleRun_LockRunning(IRunnableObject *iface, BOOL lock,
2798 BOOL last_unlock_closes)
2800 ok(0, "unexpected\n");
2801 return E_NOTIMPL;
2804 static HRESULT WINAPI OleRun_SetContainedObject(IRunnableObject *iface, BOOL contained)
2806 ok(0, "unexpected\n");
2807 return E_NOTIMPL;
2810 static const IRunnableObjectVtbl oleruntestvtbl =
2812 OleRun_QueryInterface,
2813 OleRun_AddRef,
2814 OleRun_Release,
2815 OleRun_GetRunningClass,
2816 OleRun_Run,
2817 OleRun_IsRunning,
2818 OleRun_LockRunning,
2819 OleRun_SetContainedObject
2822 static IRunnableObject testrunnable = { &oleruntestvtbl };
2824 static void test_OleRun(void)
2826 HRESULT hr;
2828 /* doesn't support IRunnableObject */
2829 hr = OleRun(&unknown);
2830 ok(hr == S_OK, "OleRun failed 0x%08x\n", hr);
2832 hr = OleRun((IUnknown*)&testrunnable);
2833 ok(hr == 0xdeadc0de, "got 0x%08x\n", hr);
2836 static void test_OleLockRunning(void)
2838 HRESULT hr;
2840 hr = OleLockRunning(&unknown, TRUE, FALSE);
2841 ok(hr == S_OK, "OleLockRunning failed 0x%08x\n", hr);
2844 static void test_OleDraw(void)
2846 HRESULT hr;
2847 RECT rect;
2849 hr = OleDraw((IUnknown*)&viewobject, 0, (HDC)0x1, NULL);
2850 ok(hr == S_OK, "got 0x%08x\n", hr);
2852 hr = OleDraw(NULL, 0, (HDC)0x1, NULL);
2853 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2855 hr = OleDraw(NULL, 0, (HDC)0x1, &rect);
2856 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2859 static const WCHAR olepres0W[] = {2,'O','l','e','P','r','e','s','0','0','0',0};
2860 static const WCHAR comp_objW[] = {1,'C','o','m','p','O','b','j',0};
2861 static IStream *comp_obj_stream;
2862 static IStream *ole_stream;
2863 static IStream *olepres_stream;
2864 static IStream *contents_stream;
2866 static HRESULT WINAPI Storage_QueryInterface(IStorage *iface, REFIID riid, void **ppvObject)
2868 ok(0, "unexpected call to QueryInterface\n");
2869 return E_NOTIMPL;
2872 static ULONG WINAPI Storage_AddRef(IStorage *iface)
2874 ok(0, "unexpected call to AddRef\n");
2875 return 2;
2878 static ULONG WINAPI Storage_Release(IStorage *iface)
2880 ok(0, "unexpected call to Release\n");
2881 return 1;
2884 static HRESULT WINAPI Storage_CreateStream(IStorage *iface, LPCOLESTR pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStream **ppstm)
2886 ULARGE_INTEGER size = {{0}};
2887 LARGE_INTEGER pos = {{0}};
2888 HRESULT hr;
2890 if (!lstrcmpW(pwcsName, comp_objW))
2892 CHECK_EXPECT(Storage_CreateStream_CompObj);
2893 *ppstm = comp_obj_stream;
2895 todo_wine ok(grfMode == (STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
2897 else if (!lstrcmpW(pwcsName, olepres0W))
2899 CHECK_EXPECT(Storage_CreateStream_OlePres);
2900 *ppstm = olepres_stream;
2902 todo_wine ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
2904 else
2906 todo_wine
2907 ok(0, "unexpected stream name %s\n", wine_dbgstr_w(pwcsName));
2908 #if 0 /* FIXME: return NULL once Wine is fixed */
2909 *ppstm = NULL;
2910 return E_NOTIMPL;
2911 #else
2912 *ppstm = contents_stream;
2913 #endif
2916 ok(!reserved1, "reserved1 = %x\n", reserved1);
2917 ok(!reserved2, "reserved2 = %x\n", reserved2);
2918 ok(!!ppstm, "ppstm = NULL\n");
2920 IStream_AddRef(*ppstm);
2921 hr = IStream_Seek(*ppstm, pos, STREAM_SEEK_SET, NULL);
2922 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
2923 hr = IStream_SetSize(*ppstm, size);
2924 ok(hr == S_OK, "IStream_SetSize returned %x\n", hr);
2925 return S_OK;
2928 static HRESULT WINAPI Storage_OpenStream(IStorage *iface, LPCOLESTR pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream **ppstm)
2930 static const WCHAR ole1W[] = {1,'O','l','e',0};
2932 LARGE_INTEGER pos = {{0}};
2933 HRESULT hr;
2935 ok(!reserved1, "reserved1 = %p\n", reserved1);
2936 ok(!reserved2, "reserved2 = %x\n", reserved2);
2937 ok(!!ppstm, "ppstm = NULL\n");
2939 if(!lstrcmpW(pwcsName, comp_objW)) {
2940 CHECK_EXPECT2(Storage_OpenStream_CompObj);
2941 ok(grfMode == STGM_SHARE_EXCLUSIVE, "grfMode = %x\n", grfMode);
2943 *ppstm = comp_obj_stream;
2944 IStream_AddRef(comp_obj_stream);
2945 hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL);
2946 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
2947 return S_OK;
2948 }else if(!lstrcmpW(pwcsName, ole1W)) {
2949 CHECK_EXPECT(Storage_OpenStream_Ole);
2951 if (!ole_stream)
2953 ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READ), "grfMode = %x\n", grfMode);
2955 *ppstm = NULL;
2956 return STG_E_FILENOTFOUND;
2959 ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
2961 *ppstm = ole_stream;
2962 IStream_AddRef(ole_stream);
2963 hr = IStream_Seek(ole_stream, pos, STREAM_SEEK_SET, NULL);
2964 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
2965 return S_OK;
2967 }else if(!lstrcmpW(pwcsName, olepres0W)) {
2968 CHECK_EXPECT(Storage_OpenStream_OlePres);
2969 ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
2971 *ppstm = olepres_stream;
2972 IStream_AddRef(olepres_stream);
2973 hr = IStream_Seek(olepres_stream, pos, STREAM_SEEK_SET, NULL);
2974 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
2975 return S_OK;
2978 ok(0, "unexpected call to OpenStream: %s\n", wine_dbgstr_w(pwcsName));
2979 return E_NOTIMPL;
2982 static HRESULT WINAPI Storage_CreateStorage(IStorage *iface, LPCOLESTR pwcsName, DWORD grfMode, DWORD dwStgFmt, DWORD reserved2, IStorage **ppstg)
2984 ok(0, "unexpected call to CreateStorage\n");
2985 return E_NOTIMPL;
2988 static HRESULT WINAPI Storage_OpenStorage(IStorage *iface, LPCOLESTR pwcsName, IStorage *pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage **ppstg)
2990 ok(0, "unexpected call to OpenStorage\n");
2991 return E_NOTIMPL;
2994 static HRESULT WINAPI Storage_CopyTo(IStorage *iface, DWORD ciidExclude, const IID *rgiidExclude, SNB snbExclude, IStorage *pstgDest)
2996 ok(0, "unexpected call to CopyTo\n");
2997 return E_NOTIMPL;
3000 static HRESULT WINAPI Storage_MoveElementTo(IStorage *iface, LPCOLESTR pwcsName, IStorage *pstgDest, LPCOLESTR pwcsNewName, DWORD grfFlags)
3002 ok(0, "unexpected call to MoveElementTo\n");
3003 return E_NOTIMPL;
3006 static HRESULT WINAPI Storage_Commit(IStorage *iface, DWORD grfCommitFlags)
3008 ok(0, "unexpected call to Commit\n");
3009 return E_NOTIMPL;
3012 static HRESULT WINAPI Storage_Revert(IStorage *iface)
3014 ok(0, "unexpected call to Revert\n");
3015 return E_NOTIMPL;
3018 static HRESULT WINAPI Storage_EnumElements(IStorage *iface, DWORD reserved1, void *reserved2, DWORD reserved3, IEnumSTATSTG **ppenum)
3020 ok(0, "unexpected call to EnumElements\n");
3021 return E_NOTIMPL;
3024 static HRESULT WINAPI Storage_DestroyElement(IStorage *iface, LPCOLESTR pwcsName)
3026 char name[32];
3027 int stream_n, cmp;
3029 CHECK_EXPECT2(Storage_DestroyElement);
3030 cmp = CompareStringW(LOCALE_NEUTRAL, 0, pwcsName, 8, olepres0W, 8);
3031 ok(cmp == CSTR_EQUAL,
3032 "unexpected call to DestroyElement(%s)\n", wine_dbgstr_w(pwcsName));
3034 WideCharToMultiByte(CP_ACP, 0, pwcsName, -1, name, sizeof(name), NULL, NULL);
3035 stream_n = atol(name + 8);
3036 if (stream_n <= Storage_DestroyElement_limit)
3037 return S_OK;
3039 return STG_E_FILENOTFOUND;
3042 static HRESULT WINAPI Storage_RenameElement(IStorage *iface, LPCOLESTR pwcsOldName, LPCOLESTR pwcsNewName)
3044 ok(0, "unexpected call to RenameElement\n");
3045 return E_NOTIMPL;
3048 static HRESULT WINAPI Storage_SetElementTimes(IStorage *iface, LPCOLESTR pwcsName, const FILETIME *pctime, const FILETIME *patime, const FILETIME *pmtime)
3050 ok(0, "unexpected call to SetElementTimes\n");
3051 return E_NOTIMPL;
3054 static HRESULT WINAPI Storage_SetClass(IStorage *iface, REFCLSID clsid)
3056 CHECK_EXPECT(Storage_SetClass);
3057 ok(IsEqualIID(clsid, Storage_SetClass_CLSID), "expected %s, got %s\n",
3058 wine_dbgstr_guid(Storage_SetClass_CLSID), wine_dbgstr_guid(clsid));
3059 return S_OK;
3062 static HRESULT WINAPI Storage_SetStateBits(IStorage *iface, DWORD grfStateBits, DWORD grfMask)
3064 ok(0, "unexpected call to SetStateBits\n");
3065 return E_NOTIMPL;
3068 static HRESULT WINAPI Storage_Stat(IStorage *iface, STATSTG *pstatstg, DWORD grfStatFlag)
3070 CHECK_EXPECT2(Storage_Stat);
3071 ok(pstatstg != NULL, "pstatstg = NULL\n");
3072 ok(grfStatFlag == STATFLAG_NONAME, "grfStatFlag = %x\n", grfStatFlag);
3074 memset(pstatstg, 0, sizeof(STATSTG));
3075 pstatstg->type = STGTY_STORAGE;
3076 pstatstg->clsid = CLSID_WineTestOld;
3077 return S_OK;
3080 static IStorageVtbl StorageVtbl =
3082 Storage_QueryInterface,
3083 Storage_AddRef,
3084 Storage_Release,
3085 Storage_CreateStream,
3086 Storage_OpenStream,
3087 Storage_CreateStorage,
3088 Storage_OpenStorage,
3089 Storage_CopyTo,
3090 Storage_MoveElementTo,
3091 Storage_Commit,
3092 Storage_Revert,
3093 Storage_EnumElements,
3094 Storage_DestroyElement,
3095 Storage_RenameElement,
3096 Storage_SetElementTimes,
3097 Storage_SetClass,
3098 Storage_SetStateBits,
3099 Storage_Stat
3102 static IStorage Storage = { &StorageVtbl };
3104 static void test_OleDoAutoConvert(void)
3106 static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0};
3107 static struct {
3108 DWORD reserved1;
3109 DWORD version;
3110 DWORD reserved2[5];
3111 DWORD ansi_user_type_len;
3112 DWORD ansi_clipboard_format_len;
3113 DWORD reserved3;
3114 DWORD unicode_marker;
3115 DWORD unicode_user_type_len;
3116 DWORD unicode_clipboard_format_len;
3117 DWORD reserved4;
3118 } comp_obj_data;
3119 static struct {
3120 DWORD version;
3121 DWORD flags;
3122 DWORD link_update_option;
3123 DWORD reserved1;
3124 DWORD reserved_moniker_stream_size;
3125 DWORD relative_source_moniker_stream_size;
3126 DWORD absolute_source_moniker_stream_size;
3127 DWORD clsid_indicator;
3128 CLSID clsid;
3129 DWORD reserved_display_name;
3130 DWORD reserved2;
3131 DWORD local_update_time;
3132 DWORD local_check_update_time;
3133 DWORD remote_update_time;
3134 } ole_data;
3136 LARGE_INTEGER pos = {{0}};
3137 WCHAR buf[39+6];
3138 DWORD i, ret;
3139 HKEY root;
3140 CLSID clsid;
3141 HRESULT hr;
3143 hr = CreateStreamOnHGlobal(NULL, TRUE, &comp_obj_stream);
3144 ok(hr == S_OK, "CreateStreamOnHGlobal returned %x\n", hr);
3145 hr = IStream_Write(comp_obj_stream, (char*)&comp_obj_data, sizeof(comp_obj_data), NULL);
3146 ok(hr == S_OK, "IStream_Write returned %x\n", hr);
3148 hr = CreateStreamOnHGlobal(NULL, TRUE, &ole_stream);
3149 ok(hr == S_OK, "CreateStreamOnHGlobal returned %x\n", hr);
3150 hr = IStream_Write(ole_stream, (char*)&ole_data, sizeof(ole_data), NULL);
3151 ok(hr == S_OK, "IStream_Write returned %x\n", hr);
3153 clsid = IID_WineTest;
3154 hr = OleDoAutoConvert(NULL, &clsid);
3155 ok(hr == E_INVALIDARG, "OleDoAutoConvert returned %x\n", hr);
3156 ok(IsEqualIID(&clsid, &IID_NULL), "clsid = %s\n", wine_dbgstr_guid(&clsid));
3158 if(0) /* crashes on Win7 */
3159 OleDoAutoConvert(&Storage, NULL);
3161 clsid = IID_WineTest;
3162 SET_EXPECT(Storage_Stat);
3163 hr = OleDoAutoConvert(&Storage, &clsid);
3164 ok(hr == REGDB_E_CLASSNOTREG, "OleDoAutoConvert returned %x\n", hr);
3165 CHECK_CALLED(Storage_Stat);
3166 ok(IsEqualIID(&clsid, &CLSID_WineTestOld), "clsid = %s\n", wine_dbgstr_guid(&clsid));
3168 lstrcpyW(buf, clsidW);
3169 StringFromGUID2(&CLSID_WineTestOld, buf+6, 39);
3171 ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, buf, 0, NULL, 0,
3172 KEY_READ | KEY_WRITE | KEY_CREATE_SUB_KEY, NULL, &root, NULL);
3173 if(ret != ERROR_SUCCESS) {
3174 win_skip("not enough permissions to create CLSID key (%u)\n", ret);
3175 return;
3178 clsid = IID_WineTest;
3179 SET_EXPECT(Storage_Stat);
3180 hr = OleDoAutoConvert(&Storage, &clsid);
3181 ok(hr == REGDB_E_KEYMISSING, "OleDoAutoConvert returned %x\n", hr);
3182 CHECK_CALLED(Storage_Stat);
3183 ok(IsEqualIID(&clsid, &CLSID_WineTestOld), "clsid = %s\n", wine_dbgstr_guid(&clsid));
3185 hr = OleSetAutoConvert(&CLSID_WineTestOld, &CLSID_WineTest);
3186 ok_ole_success(hr, "OleSetAutoConvert");
3188 hr = OleGetAutoConvert(&CLSID_WineTestOld, &clsid);
3189 ok_ole_success(hr, "OleGetAutoConvert");
3190 ok(IsEqualIID(&clsid, &CLSID_WineTest), "incorrect clsid: %s\n", wine_dbgstr_guid(&clsid));
3192 clsid = IID_WineTest;
3193 SET_EXPECT(Storage_Stat);
3194 SET_EXPECT(Storage_OpenStream_CompObj);
3195 SET_EXPECT(Storage_SetClass);
3196 SET_EXPECT(Storage_CreateStream_CompObj);
3197 SET_EXPECT(Storage_OpenStream_Ole);
3198 hr = OleDoAutoConvert(&Storage, &clsid);
3199 ok(hr == S_OK, "OleDoAutoConvert returned %x\n", hr);
3200 CHECK_CALLED(Storage_Stat);
3201 CHECK_CALLED(Storage_OpenStream_CompObj);
3202 CHECK_CALLED(Storage_SetClass);
3203 CHECK_CALLED(Storage_CreateStream_CompObj);
3204 CHECK_CALLED(Storage_OpenStream_Ole);
3205 ok(IsEqualIID(&clsid, &CLSID_WineTest), "clsid = %s\n", wine_dbgstr_guid(&clsid));
3207 hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL);
3208 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3209 hr = IStream_Read(comp_obj_stream, &comp_obj_data, sizeof(comp_obj_data), NULL);
3210 ok(hr == S_OK, "IStream_Read returned %x\n", hr);
3211 ok(comp_obj_data.reserved1 == 0xfffe0001, "reserved1 = %x\n", comp_obj_data.reserved1);
3212 ok(comp_obj_data.version == 0xa03, "version = %x\n", comp_obj_data.version);
3213 ok(comp_obj_data.reserved2[0] == -1, "reserved2[0] = %x\n", comp_obj_data.reserved2[0]);
3214 ok(IsEqualIID(comp_obj_data.reserved2+1, &CLSID_WineTestOld), "reserved2 = %s\n", wine_dbgstr_guid((CLSID*)(comp_obj_data.reserved2+1)));
3215 ok(!comp_obj_data.ansi_user_type_len, "ansi_user_type_len = %d\n", comp_obj_data.ansi_user_type_len);
3216 ok(!comp_obj_data.ansi_clipboard_format_len, "ansi_clipboard_format_len = %d\n", comp_obj_data.ansi_clipboard_format_len);
3217 ok(!comp_obj_data.reserved3, "reserved3 = %x\n", comp_obj_data.reserved3);
3218 ok(comp_obj_data.unicode_marker == 0x71b239f4, "unicode_marker = %x\n", comp_obj_data.unicode_marker);
3219 ok(!comp_obj_data.unicode_user_type_len, "unicode_user_type_len = %d\n", comp_obj_data.unicode_user_type_len);
3220 ok(!comp_obj_data.unicode_clipboard_format_len, "unicode_clipboard_format_len = %d\n", comp_obj_data.unicode_clipboard_format_len);
3221 ok(!comp_obj_data.reserved4, "reserved4 %d\n", comp_obj_data.reserved4);
3223 hr = IStream_Seek(ole_stream, pos, STREAM_SEEK_SET, NULL);
3224 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3225 hr = IStream_Read(ole_stream, &ole_data, sizeof(ole_data), NULL);
3226 ok(hr == S_OK, "IStream_Read returned %x\n", hr);
3227 ok(ole_data.version == 0, "version = %x\n", ole_data.version);
3228 ok(ole_data.flags == 4, "flags = %x\n", ole_data.flags);
3229 for(i=2; i<sizeof(ole_data)/sizeof(DWORD); i++)
3230 ok(((DWORD*)&ole_data)[i] == 0, "ole_data[%d] = %x\n", i, ((DWORD*)&ole_data)[i]);
3232 SET_EXPECT(Storage_OpenStream_Ole);
3233 hr = SetConvertStg(&Storage, TRUE);
3234 ok(hr == S_OK, "SetConvertStg returned %x\n", hr);
3235 CHECK_CALLED(Storage_OpenStream_Ole);
3237 SET_EXPECT(Storage_OpenStream_CompObj);
3238 SET_EXPECT(Storage_Stat);
3239 SET_EXPECT(Storage_CreateStream_CompObj);
3240 hr = WriteFmtUserTypeStg(&Storage, 0, NULL);
3241 ok(hr == S_OK, "WriteFmtUserTypeStg returned %x\n", hr);
3242 todo_wine CHECK_CALLED(Storage_OpenStream_CompObj);
3243 CHECK_CALLED(Storage_Stat);
3244 CHECK_CALLED(Storage_CreateStream_CompObj);
3245 hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL);
3246 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3247 hr = IStream_Read(comp_obj_stream, &comp_obj_data, sizeof(comp_obj_data), NULL);
3248 ok(hr == S_OK, "IStream_Read returned %x\n", hr);
3249 ok(comp_obj_data.reserved1 == 0xfffe0001, "reserved1 = %x\n", comp_obj_data.reserved1);
3250 ok(comp_obj_data.version == 0xa03, "version = %x\n", comp_obj_data.version);
3251 ok(comp_obj_data.reserved2[0] == -1, "reserved2[0] = %x\n", comp_obj_data.reserved2[0]);
3252 ok(IsEqualIID(comp_obj_data.reserved2+1, &CLSID_WineTestOld), "reserved2 = %s\n", wine_dbgstr_guid((CLSID*)(comp_obj_data.reserved2+1)));
3253 ok(!comp_obj_data.ansi_user_type_len, "ansi_user_type_len = %d\n", comp_obj_data.ansi_user_type_len);
3254 ok(!comp_obj_data.ansi_clipboard_format_len, "ansi_clipboard_format_len = %d\n", comp_obj_data.ansi_clipboard_format_len);
3255 ok(!comp_obj_data.reserved3, "reserved3 = %x\n", comp_obj_data.reserved3);
3256 ok(comp_obj_data.unicode_marker == 0x71b239f4, "unicode_marker = %x\n", comp_obj_data.unicode_marker);
3257 ok(!comp_obj_data.unicode_user_type_len, "unicode_user_type_len = %d\n", comp_obj_data.unicode_user_type_len);
3258 ok(!comp_obj_data.unicode_clipboard_format_len, "unicode_clipboard_format_len = %d\n", comp_obj_data.unicode_clipboard_format_len);
3259 ok(!comp_obj_data.reserved4, "reserved4 %d\n", comp_obj_data.reserved4);
3261 ret = IStream_Release(comp_obj_stream);
3262 ok(!ret, "comp_obj_stream was not freed\n");
3263 ret = IStream_Release(ole_stream);
3264 ok(!ret, "ole_stream was not freed\n");
3266 ret = RegDeleteKeyA(root, "AutoConvertTo");
3267 ok(ret == ERROR_SUCCESS, "RegDeleteKey error %u\n", ret);
3268 ret = RegDeleteKeyA(root, "");
3269 ok(ret == ERROR_SUCCESS, "RegDeleteKey error %u\n", ret);
3270 RegCloseKey(root);
3273 /* 1x1 pixel bmp */
3274 static const unsigned char bmpimage[] =
3276 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,
3277 0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
3278 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
3279 0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
3280 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,
3281 0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
3282 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,
3283 0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
3284 0x00,0x00
3287 static const unsigned char mf_blank_bits[] =
3289 0x01,0x00,0x09,0x00,0x00,0x03,0x0c,0x00,
3290 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
3291 0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00
3294 static void test_data_cache_save(void)
3296 static const WCHAR contentsW[] = { 'C','o','n','t','e','n','t','s',0 };
3297 HRESULT hr;
3298 ILockBytes *ilb;
3299 IStorage *doc;
3300 IStream *stm;
3301 IOleCache2 *cache;
3302 IPersistStorage *stg;
3303 DWORD clipformat[2];
3304 PresentationDataHeader hdr;
3306 hr = CreateILockBytesOnHGlobal(0, TRUE, &ilb);
3307 ok(hr == S_OK, "unexpected %#x\n", hr);
3308 hr = StgCreateDocfileOnILockBytes(ilb, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &doc);
3309 ok(hr == S_OK, "unexpected %#x\n", hr);
3311 ILockBytes_Release(ilb);
3313 hr = IStorage_SetClass(doc, &CLSID_WineTest);
3314 ok(hr == S_OK, "unexpected %#x\n", hr);
3316 hr = IStorage_CreateStream(doc, contentsW, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3317 ok(hr == S_OK, "unexpected %#x\n", hr);
3318 hr = IStream_Write(stm, bmpimage, sizeof(bmpimage), NULL);
3319 ok(hr == S_OK, "unexpected %#x\n", hr);
3320 IStream_Release(stm);
3322 hr = IStorage_CreateStream(doc, olepres0W, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3323 ok(hr == S_OK, "unexpected %#x\n", hr);
3325 clipformat[0] = -1;
3326 clipformat[1] = CF_METAFILEPICT;
3327 hr = IStream_Write(stm, clipformat, sizeof(clipformat), NULL);
3328 ok(hr == S_OK, "unexpected %#x\n", hr);
3330 hdr.unknown3 = 4;
3331 hdr.dvAspect = DVASPECT_CONTENT;
3332 hdr.lindex = -1;
3333 hdr.advf = ADVF_PRIMEFIRST;
3334 hdr.unknown7 = 0;
3335 hdr.dwObjectExtentX = 0;
3336 hdr.dwObjectExtentY = 0;
3337 hdr.dwSize = sizeof(mf_blank_bits);
3338 hr = IStream_Write(stm, &hdr, sizeof(hdr), NULL);
3339 ok(hr == S_OK, "unexpected %#x\n", hr);
3340 hr = IStream_Write(stm, mf_blank_bits, sizeof(mf_blank_bits), NULL);
3341 ok(hr == S_OK, "unexpected %#x\n", hr);
3343 IStream_Release(stm);
3345 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IUnknown, (void **)&cache);
3346 ok(hr == S_OK, "unexpected %#x\n", hr);
3347 hr = IOleCache2_QueryInterface(cache, &IID_IPersistStorage, (void **)&stg);
3348 ok(hr == S_OK, "unexpected %#x\n", hr);
3349 hr = IPersistStorage_Load(stg, doc);
3350 ok(hr == S_OK, "unexpected %#x\n", hr);
3352 IStorage_Release(doc);
3354 hr = IPersistStorage_IsDirty(stg);
3355 ok(hr == S_FALSE, "unexpected %#x\n", hr);
3357 ole_stream = NULL;
3358 hr = CreateStreamOnHGlobal(NULL, TRUE, &olepres_stream);
3359 ok(hr == S_OK, "unexpected %#x\n", hr);
3361 /* FIXME: remove this stream once Wine is fixed */
3362 hr = CreateStreamOnHGlobal(NULL, TRUE, &contents_stream);
3363 ok(hr == S_OK, "unexpected %#x\n", hr);
3365 SET_EXPECT(Storage_CreateStream_OlePres);
3366 SET_EXPECT(Storage_OpenStream_OlePres);
3367 SET_EXPECT(Storage_OpenStream_Ole);
3368 SET_EXPECT(Storage_DestroyElement);
3369 Storage_DestroyElement_limit = 50;
3370 Storage_SetClass_CLSID = &CLSID_NULL;
3371 trace("IPersistStorage_Save:\n");
3372 hr = IPersistStorage_Save(stg, &Storage, FALSE);
3373 ok(hr == S_OK, "unexpected %#x\n", hr);
3374 CHECK_CALLED(Storage_CreateStream_OlePres);
3375 todo_wine
3376 CHECK_CALLED(Storage_OpenStream_OlePres);
3377 todo_wine
3378 CHECK_CALLED(Storage_OpenStream_Ole);
3379 todo_wine
3380 CHECK_CALLED(Storage_DestroyElement);
3382 IStream_Release(olepres_stream);
3383 IStream_Release(contents_stream);
3385 IPersistStorage_Release(stg);
3386 IOleCache2_Release(cache);
3389 #define MAX_STREAM 16
3391 struct stream_def
3393 const char *name;
3394 int cf;
3395 DVASPECT dvAspect;
3396 ADVF advf;
3397 const void *data;
3398 size_t data_size;
3401 struct storage_def
3403 const CLSID *clsid;
3404 int stream_count;
3405 struct stream_def stream[MAX_STREAM];
3408 static const struct storage_def stg_def_0 =
3410 &CLSID_NULL, 1,
3411 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) }}
3413 static const struct storage_def stg_def_0_saved =
3415 &CLSID_NULL, 0, {{ 0 }}
3417 static const struct storage_def stg_def_1 =
3419 &CLSID_NULL, 2,
3420 {{ "Contents", -1, 0, 0, NULL, 0 },
3421 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3423 static const struct storage_def stg_def_1_saved =
3425 &CLSID_NULL, 1,
3426 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3428 static const struct storage_def stg_def_2 =
3430 &CLSID_ManualResetEvent, 2,
3431 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3432 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3434 static const struct storage_def stg_def_2_saved =
3436 &CLSID_NULL, 1,
3437 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3439 static const struct storage_def stg_def_3 =
3441 &CLSID_NULL, 5,
3442 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3443 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3444 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3445 { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
3446 { "MyStream", -1, 0, 0, "Hello World!", 13 }}
3448 static const struct storage_def stg_def_3_saved =
3450 &CLSID_NULL, 3,
3451 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3452 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3453 { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) }}
3455 static const struct storage_def stg_def_4 =
3457 &CLSID_Picture_EnhMetafile, 5,
3458 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3459 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3460 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3461 { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
3462 { "MyStream", -1, 0, 0, "Hello World!", 13 }}
3464 static const struct storage_def stg_def_4_saved =
3466 &CLSID_NULL, 1,
3467 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3469 static const struct storage_def stg_def_5 =
3471 &CLSID_Picture_Dib, 5,
3472 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3473 { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
3474 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3475 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3476 { "MyStream", -1, 0, 0, "Hello World!", 13 }}
3478 static const struct storage_def stg_def_5_saved =
3480 &CLSID_NULL, 1,
3481 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3483 static const struct storage_def stg_def_6 =
3485 &CLSID_Picture_Metafile, 5,
3486 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3487 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3488 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3489 { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
3490 { "MyStream", -1, 0, 0, "Hello World!", 13 }}
3492 static const struct storage_def stg_def_6_saved =
3494 &CLSID_NULL, 1,
3495 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3497 static const struct storage_def stg_def_7 =
3499 &CLSID_Picture_Dib, 1,
3500 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) }}
3502 static const struct storage_def stg_def_7_saved =
3504 &CLSID_NULL, 0, {{ 0 }}
3506 static const struct storage_def stg_def_8 =
3508 &CLSID_Picture_Metafile, 1,
3509 {{ "Contents", -1, 0, 0, mf_blank_bits, sizeof(mf_blank_bits) }}
3511 static const struct storage_def stg_def_8_saved =
3513 &CLSID_NULL, 0, {{ 0 }}
3515 static const struct storage_def stg_def_9 =
3517 &CLSID_Picture_EnhMetafile, 1,
3518 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) }}
3520 static const struct storage_def stg_def_9_saved =
3522 &CLSID_NULL, 0, {{ 0 }}
3525 static int read_clipformat(IStream *stream)
3527 HRESULT hr;
3528 ULONG bytes;
3529 int length, clipformat = -2;
3531 hr = IStream_Read(stream, &length, sizeof(length), &bytes);
3532 if (hr != S_OK || bytes != sizeof(length))
3533 return -2;
3534 if (length == 0)
3535 return 0;
3536 if (length == -1)
3538 hr = IStream_Read(stream, &clipformat, sizeof(clipformat), &bytes);
3539 if (hr != S_OK || bytes != sizeof(clipformat))
3540 return -2;
3542 else
3543 ok(0, "unhandled clipformat length %d\n", length);
3545 return clipformat;
3548 static void check_storage_contents(IStorage *stg, const struct storage_def *stg_def,
3549 int *enumerated_streams, int *matched_streams)
3551 HRESULT hr;
3552 IEnumSTATSTG *enumstg;
3553 IStream *stream;
3554 STATSTG stat;
3555 int i, seen_stream[MAX_STREAM] = { 0 };
3557 if (winetest_debug > 1)
3558 trace("check_storage_contents:\n=============================================\n");
3560 *enumerated_streams = 0;
3561 *matched_streams = 0;
3563 hr = IStorage_Stat(stg, &stat, STATFLAG_NONAME);
3564 ok(hr == S_OK, "unexpected %#x\n", hr);
3565 ok(IsEqualCLSID(stg_def->clsid, &stat.clsid), "expected %s, got %s\n",
3566 wine_dbgstr_guid(stg_def->clsid), wine_dbgstr_guid(&stat.clsid));
3568 hr = IStorage_EnumElements(stg, 0, NULL, 0, &enumstg);
3569 ok(hr == S_OK, "unexpected %#x\n", hr);
3571 for (;;)
3573 ULONG bytes;
3574 int clipformat = -1;
3575 PresentationDataHeader header;
3576 char name[32];
3577 BYTE data[256];
3579 memset(&header, 0, sizeof(header));
3581 hr = IEnumSTATSTG_Next(enumstg, 1, &stat, NULL);
3582 if(hr == S_FALSE) break;
3583 ok(hr == S_OK, "unexpected %#x\n", hr);
3585 if (winetest_debug > 1)
3586 trace("name %s, type %u, size %d, clsid %s\n",
3587 wine_dbgstr_w(stat.pwcsName), stat.type, stat.cbSize.u.LowPart, wine_dbgstr_guid(&stat.clsid));
3589 ok(stat.type == STGTY_STREAM, "unexpected %#x\n", stat.type);
3591 WideCharToMultiByte(CP_ACP, 0, stat.pwcsName, -1, name, sizeof(name), NULL, NULL);
3593 hr = IStorage_OpenStream(stg, stat.pwcsName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream);
3594 ok(hr == S_OK, "unexpected %#x\n", hr);
3596 if (!memcmp(name, "\2OlePres", 7))
3598 clipformat = read_clipformat(stream);
3600 hr = IStream_Read(stream, &header, sizeof(header), &bytes);
3601 ok(hr == S_OK, "unexpected %#x\n", hr);
3602 ok(bytes >= 24, "read %u bytes\n", bytes);
3604 if (winetest_debug > 1)
3605 trace("header: unknown3 %#x, dvAspect %#x, lindex %#x, advf %#x, unknown7 %#x, dwObjectExtentX %#x, dwObjectExtentY %#x, dwSize %#x\n",
3606 header.unknown3, header.dvAspect, header.lindex, header.advf, header.unknown7,
3607 header.dwObjectExtentX, header.dwObjectExtentY, header.dwSize);
3610 memset(data, 0, sizeof(data));
3611 hr = IStream_Read(stream, data, sizeof(data), &bytes);
3612 ok(hr == S_OK, "unexpected %#x\n", hr);
3613 if (winetest_debug > 1)
3614 trace("stream data (%u bytes): %02x %02x %02x %02x\n", bytes, data[0], data[1], data[2], data[3]);
3616 for (i = 0; i < stg_def->stream_count; i++)
3618 if (seen_stream[i]) continue;
3620 if (winetest_debug > 1)
3621 trace("%s/%s, %d/%d, %d/%d, %d/%d\n",
3622 stg_def->stream[i].name, name,
3623 stg_def->stream[i].cf, clipformat,
3624 stg_def->stream[i].dvAspect, header.dvAspect,
3625 stg_def->stream[i].advf, header.advf);
3627 if (!strcmp(stg_def->stream[i].name, name) &&
3628 stg_def->stream[i].cf == clipformat &&
3629 stg_def->stream[i].dvAspect == header.dvAspect &&
3630 stg_def->stream[i].advf == header.advf &&
3631 stg_def->stream[i].data_size <= bytes &&
3632 (!stg_def->stream[i].data_size ||
3633 (!memcmp(stg_def->stream[i].data, data, min(stg_def->stream[i].data_size, bytes)))))
3635 if (winetest_debug > 1)
3636 trace("stream %d matches def stream %d\n", *enumerated_streams, i);
3637 seen_stream[i] = 1;
3638 *matched_streams += 1;
3642 CoTaskMemFree(stat.pwcsName);
3643 IStream_Release(stream);
3645 *enumerated_streams += 1;
3649 static IStorage *create_storage_from_def(const struct storage_def *stg_def)
3651 HRESULT hr;
3652 IStorage *stg;
3653 IStream *stm;
3654 int i;
3656 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &stg);
3657 ok(hr == S_OK, "unexpected %#x\n", hr);
3659 hr = IStorage_SetClass(stg, stg_def->clsid);
3660 ok(hr == S_OK, "unexpected %#x\n", hr);
3662 for (i = 0; i < stg_def->stream_count; i++)
3664 WCHAR name[32];
3666 MultiByteToWideChar(CP_ACP, 0, stg_def->stream[i].name, -1, name, 32);
3667 hr = IStorage_CreateStream(stg, name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3668 ok(hr == S_OK, "unexpected %#x\n", hr);
3670 if (stg_def->stream[i].cf != -1)
3672 int clipformat[2];
3673 PresentationDataHeader hdr;
3675 if (stg_def->stream[i].cf)
3677 clipformat[0] = -1;
3678 clipformat[1] = stg_def->stream[i].cf;
3679 hr = IStream_Write(stm, clipformat, sizeof(clipformat), NULL);
3681 else
3683 clipformat[0] = 0;
3684 hr = IStream_Write(stm, &clipformat[0], sizeof(clipformat[0]), NULL);
3686 ok(hr == S_OK, "unexpected %#x\n", hr);
3688 hdr.unknown3 = 4;
3689 hdr.dvAspect = stg_def->stream[i].dvAspect;
3690 hdr.lindex = -1;
3691 hdr.advf = stg_def->stream[i].advf;
3692 hdr.unknown7 = 0;
3693 hdr.dwObjectExtentX = 0;
3694 hdr.dwObjectExtentY = 0;
3695 hdr.dwSize = stg_def->stream[i].data_size;
3696 hr = IStream_Write(stm, &hdr, sizeof(hdr), NULL);
3697 ok(hr == S_OK, "unexpected %#x\n", hr);
3700 if (stg_def->stream[i].data_size)
3702 hr = IStream_Write(stm, stg_def->stream[i].data, stg_def->stream[i].data_size, NULL);
3703 ok(hr == S_OK, "unexpected %#x\n", hr);
3706 IStream_Release(stm);
3709 return stg;
3712 static void test_data_cache_contents(void)
3714 HRESULT hr;
3715 IStorage *doc1, *doc2;
3716 IOleCache2 *cache;
3717 IPersistStorage *stg;
3718 int i, enumerated_streams, matched_streams;
3719 static const struct
3721 const struct storage_def *in;
3722 const struct storage_def *out;
3723 } test_data[] =
3725 { &stg_def_0, &stg_def_0_saved },
3726 { &stg_def_1, &stg_def_1_saved },
3727 { &stg_def_2, &stg_def_2_saved },
3728 { &stg_def_3, &stg_def_3_saved },
3729 { &stg_def_4, &stg_def_4_saved },
3730 { &stg_def_5, &stg_def_5_saved },
3731 { &stg_def_6, &stg_def_6_saved },
3732 { &stg_def_7, &stg_def_7_saved },
3733 { &stg_def_8, &stg_def_8_saved },
3734 { &stg_def_9, &stg_def_9_saved },
3737 for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); i++)
3739 if (winetest_debug > 1)
3740 trace("start testing storage def %d\n", i);
3742 doc1 = create_storage_from_def(test_data[i].in);
3743 if (!doc1) continue;
3745 enumerated_streams = matched_streams = -1;
3746 check_storage_contents(doc1, test_data[i].in, &enumerated_streams, &matched_streams);
3747 ok(enumerated_streams == matched_streams, "%d in: enumerated %d != matched %d\n", i,
3748 enumerated_streams, matched_streams);
3749 ok(enumerated_streams == test_data[i].in->stream_count, "%d: created %d != def streams %d\n", i,
3750 enumerated_streams, test_data[i].in->stream_count);
3752 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IUnknown, (void **)&cache);
3753 ok(hr == S_OK, "unexpected %#x\n", hr);
3754 hr = IOleCache2_QueryInterface(cache, &IID_IPersistStorage, (void **)&stg);
3755 ok(hr == S_OK, "unexpected %#x\n", hr);
3756 hr = IPersistStorage_Load(stg, doc1);
3757 ok(hr == S_OK, "unexpected %#x\n", hr);
3759 IStorage_Release(doc1);
3761 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &doc2);
3762 ok(hr == S_OK, "unexpected %#x\n", hr);
3764 hr = IPersistStorage_IsDirty(stg);
3765 todo_wine_if(test_data[i].in == &stg_def_4 || test_data[i].in == &stg_def_8 || test_data[i].in == &stg_def_9)
3766 ok(hr == S_FALSE, "%d: unexpected %#x\n", i, hr);
3768 hr = IPersistStorage_Save(stg, doc2, FALSE);
3769 ok(hr == S_OK, "unexpected %#x\n", hr);
3771 IPersistStorage_Release(stg);
3773 enumerated_streams = matched_streams = -1;
3774 check_storage_contents(doc2, test_data[i].out, &enumerated_streams, &matched_streams);
3775 todo_wine_if(!(test_data[i].in == &stg_def_0 || test_data[i].in == &stg_def_1 || test_data[i].in == &stg_def_2))
3776 ok(enumerated_streams == matched_streams, "%d out: enumerated %d != matched %d\n", i,
3777 enumerated_streams, matched_streams);
3778 todo_wine_if(!(test_data[i].in == &stg_def_0 || test_data[i].in == &stg_def_5))
3779 ok(enumerated_streams == test_data[i].out->stream_count, "%d: saved streams %d != def streams %d\n", i,
3780 enumerated_streams, test_data[i].out->stream_count);
3782 IStorage_Release(doc2);
3784 if (winetest_debug > 1)
3785 trace("done testing storage def %d\n", i);
3789 START_TEST(ole2)
3791 DWORD dwRegister;
3792 IStorage *pStorage;
3793 STATSTG statstg;
3794 HRESULT hr;
3796 cf_test_1 = RegisterClipboardFormatA("cf_winetest_1");
3797 cf_test_2 = RegisterClipboardFormatA("cf_winetest_2");
3798 cf_test_3 = RegisterClipboardFormatA("cf_winetest_3");
3800 CoInitialize(NULL);
3802 hr = CoRegisterClassObject(&CLSID_Equation3, (IUnknown *)&OleObjectCF, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegister);
3803 ok_ole_success(hr, "CoRegisterClassObject");
3805 hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &pStorage);
3806 ok_ole_success(hr, "StgCreateDocfile");
3808 test_OleCreate(pStorage);
3810 hr = IStorage_Stat(pStorage, &statstg, STATFLAG_NONAME);
3811 ok_ole_success(hr, "IStorage_Stat");
3812 ok(IsEqualCLSID(&CLSID_Equation3, &statstg.clsid), "Wrong CLSID in storage\n");
3814 test_OleLoad(pStorage);
3816 IStorage_Release(pStorage);
3818 hr = CoRevokeClassObject(dwRegister);
3819 ok_ole_success(hr, "CoRevokeClassObject");
3821 Storage_SetClass_CLSID = &CLSID_WineTest;
3823 test_data_cache();
3824 test_data_cache_dib_contents_stream( 0 );
3825 test_data_cache_dib_contents_stream( 1 );
3826 test_data_cache_cache();
3827 test_data_cache_init();
3828 test_data_cache_initnew();
3829 test_default_handler();
3830 test_runnable();
3831 test_OleRun();
3832 test_OleLockRunning();
3833 test_OleDraw();
3834 test_OleDoAutoConvert();
3835 test_data_cache_save();
3836 test_data_cache_contents();
3838 CoUninitialize();