ole32: Remove an optimization from DataCache_Save() that copies whole original storage.
[wine.git] / dlls / ole32 / tests / ole2.c
blob08b6a27d84e0ff7eb8af32dbea05910fadf3d200
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_bitmap(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 }
2141 hr = CreateDataCache( NULL, &CLSID_NULL, &IID_IOleCache2, (void **)&cache );
2142 ok( hr == S_OK, "got %08x\n", hr );
2144 /* create a dib entry which will also create a bitmap entry too */
2145 fmt.cfFormat = CF_DIB;
2146 fmt.ptd = NULL;
2147 fmt.dwAspect = DVASPECT_CONTENT;
2148 fmt.lindex = -1;
2149 fmt.tymed = TYMED_HGLOBAL;
2151 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2152 ok( hr == S_OK, "got %08x\n", hr );
2153 ok( conn == 2, "got %d\n", conn );
2154 expect[0].dwConnection = conn;
2155 expect[1].dwConnection = conn;
2157 check_enum_cache( cache, expect, 2 );
2159 /* now try to add a bitmap */
2160 fmt.cfFormat = CF_BITMAP;
2161 fmt.tymed = TYMED_GDI;
2163 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2164 ok( hr == CACHE_S_SAMECACHE, "got %08x\n", hr );
2166 /* metafile */
2167 fmt.cfFormat = CF_METAFILEPICT;
2168 fmt.tymed = TYMED_MFPICT;
2170 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2171 ok( hr == S_OK, "got %08x\n", hr );
2172 ok( conn == 3, "got %d\n", conn );
2173 expect[2].dwConnection = conn;
2175 check_enum_cache( cache, expect, 3);
2177 /* enhmetafile */
2178 fmt.cfFormat = CF_ENHMETAFILE;
2179 fmt.tymed = TYMED_ENHMF;
2181 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2182 ok( hr == S_OK, "got %08x\n", hr );
2183 ok( conn == 4, "got %d\n", conn );
2184 expect[3].dwConnection = conn;
2186 check_enum_cache( cache, expect, 4 );
2188 /* uncache everything */
2189 hr = IOleCache2_Uncache( cache, expect[3].dwConnection );
2190 ok( hr == S_OK, "got %08x\n", hr );
2191 hr = IOleCache2_Uncache( cache, expect[2].dwConnection );
2192 ok( hr == S_OK, "got %08x\n", hr );
2193 hr = IOleCache2_Uncache( cache, expect[0].dwConnection );
2194 ok( hr == S_OK, "got %08x\n", hr );
2195 hr = IOleCache2_Uncache( cache, expect[0].dwConnection );
2196 ok( hr == OLE_E_NOCONNECTION, "got %08x\n", hr );
2198 check_enum_cache( cache, expect, 0 );
2200 /* just create a bitmap entry which again adds both dib and bitmap */
2201 fmt.cfFormat = CF_BITMAP;
2202 fmt.tymed = TYMED_GDI;
2204 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2205 ok( hr == S_OK, "got %08x\n", hr );
2207 expect[0].dwConnection = conn;
2208 expect[1].dwConnection = conn;
2210 check_enum_cache( cache, expect, 2 );
2212 /* Try setting a 1x1 bitmap */
2213 hr = IOleCache2_QueryInterface( cache, &IID_IDataObject, (void **) &data );
2214 ok( hr == S_OK, "got %08x\n", hr );
2216 med.tymed = TYMED_GDI;
2217 U(med).hBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
2218 med.pUnkForRelease = NULL;
2220 hr = IOleCache2_SetData( cache, &fmt, &med, TRUE );
2221 ok( hr == S_OK, "got %08x\n", hr );
2223 hr = IDataObject_GetData( data, &fmt, &med );
2224 ok( hr == S_OK, "got %08x\n", hr );
2225 ok( med.tymed == TYMED_GDI, "got %d\n", med.tymed );
2226 check_bitmap_size( U(med).hBitmap, 1, 1 );
2227 ReleaseStgMedium( &med );
2229 fmt.cfFormat = CF_DIB;
2230 fmt.tymed = TYMED_HGLOBAL;
2231 hr = IDataObject_GetData( data, &fmt, &med );
2232 ok( hr == S_OK, "got %08x\n", hr );
2233 ok( med.tymed == TYMED_HGLOBAL, "got %d\n", med.tymed );
2234 check_dib_size( U(med).hGlobal, 1, 1 );
2235 ReleaseStgMedium( &med );
2237 /* Now set a 2x1 dib */
2238 fmt.cfFormat = CF_DIB;
2239 fmt.tymed = TYMED_HGLOBAL;
2240 med.tymed = TYMED_HGLOBAL;
2241 U(med).hGlobal = create_dib();
2243 hr = IOleCache2_SetData( cache, &fmt, &med, TRUE );
2244 ok( hr == S_OK, "got %08x\n", hr );
2246 fmt.cfFormat = CF_BITMAP;
2247 fmt.tymed = TYMED_GDI;
2248 hr = IDataObject_GetData( data, &fmt, &med );
2249 ok( hr == S_OK, "got %08x\n", hr );
2250 ok( med.tymed == TYMED_GDI, "got %d\n", med.tymed );
2251 check_bitmap_size( U(med).hBitmap, 2, 1 );
2252 ReleaseStgMedium( &med );
2254 fmt.cfFormat = CF_DIB;
2255 fmt.tymed = TYMED_HGLOBAL;
2256 hr = IDataObject_GetData( data, &fmt, &med );
2257 ok( hr == S_OK, "got %08x\n", hr );
2258 ok( med.tymed == TYMED_HGLOBAL, "got %d\n", med.tymed );
2259 check_dib_size( U(med).hGlobal, 2, 1 );
2260 ReleaseStgMedium( &med );
2262 IDataObject_Release( data );
2263 IOleCache2_Release( cache );
2266 /* The CLSID_Picture_ classes automatically create appropriate cache entries */
2267 static void test_data_cache_init(void)
2269 HRESULT hr;
2270 IOleCache2 *cache;
2271 IPersistStorage *persist;
2272 int i;
2273 CLSID clsid;
2274 static const STATDATA enum_expect[] =
2276 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2277 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 },
2278 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 1 },
2279 {{ CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF }, 0, NULL, 1 }
2281 static const struct
2283 const CLSID *clsid;
2284 int enum_start, enum_num;
2285 } data[] =
2287 { &CLSID_NULL, 0, 0 },
2288 { &CLSID_WineTestOld, 0, 0 },
2289 { &CLSID_Picture_Dib, 0, 2 },
2290 { &CLSID_Picture_Metafile, 2, 1 },
2291 { &CLSID_Picture_EnhMetafile, 3, 1 }
2294 for (i = 0; i < sizeof(data) / sizeof(data[0]); i++)
2296 hr = CreateDataCache( NULL, data[i].clsid, &IID_IOleCache2, (void **)&cache );
2297 ok( hr == S_OK, "got %08x\n", hr );
2299 check_enum_cache( cache, enum_expect + data[i].enum_start , data[i].enum_num );
2301 IOleCache2_QueryInterface( cache, &IID_IPersistStorage, (void **) &persist );
2302 hr = IPersistStorage_GetClassID( persist, &clsid );
2303 ok( hr == S_OK, "got %08x\n", hr );
2304 ok( IsEqualCLSID( &clsid, data[i].clsid ), "class id mismatch %s %s\n", wine_dbgstr_guid( &clsid ),
2305 wine_dbgstr_guid( data[i].clsid ) );
2307 IPersistStorage_Release( persist );
2308 IOleCache2_Release( cache );
2312 static void test_data_cache_initnew(void)
2314 HRESULT hr;
2315 IOleCache2 *cache;
2316 IPersistStorage *persist;
2317 IStorage *stg_dib, *stg_mf, *stg_wine;
2318 CLSID clsid;
2319 static const STATDATA initnew_expect[] =
2321 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2322 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 },
2324 static const STATDATA initnew2_expect[] =
2326 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 1 },
2327 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 2 },
2328 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 2 },
2330 static const STATDATA initnew3_expect[] =
2332 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2333 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 },
2334 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 2 },
2335 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 2 },
2336 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 3 },
2338 static const STATDATA initnew4_expect[] =
2340 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 2 },
2341 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 2 },
2342 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 3 },
2343 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 4 },
2344 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 4 },
2347 hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg_dib );
2348 ok( hr == S_OK, "got %08x\n", hr);
2349 hr = IStorage_SetClass( stg_dib, &CLSID_Picture_Dib );
2350 ok( hr == S_OK, "got %08x\n", hr);
2352 hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg_mf );
2353 ok( hr == S_OK, "got %08x\n", hr);
2354 hr = IStorage_SetClass( stg_mf, &CLSID_Picture_Metafile );
2355 ok( hr == S_OK, "got %08x\n", hr);
2357 hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg_wine );
2358 ok( hr == S_OK, "got %08x\n", hr);
2359 hr = IStorage_SetClass( stg_wine, &CLSID_WineTestOld );
2360 ok( hr == S_OK, "got %08x\n", hr);
2362 hr = CreateDataCache( NULL, &CLSID_WineTestOld, &IID_IOleCache2, (void **)&cache );
2363 ok( hr == S_OK, "got %08x\n", hr );
2364 IOleCache2_QueryInterface( cache, &IID_IPersistStorage, (void **) &persist );
2366 hr = IPersistStorage_InitNew( persist, stg_dib );
2367 ok( hr == S_OK, "got %08x\n", hr);
2369 hr = IPersistStorage_GetClassID( persist, &clsid );
2370 ok( hr == S_OK, "got %08x\n", hr );
2371 ok( IsEqualCLSID( &clsid, &CLSID_Picture_Dib ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2373 check_enum_cache( cache, initnew_expect, 2 );
2375 hr = IPersistStorage_InitNew( persist, stg_mf );
2376 ok( hr == CO_E_ALREADYINITIALIZED, "got %08x\n", hr);
2378 hr = IPersistStorage_HandsOffStorage( persist );
2379 ok( hr == S_OK, "got %08x\n", hr);
2381 hr = IPersistStorage_GetClassID( persist, &clsid );
2382 ok( hr == S_OK, "got %08x\n", hr );
2383 ok( IsEqualCLSID( &clsid, &CLSID_Picture_Dib ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2385 hr = IPersistStorage_InitNew( persist, stg_mf );
2386 ok( hr == S_OK, "got %08x\n", hr);
2388 hr = IPersistStorage_GetClassID( persist, &clsid );
2389 ok( hr == S_OK, "got %08x\n", hr );
2390 ok( IsEqualCLSID( &clsid, &CLSID_Picture_Metafile ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2392 check_enum_cache( cache, initnew2_expect, 3 );
2394 hr = IPersistStorage_HandsOffStorage( persist );
2395 ok( hr == S_OK, "got %08x\n", hr);
2397 hr = IPersistStorage_InitNew( persist, stg_dib );
2398 ok( hr == S_OK, "got %08x\n", hr);
2400 hr = IPersistStorage_GetClassID( persist, &clsid );
2401 ok( hr == S_OK, "got %08x\n", hr );
2402 ok( IsEqualCLSID( &clsid, &CLSID_Picture_Dib ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2404 check_enum_cache( cache, initnew3_expect, 5 );
2406 hr = IPersistStorage_HandsOffStorage( persist );
2407 ok( hr == S_OK, "got %08x\n", hr);
2409 hr = IPersistStorage_InitNew( persist, stg_wine );
2410 ok( hr == S_OK, "got %08x\n", hr);
2412 hr = IPersistStorage_GetClassID( persist, &clsid );
2413 ok( hr == S_OK, "got %08x\n", hr );
2414 ok( IsEqualCLSID( &clsid, &CLSID_WineTestOld ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2416 check_enum_cache( cache, initnew4_expect, 5 );
2418 IStorage_Release( stg_wine );
2419 IStorage_Release( stg_mf );
2420 IStorage_Release( stg_dib );
2422 IPersistStorage_Release( persist );
2423 IOleCache2_Release( cache );
2426 static void test_default_handler(void)
2428 HRESULT hr;
2429 IOleObject *pObject;
2430 IRunnableObject *pRunnableObject;
2431 IOleClientSite *pClientSite;
2432 IDataObject *pDataObject;
2433 SIZEL sizel;
2434 DWORD dwStatus;
2435 CLSID clsid;
2436 LPOLESTR pszUserType;
2437 LOGPALETTE palette;
2438 DWORD dwAdvConn;
2439 IMoniker *pMoniker;
2440 FORMATETC fmtetc;
2441 IOleInPlaceObject *pInPlaceObj;
2442 IEnumOLEVERB *pEnumVerbs;
2443 DWORD dwRegister;
2444 static const WCHAR wszUnknown[] = {'U','n','k','n','o','w','n',0};
2445 static const WCHAR wszHostName[] = {'W','i','n','e',' ','T','e','s','t',' ','P','r','o','g','r','a','m',0};
2446 static const WCHAR wszDelim[] = {'!',0};
2448 static const struct expected_method methods_embeddinghelper[] =
2450 { "OleObject_QueryInterface", 0 },
2451 { "OleObject_AddRef", 0 },
2452 { "OleObject_QueryInterface", 0 },
2453 { "OleObject_QueryInterface", TEST_TODO },
2454 { "OleObject_QueryInterface", 0 },
2455 { "OleObject_QueryInterface", 0 },
2456 { "OleObject_QueryInterface", TEST_OPTIONAL }, /* Win95/98/NT4 */
2457 { "OleObject_Release", TEST_TODO },
2458 { "WINE_EXTRA", TEST_OPTIONAL },
2459 { NULL, 0 }
2462 hr = CoCreateInstance(&CLSID_WineTest, NULL, CLSCTX_INPROC_HANDLER, &IID_IOleObject, (void **)&pObject);
2463 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance should have failed with REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2465 hr = OleCreateDefaultHandler(&CLSID_WineTest, NULL, &IID_IOleObject, (void **)&pObject);
2466 ok_ole_success(hr, "OleCreateDefaultHandler");
2468 hr = IOleObject_QueryInterface(pObject, &IID_IOleInPlaceObject, (void **)&pInPlaceObj);
2469 ok(hr == E_NOINTERFACE, "IOleObject_QueryInterface(&IID_IOleInPlaceObject) should return E_NOINTERFACE instead of 0x%08x\n", hr);
2471 hr = IOleObject_Advise(pObject, &AdviseSink, &dwAdvConn);
2472 ok_ole_success(hr, "IOleObject_Advise");
2474 hr = IOleObject_Close(pObject, OLECLOSE_NOSAVE);
2475 ok_ole_success(hr, "IOleObject_Close");
2477 /* FIXME: test IOleObject_EnumAdvise */
2479 hr = IOleObject_EnumVerbs(pObject, &pEnumVerbs);
2480 ok(hr == REGDB_E_CLASSNOTREG, "IOleObject_EnumVerbs should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2482 hr = IOleObject_GetClientSite(pObject, &pClientSite);
2483 ok_ole_success(hr, "IOleObject_GetClientSite");
2485 hr = IOleObject_SetClientSite(pObject, pClientSite);
2486 ok_ole_success(hr, "IOleObject_SetClientSite");
2488 hr = IOleObject_GetClipboardData(pObject, 0, &pDataObject);
2489 ok(hr == OLE_E_NOTRUNNING,
2490 "IOleObject_GetClipboardData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n",
2491 hr);
2493 hr = IOleObject_GetExtent(pObject, DVASPECT_CONTENT, &sizel);
2494 ok(hr == OLE_E_BLANK, "IOleObject_GetExtent should have returned OLE_E_BLANK instead of 0x%08x\n",
2495 hr);
2497 hr = IOleObject_GetMiscStatus(pObject, DVASPECT_CONTENT, &dwStatus);
2498 ok(hr == REGDB_E_CLASSNOTREG, "IOleObject_GetMiscStatus should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2500 hr = IOleObject_GetUserClassID(pObject, &clsid);
2501 ok_ole_success(hr, "IOleObject_GetUserClassID");
2502 ok(IsEqualCLSID(&clsid, &CLSID_WineTest), "clsid != CLSID_WineTest\n");
2504 hr = IOleObject_GetUserType(pObject, USERCLASSTYPE_FULL, &pszUserType);
2505 todo_wine {
2506 ok_ole_success(hr, "IOleObject_GetUserType");
2507 ok(!lstrcmpW(pszUserType, wszUnknown), "Retrieved user type was wrong\n");
2510 hr = IOleObject_InitFromData(pObject, NULL, TRUE, 0);
2511 ok(hr == OLE_E_NOTRUNNING, "IOleObject_InitFromData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
2513 hr = IOleObject_IsUpToDate(pObject);
2514 ok(hr == OLE_E_NOTRUNNING, "IOleObject_IsUpToDate should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
2516 palette.palNumEntries = 1;
2517 palette.palVersion = 2;
2518 memset(&palette.palPalEntry[0], 0, sizeof(palette.palPalEntry[0]));
2519 hr = IOleObject_SetColorScheme(pObject, &palette);
2520 ok(hr == OLE_E_NOTRUNNING, "IOleObject_SetColorScheme should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
2522 sizel.cx = sizel.cy = 0;
2523 hr = IOleObject_SetExtent(pObject, DVASPECT_CONTENT, &sizel);
2524 ok(hr == OLE_E_NOTRUNNING, "IOleObject_SetExtent should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
2526 hr = IOleObject_SetHostNames(pObject, wszHostName, NULL);
2527 ok_ole_success(hr, "IOleObject_SetHostNames");
2529 hr = CreateItemMoniker(wszDelim, wszHostName, &pMoniker);
2530 ok_ole_success(hr, "CreateItemMoniker");
2531 hr = IOleObject_SetMoniker(pObject, OLEWHICHMK_CONTAINER, pMoniker);
2532 ok_ole_success(hr, "IOleObject_SetMoniker");
2533 IMoniker_Release(pMoniker);
2535 hr = IOleObject_GetMoniker(pObject, OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_CONTAINER, &pMoniker);
2536 ok(hr == E_FAIL, "IOleObject_GetMoniker should have returned E_FAIL instead of 0x%08x\n", hr);
2538 hr = IOleObject_Update(pObject);
2539 todo_wine
2540 ok(hr == REGDB_E_CLASSNOTREG, "IOleObject_Update should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2542 hr = IOleObject_QueryInterface(pObject, &IID_IDataObject, (void **)&pDataObject);
2543 ok_ole_success(hr, "IOleObject_QueryInterface");
2545 fmtetc.cfFormat = CF_TEXT;
2546 fmtetc.ptd = NULL;
2547 fmtetc.dwAspect = DVASPECT_CONTENT;
2548 fmtetc.lindex = -1;
2549 fmtetc.tymed = TYMED_NULL;
2550 hr = IDataObject_DAdvise(pDataObject, &fmtetc, 0, &AdviseSink, &dwAdvConn);
2551 ok_ole_success(hr, "IDataObject_DAdvise");
2553 fmtetc.cfFormat = CF_ENHMETAFILE;
2554 fmtetc.ptd = NULL;
2555 fmtetc.dwAspect = DVASPECT_CONTENT;
2556 fmtetc.lindex = -1;
2557 fmtetc.tymed = TYMED_ENHMF;
2558 hr = IDataObject_DAdvise(pDataObject, &fmtetc, 0, &AdviseSink, &dwAdvConn);
2559 ok_ole_success(hr, "IDataObject_DAdvise");
2561 fmtetc.cfFormat = CF_ENHMETAFILE;
2562 fmtetc.ptd = NULL;
2563 fmtetc.dwAspect = DVASPECT_CONTENT;
2564 fmtetc.lindex = -1;
2565 fmtetc.tymed = TYMED_ENHMF;
2566 hr = IDataObject_QueryGetData(pDataObject, &fmtetc);
2567 ok(hr == OLE_E_NOTRUNNING, "IDataObject_QueryGetData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
2569 fmtetc.cfFormat = CF_TEXT;
2570 fmtetc.ptd = NULL;
2571 fmtetc.dwAspect = DVASPECT_CONTENT;
2572 fmtetc.lindex = -1;
2573 fmtetc.tymed = TYMED_NULL;
2574 hr = IDataObject_QueryGetData(pDataObject, &fmtetc);
2575 ok(hr == OLE_E_NOTRUNNING, "IDataObject_QueryGetData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
2577 hr = IOleObject_QueryInterface(pObject, &IID_IRunnableObject, (void **)&pRunnableObject);
2578 ok_ole_success(hr, "IOleObject_QueryInterface");
2580 hr = IRunnableObject_SetContainedObject(pRunnableObject, TRUE);
2581 ok_ole_success(hr, "IRunnableObject_SetContainedObject");
2583 hr = IRunnableObject_Run(pRunnableObject, NULL);
2584 ok(hr == REGDB_E_CLASSNOTREG, "IOleObject_Run should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2586 hr = IOleObject_Close(pObject, OLECLOSE_NOSAVE);
2587 ok_ole_success(hr, "IOleObject_Close");
2589 IRunnableObject_Release(pRunnableObject);
2590 IOleObject_Release(pObject);
2592 /* Test failure propagation from delegate ::QueryInterface */
2593 hr = CoRegisterClassObject(&CLSID_WineTest, (IUnknown*)&OleObjectCF,
2594 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegister);
2595 ok_ole_success(hr, "CoRegisterClassObject");
2596 if(SUCCEEDED(hr))
2598 expected_method_list = methods_embeddinghelper;
2599 hr = OleCreateEmbeddingHelper(&CLSID_WineTest, NULL, EMBDHLP_INPROC_SERVER,
2600 &OleObjectCF, &IID_IOleObject, (void**)&pObject);
2601 ok_ole_success(hr, "OleCreateEmbeddingHelper");
2602 if(SUCCEEDED(hr))
2604 IUnknown *punk;
2606 g_QIFailsWith = E_FAIL;
2607 hr = IOleObject_QueryInterface(pObject, &IID_WineTest, (void**)&punk);
2608 ok(hr == E_FAIL, "Got 0x%08x\n", hr);
2610 g_QIFailsWith = E_NOINTERFACE;
2611 hr = IOleObject_QueryInterface(pObject, &IID_WineTest, (void**)&punk);
2612 ok(hr == E_NOINTERFACE, "Got 0x%08x\n", hr);
2614 g_QIFailsWith = CO_E_OBJNOTCONNECTED;
2615 hr = IOleObject_QueryInterface(pObject, &IID_WineTest, (void**)&punk);
2616 ok(hr == CO_E_OBJNOTCONNECTED, "Got 0x%08x\n", hr);
2618 g_QIFailsWith = 0x87654321;
2619 hr = IOleObject_QueryInterface(pObject, &IID_WineTest, (void**)&punk);
2620 ok(hr == 0x87654321, "Got 0x%08x\n", hr);
2622 IOleObject_Release(pObject);
2625 CHECK_NO_EXTRA_METHODS();
2627 hr = CoRevokeClassObject(dwRegister);
2628 ok_ole_success(hr, "CoRevokeClassObject");
2632 static void test_runnable(void)
2634 static const struct expected_method methods_query_runnable[] =
2636 { "OleObject_QueryInterface", 0 },
2637 { "OleObjectRunnable_AddRef", 0 },
2638 { "OleObjectRunnable_IsRunning", 0 },
2639 { "OleObjectRunnable_Release", 0 },
2640 { NULL, 0 }
2643 static const struct expected_method methods_no_runnable[] =
2645 { "OleObject_QueryInterface", 0 },
2646 { NULL, 0 }
2649 BOOL ret;
2650 IOleObject *object = &OleObject;
2652 /* null argument */
2653 ret = OleIsRunning(NULL);
2654 ok(ret == FALSE, "got %d\n", ret);
2656 expected_method_list = methods_query_runnable;
2657 ret = OleIsRunning(object);
2658 ok(ret == TRUE, "Object should be running\n");
2659 CHECK_NO_EXTRA_METHODS();
2661 g_isRunning = FALSE;
2662 expected_method_list = methods_query_runnable;
2663 ret = OleIsRunning(object);
2664 ok(ret == FALSE, "Object should not be running\n");
2665 CHECK_NO_EXTRA_METHODS();
2667 g_showRunnable = FALSE; /* QueryInterface(IID_IRunnableObject, ...) will fail */
2668 expected_method_list = methods_no_runnable;
2669 ret = OleIsRunning(object);
2670 ok(ret == TRUE, "Object without IRunnableObject should be running\n");
2671 CHECK_NO_EXTRA_METHODS();
2673 g_isRunning = TRUE;
2674 g_showRunnable = TRUE;
2678 static HRESULT WINAPI OleRun_QueryInterface(IRunnableObject *iface, REFIID riid, void **ppv)
2680 *ppv = NULL;
2682 if (IsEqualIID(riid, &IID_IUnknown) ||
2683 IsEqualIID(riid, &IID_IRunnableObject)) {
2684 *ppv = iface;
2687 if (*ppv)
2689 IUnknown_AddRef((IUnknown *)*ppv);
2690 return S_OK;
2693 return E_NOINTERFACE;
2696 static ULONG WINAPI OleRun_AddRef(IRunnableObject *iface)
2698 return 2;
2701 static ULONG WINAPI OleRun_Release(IRunnableObject *iface)
2703 return 1;
2706 static HRESULT WINAPI OleRun_GetRunningClass(IRunnableObject *iface, CLSID *clsid)
2708 ok(0, "unexpected\n");
2709 return E_NOTIMPL;
2712 static HRESULT WINAPI OleRun_Run(IRunnableObject *iface, LPBINDCTX ctx)
2714 ok(ctx == NULL, "got %p\n", ctx);
2715 return 0xdeadc0de;
2718 static BOOL WINAPI OleRun_IsRunning(IRunnableObject *iface)
2720 ok(0, "unexpected\n");
2721 return FALSE;
2724 static HRESULT WINAPI OleRun_LockRunning(IRunnableObject *iface, BOOL lock,
2725 BOOL last_unlock_closes)
2727 ok(0, "unexpected\n");
2728 return E_NOTIMPL;
2731 static HRESULT WINAPI OleRun_SetContainedObject(IRunnableObject *iface, BOOL contained)
2733 ok(0, "unexpected\n");
2734 return E_NOTIMPL;
2737 static const IRunnableObjectVtbl oleruntestvtbl =
2739 OleRun_QueryInterface,
2740 OleRun_AddRef,
2741 OleRun_Release,
2742 OleRun_GetRunningClass,
2743 OleRun_Run,
2744 OleRun_IsRunning,
2745 OleRun_LockRunning,
2746 OleRun_SetContainedObject
2749 static IRunnableObject testrunnable = { &oleruntestvtbl };
2751 static void test_OleRun(void)
2753 HRESULT hr;
2755 /* doesn't support IRunnableObject */
2756 hr = OleRun(&unknown);
2757 ok(hr == S_OK, "OleRun failed 0x%08x\n", hr);
2759 hr = OleRun((IUnknown*)&testrunnable);
2760 ok(hr == 0xdeadc0de, "got 0x%08x\n", hr);
2763 static void test_OleLockRunning(void)
2765 HRESULT hr;
2767 hr = OleLockRunning(&unknown, TRUE, FALSE);
2768 ok(hr == S_OK, "OleLockRunning failed 0x%08x\n", hr);
2771 static void test_OleDraw(void)
2773 HRESULT hr;
2774 RECT rect;
2776 hr = OleDraw((IUnknown*)&viewobject, 0, (HDC)0x1, NULL);
2777 ok(hr == S_OK, "got 0x%08x\n", hr);
2779 hr = OleDraw(NULL, 0, (HDC)0x1, NULL);
2780 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2782 hr = OleDraw(NULL, 0, (HDC)0x1, &rect);
2783 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2786 static const WCHAR olepres0W[] = {2,'O','l','e','P','r','e','s','0','0','0',0};
2787 static const WCHAR comp_objW[] = {1,'C','o','m','p','O','b','j',0};
2788 static IStream *comp_obj_stream;
2789 static IStream *ole_stream;
2790 static IStream *olepres_stream;
2791 static IStream *contents_stream;
2793 static HRESULT WINAPI Storage_QueryInterface(IStorage *iface, REFIID riid, void **ppvObject)
2795 ok(0, "unexpected call to QueryInterface\n");
2796 return E_NOTIMPL;
2799 static ULONG WINAPI Storage_AddRef(IStorage *iface)
2801 ok(0, "unexpected call to AddRef\n");
2802 return 2;
2805 static ULONG WINAPI Storage_Release(IStorage *iface)
2807 ok(0, "unexpected call to Release\n");
2808 return 1;
2811 static HRESULT WINAPI Storage_CreateStream(IStorage *iface, LPCOLESTR pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStream **ppstm)
2813 ULARGE_INTEGER size = {{0}};
2814 LARGE_INTEGER pos = {{0}};
2815 HRESULT hr;
2817 if (!lstrcmpW(pwcsName, comp_objW))
2819 CHECK_EXPECT(Storage_CreateStream_CompObj);
2820 *ppstm = comp_obj_stream;
2822 todo_wine ok(grfMode == (STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
2824 else if (!lstrcmpW(pwcsName, olepres0W))
2826 CHECK_EXPECT(Storage_CreateStream_OlePres);
2827 *ppstm = olepres_stream;
2829 todo_wine ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
2831 else
2833 todo_wine
2834 ok(0, "unexpected stream name %s\n", wine_dbgstr_w(pwcsName));
2835 #if 0 /* FIXME: return NULL once Wine is fixed */
2836 *ppstm = NULL;
2837 return E_NOTIMPL;
2838 #else
2839 *ppstm = contents_stream;
2840 #endif
2843 ok(!reserved1, "reserved1 = %x\n", reserved1);
2844 ok(!reserved2, "reserved2 = %x\n", reserved2);
2845 ok(!!ppstm, "ppstm = NULL\n");
2847 IStream_AddRef(*ppstm);
2848 hr = IStream_Seek(*ppstm, pos, STREAM_SEEK_SET, NULL);
2849 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
2850 hr = IStream_SetSize(*ppstm, size);
2851 ok(hr == S_OK, "IStream_SetSize returned %x\n", hr);
2852 return S_OK;
2855 static HRESULT WINAPI Storage_OpenStream(IStorage *iface, LPCOLESTR pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream **ppstm)
2857 static const WCHAR ole1W[] = {1,'O','l','e',0};
2859 LARGE_INTEGER pos = {{0}};
2860 HRESULT hr;
2862 ok(!reserved1, "reserved1 = %p\n", reserved1);
2863 ok(!reserved2, "reserved2 = %x\n", reserved2);
2864 ok(!!ppstm, "ppstm = NULL\n");
2866 if(!lstrcmpW(pwcsName, comp_objW)) {
2867 CHECK_EXPECT2(Storage_OpenStream_CompObj);
2868 ok(grfMode == STGM_SHARE_EXCLUSIVE, "grfMode = %x\n", grfMode);
2870 *ppstm = comp_obj_stream;
2871 IStream_AddRef(comp_obj_stream);
2872 hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL);
2873 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
2874 return S_OK;
2875 }else if(!lstrcmpW(pwcsName, ole1W)) {
2876 CHECK_EXPECT(Storage_OpenStream_Ole);
2878 if (!ole_stream)
2880 ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READ), "grfMode = %x\n", grfMode);
2882 *ppstm = NULL;
2883 return STG_E_FILENOTFOUND;
2886 ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
2888 *ppstm = ole_stream;
2889 IStream_AddRef(ole_stream);
2890 hr = IStream_Seek(ole_stream, pos, STREAM_SEEK_SET, NULL);
2891 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
2892 return S_OK;
2894 }else if(!lstrcmpW(pwcsName, olepres0W)) {
2895 CHECK_EXPECT(Storage_OpenStream_OlePres);
2896 ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
2898 *ppstm = olepres_stream;
2899 IStream_AddRef(olepres_stream);
2900 hr = IStream_Seek(olepres_stream, pos, STREAM_SEEK_SET, NULL);
2901 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
2902 return S_OK;
2905 ok(0, "unexpected call to OpenStream: %s\n", wine_dbgstr_w(pwcsName));
2906 return E_NOTIMPL;
2909 static HRESULT WINAPI Storage_CreateStorage(IStorage *iface, LPCOLESTR pwcsName, DWORD grfMode, DWORD dwStgFmt, DWORD reserved2, IStorage **ppstg)
2911 ok(0, "unexpected call to CreateStorage\n");
2912 return E_NOTIMPL;
2915 static HRESULT WINAPI Storage_OpenStorage(IStorage *iface, LPCOLESTR pwcsName, IStorage *pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage **ppstg)
2917 ok(0, "unexpected call to OpenStorage\n");
2918 return E_NOTIMPL;
2921 static HRESULT WINAPI Storage_CopyTo(IStorage *iface, DWORD ciidExclude, const IID *rgiidExclude, SNB snbExclude, IStorage *pstgDest)
2923 ok(0, "unexpected call to CopyTo\n");
2924 return E_NOTIMPL;
2927 static HRESULT WINAPI Storage_MoveElementTo(IStorage *iface, LPCOLESTR pwcsName, IStorage *pstgDest, LPCOLESTR pwcsNewName, DWORD grfFlags)
2929 ok(0, "unexpected call to MoveElementTo\n");
2930 return E_NOTIMPL;
2933 static HRESULT WINAPI Storage_Commit(IStorage *iface, DWORD grfCommitFlags)
2935 ok(0, "unexpected call to Commit\n");
2936 return E_NOTIMPL;
2939 static HRESULT WINAPI Storage_Revert(IStorage *iface)
2941 ok(0, "unexpected call to Revert\n");
2942 return E_NOTIMPL;
2945 static HRESULT WINAPI Storage_EnumElements(IStorage *iface, DWORD reserved1, void *reserved2, DWORD reserved3, IEnumSTATSTG **ppenum)
2947 ok(0, "unexpected call to EnumElements\n");
2948 return E_NOTIMPL;
2951 static HRESULT WINAPI Storage_DestroyElement(IStorage *iface, LPCOLESTR pwcsName)
2953 char name[32];
2954 int stream_n, cmp;
2956 CHECK_EXPECT2(Storage_DestroyElement);
2957 cmp = CompareStringW(LOCALE_NEUTRAL, 0, pwcsName, 8, olepres0W, 8);
2958 ok(cmp == CSTR_EQUAL,
2959 "unexpected call to DestroyElement(%s)\n", wine_dbgstr_w(pwcsName));
2961 WideCharToMultiByte(CP_ACP, 0, pwcsName, -1, name, sizeof(name), NULL, NULL);
2962 stream_n = atol(name + 8);
2963 if (stream_n <= Storage_DestroyElement_limit)
2964 return S_OK;
2966 return STG_E_FILENOTFOUND;
2969 static HRESULT WINAPI Storage_RenameElement(IStorage *iface, LPCOLESTR pwcsOldName, LPCOLESTR pwcsNewName)
2971 ok(0, "unexpected call to RenameElement\n");
2972 return E_NOTIMPL;
2975 static HRESULT WINAPI Storage_SetElementTimes(IStorage *iface, LPCOLESTR pwcsName, const FILETIME *pctime, const FILETIME *patime, const FILETIME *pmtime)
2977 ok(0, "unexpected call to SetElementTimes\n");
2978 return E_NOTIMPL;
2981 static HRESULT WINAPI Storage_SetClass(IStorage *iface, REFCLSID clsid)
2983 CHECK_EXPECT(Storage_SetClass);
2984 ok(IsEqualIID(clsid, Storage_SetClass_CLSID), "expected %s, got %s\n",
2985 wine_dbgstr_guid(Storage_SetClass_CLSID), wine_dbgstr_guid(clsid));
2986 return S_OK;
2989 static HRESULT WINAPI Storage_SetStateBits(IStorage *iface, DWORD grfStateBits, DWORD grfMask)
2991 ok(0, "unexpected call to SetStateBits\n");
2992 return E_NOTIMPL;
2995 static HRESULT WINAPI Storage_Stat(IStorage *iface, STATSTG *pstatstg, DWORD grfStatFlag)
2997 CHECK_EXPECT2(Storage_Stat);
2998 ok(pstatstg != NULL, "pstatstg = NULL\n");
2999 ok(grfStatFlag == STATFLAG_NONAME, "grfStatFlag = %x\n", grfStatFlag);
3001 memset(pstatstg, 0, sizeof(STATSTG));
3002 pstatstg->type = STGTY_STORAGE;
3003 pstatstg->clsid = CLSID_WineTestOld;
3004 return S_OK;
3007 static IStorageVtbl StorageVtbl =
3009 Storage_QueryInterface,
3010 Storage_AddRef,
3011 Storage_Release,
3012 Storage_CreateStream,
3013 Storage_OpenStream,
3014 Storage_CreateStorage,
3015 Storage_OpenStorage,
3016 Storage_CopyTo,
3017 Storage_MoveElementTo,
3018 Storage_Commit,
3019 Storage_Revert,
3020 Storage_EnumElements,
3021 Storage_DestroyElement,
3022 Storage_RenameElement,
3023 Storage_SetElementTimes,
3024 Storage_SetClass,
3025 Storage_SetStateBits,
3026 Storage_Stat
3029 static IStorage Storage = { &StorageVtbl };
3031 static void test_OleDoAutoConvert(void)
3033 static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0};
3034 static struct {
3035 DWORD reserved1;
3036 DWORD version;
3037 DWORD reserved2[5];
3038 DWORD ansi_user_type_len;
3039 DWORD ansi_clipboard_format_len;
3040 DWORD reserved3;
3041 DWORD unicode_marker;
3042 DWORD unicode_user_type_len;
3043 DWORD unicode_clipboard_format_len;
3044 DWORD reserved4;
3045 } comp_obj_data;
3046 static struct {
3047 DWORD version;
3048 DWORD flags;
3049 DWORD link_update_option;
3050 DWORD reserved1;
3051 DWORD reserved_moniker_stream_size;
3052 DWORD relative_source_moniker_stream_size;
3053 DWORD absolute_source_moniker_stream_size;
3054 DWORD clsid_indicator;
3055 CLSID clsid;
3056 DWORD reserved_display_name;
3057 DWORD reserved2;
3058 DWORD local_update_time;
3059 DWORD local_check_update_time;
3060 DWORD remote_update_time;
3061 } ole_data;
3063 LARGE_INTEGER pos = {{0}};
3064 WCHAR buf[39+6];
3065 DWORD i, ret;
3066 HKEY root;
3067 CLSID clsid;
3068 HRESULT hr;
3070 hr = CreateStreamOnHGlobal(NULL, TRUE, &comp_obj_stream);
3071 ok(hr == S_OK, "CreateStreamOnHGlobal returned %x\n", hr);
3072 hr = IStream_Write(comp_obj_stream, (char*)&comp_obj_data, sizeof(comp_obj_data), NULL);
3073 ok(hr == S_OK, "IStream_Write returned %x\n", hr);
3075 hr = CreateStreamOnHGlobal(NULL, TRUE, &ole_stream);
3076 ok(hr == S_OK, "CreateStreamOnHGlobal returned %x\n", hr);
3077 hr = IStream_Write(ole_stream, (char*)&ole_data, sizeof(ole_data), NULL);
3078 ok(hr == S_OK, "IStream_Write returned %x\n", hr);
3080 clsid = IID_WineTest;
3081 hr = OleDoAutoConvert(NULL, &clsid);
3082 ok(hr == E_INVALIDARG, "OleDoAutoConvert returned %x\n", hr);
3083 ok(IsEqualIID(&clsid, &IID_NULL), "clsid = %s\n", wine_dbgstr_guid(&clsid));
3085 if(0) /* crashes on Win7 */
3086 OleDoAutoConvert(&Storage, NULL);
3088 clsid = IID_WineTest;
3089 SET_EXPECT(Storage_Stat);
3090 hr = OleDoAutoConvert(&Storage, &clsid);
3091 ok(hr == REGDB_E_CLASSNOTREG, "OleDoAutoConvert returned %x\n", hr);
3092 CHECK_CALLED(Storage_Stat);
3093 ok(IsEqualIID(&clsid, &CLSID_WineTestOld), "clsid = %s\n", wine_dbgstr_guid(&clsid));
3095 lstrcpyW(buf, clsidW);
3096 StringFromGUID2(&CLSID_WineTestOld, buf+6, 39);
3098 ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, buf, 0, NULL, 0,
3099 KEY_READ | KEY_WRITE | KEY_CREATE_SUB_KEY, NULL, &root, NULL);
3100 if(ret != ERROR_SUCCESS) {
3101 win_skip("not enough permissions to create CLSID key (%u)\n", ret);
3102 return;
3105 clsid = IID_WineTest;
3106 SET_EXPECT(Storage_Stat);
3107 hr = OleDoAutoConvert(&Storage, &clsid);
3108 ok(hr == REGDB_E_KEYMISSING, "OleDoAutoConvert returned %x\n", hr);
3109 CHECK_CALLED(Storage_Stat);
3110 ok(IsEqualIID(&clsid, &CLSID_WineTestOld), "clsid = %s\n", wine_dbgstr_guid(&clsid));
3112 hr = OleSetAutoConvert(&CLSID_WineTestOld, &CLSID_WineTest);
3113 ok_ole_success(hr, "OleSetAutoConvert");
3115 hr = OleGetAutoConvert(&CLSID_WineTestOld, &clsid);
3116 ok_ole_success(hr, "OleGetAutoConvert");
3117 ok(IsEqualIID(&clsid, &CLSID_WineTest), "incorrect clsid: %s\n", wine_dbgstr_guid(&clsid));
3119 clsid = IID_WineTest;
3120 SET_EXPECT(Storage_Stat);
3121 SET_EXPECT(Storage_OpenStream_CompObj);
3122 SET_EXPECT(Storage_SetClass);
3123 SET_EXPECT(Storage_CreateStream_CompObj);
3124 SET_EXPECT(Storage_OpenStream_Ole);
3125 hr = OleDoAutoConvert(&Storage, &clsid);
3126 ok(hr == S_OK, "OleDoAutoConvert returned %x\n", hr);
3127 CHECK_CALLED(Storage_Stat);
3128 CHECK_CALLED(Storage_OpenStream_CompObj);
3129 CHECK_CALLED(Storage_SetClass);
3130 CHECK_CALLED(Storage_CreateStream_CompObj);
3131 CHECK_CALLED(Storage_OpenStream_Ole);
3132 ok(IsEqualIID(&clsid, &CLSID_WineTest), "clsid = %s\n", wine_dbgstr_guid(&clsid));
3134 hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL);
3135 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3136 hr = IStream_Read(comp_obj_stream, &comp_obj_data, sizeof(comp_obj_data), NULL);
3137 ok(hr == S_OK, "IStream_Read returned %x\n", hr);
3138 ok(comp_obj_data.reserved1 == 0xfffe0001, "reserved1 = %x\n", comp_obj_data.reserved1);
3139 ok(comp_obj_data.version == 0xa03, "version = %x\n", comp_obj_data.version);
3140 ok(comp_obj_data.reserved2[0] == -1, "reserved2[0] = %x\n", comp_obj_data.reserved2[0]);
3141 ok(IsEqualIID(comp_obj_data.reserved2+1, &CLSID_WineTestOld), "reserved2 = %s\n", wine_dbgstr_guid((CLSID*)(comp_obj_data.reserved2+1)));
3142 ok(!comp_obj_data.ansi_user_type_len, "ansi_user_type_len = %d\n", comp_obj_data.ansi_user_type_len);
3143 ok(!comp_obj_data.ansi_clipboard_format_len, "ansi_clipboard_format_len = %d\n", comp_obj_data.ansi_clipboard_format_len);
3144 ok(!comp_obj_data.reserved3, "reserved3 = %x\n", comp_obj_data.reserved3);
3145 ok(comp_obj_data.unicode_marker == 0x71b239f4, "unicode_marker = %x\n", comp_obj_data.unicode_marker);
3146 ok(!comp_obj_data.unicode_user_type_len, "unicode_user_type_len = %d\n", comp_obj_data.unicode_user_type_len);
3147 ok(!comp_obj_data.unicode_clipboard_format_len, "unicode_clipboard_format_len = %d\n", comp_obj_data.unicode_clipboard_format_len);
3148 ok(!comp_obj_data.reserved4, "reserved4 %d\n", comp_obj_data.reserved4);
3150 hr = IStream_Seek(ole_stream, pos, STREAM_SEEK_SET, NULL);
3151 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3152 hr = IStream_Read(ole_stream, &ole_data, sizeof(ole_data), NULL);
3153 ok(hr == S_OK, "IStream_Read returned %x\n", hr);
3154 ok(ole_data.version == 0, "version = %x\n", ole_data.version);
3155 ok(ole_data.flags == 4, "flags = %x\n", ole_data.flags);
3156 for(i=2; i<sizeof(ole_data)/sizeof(DWORD); i++)
3157 ok(((DWORD*)&ole_data)[i] == 0, "ole_data[%d] = %x\n", i, ((DWORD*)&ole_data)[i]);
3159 SET_EXPECT(Storage_OpenStream_Ole);
3160 hr = SetConvertStg(&Storage, TRUE);
3161 ok(hr == S_OK, "SetConvertStg returned %x\n", hr);
3162 CHECK_CALLED(Storage_OpenStream_Ole);
3164 SET_EXPECT(Storage_OpenStream_CompObj);
3165 SET_EXPECT(Storage_Stat);
3166 SET_EXPECT(Storage_CreateStream_CompObj);
3167 hr = WriteFmtUserTypeStg(&Storage, 0, NULL);
3168 ok(hr == S_OK, "WriteFmtUserTypeStg returned %x\n", hr);
3169 todo_wine CHECK_CALLED(Storage_OpenStream_CompObj);
3170 CHECK_CALLED(Storage_Stat);
3171 CHECK_CALLED(Storage_CreateStream_CompObj);
3172 hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL);
3173 ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3174 hr = IStream_Read(comp_obj_stream, &comp_obj_data, sizeof(comp_obj_data), NULL);
3175 ok(hr == S_OK, "IStream_Read returned %x\n", hr);
3176 ok(comp_obj_data.reserved1 == 0xfffe0001, "reserved1 = %x\n", comp_obj_data.reserved1);
3177 ok(comp_obj_data.version == 0xa03, "version = %x\n", comp_obj_data.version);
3178 ok(comp_obj_data.reserved2[0] == -1, "reserved2[0] = %x\n", comp_obj_data.reserved2[0]);
3179 ok(IsEqualIID(comp_obj_data.reserved2+1, &CLSID_WineTestOld), "reserved2 = %s\n", wine_dbgstr_guid((CLSID*)(comp_obj_data.reserved2+1)));
3180 ok(!comp_obj_data.ansi_user_type_len, "ansi_user_type_len = %d\n", comp_obj_data.ansi_user_type_len);
3181 ok(!comp_obj_data.ansi_clipboard_format_len, "ansi_clipboard_format_len = %d\n", comp_obj_data.ansi_clipboard_format_len);
3182 ok(!comp_obj_data.reserved3, "reserved3 = %x\n", comp_obj_data.reserved3);
3183 ok(comp_obj_data.unicode_marker == 0x71b239f4, "unicode_marker = %x\n", comp_obj_data.unicode_marker);
3184 ok(!comp_obj_data.unicode_user_type_len, "unicode_user_type_len = %d\n", comp_obj_data.unicode_user_type_len);
3185 ok(!comp_obj_data.unicode_clipboard_format_len, "unicode_clipboard_format_len = %d\n", comp_obj_data.unicode_clipboard_format_len);
3186 ok(!comp_obj_data.reserved4, "reserved4 %d\n", comp_obj_data.reserved4);
3188 ret = IStream_Release(comp_obj_stream);
3189 ok(!ret, "comp_obj_stream was not freed\n");
3190 ret = IStream_Release(ole_stream);
3191 ok(!ret, "ole_stream was not freed\n");
3193 ret = RegDeleteKeyA(root, "AutoConvertTo");
3194 ok(ret == ERROR_SUCCESS, "RegDeleteKey error %u\n", ret);
3195 ret = RegDeleteKeyA(root, "");
3196 ok(ret == ERROR_SUCCESS, "RegDeleteKey error %u\n", ret);
3197 RegCloseKey(root);
3200 /* 1x1 pixel bmp */
3201 static const unsigned char bmpimage[] =
3203 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,
3204 0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
3205 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
3206 0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
3207 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,
3208 0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
3209 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,
3210 0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
3211 0x00,0x00
3214 static const unsigned char mf_blank_bits[] =
3216 0x01,0x00,0x09,0x00,0x00,0x03,0x0c,0x00,
3217 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
3218 0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00
3221 static void test_data_cache_save(void)
3223 static const WCHAR contentsW[] = { 'C','o','n','t','e','n','t','s',0 };
3224 HRESULT hr;
3225 ILockBytes *ilb;
3226 IStorage *doc;
3227 IStream *stm;
3228 IOleCache2 *cache;
3229 IPersistStorage *stg;
3230 DWORD clipformat[2];
3231 PresentationDataHeader hdr;
3233 hr = CreateILockBytesOnHGlobal(0, TRUE, &ilb);
3234 ok(hr == S_OK, "unexpected %#x\n", hr);
3235 hr = StgCreateDocfileOnILockBytes(ilb, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &doc);
3236 ok(hr == S_OK, "unexpected %#x\n", hr);
3238 ILockBytes_Release(ilb);
3240 hr = IStorage_SetClass(doc, &CLSID_WineTest);
3241 ok(hr == S_OK, "unexpected %#x\n", hr);
3243 hr = IStorage_CreateStream(doc, contentsW, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3244 ok(hr == S_OK, "unexpected %#x\n", hr);
3245 hr = IStream_Write(stm, bmpimage, sizeof(bmpimage), NULL);
3246 ok(hr == S_OK, "unexpected %#x\n", hr);
3247 IStream_Release(stm);
3249 hr = IStorage_CreateStream(doc, olepres0W, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3250 ok(hr == S_OK, "unexpected %#x\n", hr);
3252 clipformat[0] = -1;
3253 clipformat[1] = CF_METAFILEPICT;
3254 hr = IStream_Write(stm, clipformat, sizeof(clipformat), NULL);
3255 ok(hr == S_OK, "unexpected %#x\n", hr);
3257 hdr.unknown3 = 4;
3258 hdr.dvAspect = DVASPECT_CONTENT;
3259 hdr.lindex = -1;
3260 hdr.advf = ADVF_PRIMEFIRST;
3261 hdr.unknown7 = 0;
3262 hdr.dwObjectExtentX = 0;
3263 hdr.dwObjectExtentY = 0;
3264 hdr.dwSize = sizeof(mf_blank_bits);
3265 hr = IStream_Write(stm, &hdr, sizeof(hdr), NULL);
3266 ok(hr == S_OK, "unexpected %#x\n", hr);
3267 hr = IStream_Write(stm, mf_blank_bits, sizeof(mf_blank_bits), NULL);
3268 ok(hr == S_OK, "unexpected %#x\n", hr);
3270 IStream_Release(stm);
3272 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IUnknown, (void **)&cache);
3273 ok(hr == S_OK, "unexpected %#x\n", hr);
3274 hr = IOleCache2_QueryInterface(cache, &IID_IPersistStorage, (void **)&stg);
3275 ok(hr == S_OK, "unexpected %#x\n", hr);
3276 hr = IPersistStorage_Load(stg, doc);
3277 ok(hr == S_OK, "unexpected %#x\n", hr);
3279 IStorage_Release(doc);
3281 hr = IPersistStorage_IsDirty(stg);
3282 ok(hr == S_FALSE, "unexpected %#x\n", hr);
3284 ole_stream = NULL;
3285 hr = CreateStreamOnHGlobal(NULL, TRUE, &olepres_stream);
3286 ok(hr == S_OK, "unexpected %#x\n", hr);
3288 /* FIXME: remove this stream once Wine is fixed */
3289 hr = CreateStreamOnHGlobal(NULL, TRUE, &contents_stream);
3290 ok(hr == S_OK, "unexpected %#x\n", hr);
3292 SET_EXPECT(Storage_CreateStream_OlePres);
3293 SET_EXPECT(Storage_OpenStream_OlePres);
3294 SET_EXPECT(Storage_OpenStream_Ole);
3295 SET_EXPECT(Storage_DestroyElement);
3296 Storage_DestroyElement_limit = 50;
3297 Storage_SetClass_CLSID = &CLSID_NULL;
3298 trace("IPersistStorage_Save:\n");
3299 hr = IPersistStorage_Save(stg, &Storage, FALSE);
3300 ok(hr == S_OK, "unexpected %#x\n", hr);
3301 CHECK_CALLED(Storage_CreateStream_OlePres);
3302 todo_wine
3303 CHECK_CALLED(Storage_OpenStream_OlePres);
3304 todo_wine
3305 CHECK_CALLED(Storage_OpenStream_Ole);
3306 todo_wine
3307 CHECK_CALLED(Storage_DestroyElement);
3309 IStream_Release(olepres_stream);
3310 IStream_Release(contents_stream);
3312 IPersistStorage_Release(stg);
3313 IOleCache2_Release(cache);
3316 #define MAX_STREAM 16
3318 struct stream_def
3320 const char *name;
3321 int cf;
3322 DVASPECT dvAspect;
3323 ADVF advf;
3324 const void *data;
3325 size_t data_size;
3328 struct storage_def
3330 const CLSID *clsid;
3331 int stream_count;
3332 struct stream_def stream[MAX_STREAM];
3335 static const struct storage_def stg_def_0 =
3337 &CLSID_NULL, 1,
3338 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) }}
3340 static const struct storage_def stg_def_0_saved =
3342 &CLSID_NULL, 0, {{ 0 }}
3344 static const struct storage_def stg_def_1 =
3346 &CLSID_NULL, 2,
3347 {{ "Contents", -1, 0, 0, NULL, 0 },
3348 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3350 static const struct storage_def stg_def_1_saved =
3352 &CLSID_NULL, 1,
3353 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3355 static const struct storage_def stg_def_2 =
3357 &CLSID_ManualResetEvent, 2,
3358 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3359 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3361 static const struct storage_def stg_def_2_saved =
3363 &CLSID_NULL, 1,
3364 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3366 static const struct storage_def stg_def_3 =
3368 &CLSID_NULL, 5,
3369 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3370 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3371 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3372 { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
3373 { "MyStream", -1, 0, 0, "Hello World!", 13 }}
3375 static const struct storage_def stg_def_3_saved =
3377 &CLSID_NULL, 3,
3378 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3379 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3380 { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) }}
3382 static const struct storage_def stg_def_4 =
3384 &CLSID_Picture_EnhMetafile, 5,
3385 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3386 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3387 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3388 { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
3389 { "MyStream", -1, 0, 0, "Hello World!", 13 }}
3391 static const struct storage_def stg_def_4_saved =
3393 &CLSID_NULL, 1,
3394 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3396 static const struct storage_def stg_def_5 =
3398 &CLSID_Picture_Dib, 5,
3399 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3400 { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
3401 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3402 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3403 { "MyStream", -1, 0, 0, "Hello World!", 13 }}
3405 static const struct storage_def stg_def_5_saved =
3407 &CLSID_NULL, 1,
3408 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3410 static const struct storage_def stg_def_6 =
3412 &CLSID_Picture_Metafile, 5,
3413 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3414 { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3415 { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3416 { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
3417 { "MyStream", -1, 0, 0, "Hello World!", 13 }}
3419 static const struct storage_def stg_def_6_saved =
3421 &CLSID_NULL, 1,
3422 {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3424 static const struct storage_def stg_def_7 =
3426 &CLSID_Picture_Dib, 1,
3427 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) }}
3429 static const struct storage_def stg_def_7_saved =
3431 &CLSID_NULL, 0, {{ 0 }}
3433 static const struct storage_def stg_def_8 =
3435 &CLSID_Picture_Metafile, 1,
3436 {{ "Contents", -1, 0, 0, mf_blank_bits, sizeof(mf_blank_bits) }}
3438 static const struct storage_def stg_def_8_saved =
3440 &CLSID_NULL, 0, {{ 0 }}
3442 static const struct storage_def stg_def_9 =
3444 &CLSID_Picture_EnhMetafile, 1,
3445 {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) }}
3447 static const struct storage_def stg_def_9_saved =
3449 &CLSID_NULL, 0, {{ 0 }}
3452 static int read_clipformat(IStream *stream)
3454 HRESULT hr;
3455 ULONG bytes;
3456 int length, clipformat = -2;
3458 hr = IStream_Read(stream, &length, sizeof(length), &bytes);
3459 if (hr != S_OK || bytes != sizeof(length))
3460 return -2;
3461 if (length == 0)
3462 return 0;
3463 if (length == -1)
3465 hr = IStream_Read(stream, &clipformat, sizeof(clipformat), &bytes);
3466 if (hr != S_OK || bytes != sizeof(clipformat))
3467 return -2;
3469 else
3470 ok(0, "unhandled clipformat length %d\n", length);
3472 return clipformat;
3475 static void check_storage_contents(IStorage *stg, const struct storage_def *stg_def,
3476 int *enumerated_streams, int *matched_streams)
3478 HRESULT hr;
3479 IEnumSTATSTG *enumstg;
3480 IStream *stream;
3481 STATSTG stat;
3482 int i, seen_stream[MAX_STREAM] = { 0 };
3484 if (winetest_debug > 1)
3485 trace("check_storage_contents:\n=============================================\n");
3487 *enumerated_streams = 0;
3488 *matched_streams = 0;
3490 hr = IStorage_Stat(stg, &stat, STATFLAG_NONAME);
3491 ok(hr == S_OK, "unexpected %#x\n", hr);
3492 ok(IsEqualCLSID(stg_def->clsid, &stat.clsid), "expected %s, got %s\n",
3493 wine_dbgstr_guid(stg_def->clsid), wine_dbgstr_guid(&stat.clsid));
3495 hr = IStorage_EnumElements(stg, 0, NULL, 0, &enumstg);
3496 ok(hr == S_OK, "unexpected %#x\n", hr);
3498 for (;;)
3500 ULONG bytes;
3501 int clipformat = -1;
3502 PresentationDataHeader header;
3503 char name[32];
3504 BYTE data[256];
3506 memset(&header, 0, sizeof(header));
3508 hr = IEnumSTATSTG_Next(enumstg, 1, &stat, NULL);
3509 if(hr == S_FALSE) break;
3510 ok(hr == S_OK, "unexpected %#x\n", hr);
3512 if (winetest_debug > 1)
3513 trace("name %s, type %u, size %d, clsid %s\n",
3514 wine_dbgstr_w(stat.pwcsName), stat.type, stat.cbSize.u.LowPart, wine_dbgstr_guid(&stat.clsid));
3516 ok(stat.type == STGTY_STREAM, "unexpected %#x\n", stat.type);
3518 WideCharToMultiByte(CP_ACP, 0, stat.pwcsName, -1, name, sizeof(name), NULL, NULL);
3520 hr = IStorage_OpenStream(stg, stat.pwcsName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream);
3521 ok(hr == S_OK, "unexpected %#x\n", hr);
3523 if (!memcmp(name, "\2OlePres", 7))
3525 clipformat = read_clipformat(stream);
3527 hr = IStream_Read(stream, &header, sizeof(header), &bytes);
3528 ok(hr == S_OK, "unexpected %#x\n", hr);
3529 ok(bytes >= 24, "read %u bytes\n", bytes);
3531 if (winetest_debug > 1)
3532 trace("header: unknown3 %#x, dvAspect %#x, lindex %#x, advf %#x, unknown7 %#x, dwObjectExtentX %#x, dwObjectExtentY %#x, dwSize %#x\n",
3533 header.unknown3, header.dvAspect, header.lindex, header.advf, header.unknown7,
3534 header.dwObjectExtentX, header.dwObjectExtentY, header.dwSize);
3537 memset(data, 0, sizeof(data));
3538 hr = IStream_Read(stream, data, sizeof(data), &bytes);
3539 ok(hr == S_OK, "unexpected %#x\n", hr);
3540 if (winetest_debug > 1)
3541 trace("stream data (%u bytes): %02x %02x %02x %02x\n", bytes, data[0], data[1], data[2], data[3]);
3543 for (i = 0; i < stg_def->stream_count; i++)
3545 if (seen_stream[i]) continue;
3547 if (winetest_debug > 1)
3548 trace("%s/%s, %d/%d, %d/%d, %d/%d\n",
3549 stg_def->stream[i].name, name,
3550 stg_def->stream[i].cf, clipformat,
3551 stg_def->stream[i].dvAspect, header.dvAspect,
3552 stg_def->stream[i].advf, header.advf);
3554 if (!strcmp(stg_def->stream[i].name, name) &&
3555 stg_def->stream[i].cf == clipformat &&
3556 stg_def->stream[i].dvAspect == header.dvAspect &&
3557 stg_def->stream[i].advf == header.advf &&
3558 stg_def->stream[i].data_size <= bytes &&
3559 (!stg_def->stream[i].data_size ||
3560 (!memcmp(stg_def->stream[i].data, data, min(stg_def->stream[i].data_size, bytes)))))
3562 if (winetest_debug > 1)
3563 trace("stream %d matches def stream %d\n", *enumerated_streams, i);
3564 seen_stream[i] = 1;
3565 *matched_streams += 1;
3569 CoTaskMemFree(stat.pwcsName);
3570 IStream_Release(stream);
3572 *enumerated_streams += 1;
3576 static IStorage *create_storage_from_def(const struct storage_def *stg_def)
3578 HRESULT hr;
3579 IStorage *stg;
3580 IStream *stm;
3581 int i;
3583 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &stg);
3584 ok(hr == S_OK, "unexpected %#x\n", hr);
3586 hr = IStorage_SetClass(stg, stg_def->clsid);
3587 ok(hr == S_OK, "unexpected %#x\n", hr);
3589 for (i = 0; i < stg_def->stream_count; i++)
3591 WCHAR name[32];
3593 MultiByteToWideChar(CP_ACP, 0, stg_def->stream[i].name, -1, name, 32);
3594 hr = IStorage_CreateStream(stg, name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3595 ok(hr == S_OK, "unexpected %#x\n", hr);
3597 if (stg_def->stream[i].cf != -1)
3599 int clipformat[2];
3600 PresentationDataHeader hdr;
3602 if (stg_def->stream[i].cf)
3604 clipformat[0] = -1;
3605 clipformat[1] = stg_def->stream[i].cf;
3606 hr = IStream_Write(stm, clipformat, sizeof(clipformat), NULL);
3608 else
3610 clipformat[0] = 0;
3611 hr = IStream_Write(stm, &clipformat[0], sizeof(clipformat[0]), NULL);
3613 ok(hr == S_OK, "unexpected %#x\n", hr);
3615 hdr.unknown3 = 4;
3616 hdr.dvAspect = stg_def->stream[i].dvAspect;
3617 hdr.lindex = -1;
3618 hdr.advf = stg_def->stream[i].advf;
3619 hdr.unknown7 = 0;
3620 hdr.dwObjectExtentX = 0;
3621 hdr.dwObjectExtentY = 0;
3622 hdr.dwSize = stg_def->stream[i].data_size;
3623 hr = IStream_Write(stm, &hdr, sizeof(hdr), NULL);
3624 ok(hr == S_OK, "unexpected %#x\n", hr);
3627 if (stg_def->stream[i].data_size)
3629 hr = IStream_Write(stm, stg_def->stream[i].data, stg_def->stream[i].data_size, NULL);
3630 ok(hr == S_OK, "unexpected %#x\n", hr);
3633 IStream_Release(stm);
3636 return stg;
3639 static void test_data_cache_contents(void)
3641 HRESULT hr;
3642 IStorage *doc1, *doc2;
3643 IOleCache2 *cache;
3644 IPersistStorage *stg;
3645 int i, enumerated_streams, matched_streams;
3646 static const struct
3648 const struct storage_def *in;
3649 const struct storage_def *out;
3650 } test_data[] =
3652 { &stg_def_0, &stg_def_0_saved },
3653 { &stg_def_1, &stg_def_1_saved },
3654 { &stg_def_2, &stg_def_2_saved },
3655 { &stg_def_3, &stg_def_3_saved },
3656 { &stg_def_4, &stg_def_4_saved },
3657 { &stg_def_5, &stg_def_5_saved },
3658 { &stg_def_6, &stg_def_6_saved },
3659 { &stg_def_7, &stg_def_7_saved },
3660 { &stg_def_8, &stg_def_8_saved },
3661 { &stg_def_9, &stg_def_9_saved },
3664 for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); i++)
3666 if (winetest_debug > 1)
3667 trace("start testing storage def %d\n", i);
3669 doc1 = create_storage_from_def(test_data[i].in);
3670 if (!doc1) continue;
3672 enumerated_streams = matched_streams = -1;
3673 check_storage_contents(doc1, test_data[i].in, &enumerated_streams, &matched_streams);
3674 ok(enumerated_streams == matched_streams, "%d in: enumerated %d != matched %d\n", i,
3675 enumerated_streams, matched_streams);
3676 ok(enumerated_streams == test_data[i].in->stream_count, "%d: created %d != def streams %d\n", i,
3677 enumerated_streams, test_data[i].in->stream_count);
3679 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IUnknown, (void **)&cache);
3680 ok(hr == S_OK, "unexpected %#x\n", hr);
3681 hr = IOleCache2_QueryInterface(cache, &IID_IPersistStorage, (void **)&stg);
3682 ok(hr == S_OK, "unexpected %#x\n", hr);
3683 hr = IPersistStorage_Load(stg, doc1);
3684 ok(hr == S_OK, "unexpected %#x\n", hr);
3686 IStorage_Release(doc1);
3688 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &doc2);
3689 ok(hr == S_OK, "unexpected %#x\n", hr);
3691 hr = IPersistStorage_IsDirty(stg);
3692 todo_wine_if(test_data[i].in == &stg_def_4 || test_data[i].in == &stg_def_8 || test_data[i].in == &stg_def_9)
3693 ok(hr == S_FALSE, "%d: unexpected %#x\n", i, hr);
3695 hr = IPersistStorage_Save(stg, doc2, FALSE);
3696 ok(hr == S_OK, "unexpected %#x\n", hr);
3698 IPersistStorage_Release(stg);
3700 enumerated_streams = matched_streams = -1;
3701 check_storage_contents(doc2, test_data[i].out, &enumerated_streams, &matched_streams);
3702 todo_wine_if(!(test_data[i].in == &stg_def_0 || test_data[i].in == &stg_def_1 || test_data[i].in == &stg_def_2))
3703 ok(enumerated_streams == matched_streams, "%d out: enumerated %d != matched %d\n", i,
3704 enumerated_streams, matched_streams);
3705 todo_wine_if(!(test_data[i].in == &stg_def_0 || test_data[i].in == &stg_def_5))
3706 ok(enumerated_streams == test_data[i].out->stream_count, "%d: saved streams %d != def streams %d\n", i,
3707 enumerated_streams, test_data[i].out->stream_count);
3709 IStorage_Release(doc2);
3711 if (winetest_debug > 1)
3712 trace("done testing storage def %d\n", i);
3716 START_TEST(ole2)
3718 DWORD dwRegister;
3719 IStorage *pStorage;
3720 STATSTG statstg;
3721 HRESULT hr;
3723 cf_test_1 = RegisterClipboardFormatA("cf_winetest_1");
3724 cf_test_2 = RegisterClipboardFormatA("cf_winetest_2");
3725 cf_test_3 = RegisterClipboardFormatA("cf_winetest_3");
3727 CoInitialize(NULL);
3729 hr = CoRegisterClassObject(&CLSID_Equation3, (IUnknown *)&OleObjectCF, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegister);
3730 ok_ole_success(hr, "CoRegisterClassObject");
3732 hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &pStorage);
3733 ok_ole_success(hr, "StgCreateDocfile");
3735 test_OleCreate(pStorage);
3737 hr = IStorage_Stat(pStorage, &statstg, STATFLAG_NONAME);
3738 ok_ole_success(hr, "IStorage_Stat");
3739 ok(IsEqualCLSID(&CLSID_Equation3, &statstg.clsid), "Wrong CLSID in storage\n");
3741 test_OleLoad(pStorage);
3743 IStorage_Release(pStorage);
3745 hr = CoRevokeClassObject(dwRegister);
3746 ok_ole_success(hr, "CoRevokeClassObject");
3748 Storage_SetClass_CLSID = &CLSID_WineTest;
3750 test_data_cache();
3751 test_data_cache_dib_contents_stream( 0 );
3752 test_data_cache_dib_contents_stream( 1 );
3753 test_data_cache_bitmap();
3754 test_data_cache_init();
3755 test_data_cache_initnew();
3756 test_default_handler();
3757 test_runnable();
3758 test_OleRun();
3759 test_OleLockRunning();
3760 test_OleDraw();
3761 test_OleDoAutoConvert();
3762 test_data_cache_save();
3763 test_data_cache_contents();
3765 CoUninitialize();