1 /*
2  * Object Linking and Embedding Tests
3  *
4  * Copyright 2005 Robert Shearman
5  * Copyright 2017 Dmitry Timoshkov
6  *
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.
11  *
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.
16  *
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
20  */
21 
22 #define COBJMACROS
23 #define CONST_VTABLE
24 #define WIN32_LEAN_AND_MEAN
25 
26 #include <stdarg.h>
27 
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "objbase.h"
32 #include "shlguid.h"
33 
34 #include "wine/test.h"
35 
36 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
37 
38 #define DEFINE_EXPECT(func) \
39     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
40 
41 #define SET_EXPECT(func) \
42     expect_ ## func = TRUE
43 
44 #define CHECK_EXPECT2(func) \
45     do { \
46         ok(expect_ ##func, "unexpected call " #func "\n"); \
47         called_ ## func = TRUE; \
48     }while(0)
49 
50 #define CHECK_EXPECT(func) \
51     do { \
52         CHECK_EXPECT2(func); \
53         expect_ ## func = FALSE; \
54     }while(0)
55 
56 #define CHECK_CALLED(func) \
57     do { \
58         ok(called_ ## func, "expected " #func "\n"); \
59         expect_ ## func = called_ ## func = FALSE; \
60     }while(0)
61 
62 DEFINE_EXPECT(Storage_Stat);
63 DEFINE_EXPECT(Storage_OpenStream_CompObj);
64 DEFINE_EXPECT(Storage_OpenStream_OlePres);
65 DEFINE_EXPECT(Storage_SetClass);
66 DEFINE_EXPECT(Storage_CreateStream_CompObj);
67 DEFINE_EXPECT(Storage_CreateStream_OlePres);
68 DEFINE_EXPECT(Storage_OpenStream_Ole);
69 DEFINE_EXPECT(Storage_DestroyElement);
70 
71 static const CLSID *Storage_SetClass_CLSID;
72 static int Storage_DestroyElement_limit;
73 
74 static IPersistStorage OleObjectPersistStg;
75 static IOleCache *cache;
76 static IRunnableObject *runnable;
77 
78 static const CLSID CLSID_WineTestOld =
79 { /* 9474ba1a-258b-490b-bc13-516e9239acd0 */
80     0x9474ba1a,
81     0x258b,
82     0x490b,
83     {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xd0}
84 };
85 
86 static const CLSID CLSID_WineTest =
87 { /* 9474ba1a-258b-490b-bc13-516e9239ace0 */
88     0x9474ba1a,
89     0x258b,
90     0x490b,
91     {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xe0}
92 };
93 
94 static const IID IID_WineTest =
95 { /* 9474ba1a-258b-490b-bc13-516e9239ace1 */
96     0x9474ba1a,
97     0x258b,
98     0x490b,
99     {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xe1}
100 };
101 
102 #define TEST_OPTIONAL 0x1
103 #define TEST_TODO     0x2
104 
105 struct expected_method
106 {
107     const char *method;
108     unsigned int flags;
109     FORMATETC fmt;
110 };
111 
112 static const struct expected_method *expected_method_list;
113 static FORMATETC *g_expected_fetc = NULL;
114 
115 static BOOL g_showRunnable = TRUE;
116 static BOOL g_isRunning = TRUE;
117 static HRESULT g_GetMiscStatusFailsWith = S_OK;
118 static HRESULT g_QIFailsWith;
119 
120 static UINT cf_test_1, cf_test_2, cf_test_3;
121 
122 static FORMATETC *g_dataobject_fmts;
123 
124 /****************************************************************************
125  * PresentationDataHeader
126  *
127  * This structure represents the header of the \002OlePresXXX stream in
128  * the OLE object storage.
129  */
130 typedef struct PresentationDataHeader
131 {
132     /* clipformat:
133      *  - standard clipformat:
134      *  DWORD length = 0xffffffff;
135      *  DWORD cfFormat;
136      *  - or custom clipformat:
137      *  DWORD length;
138      *  CHAR format_name[length]; (null-terminated)
139      */
140     DWORD tdSize; /* This is actually a truncated DVTARGETDEVICE, if tdSize > sizeof(DWORD)
141                      then there are tdSize - sizeof(DWORD) more bytes before dvAspect */
142     DVASPECT dvAspect;
143     DWORD lindex;
144     DWORD advf;
145     DWORD unknown7; /* 0 */
146     DWORD dwObjectExtentX;
147     DWORD dwObjectExtentY;
148     DWORD dwSize;
149 } PresentationDataHeader;
150 
151 #ifdef __REACTOS__
check_expected_method_fmt(const char * method_name,const FORMATETC * fmt)152 static inline void check_expected_method_fmt(const char *method_name, const FORMATETC *fmt)
153 #else
154 static void inline check_expected_method_fmt(const char *method_name, const FORMATETC *fmt)
155 #endif
156 {
157     trace("%s\n", method_name);
158     ok(expected_method_list->method != NULL, "Extra method %s called\n", method_name);
159     if (!strcmp(expected_method_list->method, "WINE_EXTRA"))
160     {
161         todo_wine ok(0, "Too many method calls.\n");
162         return;
163     }
164     if (expected_method_list->method)
165     {
166         while (expected_method_list->flags & TEST_OPTIONAL &&
167                strcmp(expected_method_list->method, method_name) != 0)
168             expected_method_list++;
169         todo_wine_if (expected_method_list->flags & TEST_TODO)
170         {
171             ok(!strcmp(expected_method_list->method, method_name),
172                "Expected %s to be called instead of %s\n",
173                expected_method_list->method, method_name);
174             if (fmt)
175             {
176                 ok(fmt->cfFormat == expected_method_list->fmt.cfFormat, "got cf %04x vs %04x\n",
177                    fmt->cfFormat, expected_method_list->fmt.cfFormat );
178                 ok(fmt->dwAspect == expected_method_list->fmt.dwAspect, "got aspect %d vs %d\n",
179                    fmt->dwAspect, expected_method_list->fmt.dwAspect );
180                 ok(fmt->lindex == expected_method_list->fmt.lindex, "got lindex %d vs %d\n",
181                    fmt->lindex, expected_method_list->fmt.lindex );
182                 ok(fmt->tymed == expected_method_list->fmt.tymed, "got tymed %d vs %d\n",
183                    fmt->tymed, expected_method_list->fmt.tymed );
184             }
185         }
186         expected_method_list++;
187     }
188 }
189 
190 #define CHECK_EXPECTED_METHOD(method_name) check_expected_method_fmt(method_name, NULL)
191 #define CHECK_EXPECTED_METHOD_FMT(method_name, fmt) check_expected_method_fmt(method_name, fmt)
192 
193 #define CHECK_NO_EXTRA_METHODS() \
194     do { \
195         while (expected_method_list->flags & TEST_OPTIONAL) \
196             expected_method_list++; \
197         ok(!expected_method_list->method, "Method sequence starting from %s not called\n", expected_method_list->method); \
198     } while (0)
199 
200 /* 2 x 1 x 32 bpp dib. PelsPerMeter = 200x400 */
201 static const BYTE dib[] =
202 {
203     0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
204     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00,
205     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206     0xc8, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
207     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
209 };
210 
create_dib(STGMEDIUM * med)211 static void create_dib( STGMEDIUM *med )
212 {
213     void *ptr;
214 
215     med->tymed = TYMED_HGLOBAL;
216     U(med)->hGlobal = GlobalAlloc( GMEM_MOVEABLE, sizeof(dib) );
217     ptr = GlobalLock( U(med)->hGlobal );
218     memcpy( ptr, dib, sizeof(dib) );
219     GlobalUnlock( U(med)->hGlobal );
220     med->pUnkForRelease = NULL;
221 }
222 
create_bitmap(STGMEDIUM * med)223 static void create_bitmap( STGMEDIUM *med )
224 {
225     med->tymed = TYMED_GDI;
226     U(med)->hBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
227     med->pUnkForRelease = NULL;
228 }
229 
create_emf(STGMEDIUM * med)230 static void create_emf(STGMEDIUM *med)
231 {
232     HDC hdc = CreateEnhMetaFileW(NULL, NULL, NULL, NULL);
233 
234     Rectangle(hdc, 0, 0, 150, 300);
235     med->tymed = TYMED_ENHMF;
236     U(med)->hEnhMetaFile = CloseEnhMetaFile(hdc);
237     med->pUnkForRelease = NULL;
238 }
239 
create_mfpict(STGMEDIUM * med)240 static void create_mfpict(STGMEDIUM *med)
241 {
242     METAFILEPICT *mf;
243     HDC hdc = CreateMetaFileW(NULL);
244 
245     Rectangle(hdc, 0, 0, 100, 200);
246 
247     med->tymed = TYMED_MFPICT;
248     U(med)->hMetaFilePict = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT));
249     mf = GlobalLock(U(med)->hMetaFilePict);
250     mf->mm = MM_ANISOTROPIC;
251     mf->xExt = 100;
252     mf->yExt = 200;
253     mf->hMF = CloseMetaFile(hdc);
254     GlobalUnlock(U(med)->hMetaFilePict);
255     med->pUnkForRelease = NULL;
256 }
257 
create_text(STGMEDIUM * med)258 static void create_text(STGMEDIUM *med)
259 {
260     HGLOBAL handle;
261     char *p;
262 
263     handle = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5);
264     p = GlobalLock(handle);
265     strcpy(p, "test");
266     GlobalUnlock(handle);
267 
268     med->tymed = TYMED_HGLOBAL;
269     U(med)->hGlobal = handle;
270     med->pUnkForRelease = NULL;
271 }
272 
OleObject_QueryInterface(IOleObject * iface,REFIID riid,void ** ppv)273 static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, void **ppv)
274 {
275     CHECK_EXPECTED_METHOD("OleObject_QueryInterface");
276 
277     *ppv = NULL;
278 
279     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IOleObject))
280         *ppv = iface;
281     else if (IsEqualIID(riid, &IID_IPersistStorage))
282         *ppv = &OleObjectPersistStg;
283     else if (IsEqualIID(riid, &IID_IOleCache))
284         *ppv = cache;
285     else if (IsEqualIID(riid, &IID_IRunnableObject) && g_showRunnable)
286         *ppv = runnable;
287     else if (IsEqualIID(riid, &IID_WineTest))
288         return g_QIFailsWith;
289 
290     if(*ppv) {
291         IUnknown_AddRef((IUnknown*)*ppv);
292         return S_OK;
293     }
294 
295     trace("OleObject_QueryInterface: returning E_NOINTERFACE\n");
296     return E_NOINTERFACE;
297 }
298 
OleObject_AddRef(IOleObject * iface)299 static ULONG WINAPI OleObject_AddRef(IOleObject *iface)
300 {
301     CHECK_EXPECTED_METHOD("OleObject_AddRef");
302     return 2;
303 }
304 
OleObject_Release(IOleObject * iface)305 static ULONG WINAPI OleObject_Release(IOleObject *iface)
306 {
307     CHECK_EXPECTED_METHOD("OleObject_Release");
308     return 1;
309 }
310 
OleObject_SetClientSite(IOleObject * iface,IOleClientSite * pClientSite)311 static HRESULT WINAPI OleObject_SetClientSite
312     (
313         IOleObject *iface,
314         IOleClientSite *pClientSite
315     )
316 {
317     CHECK_EXPECTED_METHOD("OleObject_SetClientSite");
318     return S_OK;
319 }
320 
OleObject_GetClientSite(IOleObject * iface,IOleClientSite ** ppClientSite)321 static HRESULT WINAPI OleObject_GetClientSite
322     (
323         IOleObject *iface,
324         IOleClientSite **ppClientSite
325     )
326 {
327     CHECK_EXPECTED_METHOD("OleObject_GetClientSite");
328     return E_NOTIMPL;
329 }
330 
OleObject_SetHostNames(IOleObject * iface,LPCOLESTR szContainerApp,LPCOLESTR szContainerObj)331 static HRESULT WINAPI OleObject_SetHostNames
332     (
333         IOleObject *iface,
334         LPCOLESTR szContainerApp,
335         LPCOLESTR szContainerObj
336     )
337 {
338     CHECK_EXPECTED_METHOD("OleObject_SetHostNames");
339     return S_OK;
340 }
341 
OleObject_Close(IOleObject * iface,DWORD dwSaveOption)342 static HRESULT WINAPI OleObject_Close
343     (
344         IOleObject *iface,
345         DWORD dwSaveOption
346     )
347 {
348     CHECK_EXPECTED_METHOD("OleObject_Close");
349     return S_OK;
350 }
351 
OleObject_SetMoniker(IOleObject * iface,DWORD dwWhichMoniker,IMoniker * pmk)352 static HRESULT WINAPI OleObject_SetMoniker
353     (
354         IOleObject *iface,
355         DWORD dwWhichMoniker,
356         IMoniker *pmk
357     )
358 {
359     CHECK_EXPECTED_METHOD("OleObject_SetMoniker");
360     return S_OK;
361 }
362 
OleObject_GetMoniker(IOleObject * iface,DWORD dwAssign,DWORD dwWhichMoniker,IMoniker ** ppmk)363 static HRESULT WINAPI OleObject_GetMoniker
364     (
365         IOleObject *iface,
366         DWORD dwAssign,
367         DWORD dwWhichMoniker,
368         IMoniker **ppmk
369     )
370 {
371     CHECK_EXPECTED_METHOD("OleObject_GetMoniker");
372     return S_OK;
373 }
374 
OleObject_InitFromData(IOleObject * iface,IDataObject * pDataObject,BOOL fCreation,DWORD dwReserved)375 static HRESULT WINAPI OleObject_InitFromData
376     (
377         IOleObject *iface,
378         IDataObject *pDataObject,
379         BOOL fCreation,
380         DWORD dwReserved
381     )
382 {
383     CHECK_EXPECTED_METHOD("OleObject_InitFromData");
384     return S_OK;
385 }
386 
OleObject_GetClipboardData(IOleObject * iface,DWORD dwReserved,IDataObject ** ppDataObject)387 static HRESULT WINAPI OleObject_GetClipboardData
388     (
389         IOleObject *iface,
390         DWORD dwReserved,
391         IDataObject **ppDataObject
392     )
393 {
394     CHECK_EXPECTED_METHOD("OleObject_GetClipboardData");
395     return E_NOTIMPL;
396 }
397 
OleObject_DoVerb(IOleObject * iface,LONG iVerb,LPMSG lpmsg,IOleClientSite * pActiveSite,LONG lindex,HWND hwndParent,LPCRECT lprcPosRect)398 static HRESULT WINAPI OleObject_DoVerb
399     (
400         IOleObject *iface,
401         LONG iVerb,
402         LPMSG lpmsg,
403         IOleClientSite *pActiveSite,
404         LONG lindex,
405         HWND hwndParent,
406         LPCRECT lprcPosRect
407     )
408 {
409     CHECK_EXPECTED_METHOD("OleObject_DoVerb");
410     return S_OK;
411 }
412 
OleObject_EnumVerbs(IOleObject * iface,IEnumOLEVERB ** ppEnumOleVerb)413 static HRESULT WINAPI OleObject_EnumVerbs
414     (
415         IOleObject *iface,
416         IEnumOLEVERB **ppEnumOleVerb
417     )
418 {
419     CHECK_EXPECTED_METHOD("OleObject_EnumVerbs");
420     return E_NOTIMPL;
421 }
422 
OleObject_Update(IOleObject * iface)423 static HRESULT WINAPI OleObject_Update
424     (
425         IOleObject *iface
426     )
427 {
428     CHECK_EXPECTED_METHOD("OleObject_Update");
429     return S_OK;
430 }
431 
OleObject_IsUpToDate(IOleObject * iface)432 static HRESULT WINAPI OleObject_IsUpToDate
433     (
434         IOleObject *iface
435     )
436 {
437     CHECK_EXPECTED_METHOD("OleObject_IsUpToDate");
438     return S_OK;
439 }
440 
OleObject_GetUserClassID(IOleObject * iface,CLSID * pClsid)441 static HRESULT WINAPI OleObject_GetUserClassID
442 (
443     IOleObject *iface,
444     CLSID *pClsid
445 )
446 {
447     CHECK_EXPECTED_METHOD("OleObject_GetUserClassID");
448     return E_NOTIMPL;
449 }
450 
OleObject_GetUserType(IOleObject * iface,DWORD dwFormOfType,LPOLESTR * pszUserType)451 static HRESULT WINAPI OleObject_GetUserType
452 (
453     IOleObject *iface,
454     DWORD dwFormOfType,
455     LPOLESTR *pszUserType
456 )
457 {
458     CHECK_EXPECTED_METHOD("OleObject_GetUserType");
459     return E_NOTIMPL;
460 }
461 
OleObject_SetExtent(IOleObject * iface,DWORD dwDrawAspect,SIZEL * psizel)462 static HRESULT WINAPI OleObject_SetExtent
463 (
464     IOleObject *iface,
465     DWORD dwDrawAspect,
466     SIZEL *psizel
467 )
468 {
469     CHECK_EXPECTED_METHOD("OleObject_SetExtent");
470     return S_OK;
471 }
472 
OleObject_GetExtent(IOleObject * iface,DWORD dwDrawAspect,SIZEL * psizel)473 static HRESULT WINAPI OleObject_GetExtent
474 (
475     IOleObject *iface,
476     DWORD dwDrawAspect,
477     SIZEL *psizel
478 )
479 {
480     CHECK_EXPECTED_METHOD("OleObject_GetExtent");
481     return E_NOTIMPL;
482 }
483 
OleObject_Advise(IOleObject * iface,IAdviseSink * pAdvSink,DWORD * pdwConnection)484 static HRESULT WINAPI OleObject_Advise
485 (
486     IOleObject *iface,
487     IAdviseSink *pAdvSink,
488     DWORD *pdwConnection
489 )
490 {
491     CHECK_EXPECTED_METHOD("OleObject_Advise");
492     return S_OK;
493 }
494 
OleObject_Unadvise(IOleObject * iface,DWORD dwConnection)495 static HRESULT WINAPI OleObject_Unadvise
496 (
497     IOleObject *iface,
498     DWORD dwConnection
499 )
500 {
501     CHECK_EXPECTED_METHOD("OleObject_Unadvise");
502     return S_OK;
503 }
504 
OleObject_EnumAdvise(IOleObject * iface,IEnumSTATDATA ** ppenumAdvise)505 static HRESULT WINAPI OleObject_EnumAdvise
506 (
507     IOleObject *iface,
508     IEnumSTATDATA **ppenumAdvise
509 )
510 {
511     CHECK_EXPECTED_METHOD("OleObject_EnumAdvise");
512     return E_NOTIMPL;
513 }
514 
OleObject_GetMiscStatus(IOleObject * iface,DWORD aspect,DWORD * pdwStatus)515 static HRESULT WINAPI OleObject_GetMiscStatus
516 (
517     IOleObject *iface,
518     DWORD aspect,
519     DWORD *pdwStatus
520 )
521 {
522     CHECK_EXPECTED_METHOD("OleObject_GetMiscStatus");
523 
524     ok(aspect == DVASPECT_CONTENT, "got aspect %d\n", aspect);
525 
526     if (g_GetMiscStatusFailsWith == S_OK)
527     {
528         *pdwStatus = OLEMISC_RECOMPOSEONRESIZE;
529         return S_OK;
530     }
531     else
532     {
533         *pdwStatus = 0x1234;
534         return g_GetMiscStatusFailsWith;
535     }
536 }
537 
OleObject_SetColorScheme(IOleObject * iface,LOGPALETTE * pLogpal)538 static HRESULT WINAPI OleObject_SetColorScheme
539 (
540     IOleObject *iface,
541     LOGPALETTE *pLogpal
542 )
543 {
544     CHECK_EXPECTED_METHOD("OleObject_SetColorScheme");
545     return E_NOTIMPL;
546 }
547 
548 static const IOleObjectVtbl OleObjectVtbl =
549 {
550     OleObject_QueryInterface,
551     OleObject_AddRef,
552     OleObject_Release,
553     OleObject_SetClientSite,
554     OleObject_GetClientSite,
555     OleObject_SetHostNames,
556     OleObject_Close,
557     OleObject_SetMoniker,
558     OleObject_GetMoniker,
559     OleObject_InitFromData,
560     OleObject_GetClipboardData,
561     OleObject_DoVerb,
562     OleObject_EnumVerbs,
563     OleObject_Update,
564     OleObject_IsUpToDate,
565     OleObject_GetUserClassID,
566     OleObject_GetUserType,
567     OleObject_SetExtent,
568     OleObject_GetExtent,
569     OleObject_Advise,
570     OleObject_Unadvise,
571     OleObject_EnumAdvise,
572     OleObject_GetMiscStatus,
573     OleObject_SetColorScheme
574 };
575 
576 static IOleObject OleObject = { &OleObjectVtbl };
577 
OleObjectPersistStg_QueryInterface(IPersistStorage * iface,REFIID riid,void ** ppv)578 static HRESULT WINAPI OleObjectPersistStg_QueryInterface(IPersistStorage *iface, REFIID riid, void **ppv)
579 {
580     trace("OleObjectPersistStg_QueryInterface\n");
581     return IOleObject_QueryInterface(&OleObject, riid, ppv);
582 }
583 
OleObjectPersistStg_AddRef(IPersistStorage * iface)584 static ULONG WINAPI OleObjectPersistStg_AddRef(IPersistStorage *iface)
585 {
586     CHECK_EXPECTED_METHOD("OleObjectPersistStg_AddRef");
587     return 2;
588 }
589 
OleObjectPersistStg_Release(IPersistStorage * iface)590 static ULONG WINAPI OleObjectPersistStg_Release(IPersistStorage *iface)
591 {
592     CHECK_EXPECTED_METHOD("OleObjectPersistStg_Release");
593     return 1;
594 }
595 
OleObjectPersistStg_GetClassId(IPersistStorage * iface,CLSID * clsid)596 static HRESULT WINAPI OleObjectPersistStg_GetClassId(IPersistStorage *iface, CLSID *clsid)
597 {
598     CHECK_EXPECTED_METHOD("OleObjectPersistStg_GetClassId");
599     return E_NOTIMPL;
600 }
601 
OleObjectPersistStg_IsDirty(IPersistStorage * iface)602 static HRESULT WINAPI OleObjectPersistStg_IsDirty
603 (
604     IPersistStorage *iface
605 )
606 {
607     CHECK_EXPECTED_METHOD("OleObjectPersistStg_IsDirty");
608     return S_OK;
609 }
610 
OleObjectPersistStg_InitNew(IPersistStorage * iface,IStorage * pStg)611 static HRESULT WINAPI OleObjectPersistStg_InitNew
612 (
613     IPersistStorage *iface,
614     IStorage *pStg
615 )
616 {
617     CHECK_EXPECTED_METHOD("OleObjectPersistStg_InitNew");
618     return S_OK;
619 }
620 
OleObjectPersistStg_Load(IPersistStorage * iface,IStorage * pStg)621 static HRESULT WINAPI OleObjectPersistStg_Load
622 (
623     IPersistStorage *iface,
624     IStorage *pStg
625 )
626 {
627     CHECK_EXPECTED_METHOD("OleObjectPersistStg_Load");
628     return S_OK;
629 }
630 
OleObjectPersistStg_Save(IPersistStorage * iface,IStorage * pStgSave,BOOL fSameAsLoad)631 static HRESULT WINAPI OleObjectPersistStg_Save
632 (
633     IPersistStorage *iface,
634     IStorage *pStgSave,
635     BOOL fSameAsLoad
636 )
637 {
638     CHECK_EXPECTED_METHOD("OleObjectPersistStg_Save");
639     return S_OK;
640 }
641 
OleObjectPersistStg_SaveCompleted(IPersistStorage * iface,IStorage * pStgNew)642 static HRESULT WINAPI OleObjectPersistStg_SaveCompleted
643 (
644     IPersistStorage *iface,
645     IStorage *pStgNew
646 )
647 {
648     CHECK_EXPECTED_METHOD("OleObjectPersistStg_SaveCompleted");
649     return S_OK;
650 }
651 
OleObjectPersistStg_HandsOffStorage(IPersistStorage * iface)652 static HRESULT WINAPI OleObjectPersistStg_HandsOffStorage
653 (
654     IPersistStorage *iface
655 )
656 {
657     CHECK_EXPECTED_METHOD("OleObjectPersistStg_HandsOffStorage");
658     return S_OK;
659 }
660 
661 static const IPersistStorageVtbl OleObjectPersistStgVtbl =
662 {
663     OleObjectPersistStg_QueryInterface,
664     OleObjectPersistStg_AddRef,
665     OleObjectPersistStg_Release,
666     OleObjectPersistStg_GetClassId,
667     OleObjectPersistStg_IsDirty,
668     OleObjectPersistStg_InitNew,
669     OleObjectPersistStg_Load,
670     OleObjectPersistStg_Save,
671     OleObjectPersistStg_SaveCompleted,
672     OleObjectPersistStg_HandsOffStorage
673 };
674 
675 static IPersistStorage OleObjectPersistStg = { &OleObjectPersistStgVtbl };
676 
OleObjectCache_QueryInterface(IOleCache * iface,REFIID riid,void ** ppv)677 static HRESULT WINAPI OleObjectCache_QueryInterface(IOleCache *iface, REFIID riid, void **ppv)
678 {
679     return IOleObject_QueryInterface(&OleObject, riid, ppv);
680 }
681 
OleObjectCache_AddRef(IOleCache * iface)682 static ULONG WINAPI OleObjectCache_AddRef(IOleCache *iface)
683 {
684     CHECK_EXPECTED_METHOD("OleObjectCache_AddRef");
685     return 2;
686 }
687 
OleObjectCache_Release(IOleCache * iface)688 static ULONG WINAPI OleObjectCache_Release(IOleCache *iface)
689 {
690     CHECK_EXPECTED_METHOD("OleObjectCache_Release");
691     return 1;
692 }
693 
OleObjectCache_Cache(IOleCache * iface,FORMATETC * pformatetc,DWORD advf,DWORD * pdwConnection)694 static HRESULT WINAPI OleObjectCache_Cache
695 (
696     IOleCache *iface,
697     FORMATETC *pformatetc,
698     DWORD advf,
699     DWORD *pdwConnection
700 )
701 {
702     CHECK_EXPECTED_METHOD("OleObjectCache_Cache");
703     if (g_expected_fetc) {
704         ok(pformatetc != NULL, "pformatetc should not be NULL\n");
705         if (pformatetc) {
706             ok(pformatetc->cfFormat == g_expected_fetc->cfFormat,
707                     "cfFormat: %x\n", pformatetc->cfFormat);
708             ok((pformatetc->ptd != NULL) == (g_expected_fetc->ptd != NULL),
709                     "ptd: %p\n", pformatetc->ptd);
710             ok(pformatetc->dwAspect == g_expected_fetc->dwAspect,
711                     "dwAspect: %x\n", pformatetc->dwAspect);
712             ok(pformatetc->lindex == g_expected_fetc->lindex,
713                     "lindex: %x\n", pformatetc->lindex);
714             ok(pformatetc->tymed == g_expected_fetc->tymed,
715                     "tymed: %x\n", pformatetc->tymed);
716         }
717     } else
718         ok(pformatetc == NULL, "pformatetc should be NULL\n");
719     return S_OK;
720 }
721 
OleObjectCache_Uncache(IOleCache * iface,DWORD dwConnection)722 static HRESULT WINAPI OleObjectCache_Uncache
723 (
724     IOleCache *iface,
725     DWORD dwConnection
726 )
727 {
728     CHECK_EXPECTED_METHOD("OleObjectCache_Uncache");
729     return S_OK;
730 }
731 
OleObjectCache_EnumCache(IOleCache * iface,IEnumSTATDATA ** ppenumSTATDATA)732 static HRESULT WINAPI OleObjectCache_EnumCache
733 (
734     IOleCache *iface,
735     IEnumSTATDATA **ppenumSTATDATA
736 )
737 {
738     CHECK_EXPECTED_METHOD("OleObjectCache_EnumCache");
739     return S_OK;
740 }
741 
742 
OleObjectCache_InitCache(IOleCache * iface,IDataObject * pDataObject)743 static HRESULT WINAPI OleObjectCache_InitCache
744 (
745     IOleCache *iface,
746     IDataObject *pDataObject
747 )
748 {
749     CHECK_EXPECTED_METHOD("OleObjectCache_InitCache");
750     return S_OK;
751 }
752 
753 
OleObjectCache_SetData(IOleCache * iface,FORMATETC * pformatetc,STGMEDIUM * pmedium,BOOL fRelease)754 static HRESULT WINAPI OleObjectCache_SetData
755 (
756     IOleCache *iface,
757     FORMATETC *pformatetc,
758     STGMEDIUM *pmedium,
759     BOOL fRelease
760 )
761 {
762     CHECK_EXPECTED_METHOD("OleObjectCache_SetData");
763     return S_OK;
764 }
765 
766 
767 static const IOleCacheVtbl OleObjectCacheVtbl =
768 {
769     OleObjectCache_QueryInterface,
770     OleObjectCache_AddRef,
771     OleObjectCache_Release,
772     OleObjectCache_Cache,
773     OleObjectCache_Uncache,
774     OleObjectCache_EnumCache,
775     OleObjectCache_InitCache,
776     OleObjectCache_SetData
777 };
778 
779 static IOleCache OleObjectCache = { &OleObjectCacheVtbl };
780 
OleObjectCF_QueryInterface(IClassFactory * iface,REFIID riid,void ** ppv)781 static HRESULT WINAPI OleObjectCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
782 {
783     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
784     {
785         *ppv = iface;
786         IClassFactory_AddRef(iface);
787         return S_OK;
788     }
789     *ppv = NULL;
790     return E_NOINTERFACE;
791 }
792 
OleObjectCF_AddRef(IClassFactory * iface)793 static ULONG WINAPI OleObjectCF_AddRef(IClassFactory *iface)
794 {
795     return 2;
796 }
797 
OleObjectCF_Release(IClassFactory * iface)798 static ULONG WINAPI OleObjectCF_Release(IClassFactory *iface)
799 {
800     return 1;
801 }
802 
OleObjectCF_CreateInstance(IClassFactory * iface,IUnknown * punkOuter,REFIID riid,void ** ppv)803 static HRESULT WINAPI OleObjectCF_CreateInstance(IClassFactory *iface, IUnknown *punkOuter, REFIID riid, void **ppv)
804 {
805     return IOleObject_QueryInterface(&OleObject, riid, ppv);
806 }
807 
OleObjectCF_LockServer(IClassFactory * iface,BOOL lock)808 static HRESULT WINAPI OleObjectCF_LockServer(IClassFactory *iface, BOOL lock)
809 {
810     return S_OK;
811 }
812 
813 static const IClassFactoryVtbl OleObjectCFVtbl =
814 {
815     OleObjectCF_QueryInterface,
816     OleObjectCF_AddRef,
817     OleObjectCF_Release,
818     OleObjectCF_CreateInstance,
819     OleObjectCF_LockServer
820 };
821 
822 static IClassFactory OleObjectCF = { &OleObjectCFVtbl };
823 
OleObjectRunnable_QueryInterface(IRunnableObject * iface,REFIID riid,void ** ppv)824 static HRESULT WINAPI OleObjectRunnable_QueryInterface(IRunnableObject *iface, REFIID riid, void **ppv)
825 {
826     return IOleObject_QueryInterface(&OleObject, riid, ppv);
827 }
828 
OleObjectRunnable_AddRef(IRunnableObject * iface)829 static ULONG WINAPI OleObjectRunnable_AddRef(IRunnableObject *iface)
830 {
831     CHECK_EXPECTED_METHOD("OleObjectRunnable_AddRef");
832     return 2;
833 }
834 
OleObjectRunnable_Release(IRunnableObject * iface)835 static ULONG WINAPI OleObjectRunnable_Release(IRunnableObject *iface)
836 {
837     CHECK_EXPECTED_METHOD("OleObjectRunnable_Release");
838     return 1;
839 }
840 
OleObjectRunnable_GetRunningClass(IRunnableObject * iface,LPCLSID lpClsid)841 static HRESULT WINAPI OleObjectRunnable_GetRunningClass(
842     IRunnableObject *iface,
843     LPCLSID lpClsid)
844 {
845     CHECK_EXPECTED_METHOD("OleObjectRunnable_GetRunningClass");
846     return E_NOTIMPL;
847 }
848 
OleObjectRunnable_Run(IRunnableObject * iface,LPBINDCTX pbc)849 static HRESULT WINAPI OleObjectRunnable_Run(
850     IRunnableObject *iface,
851     LPBINDCTX pbc)
852 {
853     CHECK_EXPECTED_METHOD("OleObjectRunnable_Run");
854     return S_OK;
855 }
856 
OleObjectRunnable_IsRunning(IRunnableObject * iface)857 static BOOL WINAPI OleObjectRunnable_IsRunning(IRunnableObject *iface)
858 {
859     CHECK_EXPECTED_METHOD("OleObjectRunnable_IsRunning");
860     return g_isRunning;
861 }
862 
OleObjectRunnable_LockRunning(IRunnableObject * iface,BOOL fLock,BOOL fLastUnlockCloses)863 static HRESULT WINAPI OleObjectRunnable_LockRunning(
864     IRunnableObject *iface,
865     BOOL fLock,
866     BOOL fLastUnlockCloses)
867 {
868     CHECK_EXPECTED_METHOD("OleObjectRunnable_LockRunning");
869     return S_OK;
870 }
871 
OleObjectRunnable_SetContainedObject(IRunnableObject * iface,BOOL fContained)872 static HRESULT WINAPI OleObjectRunnable_SetContainedObject(
873     IRunnableObject *iface,
874     BOOL fContained)
875 {
876     CHECK_EXPECTED_METHOD("OleObjectRunnable_SetContainedObject");
877     return S_OK;
878 }
879 
880 static const IRunnableObjectVtbl OleObjectRunnableVtbl =
881 {
882     OleObjectRunnable_QueryInterface,
883     OleObjectRunnable_AddRef,
884     OleObjectRunnable_Release,
885     OleObjectRunnable_GetRunningClass,
886     OleObjectRunnable_Run,
887     OleObjectRunnable_IsRunning,
888     OleObjectRunnable_LockRunning,
889     OleObjectRunnable_SetContainedObject
890 };
891 
892 static IRunnableObject OleObjectRunnable = { &OleObjectRunnableVtbl };
893 
894 static const CLSID CLSID_Equation3 = {0x0002CE02, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
895 
viewobject_QueryInterface(IViewObject * iface,REFIID riid,void ** obj)896 static HRESULT WINAPI viewobject_QueryInterface(IViewObject *iface, REFIID riid, void **obj)
897 {
898     if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IViewObject))
899     {
900         *obj = iface;
901         return S_OK;
902     }
903 
904     *obj = NULL;
905     return E_NOINTERFACE;
906 }
907 
viewobject_AddRef(IViewObject * iface)908 static ULONG WINAPI viewobject_AddRef(IViewObject *iface)
909 {
910     return 2;
911 }
912 
viewobject_Release(IViewObject * iface)913 static ULONG WINAPI viewobject_Release(IViewObject *iface)
914 {
915     return 1;
916 }
917 
viewobject_Draw(IViewObject * iface,DWORD aspect,LONG index,void * paspect,DVTARGETDEVICE * ptd,HDC hdcTargetDev,HDC hdcDraw,LPCRECTL bounds,LPCRECTL wbounds,BOOL (STDMETHODCALLTYPE * pfnContinue)(ULONG_PTR dwContinue),ULONG_PTR dwContinue)918 static HRESULT WINAPI viewobject_Draw(IViewObject *iface, DWORD aspect, LONG index,
919     void *paspect, DVTARGETDEVICE *ptd, HDC hdcTargetDev, HDC hdcDraw,
920     LPCRECTL bounds, LPCRECTL wbounds, BOOL (STDMETHODCALLTYPE *pfnContinue)(ULONG_PTR dwContinue),
921     ULONG_PTR dwContinue)
922 {
923     ok(index == -1, "index=%d\n", index);
924     return S_OK;
925 }
926 
viewobject_GetColorSet(IViewObject * iface,DWORD draw_aspect,LONG index,void * aspect,DVTARGETDEVICE * ptd,HDC hicTargetDev,LOGPALETTE ** colorset)927 static HRESULT WINAPI viewobject_GetColorSet(IViewObject *iface, DWORD draw_aspect, LONG index,
928     void *aspect, DVTARGETDEVICE *ptd, HDC hicTargetDev, LOGPALETTE **colorset)
929 {
930     ok(0, "unexpected call GetColorSet\n");
931     return E_NOTIMPL;
932 }
933 
viewobject_Freeze(IViewObject * iface,DWORD draw_aspect,LONG index,void * aspect,DWORD * freeze)934 static HRESULT WINAPI viewobject_Freeze(IViewObject *iface, DWORD draw_aspect, LONG index,
935     void *aspect, DWORD *freeze)
936 {
937     ok(0, "unexpected call Freeze\n");
938     return E_NOTIMPL;
939 }
940 
viewobject_Unfreeze(IViewObject * iface,DWORD freeze)941 static HRESULT WINAPI viewobject_Unfreeze(IViewObject *iface, DWORD freeze)
942 {
943     ok(0, "unexpected call Unfreeze\n");
944     return E_NOTIMPL;
945 }
946 
viewobject_SetAdvise(IViewObject * iface,DWORD aspects,DWORD advf,IAdviseSink * sink)947 static HRESULT WINAPI viewobject_SetAdvise(IViewObject *iface, DWORD aspects, DWORD advf, IAdviseSink *sink)
948 {
949     ok(0, "unexpected call SetAdvise\n");
950     return E_NOTIMPL;
951 }
952 
viewobject_GetAdvise(IViewObject * iface,DWORD * aspects,DWORD * advf,IAdviseSink ** sink)953 static HRESULT WINAPI viewobject_GetAdvise(IViewObject *iface, DWORD *aspects, DWORD *advf,
954     IAdviseSink **sink)
955 {
956     ok(0, "unexpected call GetAdvise\n");
957     return E_NOTIMPL;
958 }
959 
960 static const struct IViewObjectVtbl viewobjectvtbl = {
961     viewobject_QueryInterface,
962     viewobject_AddRef,
963     viewobject_Release,
964     viewobject_Draw,
965     viewobject_GetColorSet,
966     viewobject_Freeze,
967     viewobject_Unfreeze,
968     viewobject_SetAdvise,
969     viewobject_GetAdvise
970 };
971 
972 static IViewObject viewobject = { &viewobjectvtbl };
973 
test_OleCreate(IStorage * pStorage)974 static void test_OleCreate(IStorage *pStorage)
975 {
976     HRESULT hr;
977     IOleObject *pObject;
978     FORMATETC formatetc;
979     static const struct expected_method methods_olerender_none[] =
980     {
981         { "OleObject_QueryInterface", 0 },
982         { "OleObject_AddRef", 0 },
983         { "OleObject_QueryInterface", 0 },
984         { "OleObject_AddRef", TEST_OPTIONAL },
985         { "OleObject_Release", TEST_OPTIONAL },
986         { "OleObject_QueryInterface", TEST_OPTIONAL },
987         { "OleObjectPersistStg_AddRef", 0 },
988         { "OleObjectPersistStg_InitNew", 0 },
989         { "OleObjectPersistStg_Release", 0 },
990         { "OleObject_Release", 0 },
991         { "OleObject_Release", TEST_OPTIONAL },
992         { NULL, 0 }
993     };
994     static const struct expected_method methods_olerender_draw[] =
995     {
996         { "OleObject_QueryInterface", 0 },
997         { "OleObject_AddRef", 0 },
998         { "OleObject_QueryInterface", 0 },
999         { "OleObject_AddRef", TEST_OPTIONAL /* NT4 only */ },
1000         { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1001         { "OleObject_QueryInterface", TEST_OPTIONAL /* NT4 only */ },
1002         { "OleObjectPersistStg_AddRef", 0 },
1003         { "OleObjectPersistStg_InitNew", 0 },
1004         { "OleObjectPersistStg_Release", 0 },
1005         { "OleObject_QueryInterface", 0 },
1006         { "OleObjectRunnable_AddRef", 0 },
1007         { "OleObjectRunnable_Run", 0 },
1008         { "OleObjectRunnable_Release", 0 },
1009         { "OleObject_QueryInterface", 0 },
1010         { "OleObjectCache_AddRef", 0 },
1011         { "OleObjectCache_Cache", 0 },
1012         { "OleObjectCache_Release", 0 },
1013         { "OleObject_Release", 0 },
1014         { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1015         { NULL, 0 }
1016     };
1017     static const struct expected_method methods_olerender_draw_with_site[] =
1018     {
1019         { "OleObject_QueryInterface", 0 },
1020         { "OleObject_AddRef", 0 },
1021         { "OleObject_QueryInterface", 0 },
1022         { "OleObject_AddRef", 0 },
1023         { "OleObject_GetMiscStatus", 0 },
1024         { "OleObject_QueryInterface", 0 },
1025         { "OleObjectPersistStg_AddRef", 0 },
1026         { "OleObjectPersistStg_InitNew", 0 },
1027         { "OleObjectPersistStg_Release", 0 },
1028         { "OleObject_SetClientSite", 0 },
1029         { "OleObject_Release", 0 },
1030         { "OleObject_QueryInterface", 0 },
1031         { "OleObjectRunnable_AddRef", 0 },
1032         { "OleObjectRunnable_Run", 0 },
1033         { "OleObjectRunnable_Release", 0 },
1034         { "OleObject_QueryInterface", 0 },
1035         { "OleObjectCache_AddRef", 0 },
1036         { "OleObjectCache_Cache", 0 },
1037         { "OleObjectCache_Release", 0 },
1038         { "OleObject_Release", 0 },
1039         { NULL, 0 }
1040     };
1041     static const struct expected_method methods_olerender_format[] =
1042     {
1043         { "OleObject_QueryInterface", 0 },
1044         { "OleObject_AddRef", 0 },
1045         { "OleObject_QueryInterface", 0 },
1046         { "OleObject_AddRef", 0 },
1047         { "OleObject_GetMiscStatus", 0 },
1048         { "OleObject_QueryInterface", 0 },
1049         { "OleObjectPersistStg_AddRef", 0 },
1050         { "OleObjectPersistStg_InitNew", 0 },
1051         { "OleObjectPersistStg_Release", 0 },
1052         { "OleObject_SetClientSite", 0 },
1053         { "OleObject_Release", 0 },
1054         { "OleObject_QueryInterface", 0 },
1055         { "OleObjectRunnable_AddRef", 0 },
1056         { "OleObjectRunnable_Run", 0 },
1057         { "OleObjectRunnable_Release", 0 },
1058         { "OleObject_QueryInterface", 0 },
1059         { "OleObjectCache_AddRef", 0 },
1060         { "OleObjectCache_Cache", 0 },
1061         { "OleObjectCache_Release", 0 },
1062         { "OleObject_Release", 0 },
1063         { NULL, 0 }
1064     };
1065     static const struct expected_method methods_olerender_asis[] =
1066     {
1067         { "OleObject_QueryInterface", 0 },
1068         { "OleObject_AddRef", 0 },
1069         { "OleObject_QueryInterface", 0 },
1070         { "OleObject_AddRef", TEST_OPTIONAL /* NT4 only */ },
1071         { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1072         { "OleObject_QueryInterface", TEST_OPTIONAL /* NT4 only */ },
1073         { "OleObjectPersistStg_AddRef", 0 },
1074         { "OleObjectPersistStg_InitNew", 0 },
1075         { "OleObjectPersistStg_Release", 0 },
1076         { "OleObject_Release", 0 },
1077         { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1078         { NULL, 0 }
1079     };
1080     static const struct expected_method methods_olerender_draw_no_runnable[] =
1081     {
1082         { "OleObject_QueryInterface", 0 },
1083         { "OleObject_AddRef", 0 },
1084         { "OleObject_QueryInterface", 0 },
1085         { "OleObject_AddRef", TEST_OPTIONAL /* NT4 only */ },
1086         { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1087         { "OleObject_QueryInterface", TEST_OPTIONAL /* NT4 only */ },
1088         { "OleObjectPersistStg_AddRef", 0 },
1089         { "OleObjectPersistStg_InitNew", 0 },
1090         { "OleObjectPersistStg_Release", 0 },
1091         { "OleObject_QueryInterface", 0 },
1092         { "OleObject_QueryInterface", 0 },
1093         { "OleObjectCache_AddRef", 0 },
1094         { "OleObjectCache_Cache", 0 },
1095         { "OleObjectCache_Release", 0 },
1096         { "OleObject_Release", 0 },
1097         { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1098         { NULL, 0 },
1099     };
1100     static const struct expected_method methods_olerender_draw_no_cache[] =
1101     {
1102         { "OleObject_QueryInterface", 0 },
1103         { "OleObject_AddRef", 0 },
1104         { "OleObject_QueryInterface", 0 },
1105         { "OleObject_AddRef", TEST_OPTIONAL /* NT4 only */ },
1106         { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1107         { "OleObject_QueryInterface", TEST_OPTIONAL /* NT4 only */ },
1108         { "OleObjectPersistStg_AddRef", 0 },
1109         { "OleObjectPersistStg_InitNew", 0 },
1110         { "OleObjectPersistStg_Release", 0 },
1111         { "OleObject_QueryInterface", 0 },
1112         { "OleObjectRunnable_AddRef", 0 },
1113         { "OleObjectRunnable_Run", 0 },
1114         { "OleObjectRunnable_Release", 0 },
1115         { "OleObject_QueryInterface", 0 },
1116         { "OleObject_Release", 0 },
1117         { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1118         { NULL, 0 }
1119     };
1120 
1121     g_expected_fetc = &formatetc;
1122     formatetc.cfFormat = 0;
1123     formatetc.ptd = NULL;
1124     formatetc.dwAspect = DVASPECT_CONTENT;
1125     formatetc.lindex = -1;
1126     formatetc.tymed = TYMED_NULL;
1127     runnable = &OleObjectRunnable;
1128     cache = &OleObjectCache;
1129     expected_method_list = methods_olerender_none;
1130     trace("OleCreate with OLERENDER_NONE:\n");
1131     hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_NONE, NULL, NULL, pStorage, (void **)&pObject);
1132     ok_ole_success(hr, "OleCreate");
1133     IOleObject_Release(pObject);
1134     CHECK_NO_EXTRA_METHODS();
1135 
1136     expected_method_list = methods_olerender_draw;
1137     trace("OleCreate with OLERENDER_DRAW:\n");
1138     hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, NULL, pStorage, (void **)&pObject);
1139     ok_ole_success(hr, "OleCreate");
1140     IOleObject_Release(pObject);
1141     CHECK_NO_EXTRA_METHODS();
1142 
1143     expected_method_list = methods_olerender_draw_with_site;
1144     trace("OleCreate with OLERENDER_DRAW, with site:\n");
1145     hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, (IOleClientSite*)0xdeadbeef, pStorage, (void **)&pObject);
1146     ok_ole_success(hr, "OleCreate");
1147     IOleObject_Release(pObject);
1148     CHECK_NO_EXTRA_METHODS();
1149 
1150     /* GetMiscStatus fails */
1151     g_GetMiscStatusFailsWith = 0x8fafefaf;
1152     expected_method_list = methods_olerender_draw_with_site;
1153     trace("OleCreate with OLERENDER_DRAW, with site:\n");
1154     hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, (IOleClientSite*)0xdeadbeef, pStorage, (void **)&pObject);
1155     ok_ole_success(hr, "OleCreate");
1156     IOleObject_Release(pObject);
1157     CHECK_NO_EXTRA_METHODS();
1158     g_GetMiscStatusFailsWith = S_OK;
1159 
1160     formatetc.cfFormat = CF_TEXT;
1161     formatetc.ptd = NULL;
1162     formatetc.dwAspect = DVASPECT_CONTENT;
1163     formatetc.lindex = -1;
1164     formatetc.tymed = TYMED_HGLOBAL;
1165     expected_method_list = methods_olerender_format;
1166     trace("OleCreate with OLERENDER_FORMAT:\n");
1167     hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_FORMAT, &formatetc, (IOleClientSite *)0xdeadbeef, pStorage, (void **)&pObject);
1168     ok(hr == S_OK ||
1169        broken(hr == E_INVALIDARG), /* win2k */
1170        "OleCreate failed with error 0x%08x\n", hr);
1171     if (pObject)
1172     {
1173         IOleObject_Release(pObject);
1174         CHECK_NO_EXTRA_METHODS();
1175     }
1176 
1177     expected_method_list = methods_olerender_asis;
1178     trace("OleCreate with OLERENDER_ASIS:\n");
1179     hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_ASIS, NULL, NULL, pStorage, (void **)&pObject);
1180     ok_ole_success(hr, "OleCreate");
1181     IOleObject_Release(pObject);
1182     CHECK_NO_EXTRA_METHODS();
1183 
1184     formatetc.cfFormat = 0;
1185     formatetc.tymed = TYMED_NULL;
1186     runnable = NULL;
1187     expected_method_list = methods_olerender_draw_no_runnable;
1188     trace("OleCreate with OLERENDER_DRAW (no IRunnableObject):\n");
1189     hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, NULL, pStorage, (void **)&pObject);
1190     ok_ole_success(hr, "OleCreate");
1191     IOleObject_Release(pObject);
1192     CHECK_NO_EXTRA_METHODS();
1193 
1194     runnable = &OleObjectRunnable;
1195     cache = NULL;
1196     expected_method_list = methods_olerender_draw_no_cache;
1197     trace("OleCreate with OLERENDER_DRAW (no IOleCache):\n");
1198     hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, NULL, pStorage, (void **)&pObject);
1199     ok_ole_success(hr, "OleCreate");
1200     IOleObject_Release(pObject);
1201     CHECK_NO_EXTRA_METHODS();
1202     trace("end\n");
1203     g_expected_fetc = NULL;
1204 }
1205 
test_OleLoad(IStorage * pStorage)1206 static void test_OleLoad(IStorage *pStorage)
1207 {
1208     HRESULT hr;
1209     IOleObject *pObject;
1210     DWORD fmt;
1211 
1212     static const struct expected_method methods_oleload[] =
1213     {
1214         { "OleObject_QueryInterface", 0 },
1215         { "OleObject_AddRef", 0 },
1216         { "OleObject_QueryInterface", 0 },
1217         { "OleObject_AddRef", 0 },
1218         { "OleObject_GetMiscStatus", 0 },
1219         { "OleObject_QueryInterface", 0 },
1220         { "OleObjectPersistStg_AddRef", 0 },
1221         { "OleObjectPersistStg_Load", 0 },
1222         { "OleObjectPersistStg_Release", 0 },
1223         { "OleObject_SetClientSite", 0 },
1224         { "OleObject_Release", 0 },
1225         { "OleObject_QueryInterface", 0 },
1226         { "OleObject_GetMiscStatus", 0 },
1227         { "OleObject_Release", 0 },
1228         { NULL, 0 }
1229     };
1230 
1231     /* Test once with IOleObject_GetMiscStatus failing */
1232     expected_method_list = methods_oleload;
1233     g_GetMiscStatusFailsWith = E_FAIL;
1234     trace("OleLoad:\n");
1235     hr = OleLoad(pStorage, &IID_IOleObject, (IOleClientSite *)0xdeadbeef, (void **)&pObject);
1236     ok(hr == S_OK ||
1237        broken(hr == E_INVALIDARG), /* win98 and win2k */
1238        "OleLoad failed with error 0x%08x\n", hr);
1239     if(pObject)
1240     {
1241         DWORD dwStatus = 0xdeadbeef;
1242         hr = IOleObject_GetMiscStatus(pObject, DVASPECT_CONTENT, &dwStatus);
1243         ok(hr == E_FAIL, "Got 0x%08x\n", hr);
1244         ok(dwStatus == 0x1234, "Got 0x%08x\n", dwStatus);
1245 
1246         IOleObject_Release(pObject);
1247         CHECK_NO_EXTRA_METHODS();
1248     }
1249     g_GetMiscStatusFailsWith = S_OK;
1250 
1251     /* Test again, let IOleObject_GetMiscStatus succeed. */
1252     expected_method_list = methods_oleload;
1253     trace("OleLoad:\n");
1254     hr = OleLoad(pStorage, &IID_IOleObject, (IOleClientSite *)0xdeadbeef, (void **)&pObject);
1255     ok(hr == S_OK ||
1256        broken(hr == E_INVALIDARG), /* win98 and win2k */
1257        "OleLoad failed with error 0x%08x\n", hr);
1258     if (pObject)
1259     {
1260         DWORD dwStatus = 0xdeadbeef;
1261         hr = IOleObject_GetMiscStatus(pObject, DVASPECT_CONTENT, &dwStatus);
1262         ok(hr == S_OK, "Got 0x%08x\n", hr);
1263         ok(dwStatus == 1, "Got 0x%08x\n", dwStatus);
1264 
1265         IOleObject_Release(pObject);
1266         CHECK_NO_EXTRA_METHODS();
1267     }
1268 
1269     for (fmt = CF_TEXT; fmt < CF_MAX; fmt++)
1270     {
1271         static const WCHAR olrepres[] = { 2,'O','l','e','P','r','e','s','0','0','0',0 };
1272         IStorage *stg;
1273         IStream *stream;
1274         IUnknown *obj;
1275         DWORD data, i, data_size;
1276         PresentationDataHeader header;
1277         HDC hdc;
1278         HGDIOBJ hobj;
1279         RECT rc;
1280         char buf[256];
1281 
1282         for (i = 0; i < 7; i++)
1283         {
1284             hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &stg);
1285             ok(hr == S_OK, "StgCreateDocfile error %#x\n", hr);
1286 
1287             hr = IStorage_SetClass(stg, &CLSID_WineTest);
1288             ok(hr == S_OK, "SetClass error %#x\n", hr);
1289 
1290             hr = IStorage_CreateStream(stg, olrepres, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, &stream);
1291             ok(hr == S_OK, "CreateStream error %#x\n", hr);
1292 
1293             data = ~0;
1294             hr = IStream_Write(stream, &data, sizeof(data), NULL);
1295             ok(hr == S_OK, "Write error %#x\n", hr);
1296 
1297             data = fmt;
1298             hr = IStream_Write(stream, &data, sizeof(data), NULL);
1299             ok(hr == S_OK, "Write error %#x\n", hr);
1300 
1301             switch (fmt)
1302             {
1303             case CF_BITMAP:
1304                 /* FIXME: figure out stream format */
1305                 hobj = CreateBitmap(1, 1, 1, 1, NULL);
1306                 data_size = GetBitmapBits(hobj, sizeof(buf), buf);
1307                 DeleteObject(hobj);
1308                 break;
1309 
1310             case CF_METAFILEPICT:
1311             case CF_ENHMETAFILE:
1312                 hdc = CreateMetaFileA(NULL);
1313                 hobj = CloseMetaFile(hdc);
1314                 data_size = GetMetaFileBitsEx(hobj, sizeof(buf), buf);
1315                 DeleteMetaFile(hobj);
1316                 break;
1317 
1318             default:
1319                 data_size = sizeof(buf);
1320                 memset(buf, 'A', sizeof(buf));
1321                 break;
1322             }
1323 
1324             header.tdSize = sizeof(header.tdSize);
1325             header.dvAspect = DVASPECT_CONTENT;
1326             header.lindex = -1;
1327             header.advf = 1 << i;
1328             header.unknown7 = 0;
1329             header.dwObjectExtentX = 1;
1330             header.dwObjectExtentY = 1;
1331             header.dwSize = data_size;
1332             hr = IStream_Write(stream, &header, sizeof(header), NULL);
1333             ok(hr == S_OK, "Write error %#x\n", hr);
1334 
1335             hr = IStream_Write(stream, buf, data_size, NULL);
1336             ok(hr == S_OK, "Write error %#x\n", hr);
1337 
1338             IStream_Release(stream);
1339 
1340             hr = OleLoad(stg, &IID_IUnknown, NULL, (void **)&obj);
1341             /* FIXME: figure out stream format */
1342             if (fmt == CF_BITMAP && hr != S_OK)
1343             {
1344                 IStorage_Release(stg);
1345                 continue;
1346             }
1347             ok(hr == S_OK, "OleLoad error %#x: cfFormat = %u, advf = %#x\n", hr, fmt, header.advf);
1348 
1349             hdc = CreateCompatibleDC(0);
1350             SetRect(&rc, 0, 0, 100, 100);
1351             hr = OleDraw(obj, DVASPECT_CONTENT, hdc, &rc);
1352             DeleteDC(hdc);
1353             if (fmt == CF_METAFILEPICT)
1354                 ok(hr == S_OK, "OleDraw error %#x: cfFormat = %u, advf = %#x\n", hr, fmt, header.advf);
1355             else if (fmt == CF_ENHMETAFILE)
1356 todo_wine
1357                 ok(hr == S_OK, "OleDraw error %#x: cfFormat = %u, advf = %#x\n", hr, fmt, header.advf);
1358             else
1359                 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);
1360 
1361             IUnknown_Release(obj);
1362             IStorage_Release(stg);
1363         }
1364     }
1365 }
1366 
draw_continue(ULONG_PTR param)1367 static BOOL STDMETHODCALLTYPE draw_continue(ULONG_PTR param)
1368 {
1369     CHECK_EXPECTED_METHOD("draw_continue");
1370     return TRUE;
1371 }
1372 
draw_continue_false(ULONG_PTR param)1373 static BOOL STDMETHODCALLTYPE draw_continue_false(ULONG_PTR param)
1374 {
1375     CHECK_EXPECTED_METHOD("draw_continue_false");
1376     return FALSE;
1377 }
1378 
AdviseSink_QueryInterface(IAdviseSink * iface,REFIID riid,void ** ppv)1379 static HRESULT WINAPI AdviseSink_QueryInterface(IAdviseSink *iface, REFIID riid, void **ppv)
1380 {
1381     if (IsEqualIID(riid, &IID_IAdviseSink) || IsEqualIID(riid, &IID_IUnknown))
1382     {
1383         *ppv = iface;
1384         IAdviseSink_AddRef(iface);
1385         return S_OK;
1386     }
1387     *ppv = NULL;
1388     return E_NOINTERFACE;
1389 }
1390 
AdviseSink_AddRef(IAdviseSink * iface)1391 static ULONG WINAPI AdviseSink_AddRef(IAdviseSink *iface)
1392 {
1393     return 2;
1394 }
1395 
AdviseSink_Release(IAdviseSink * iface)1396 static ULONG WINAPI AdviseSink_Release(IAdviseSink *iface)
1397 {
1398     return 1;
1399 }
1400 
1401 
AdviseSink_OnDataChange(IAdviseSink * iface,FORMATETC * pFormatetc,STGMEDIUM * pStgmed)1402 static void WINAPI AdviseSink_OnDataChange(
1403     IAdviseSink *iface,
1404     FORMATETC *pFormatetc,
1405     STGMEDIUM *pStgmed)
1406 {
1407     CHECK_EXPECTED_METHOD("AdviseSink_OnDataChange");
1408 }
1409 
AdviseSink_OnViewChange(IAdviseSink * iface,DWORD dwAspect,LONG lindex)1410 static void WINAPI AdviseSink_OnViewChange(
1411     IAdviseSink *iface,
1412     DWORD dwAspect,
1413     LONG lindex)
1414 {
1415     CHECK_EXPECTED_METHOD("AdviseSink_OnViewChange");
1416 }
1417 
AdviseSink_OnRename(IAdviseSink * iface,IMoniker * pmk)1418 static void WINAPI AdviseSink_OnRename(
1419     IAdviseSink *iface,
1420     IMoniker *pmk)
1421 {
1422     CHECK_EXPECTED_METHOD("AdviseSink_OnRename");
1423 }
1424 
AdviseSink_OnSave(IAdviseSink * iface)1425 static void WINAPI AdviseSink_OnSave(IAdviseSink *iface)
1426 {
1427     CHECK_EXPECTED_METHOD("AdviseSink_OnSave");
1428 }
1429 
AdviseSink_OnClose(IAdviseSink * iface)1430 static void WINAPI AdviseSink_OnClose(IAdviseSink *iface)
1431 {
1432     CHECK_EXPECTED_METHOD("AdviseSink_OnClose");
1433 }
1434 
1435 static const IAdviseSinkVtbl AdviseSinkVtbl =
1436 {
1437     AdviseSink_QueryInterface,
1438     AdviseSink_AddRef,
1439     AdviseSink_Release,
1440     AdviseSink_OnDataChange,
1441     AdviseSink_OnViewChange,
1442     AdviseSink_OnRename,
1443     AdviseSink_OnSave,
1444     AdviseSink_OnClose
1445 };
1446 
1447 static IAdviseSink AdviseSink = { &AdviseSinkVtbl };
1448 
DataObject_QueryInterface(IDataObject * iface,REFIID riid,void ** ppvObject)1449 static HRESULT WINAPI DataObject_QueryInterface(
1450             IDataObject*     iface,
1451             REFIID           riid,
1452             void**           ppvObject)
1453 {
1454     CHECK_EXPECTED_METHOD("DataObject_QueryInterface");
1455 
1456     if (IsEqualIID(riid, &IID_IDataObject) || IsEqualIID(riid, &IID_IUnknown))
1457     {
1458         *ppvObject = iface;
1459         return S_OK;
1460     }
1461     *ppvObject = NULL;
1462     return S_OK;
1463 }
1464 
DataObject_AddRef(IDataObject * iface)1465 static ULONG WINAPI DataObject_AddRef(
1466             IDataObject*     iface)
1467 {
1468     CHECK_EXPECTED_METHOD("DataObject_AddRef");
1469     return 2;
1470 }
1471 
DataObject_Release(IDataObject * iface)1472 static ULONG WINAPI DataObject_Release(
1473             IDataObject*     iface)
1474 {
1475     CHECK_EXPECTED_METHOD("DataObject_Release");
1476     return 1;
1477 }
1478 
fmtetc_equal(const FORMATETC * a,const FORMATETC * b)1479 static inline BOOL fmtetc_equal( const FORMATETC *a, const FORMATETC *b )
1480 {
1481     /* FIXME ptd */
1482     return a->cfFormat == b->cfFormat && a->dwAspect == b->dwAspect &&
1483         a->lindex == b->lindex && a->tymed == b->tymed;
1484 
1485 }
1486 
DataObject_GetData(IDataObject * iface,FORMATETC * fmt_in,STGMEDIUM * med)1487 static HRESULT WINAPI DataObject_GetData( IDataObject *iface, FORMATETC *fmt_in,
1488                                           STGMEDIUM *med )
1489 {
1490     FORMATETC *fmt;
1491 
1492     CHECK_EXPECTED_METHOD_FMT("DataObject_GetData", fmt_in);
1493 
1494     for (fmt = g_dataobject_fmts; fmt && fmt->cfFormat != 0; fmt++)
1495     {
1496         if (fmtetc_equal( fmt_in, fmt ))
1497         {
1498             switch (fmt->cfFormat)
1499             {
1500             case CF_DIB:
1501                 create_dib( med );
1502                 return S_OK;
1503             case CF_BITMAP:
1504                 create_bitmap( med );
1505                 return S_OK;
1506             case CF_ENHMETAFILE:
1507                 create_emf( med );
1508                 return S_OK;
1509             case CF_TEXT:
1510                 create_text( med );
1511                 return S_OK;
1512             default:
1513                 trace( "unhandled fmt %d\n", fmt->cfFormat );
1514             }
1515         }
1516     }
1517 
1518     return S_FALSE;
1519 }
1520 
DataObject_GetDataHere(IDataObject * iface,LPFORMATETC pformatetc,STGMEDIUM * pmedium)1521 static HRESULT WINAPI DataObject_GetDataHere(
1522         IDataObject*     iface,
1523         LPFORMATETC      pformatetc,
1524         STGMEDIUM*       pmedium)
1525 {
1526     CHECK_EXPECTED_METHOD("DataObject_GetDataHere");
1527     return E_NOTIMPL;
1528 }
1529 
DataObject_QueryGetData(IDataObject * iface,FORMATETC * fmt_in)1530 static HRESULT WINAPI DataObject_QueryGetData( IDataObject *iface, FORMATETC *fmt_in )
1531 {
1532     FORMATETC *fmt;
1533 
1534     CHECK_EXPECTED_METHOD_FMT("DataObject_QueryGetData", fmt_in);
1535 
1536     for (fmt = g_dataobject_fmts; fmt && fmt->cfFormat != 0; fmt++)
1537         if (fmtetc_equal( fmt_in, fmt )) return S_OK;
1538 
1539     return S_FALSE;
1540 }
1541 
DataObject_GetCanonicalFormatEtc(IDataObject * iface,LPFORMATETC pformatectIn,LPFORMATETC pformatetcOut)1542 static HRESULT WINAPI DataObject_GetCanonicalFormatEtc(
1543         IDataObject*     iface,
1544         LPFORMATETC      pformatectIn,
1545         LPFORMATETC      pformatetcOut)
1546 {
1547     CHECK_EXPECTED_METHOD("DataObject_GetCanonicalFormatEtc");
1548     return E_NOTIMPL;
1549 }
1550 
DataObject_SetData(IDataObject * iface,LPFORMATETC pformatetc,STGMEDIUM * pmedium,BOOL fRelease)1551 static HRESULT WINAPI DataObject_SetData(
1552         IDataObject*     iface,
1553         LPFORMATETC      pformatetc,
1554         STGMEDIUM*       pmedium,
1555         BOOL             fRelease)
1556 {
1557     CHECK_EXPECTED_METHOD("DataObject_SetData");
1558     return E_NOTIMPL;
1559 }
1560 
DataObject_EnumFormatEtc(IDataObject * iface,DWORD dwDirection,IEnumFORMATETC ** ppenumFormatEtc)1561 static HRESULT WINAPI DataObject_EnumFormatEtc(
1562         IDataObject*     iface,
1563         DWORD            dwDirection,
1564         IEnumFORMATETC** ppenumFormatEtc)
1565 {
1566     CHECK_EXPECTED_METHOD("DataObject_EnumFormatEtc");
1567     return E_NOTIMPL;
1568 }
1569 
DataObject_DAdvise(IDataObject * iface,FORMATETC * pformatetc,DWORD advf,IAdviseSink * pAdvSink,DWORD * pdwConnection)1570 static HRESULT WINAPI DataObject_DAdvise(
1571         IDataObject*     iface,
1572         FORMATETC*       pformatetc,
1573         DWORD            advf,
1574         IAdviseSink*     pAdvSink,
1575         DWORD*           pdwConnection)
1576 {
1577     STGMEDIUM stgmedium;
1578 
1579     CHECK_EXPECTED_METHOD("DataObject_DAdvise");
1580     *pdwConnection = 1;
1581 
1582     if(advf & ADVF_PRIMEFIRST)
1583     {
1584         ok(pformatetc->cfFormat == cf_test_2, "got %04x\n", pformatetc->cfFormat);
1585         stgmedium.tymed = TYMED_HGLOBAL;
1586         U(stgmedium).hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 4);
1587         stgmedium.pUnkForRelease = NULL;
1588         IAdviseSink_OnDataChange(pAdvSink, pformatetc, &stgmedium);
1589     }
1590 
1591     return S_OK;
1592 }
1593 
DataObject_DUnadvise(IDataObject * iface,DWORD dwConnection)1594 static HRESULT WINAPI DataObject_DUnadvise(
1595         IDataObject*     iface,
1596         DWORD            dwConnection)
1597 {
1598     CHECK_EXPECTED_METHOD("DataObject_DUnadvise");
1599     return S_OK;
1600 }
1601 
DataObject_EnumDAdvise(IDataObject * iface,IEnumSTATDATA ** ppenumAdvise)1602 static HRESULT WINAPI DataObject_EnumDAdvise(
1603         IDataObject*     iface,
1604         IEnumSTATDATA**  ppenumAdvise)
1605 {
1606     CHECK_EXPECTED_METHOD("DataObject_EnumDAdvise");
1607     return OLE_E_ADVISENOTSUPPORTED;
1608 }
1609 
1610 static IDataObjectVtbl DataObjectVtbl =
1611 {
1612     DataObject_QueryInterface,
1613     DataObject_AddRef,
1614     DataObject_Release,
1615     DataObject_GetData,
1616     DataObject_GetDataHere,
1617     DataObject_QueryGetData,
1618     DataObject_GetCanonicalFormatEtc,
1619     DataObject_SetData,
1620     DataObject_EnumFormatEtc,
1621     DataObject_DAdvise,
1622     DataObject_DUnadvise,
1623     DataObject_EnumDAdvise
1624 };
1625 
1626 static IDataObject DataObject = { &DataObjectVtbl };
1627 
Unknown_QueryInterface(IUnknown * iface,REFIID riid,void ** ppv)1628 static HRESULT WINAPI Unknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1629 {
1630     *ppv = NULL;
1631     if (IsEqualIID(riid, &IID_IUnknown)) *ppv = iface;
1632     if (*ppv)
1633     {
1634         IUnknown_AddRef((IUnknown *)*ppv);
1635         return S_OK;
1636     }
1637     return E_NOINTERFACE;
1638 }
1639 
Unknown_AddRef(IUnknown * iface)1640 static ULONG WINAPI Unknown_AddRef(IUnknown *iface)
1641 {
1642     return 2;
1643 }
1644 
Unknown_Release(IUnknown * iface)1645 static ULONG WINAPI Unknown_Release(IUnknown *iface)
1646 {
1647     return 1;
1648 }
1649 
1650 static const IUnknownVtbl UnknownVtbl =
1651 {
1652     Unknown_QueryInterface,
1653     Unknown_AddRef,
1654     Unknown_Release
1655 };
1656 
1657 static IUnknown unknown = { &UnknownVtbl };
1658 
check_enum_cache(IOleCache2 * cache,const STATDATA * expect,int num)1659 static void check_enum_cache(IOleCache2 *cache, const STATDATA *expect, int num)
1660 {
1661     IEnumSTATDATA *enum_stat;
1662     STATDATA stat;
1663     HRESULT hr;
1664 
1665     hr = IOleCache2_EnumCache( cache, &enum_stat );
1666     ok( hr == S_OK, "got %08x\n", hr );
1667 
1668     while (IEnumSTATDATA_Next(enum_stat, 1, &stat, NULL) == S_OK)
1669     {
1670         ok( stat.formatetc.cfFormat == expect->formatetc.cfFormat, "got %d expect %d\n",
1671             stat.formatetc.cfFormat, expect->formatetc.cfFormat );
1672         ok( !stat.formatetc.ptd == !expect->formatetc.ptd, "got %p expect %p\n",
1673             stat.formatetc.ptd, expect->formatetc.ptd );
1674         ok( stat.formatetc.dwAspect == expect->formatetc.dwAspect, "got %d expect %d\n",
1675             stat.formatetc.dwAspect, expect->formatetc.dwAspect );
1676         ok( stat.formatetc.lindex == expect->formatetc.lindex, "got %d expect %d\n",
1677             stat.formatetc.lindex, expect->formatetc.lindex );
1678         ok( stat.formatetc.tymed == expect->formatetc.tymed, "got %d expect %d\n",
1679             stat.formatetc.tymed, expect->formatetc.tymed );
1680         ok( stat.advf == expect->advf, "got %d expect %d\n", stat.advf, expect->advf );
1681         ok( stat.pAdvSink == 0, "got %p\n", stat.pAdvSink );
1682         ok( stat.dwConnection == expect->dwConnection, "got %d expect %d\n", stat.dwConnection, expect->dwConnection );
1683         num--;
1684         expect++;
1685     }
1686 
1687     ok( num == 0, "incorrect number. num %d\n", num );
1688 
1689     IEnumSTATDATA_Release( enum_stat );
1690 }
1691 
test_data_cache(void)1692 static void test_data_cache(void)
1693 {
1694     HRESULT hr;
1695     IOleCache2 *pOleCache;
1696     IOleCache *olecache;
1697     IStorage *pStorage;
1698     IUnknown *unk, *unk2;
1699     IPersistStorage *pPS;
1700     IViewObject *pViewObject;
1701     IOleCacheControl *pOleCacheControl;
1702     IDataObject *pCacheDataObject;
1703     FORMATETC fmtetc;
1704     STGMEDIUM stgmedium;
1705     DWORD dwConnection;
1706     DWORD dwFreeze;
1707     RECTL rcBounds;
1708     HDC hdcMem;
1709     CLSID clsid;
1710     char szSystemDir[MAX_PATH];
1711     WCHAR wszPath[MAX_PATH];
1712     static const WCHAR wszShell32[] = {'\\','s','h','e','l','l','3','2','.','d','l','l',0};
1713 
1714     static const struct expected_method methods_cacheinitnew[] =
1715     {
1716         { "AdviseSink_OnViewChange", 0 },
1717         { "AdviseSink_OnViewChange", 0 },
1718         { "draw_continue", 1 },
1719         { "draw_continue_false", 1 },
1720         { "DataObject_DAdvise", 0 },
1721         { "DataObject_DAdvise", 0 },
1722         { "DataObject_DUnadvise", 0 },
1723         { "DataObject_DUnadvise", 0 },
1724         { NULL, 0 }
1725     };
1726     static const struct expected_method methods_cacheload[] =
1727     {
1728         { "AdviseSink_OnViewChange", 0 },
1729         { "draw_continue", 1 },
1730         { "draw_continue", 1 },
1731         { "draw_continue", 1 },
1732         { "DataObject_GetData", 0, { CF_DIB,          NULL, DVASPECT_THUMBNAIL, -1, TYMED_HGLOBAL} },
1733         { "DataObject_GetData", 0, { CF_BITMAP,       NULL, DVASPECT_THUMBNAIL, -1, TYMED_GDI} },
1734         { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_ICON,      -1, TYMED_MFPICT} },
1735         { NULL, 0 }
1736     };
1737     static const struct expected_method methods_cachethenrun[] =
1738     {
1739         { "DataObject_DAdvise", 0 },
1740         { "DataObject_DAdvise", 0 },
1741         { "DataObject_DAdvise", 0 },
1742         { "DataObject_DAdvise", 0 },
1743         { "DataObject_DUnadvise", 0 },
1744         { "DataObject_DUnadvise", 0 },
1745         { "DataObject_DUnadvise", 0 },
1746         { "DataObject_DUnadvise", 0 },
1747         { NULL, 0 }
1748     };
1749 
1750     GetSystemDirectoryA(szSystemDir, ARRAY_SIZE(szSystemDir));
1751 
1752     expected_method_list = methods_cacheinitnew;
1753 
1754     fmtetc.cfFormat = CF_METAFILEPICT;
1755     fmtetc.dwAspect = DVASPECT_ICON;
1756     fmtetc.lindex = -1;
1757     fmtetc.ptd = NULL;
1758     fmtetc.tymed = TYMED_MFPICT;
1759 
1760     hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &pStorage);
1761     ok_ole_success(hr, "StgCreateDocfile");
1762 
1763     /* aggregation */
1764 
1765     /* requested is not IUnknown */
1766     hr = CreateDataCache(&unknown, &CLSID_NULL, &IID_IOleCache2, (void**)&pOleCache);
1767     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1768 
1769     hr = CreateDataCache(&unknown, &CLSID_NULL, &IID_IUnknown, (void**)&unk);
1770     ok(hr == S_OK, "got 0x%08x\n", hr);
1771 
1772     hr = IUnknown_QueryInterface(unk, &IID_IOleCache, (void**)&olecache);
1773     ok(hr == S_OK, "got 0x%08x\n", hr);
1774     hr = IUnknown_QueryInterface(unk, &IID_IOleCache2, (void**)&pOleCache);
1775     ok(hr == S_OK, "got 0x%08x\n", hr);
1776     ok(unk != (IUnknown*)olecache, "got %p, expected %p\n", olecache, unk);
1777     ok(unk != (IUnknown*)pOleCache, "got %p, expected %p\n", pOleCache, unk);
1778     IOleCache2_Release(pOleCache);
1779     IOleCache_Release(olecache);
1780     IUnknown_Release(unk);
1781 
1782     hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IUnknown, (void**)&unk);
1783     ok(hr == S_OK, "got 0x%08x\n", hr);
1784     hr = IUnknown_QueryInterface(unk, &IID_IOleCache, (void**)&olecache);
1785     ok(hr == S_OK, "got 0x%08x\n", hr);
1786     hr = IUnknown_QueryInterface(unk, &IID_IOleCache2, (void**)&pOleCache);
1787     ok(hr == S_OK, "got 0x%08x\n", hr);
1788     hr = IUnknown_QueryInterface(unk, &IID_IUnknown, (void**)&unk2);
1789     ok(hr == S_OK, "got 0x%08x\n", hr);
1790     ok(unk == (IUnknown*)olecache, "got %p, expected %p\n", olecache, unk);
1791     ok(unk == (IUnknown*)pOleCache, "got %p, expected %p\n", pOleCache, unk);
1792     ok(unk == unk2, "got %p, expected %p\n", unk2, unk);
1793     IUnknown_Release(unk2);
1794     IOleCache2_Release(pOleCache);
1795     IOleCache_Release(olecache);
1796     IUnknown_Release(unk);
1797 
1798     /* Test with new data */
1799 
1800     hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IOleCache2, (LPVOID *)&pOleCache);
1801     ok_ole_success(hr, "CreateDataCache");
1802 
1803     hr = IOleCache2_QueryInterface(pOleCache, &IID_IPersistStorage, (LPVOID *)&pPS);
1804     ok_ole_success(hr, "IOleCache_QueryInterface(IID_IPersistStorage)");
1805     hr = IOleCache2_QueryInterface(pOleCache, &IID_IViewObject, (LPVOID *)&pViewObject);
1806     ok_ole_success(hr, "IOleCache_QueryInterface(IID_IViewObject)");
1807     hr = IOleCache2_QueryInterface(pOleCache, &IID_IOleCacheControl, (LPVOID *)&pOleCacheControl);
1808     ok_ole_success(hr, "IOleCache_QueryInterface(IID_IOleCacheControl)");
1809 
1810     hr = IViewObject_SetAdvise(pViewObject, DVASPECT_ICON, ADVF_PRIMEFIRST, &AdviseSink);
1811     ok_ole_success(hr, "IViewObject_SetAdvise");
1812 
1813     hr = IPersistStorage_InitNew(pPS, pStorage);
1814     ok_ole_success(hr, "IPersistStorage_InitNew");
1815 
1816     hr = IPersistStorage_IsDirty(pPS);
1817     ok_ole_success(hr, "IPersistStorage_IsDirty");
1818 
1819     hr = IPersistStorage_GetClassID(pPS, &clsid);
1820     ok_ole_success(hr, "IPersistStorage_GetClassID");
1821     ok(IsEqualCLSID(&clsid, &IID_NULL), "clsid should be blank\n");
1822 
1823     hr = IOleCache2_Uncache(pOleCache, 0xdeadbeef);
1824     ok(hr == OLE_E_NOCONNECTION, "IOleCache_Uncache with invalid value should return OLE_E_NOCONNECTION instead of 0x%x\n", hr);
1825 
1826     /* Both tests crash on NT4 and below. StgCreatePropSetStg is only available on w2k and above. */
1827     if (GetProcAddress(GetModuleHandleA("ole32.dll"), "StgCreatePropSetStg"))
1828     {
1829         hr = IOleCache2_Cache(pOleCache, NULL, 0, &dwConnection);
1830         ok(hr == E_INVALIDARG, "IOleCache_Cache with NULL fmtetc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1831 
1832         hr = IOleCache2_Cache(pOleCache, NULL, 0, NULL);
1833         ok(hr == E_INVALIDARG, "IOleCache_Cache with NULL pdwConnection should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1834     }
1835     else
1836     {
1837         skip("tests with NULL parameters will crash on NT4 and below\n");
1838     }
1839 
1840     for (fmtetc.cfFormat = CF_TEXT; fmtetc.cfFormat < CF_MAX; fmtetc.cfFormat++)
1841     {
1842         int i;
1843         fmtetc.dwAspect = DVASPECT_THUMBNAIL;
1844         for (i = 0; i < 7; i++)
1845         {
1846             fmtetc.tymed = 1 << i;
1847             hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1848             if ((fmtetc.cfFormat == CF_METAFILEPICT && fmtetc.tymed == TYMED_MFPICT) ||
1849                 (fmtetc.cfFormat == CF_BITMAP && fmtetc.tymed == TYMED_GDI) ||
1850                 (fmtetc.cfFormat == CF_DIB && fmtetc.tymed == TYMED_HGLOBAL) ||
1851                 (fmtetc.cfFormat == CF_ENHMETAFILE && fmtetc.tymed == TYMED_ENHMF))
1852                 ok(hr == S_OK, "IOleCache_Cache cfFormat = %d, tymed = %d should have returned S_OK instead of 0x%08x\n",
1853                     fmtetc.cfFormat, fmtetc.tymed, hr);
1854             else if (fmtetc.tymed == TYMED_HGLOBAL)
1855                 ok(hr == CACHE_S_FORMATETC_NOTSUPPORTED ||
1856                    broken(hr == S_OK && fmtetc.cfFormat == CF_BITMAP) /* Win9x & NT4 */,
1857                     "IOleCache_Cache cfFormat = %d, tymed = %d should have returned CACHE_S_FORMATETC_NOTSUPPORTED instead of 0x%08x\n",
1858                     fmtetc.cfFormat, fmtetc.tymed, hr);
1859             else
1860                 ok(hr == DV_E_TYMED, "IOleCache_Cache cfFormat = %d, tymed = %d should have returned DV_E_TYMED instead of 0x%08x\n",
1861                     fmtetc.cfFormat, fmtetc.tymed, hr);
1862             if (SUCCEEDED(hr))
1863             {
1864                 hr = IOleCache2_Uncache(pOleCache, dwConnection);
1865                 ok_ole_success(hr, "IOleCache_Uncache");
1866             }
1867         }
1868     }
1869 
1870     fmtetc.cfFormat = CF_BITMAP;
1871     fmtetc.dwAspect = DVASPECT_THUMBNAIL;
1872     fmtetc.tymed = TYMED_GDI;
1873     hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1874     ok_ole_success(hr, "IOleCache_Cache");
1875 
1876     fmtetc.cfFormat = 0;
1877     fmtetc.dwAspect = DVASPECT_ICON;
1878     fmtetc.tymed = TYMED_MFPICT;
1879     hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1880     ok_ole_success(hr, "IOleCache_Cache");
1881 
1882     MultiByteToWideChar(CP_ACP, 0, szSystemDir, -1, wszPath, ARRAY_SIZE(wszPath));
1883     memcpy(wszPath+lstrlenW(wszPath), wszShell32, sizeof(wszShell32));
1884 
1885     fmtetc.cfFormat = CF_METAFILEPICT;
1886     stgmedium.tymed = TYMED_MFPICT;
1887     U(stgmedium).hMetaFilePict = OleMetafilePictFromIconAndLabel(
1888         LoadIconA(NULL, (LPSTR)IDI_APPLICATION), wszPath, wszPath, 0);
1889     stgmedium.pUnkForRelease = NULL;
1890 
1891     fmtetc.dwAspect = DVASPECT_CONTENT;
1892     hr = IOleCache2_SetData(pOleCache, &fmtetc, &stgmedium, FALSE);
1893     ok(hr == OLE_E_BLANK, "IOleCache_SetData for aspect not in cache should have return OLE_E_BLANK instead of 0x%08x\n", hr);
1894 
1895     fmtetc.dwAspect = DVASPECT_ICON;
1896     hr = IOleCache2_SetData(pOleCache, &fmtetc, &stgmedium, FALSE);
1897     ok_ole_success(hr, "IOleCache_SetData");
1898     ReleaseStgMedium(&stgmedium);
1899 
1900     hr = IViewObject_Freeze(pViewObject, DVASPECT_ICON, -1, NULL, &dwFreeze);
1901     todo_wine {
1902     ok_ole_success(hr, "IViewObject_Freeze");
1903     hr = IViewObject_Freeze(pViewObject, DVASPECT_CONTENT, -1, NULL, &dwFreeze);
1904     ok(hr == OLE_E_BLANK, "IViewObject_Freeze with uncached aspect should have returned OLE_E_BLANK instead of 0x%08x\n", hr);
1905     }
1906 
1907     rcBounds.left = 0;
1908     rcBounds.top = 0;
1909     rcBounds.right = 100;
1910     rcBounds.bottom = 100;
1911     hdcMem = CreateCompatibleDC(NULL);
1912 
1913     hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1914     ok_ole_success(hr, "IViewObject_Draw");
1915 
1916     hr = IViewObject_Draw(pViewObject, DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1917     ok(hr == OLE_E_BLANK, "IViewObject_Draw with uncached aspect should have returned OLE_E_BLANK instead of 0x%08x\n", hr);
1918 
1919     /* a NULL draw_continue fn ptr */
1920     hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, NULL, 0xdeadbeef);
1921     ok_ole_success(hr, "IViewObject_Draw");
1922 
1923     /* draw_continue that returns FALSE to abort drawing */
1924     hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue_false, 0xdeadbeef);
1925     ok(hr == E_ABORT ||
1926        broken(hr == S_OK), /* win9x may skip the callbacks */
1927        "IViewObject_Draw with draw_continue_false returns 0x%08x\n", hr);
1928 
1929     DeleteDC(hdcMem);
1930 
1931     hr = IOleCacheControl_OnRun(pOleCacheControl, &DataObject);
1932     ok_ole_success(hr, "IOleCacheControl_OnRun");
1933 
1934     hr = IPersistStorage_Save(pPS, pStorage, TRUE);
1935     ok_ole_success(hr, "IPersistStorage_Save");
1936 
1937     hr = IPersistStorage_SaveCompleted(pPS, NULL);
1938     ok_ole_success(hr, "IPersistStorage_SaveCompleted");
1939 
1940     hr = IPersistStorage_IsDirty(pPS);
1941     ok(hr == S_FALSE, "IPersistStorage_IsDirty should have returned S_FALSE instead of 0x%x\n", hr);
1942 
1943     IPersistStorage_Release(pPS);
1944     IViewObject_Release(pViewObject);
1945     IOleCache2_Release(pOleCache);
1946     IOleCacheControl_Release(pOleCacheControl);
1947 
1948     CHECK_NO_EXTRA_METHODS();
1949 
1950     /* Test with loaded data */
1951     trace("Testing loaded data with CreateDataCache:\n");
1952     expected_method_list = methods_cacheload;
1953 
1954     hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IOleCache2, (LPVOID *)&pOleCache);
1955     ok_ole_success(hr, "CreateDataCache");
1956 
1957     hr = IOleCache2_QueryInterface(pOleCache, &IID_IPersistStorage, (LPVOID *)&pPS);
1958     ok_ole_success(hr, "IOleCache_QueryInterface(IID_IPersistStorage)");
1959     hr = IOleCache2_QueryInterface(pOleCache, &IID_IViewObject, (LPVOID *)&pViewObject);
1960     ok_ole_success(hr, "IOleCache_QueryInterface(IID_IViewObject)");
1961 
1962     hr = IViewObject_SetAdvise(pViewObject, DVASPECT_ICON, ADVF_PRIMEFIRST, &AdviseSink);
1963     ok_ole_success(hr, "IViewObject_SetAdvise");
1964 
1965     hr = IPersistStorage_Load(pPS, pStorage);
1966     ok_ole_success(hr, "IPersistStorage_Load");
1967 
1968     hr = IPersistStorage_IsDirty(pPS);
1969     ok(hr == S_FALSE, "IPersistStorage_IsDirty should have returned S_FALSE instead of 0x%x\n", hr);
1970 
1971     fmtetc.cfFormat = 0;
1972     fmtetc.dwAspect = DVASPECT_ICON;
1973     fmtetc.lindex = -1;
1974     fmtetc.ptd = NULL;
1975     fmtetc.tymed = TYMED_MFPICT;
1976     hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1977     ok(hr == CACHE_S_SAMECACHE, "IOleCache_Cache with already loaded data format type should return CACHE_S_SAMECACHE instead of 0x%x\n", hr);
1978 
1979     rcBounds.left = 0;
1980     rcBounds.top = 0;
1981     rcBounds.right = 100;
1982     rcBounds.bottom = 100;
1983     hdcMem = CreateCompatibleDC(NULL);
1984 
1985     hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1986     ok_ole_success(hr, "IViewObject_Draw");
1987 
1988     hr = IViewObject_Draw(pViewObject, DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1989     ok(hr == OLE_E_BLANK, "IViewObject_Draw with uncached aspect should have returned OLE_E_BLANK instead of 0x%08x\n", hr);
1990 
1991     /* unload the cached storage object, causing it to be reloaded */
1992     hr = IOleCache2_DiscardCache(pOleCache, DISCARDCACHE_NOSAVE);
1993     ok_ole_success(hr, "IOleCache2_DiscardCache");
1994     hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1995     ok_ole_success(hr, "IViewObject_Draw");
1996 
1997     /* unload the cached storage object, but don't allow it to be reloaded */
1998     hr = IPersistStorage_HandsOffStorage(pPS);
1999     ok_ole_success(hr, "IPersistStorage_HandsOffStorage");
2000     hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
2001     ok_ole_success(hr, "IViewObject_Draw");
2002     hr = IOleCache2_DiscardCache(pOleCache, DISCARDCACHE_NOSAVE);
2003     ok_ole_success(hr, "IOleCache2_DiscardCache");
2004     hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
2005     ok(hr == OLE_E_BLANK, "IViewObject_Draw with uncached aspect should have returned OLE_E_BLANK instead of 0x%08x\n", hr);
2006 
2007     DeleteDC(hdcMem);
2008 
2009     hr = IOleCache2_InitCache(pOleCache, &DataObject);
2010     ok(hr == CACHE_E_NOCACHE_UPDATED, "IOleCache_InitCache should have returned CACHE_E_NOCACHE_UPDATED instead of 0x%08x\n", hr);
2011 
2012     IPersistStorage_Release(pPS);
2013     IViewObject_Release(pViewObject);
2014     IOleCache2_Release(pOleCache);
2015 
2016     CHECK_NO_EXTRA_METHODS();
2017 
2018     hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IOleCache2, (LPVOID *)&pOleCache);
2019     ok_ole_success(hr, "CreateDataCache");
2020 
2021     expected_method_list = methods_cachethenrun;
2022 
2023     hr = IOleCache2_QueryInterface(pOleCache, &IID_IDataObject, (LPVOID *)&pCacheDataObject);
2024     ok_ole_success(hr, "IOleCache_QueryInterface(IID_IDataObject)");
2025     hr = IOleCache2_QueryInterface(pOleCache, &IID_IOleCacheControl, (LPVOID *)&pOleCacheControl);
2026     ok_ole_success(hr, "IOleCache_QueryInterface(IID_IOleCacheControl)");
2027 
2028     fmtetc.cfFormat = CF_METAFILEPICT;
2029     fmtetc.dwAspect = DVASPECT_CONTENT;
2030     fmtetc.tymed = TYMED_MFPICT;
2031 
2032     hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
2033     ok_ole_success(hr, "IOleCache_Cache");
2034 
2035     hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2036     ok(hr == OLE_E_BLANK, "got %08x\n", hr);
2037 
2038     fmtetc.cfFormat = cf_test_1;
2039     fmtetc.dwAspect = DVASPECT_CONTENT;
2040     fmtetc.tymed = TYMED_HGLOBAL;
2041 
2042     hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
2043     ok(hr == CACHE_S_FORMATETC_NOTSUPPORTED, "got %08x\n", hr);
2044 
2045     hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2046     ok(hr == OLE_E_BLANK, "got %08x\n", hr);
2047 
2048     fmtetc.cfFormat = cf_test_2;
2049     hr = IOleCache2_Cache(pOleCache, &fmtetc, ADVF_PRIMEFIRST, &dwConnection);
2050     ok(hr == CACHE_S_FORMATETC_NOTSUPPORTED, "got %08x\n", hr);
2051 
2052     hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2053     ok(hr == OLE_E_BLANK, "got %08x\n", hr);
2054 
2055     hr = IOleCacheControl_OnRun(pOleCacheControl, &DataObject);
2056     ok_ole_success(hr, "IOleCacheControl_OnRun");
2057 
2058     fmtetc.cfFormat = cf_test_3;
2059     hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
2060     ok(hr == CACHE_S_FORMATETC_NOTSUPPORTED, "got %08x\n", hr);
2061 
2062     fmtetc.cfFormat = cf_test_1;
2063     hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2064     ok(hr == OLE_E_BLANK, "got %08x\n", hr);
2065 
2066     fmtetc.cfFormat = cf_test_2;
2067     hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2068     ok(hr == S_OK, "got %08x\n", hr);
2069     ReleaseStgMedium(&stgmedium);
2070 
2071     fmtetc.cfFormat = cf_test_3;
2072     hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2073     ok(hr == OLE_E_BLANK, "got %08x\n", hr);
2074 
2075     IOleCacheControl_Release(pOleCacheControl);
2076     IDataObject_Release(pCacheDataObject);
2077     IOleCache2_Release(pOleCache);
2078 
2079     CHECK_NO_EXTRA_METHODS();
2080 
2081     IStorage_Release(pStorage);
2082 }
2083 
2084 static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0};
2085 
2086 /* 2 x 1 x 32 bpp dib. PelsPerMeter = 200x400 */
2087 static BYTE file_dib[] =
2088 {
2089     0x42, 0x4d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
2090     0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
2091     0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00,
2092     0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
2093     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00,
2094     0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00,
2095     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
2096     0xff, 0xff, 0xff, 0xff, 0xff, 0xff
2097 };
2098 
create_storage(int num)2099 static IStorage *create_storage( int num )
2100 {
2101     IStorage *stg;
2102     IStream *stm;
2103     HRESULT hr;
2104     ULONG written;
2105 
2106     hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg );
2107     ok( hr == S_OK, "got %08x\n", hr);
2108     hr = IStorage_SetClass( stg, &CLSID_Picture_Dib );
2109     ok( hr == S_OK, "got %08x\n", hr);
2110     hr = IStorage_CreateStream( stg, CONTENTS, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, &stm );
2111     ok( hr == S_OK, "got %08x\n", hr);
2112     if (num == 1) /* Set biXPelsPerMeter = 0 */
2113     {
2114         file_dib[0x26] = 0;
2115         file_dib[0x27] = 0;
2116     }
2117     hr = IStream_Write( stm, file_dib, sizeof(file_dib), &written );
2118     ok( hr == S_OK, "got %08x\n", hr);
2119     IStream_Release( stm );
2120     return stg;
2121 }
2122 
test_data_cache_dib_contents_stream(int num)2123 static void test_data_cache_dib_contents_stream(int num)
2124 {
2125     HRESULT hr;
2126     IUnknown *unk;
2127     IPersistStorage *persist;
2128     IDataObject *data;
2129     IViewObject2 *view;
2130     IStorage *stg;
2131     IOleCache2 *cache;
2132     FORMATETC fmt = {CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
2133     STGMEDIUM med;
2134     CLSID cls;
2135     SIZEL sz;
2136     BYTE *ptr;
2137     BITMAPINFOHEADER expect_info;
2138     STATDATA enum_expect[] =
2139     {
2140         {{ CF_DIB,          0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2141         {{ CF_BITMAP,       0, DVASPECT_CONTENT, -1, TYMED_GDI },     0, NULL, 1 },
2142     };
2143 
2144     hr = CreateDataCache( NULL, &CLSID_Picture_Metafile, &IID_IUnknown, (void **)&unk );
2145     ok( SUCCEEDED(hr), "got %08x\n", hr );
2146     hr = IUnknown_QueryInterface( unk, &IID_IPersistStorage, (void **)&persist );
2147     ok( SUCCEEDED(hr), "got %08x\n", hr );
2148     hr = IUnknown_QueryInterface( unk, &IID_IDataObject, (void **)&data );
2149     ok( SUCCEEDED(hr), "got %08x\n", hr );
2150     hr = IUnknown_QueryInterface( unk, &IID_IViewObject2, (void **)&view );
2151     ok( SUCCEEDED(hr), "got %08x\n", hr );
2152     hr = IUnknown_QueryInterface( unk, &IID_IOleCache2, (void **)&cache );
2153     ok( SUCCEEDED(hr), "got %08x\n", hr );
2154 
2155     stg = create_storage( num );
2156 
2157     hr = IPersistStorage_Load( persist, stg );
2158     ok( SUCCEEDED(hr), "got %08x\n", hr );
2159     IStorage_Release( stg );
2160 
2161     hr = IPersistStorage_GetClassID( persist, &cls );
2162     ok( SUCCEEDED(hr), "got %08x\n", hr );
2163     ok( IsEqualCLSID( &cls, &CLSID_Picture_Dib ), "class id mismatch\n" );
2164 
2165     hr = IDataObject_GetData( data, &fmt, &med );
2166     ok( SUCCEEDED(hr), "got %08x\n", hr );
2167     ok( med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed );
2168     ok( GlobalSize( U(med).hGlobal ) >= sizeof(dib) - sizeof(BITMAPFILEHEADER),
2169         "got %lu\n", GlobalSize( U(med).hGlobal ) );
2170     ptr = GlobalLock( U(med).hGlobal );
2171 
2172     expect_info = *(BITMAPINFOHEADER *)(file_dib + sizeof(BITMAPFILEHEADER));
2173     if (expect_info.biXPelsPerMeter == 0 || expect_info.biYPelsPerMeter == 0)
2174     {
2175         HDC hdc = GetDC( 0 );
2176         expect_info.biXPelsPerMeter = MulDiv( GetDeviceCaps( hdc, LOGPIXELSX ), 10000, 254 );
2177         expect_info.biYPelsPerMeter = MulDiv( GetDeviceCaps( hdc, LOGPIXELSY ), 10000, 254 );
2178         ReleaseDC( 0, hdc );
2179     }
2180     ok( !memcmp( ptr, &expect_info, sizeof(expect_info) ), "mismatch\n" );
2181     ok( !memcmp( ptr + sizeof(expect_info), file_dib + sizeof(BITMAPFILEHEADER) + sizeof(expect_info),
2182                  sizeof(file_dib) - sizeof(BITMAPFILEHEADER) - sizeof(expect_info) ), "mismatch\n" );
2183     GlobalUnlock( U(med).hGlobal );
2184     ReleaseStgMedium( &med );
2185 
2186     check_enum_cache( cache, enum_expect, 2 );
2187 
2188     hr = IViewObject2_GetExtent( view, DVASPECT_CONTENT, -1, NULL, &sz );
2189     ok( SUCCEEDED(hr), "got %08x\n", hr );
2190     if (num == 0)
2191     {
2192         ok( sz.cx == 1000, "got %d\n", sz.cx );
2193         ok( sz.cy == 250, "got %d\n", sz.cy );
2194     }
2195     else
2196     {
2197         HDC hdc = GetDC( 0 );
2198         LONG x = 2 * 2540 / GetDeviceCaps( hdc, LOGPIXELSX );
2199         LONG y = 1 * 2540 / GetDeviceCaps( hdc, LOGPIXELSY );
2200         ok( sz.cx == x, "got %d %d\n", sz.cx, x );
2201         ok( sz.cy == y, "got %d %d\n", sz.cy, y );
2202 
2203         ReleaseDC( 0, hdc );
2204     }
2205 
2206     IOleCache2_Release( cache );
2207     IViewObject2_Release( view );
2208     IDataObject_Release( data );
2209     IPersistStorage_Release( persist );
2210     IUnknown_Release( unk );
2211 }
2212 
check_bitmap_size(HBITMAP h,int cx,int cy)2213 static void check_bitmap_size( HBITMAP h, int cx, int cy )
2214 {
2215     BITMAP bm;
2216 
2217     GetObjectW( h, sizeof(bm), &bm );
2218     ok( bm.bmWidth == cx, "got %d expect %d\n", bm.bmWidth, cx );
2219     ok( bm.bmHeight == cy, "got %d expect %d\n", bm.bmHeight, cy );
2220 }
2221 
check_dib_size(HGLOBAL h,int cx,int cy)2222 static void check_dib_size( HGLOBAL h, int cx, int cy )
2223 {
2224     BITMAPINFO *info;
2225 
2226     info = GlobalLock( h );
2227     ok( info->bmiHeader.biWidth == cx, "got %d expect %d\n", info->bmiHeader.biWidth, cx );
2228     ok( info->bmiHeader.biHeight == cy, "got %d expect %d\n", info->bmiHeader.biHeight, cy );
2229     GlobalUnlock( h );
2230 }
2231 
test_data_cache_cache(void)2232 static void test_data_cache_cache(void)
2233 {
2234     HRESULT hr;
2235     IOleCache2 *cache;
2236     IDataObject *data;
2237     FORMATETC fmt;
2238     DWORD conn;
2239     STGMEDIUM med;
2240     STATDATA expect[] =
2241     {
2242         {{ CF_DIB,          0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 0 },
2243         {{ CF_BITMAP,       0, DVASPECT_CONTENT, -1, TYMED_GDI },     0, NULL, 0 },
2244         {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT },  0, NULL, 0 },
2245         {{ CF_ENHMETAFILE,  0, DVASPECT_CONTENT, -1, TYMED_ENHMF },   0, NULL, 0 }
2246     };
2247     STATDATA view_caching[] =
2248     {
2249         {{ 0,               0, DVASPECT_CONTENT,   -1, TYMED_ENHMF },   0, NULL, 0 },
2250         {{ 0,               0, DVASPECT_THUMBNAIL, -1, TYMED_HGLOBAL }, 0, NULL, 0 },
2251         {{ 0,               0, DVASPECT_DOCPRINT,  -1, TYMED_HGLOBAL }, 0, NULL, 0 },
2252         {{ CF_METAFILEPICT, 0, DVASPECT_ICON,      -1, TYMED_MFPICT },  0, NULL, 0 }
2253     };
2254 
2255     hr = CreateDataCache( NULL, &CLSID_NULL, &IID_IOleCache2, (void **)&cache );
2256     ok( hr == S_OK, "got %08x\n", hr );
2257 
2258     /* create a dib entry which will also create a bitmap entry too */
2259     fmt.cfFormat = CF_DIB;
2260     fmt.ptd = NULL;
2261     fmt.dwAspect = DVASPECT_CONTENT;
2262     fmt.lindex = -1;
2263     fmt.tymed = TYMED_HGLOBAL;
2264 
2265     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2266     ok( hr == S_OK, "got %08x\n", hr );
2267     ok( conn == 2, "got %d\n", conn );
2268     expect[0].dwConnection = conn;
2269     expect[1].dwConnection = conn;
2270 
2271     check_enum_cache( cache, expect, 2 );
2272 
2273     /* now try to add a bitmap */
2274     fmt.cfFormat = CF_BITMAP;
2275     fmt.tymed = TYMED_GDI;
2276 
2277     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2278     ok( hr == CACHE_S_SAMECACHE, "got %08x\n", hr );
2279 
2280     /* metafile */
2281     fmt.cfFormat = CF_METAFILEPICT;
2282     fmt.tymed = TYMED_MFPICT;
2283 
2284     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2285     ok( hr == S_OK, "got %08x\n", hr );
2286     ok( conn == 3, "got %d\n", conn );
2287     expect[2].dwConnection = conn;
2288 
2289     check_enum_cache( cache, expect,  3);
2290 
2291     /* enhmetafile */
2292     fmt.cfFormat = CF_ENHMETAFILE;
2293     fmt.tymed = TYMED_ENHMF;
2294 
2295     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2296     ok( hr == S_OK, "got %08x\n", hr );
2297     ok( conn == 4, "got %d\n", conn );
2298     expect[3].dwConnection = conn;
2299 
2300     check_enum_cache( cache, expect, 4 );
2301 
2302     /* uncache everything */
2303     hr = IOleCache2_Uncache( cache, expect[3].dwConnection );
2304     ok( hr == S_OK, "got %08x\n", hr );
2305     hr = IOleCache2_Uncache( cache, expect[2].dwConnection );
2306     ok( hr == S_OK, "got %08x\n", hr );
2307     hr = IOleCache2_Uncache( cache, expect[0].dwConnection );
2308     ok( hr == S_OK, "got %08x\n", hr );
2309     hr = IOleCache2_Uncache( cache, expect[0].dwConnection );
2310     ok( hr == OLE_E_NOCONNECTION, "got %08x\n", hr );
2311 
2312     check_enum_cache( cache, expect, 0 );
2313 
2314     /* just create a bitmap entry which again adds both dib and bitmap */
2315     fmt.cfFormat = CF_BITMAP;
2316     fmt.tymed = TYMED_GDI;
2317 
2318     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2319     ok( hr == S_OK, "got %08x\n", hr );
2320 
2321     expect[0].dwConnection = conn;
2322     expect[1].dwConnection = conn;
2323 
2324     check_enum_cache( cache, expect, 2 );
2325 
2326     /* Try setting a 1x1 bitmap */
2327     hr = IOleCache2_QueryInterface( cache, &IID_IDataObject, (void **) &data );
2328     ok( hr == S_OK, "got %08x\n", hr );
2329 
2330     create_bitmap( &med );
2331 
2332     hr = IOleCache2_SetData( cache, &fmt, &med, TRUE );
2333     ok( hr == S_OK, "got %08x\n", hr );
2334 
2335     hr = IDataObject_GetData( data, &fmt, &med );
2336     ok( hr == S_OK, "got %08x\n", hr );
2337     ok( med.tymed == TYMED_GDI, "got %d\n", med.tymed );
2338     check_bitmap_size( U(med).hBitmap, 1, 1 );
2339     ReleaseStgMedium( &med );
2340 
2341     fmt.cfFormat = CF_DIB;
2342     fmt.tymed = TYMED_HGLOBAL;
2343     hr = IDataObject_GetData( data, &fmt, &med );
2344     ok( hr == S_OK, "got %08x\n", hr );
2345     ok( med.tymed == TYMED_HGLOBAL, "got %d\n", med.tymed );
2346     check_dib_size( U(med).hGlobal, 1, 1 );
2347     ReleaseStgMedium( &med );
2348 
2349     /* Now set a 2x1 dib */
2350     fmt.cfFormat = CF_DIB;
2351     fmt.tymed = TYMED_HGLOBAL;
2352     create_dib( &med );
2353 
2354     hr = IOleCache2_SetData( cache, &fmt, &med, TRUE );
2355     ok( hr == S_OK, "got %08x\n", hr );
2356 
2357     fmt.cfFormat = CF_BITMAP;
2358     fmt.tymed = TYMED_GDI;
2359     hr = IDataObject_GetData( data, &fmt, &med );
2360     ok( hr == S_OK, "got %08x\n", hr );
2361     ok( med.tymed == TYMED_GDI, "got %d\n", med.tymed );
2362     check_bitmap_size( U(med).hBitmap, 2, 1 );
2363     ReleaseStgMedium( &med );
2364 
2365     fmt.cfFormat = CF_DIB;
2366     fmt.tymed = TYMED_HGLOBAL;
2367     hr = IDataObject_GetData( data, &fmt, &med );
2368     ok( hr == S_OK, "got %08x\n", hr );
2369     ok( med.tymed == TYMED_HGLOBAL, "got %d\n", med.tymed );
2370     check_dib_size( U(med).hGlobal, 2, 1 );
2371     ReleaseStgMedium( &med );
2372 
2373     /* uncache everything */
2374     hr = IOleCache2_Uncache( cache, conn );
2375     ok( hr == S_OK, "got %08x\n", hr );
2376 
2377     /* view caching */
2378     fmt.cfFormat = 0;
2379     fmt.tymed = TYMED_ENHMF;
2380     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2381     ok( hr == S_OK, "got %08x\n", hr );
2382     view_caching[0].dwConnection = conn;
2383 
2384     fmt.tymed = TYMED_HGLOBAL;
2385     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2386     ok( hr == CACHE_S_SAMECACHE, "got %08x\n", hr );
2387 
2388     fmt.dwAspect = DVASPECT_THUMBNAIL;
2389     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2390     ok( hr == S_OK, "got %08x\n", hr );
2391     view_caching[1].dwConnection = conn;
2392 
2393     fmt.dwAspect = DVASPECT_DOCPRINT;
2394     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2395     ok( hr == S_OK, "got %08x\n", hr );
2396     view_caching[2].dwConnection = conn;
2397 
2398     /* DVASPECT_ICON view cache gets mapped to CF_METAFILEPICT */
2399     fmt.dwAspect = DVASPECT_ICON;
2400     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2401     ok( hr == S_OK, "got %08x\n", hr );
2402     view_caching[3].dwConnection = conn;
2403 
2404     check_enum_cache( cache, view_caching, 4 );
2405 
2406     /* uncache everything */
2407     hr = IOleCache2_Uncache( cache, view_caching[3].dwConnection );
2408     ok( hr == S_OK, "got %08x\n", hr );
2409     hr = IOleCache2_Uncache( cache, view_caching[2].dwConnection );
2410     ok( hr == S_OK, "got %08x\n", hr );
2411     hr = IOleCache2_Uncache( cache, view_caching[1].dwConnection );
2412     ok( hr == S_OK, "got %08x\n", hr );
2413     hr = IOleCache2_Uncache( cache, view_caching[0].dwConnection );
2414     ok( hr == S_OK, "got %08x\n", hr );
2415 
2416     /* Only able to set cfFormat == CF_METAFILEPICT (or == 0, see above) for DVASPECT_ICON */
2417     fmt.dwAspect = DVASPECT_ICON;
2418     fmt.cfFormat = CF_DIB;
2419     fmt.tymed = TYMED_HGLOBAL;
2420     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2421     ok( hr == DV_E_FORMATETC, "got %08x\n", hr );
2422     fmt.cfFormat = CF_BITMAP;
2423     fmt.tymed = TYMED_GDI;
2424     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2425     ok( hr == DV_E_FORMATETC, "got %08x\n", hr );
2426     fmt.cfFormat = CF_ENHMETAFILE;
2427     fmt.tymed = TYMED_ENHMF;
2428     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2429     ok( hr == DV_E_FORMATETC, "got %08x\n", hr );
2430     fmt.cfFormat = CF_METAFILEPICT;
2431     fmt.tymed = TYMED_MFPICT;
2432     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2433     ok( hr == S_OK, "got %08x\n", hr );
2434 
2435     /* uncache everything */
2436     hr = IOleCache2_Uncache( cache, conn );
2437     ok( hr == S_OK, "got %08x\n", hr );
2438 
2439     /* tymed == 0 */
2440     fmt.cfFormat = CF_ENHMETAFILE;
2441     fmt.dwAspect = DVASPECT_CONTENT;
2442     fmt.tymed = 0;
2443     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2444     ok( hr == DV_E_TYMED, "got %08x\n", hr );
2445 
2446     IDataObject_Release( data );
2447     IOleCache2_Release( cache );
2448 
2449     /* tests for a static class cache */
2450     hr = CreateDataCache( NULL, &CLSID_Picture_Dib, &IID_IOleCache2, (void **)&cache );
2451 
2452     fmt.cfFormat = CF_DIB;
2453     fmt.dwAspect = DVASPECT_CONTENT;
2454     fmt.tymed = TYMED_HGLOBAL;
2455     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2456     ok( hr == CACHE_S_SAMECACHE, "got %08x\n", hr );
2457 
2458     /* aspect other than DVASPECT_CONTENT should fail */
2459     fmt.dwAspect = DVASPECT_THUMBNAIL;
2460     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2461     ok( FAILED(hr), "got %08x\n", hr );
2462 
2463     fmt.dwAspect = DVASPECT_DOCPRINT;
2464     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2465     ok( FAILED(hr), "got %08x\n", hr );
2466 
2467     /* try caching another clip format */
2468     fmt.cfFormat = CF_METAFILEPICT;
2469     fmt.dwAspect = DVASPECT_CONTENT;
2470     fmt.tymed = TYMED_MFPICT;
2471     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2472     ok( FAILED(hr), "got %08x\n", hr );
2473 
2474     /* As an exception, it's possible to add an icon aspect */
2475     fmt.cfFormat = CF_METAFILEPICT;
2476     fmt.dwAspect = DVASPECT_ICON;
2477     fmt.tymed = TYMED_MFPICT;
2478     hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2479     ok( hr == S_OK, "got %08x\n", hr );
2480 
2481     IOleCache2_Release( cache );
2482 }
2483 
2484 /* The CLSID_Picture_ classes automatically create appropriate cache entries */
test_data_cache_init(void)2485 static void test_data_cache_init(void)
2486 {
2487     HRESULT hr;
2488     IOleCache2 *cache;
2489     IPersistStorage *persist;
2490     int i;
2491     CLSID clsid;
2492     static const STATDATA enum_expect[] =
2493     {
2494         {{ CF_DIB,          0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2495         {{ CF_BITMAP,       0, DVASPECT_CONTENT, -1, TYMED_GDI },     0, NULL, 1 },
2496         {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT },  0, NULL, 1 },
2497         {{ CF_ENHMETAFILE,  0, DVASPECT_CONTENT, -1, TYMED_ENHMF },   0, NULL, 1 }
2498     };
2499     static const struct
2500     {
2501         const CLSID *clsid;
2502         int enum_start, enum_num;
2503     } data[] =
2504     {
2505         { &CLSID_NULL, 0, 0 },
2506         { &CLSID_WineTestOld, 0, 0 },
2507         { &CLSID_Picture_Dib, 0, 2 },
2508         { &CLSID_Picture_Metafile, 2, 1 },
2509         { &CLSID_Picture_EnhMetafile, 3, 1 }
2510     };
2511 
2512     for (i = 0; i < ARRAY_SIZE(data); i++)
2513     {
2514         hr = CreateDataCache( NULL, data[i].clsid, &IID_IOleCache2, (void **)&cache );
2515         ok( hr == S_OK, "got %08x\n", hr );
2516 
2517         check_enum_cache( cache, enum_expect + data[i].enum_start , data[i].enum_num );
2518 
2519         IOleCache2_QueryInterface( cache, &IID_IPersistStorage, (void **) &persist );
2520         hr = IPersistStorage_GetClassID( persist, &clsid );
2521         ok( hr == S_OK, "got %08x\n", hr );
2522         ok( IsEqualCLSID( &clsid, data[i].clsid ), "class id mismatch %s %s\n", wine_dbgstr_guid( &clsid ),
2523             wine_dbgstr_guid( data[i].clsid ) );
2524 
2525         IPersistStorage_Release( persist );
2526         IOleCache2_Release( cache );
2527     }
2528 }
2529 
test_data_cache_initnew(void)2530 static void test_data_cache_initnew(void)
2531 {
2532     HRESULT hr;
2533     IOleCache2 *cache;
2534     IPersistStorage *persist;
2535     IStorage *stg_dib, *stg_mf, *stg_wine;
2536     CLSID clsid;
2537     static const STATDATA initnew_expect[] =
2538     {
2539         {{ CF_DIB,          0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2540         {{ CF_BITMAP,       0, DVASPECT_CONTENT, -1, TYMED_GDI },     0, NULL, 1 },
2541     };
2542     static const STATDATA initnew2_expect[] =
2543     {
2544         {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT },  0, NULL, 1 },
2545         {{ CF_DIB,          0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 2 },
2546         {{ CF_BITMAP,       0, DVASPECT_CONTENT, -1, TYMED_GDI },     0, NULL, 2 },
2547     };
2548     static const STATDATA initnew3_expect[] =
2549     {
2550         {{ CF_DIB,          0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2551         {{ CF_BITMAP,       0, DVASPECT_CONTENT, -1, TYMED_GDI },     0, NULL, 1 },
2552         {{ CF_DIB,          0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 2 },
2553         {{ CF_BITMAP,       0, DVASPECT_CONTENT, -1, TYMED_GDI },     0, NULL, 2 },
2554         {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT },  0, NULL, 3 },
2555     };
2556     static const STATDATA initnew4_expect[] =
2557     {
2558         {{ CF_DIB,          0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 2 },
2559         {{ CF_BITMAP,       0, DVASPECT_CONTENT, -1, TYMED_GDI },     0, NULL, 2 },
2560         {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT },  0, NULL, 3 },
2561         {{ CF_DIB,          0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 4 },
2562         {{ CF_BITMAP,       0, DVASPECT_CONTENT, -1, TYMED_GDI },     0, NULL, 4 },
2563     };
2564 
2565     hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg_dib );
2566     ok( hr == S_OK, "got %08x\n", hr);
2567     hr = IStorage_SetClass( stg_dib, &CLSID_Picture_Dib );
2568     ok( hr == S_OK, "got %08x\n", hr);
2569 
2570     hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg_mf );
2571     ok( hr == S_OK, "got %08x\n", hr);
2572     hr = IStorage_SetClass( stg_mf, &CLSID_Picture_Metafile );
2573     ok( hr == S_OK, "got %08x\n", hr);
2574 
2575     hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg_wine );
2576     ok( hr == S_OK, "got %08x\n", hr);
2577     hr = IStorage_SetClass( stg_wine, &CLSID_WineTestOld );
2578     ok( hr == S_OK, "got %08x\n", hr);
2579 
2580     hr = CreateDataCache( NULL, &CLSID_WineTestOld, &IID_IOleCache2, (void **)&cache );
2581     ok( hr == S_OK, "got %08x\n", hr );
2582     IOleCache2_QueryInterface( cache, &IID_IPersistStorage, (void **) &persist );
2583 
2584     hr = IPersistStorage_InitNew( persist, stg_dib );
2585     ok( hr == S_OK, "got %08x\n", hr);
2586 
2587     hr = IPersistStorage_GetClassID( persist, &clsid );
2588     ok( hr == S_OK, "got %08x\n", hr );
2589     ok( IsEqualCLSID( &clsid, &CLSID_Picture_Dib ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2590 
2591     check_enum_cache( cache, initnew_expect, 2 );
2592 
2593     hr = IPersistStorage_InitNew( persist, stg_mf );
2594     ok( hr == CO_E_ALREADYINITIALIZED, "got %08x\n", hr);
2595 
2596     hr = IPersistStorage_HandsOffStorage( persist );
2597     ok( hr == S_OK, "got %08x\n", hr);
2598 
2599     hr = IPersistStorage_GetClassID( persist, &clsid );
2600     ok( hr == S_OK, "got %08x\n", hr );
2601     ok( IsEqualCLSID( &clsid, &CLSID_Picture_Dib ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2602 
2603     hr = IPersistStorage_InitNew( persist, stg_mf );
2604     ok( hr == S_OK, "got %08x\n", hr);
2605 
2606     hr = IPersistStorage_GetClassID( persist, &clsid );
2607     ok( hr == S_OK, "got %08x\n", hr );
2608     ok( IsEqualCLSID( &clsid, &CLSID_Picture_Metafile ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2609 
2610     check_enum_cache( cache, initnew2_expect, 3 );
2611 
2612     hr = IPersistStorage_HandsOffStorage( persist );
2613     ok( hr == S_OK, "got %08x\n", hr);
2614 
2615     hr = IPersistStorage_InitNew( persist, stg_dib );
2616     ok( hr == S_OK, "got %08x\n", hr);
2617 
2618     hr = IPersistStorage_GetClassID( persist, &clsid );
2619     ok( hr == S_OK, "got %08x\n", hr );
2620     ok( IsEqualCLSID( &clsid, &CLSID_Picture_Dib ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2621 
2622     check_enum_cache( cache, initnew3_expect, 5 );
2623 
2624     hr = IPersistStorage_HandsOffStorage( persist );
2625     ok( hr == S_OK, "got %08x\n", hr);
2626 
2627     hr = IPersistStorage_InitNew( persist, stg_wine );
2628     ok( hr == S_OK, "got %08x\n", hr);
2629 
2630     hr = IPersistStorage_GetClassID( persist, &clsid );
2631     ok( hr == S_OK, "got %08x\n", hr );
2632     ok( IsEqualCLSID( &clsid, &CLSID_WineTestOld ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2633 
2634     check_enum_cache( cache, initnew4_expect, 5 );
2635 
2636     IStorage_Release( stg_wine );
2637     IStorage_Release( stg_mf );
2638     IStorage_Release( stg_dib );
2639 
2640     IPersistStorage_Release( persist );
2641     IOleCache2_Release( cache );
2642 }
2643 
test_data_cache_updatecache(void)2644 static void test_data_cache_updatecache( void )
2645 {
2646     HRESULT hr;
2647     IOleCache2 *cache;
2648     FORMATETC fmt;
2649     DWORD conn[4];
2650 
2651     static const struct expected_method methods_dib[] =
2652     {
2653         { "DataObject_GetData", 0, { CF_DIB,          NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2654         { "DataObject_GetData", 0, { CF_BITMAP,       NULL, DVASPECT_CONTENT, -1, TYMED_GDI } },
2655         { NULL }
2656     };
2657 
2658     static const struct expected_method methods_dib_emf[] =
2659     {
2660         { "DataObject_GetData", 0, { CF_DIB,          NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2661         { "DataObject_GetData", 0, { CF_ENHMETAFILE,  NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } },
2662         { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2663         { NULL }
2664     };
2665     static const struct expected_method methods_dib_wmf[] =
2666     {
2667         { "DataObject_GetData", 0, { CF_DIB,          NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2668         { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2669         { NULL }
2670     };
2671     static const struct expected_method methods_viewcache[] =
2672     {
2673         { "DataObject_QueryGetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2674         { "DataObject_QueryGetData", 0, { CF_ENHMETAFILE,  NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } },
2675         { "DataObject_QueryGetData", 0, { CF_DIB,          NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2676         { "DataObject_QueryGetData", 0, { CF_BITMAP,       NULL, DVASPECT_CONTENT, -1, TYMED_GDI } },
2677         { NULL }
2678     };
2679     static const struct expected_method methods_viewcache_with_dib[] =
2680     {
2681         { "DataObject_QueryGetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2682         { "DataObject_QueryGetData", 0, { CF_ENHMETAFILE,  NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } },
2683         { "DataObject_QueryGetData", 0, { CF_DIB,          NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2684         { "DataObject_GetData",      0, { CF_DIB,          NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2685         { NULL }
2686     };
2687     static const struct expected_method methods_flags_all[] =
2688     {
2689         { "DataObject_GetData", 0, { CF_DIB,          NULL, DVASPECT_CONTENT,   -1, TYMED_HGLOBAL } },
2690         { "DataObject_GetData", 0, { CF_ENHMETAFILE,  NULL, DVASPECT_CONTENT,   -1, TYMED_ENHMF } },
2691         { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT,   -1, TYMED_MFPICT } },
2692         { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT,   -1, TYMED_MFPICT } },
2693         { NULL }
2694     };
2695     static const struct expected_method methods_flags_ifblank_1[] =
2696     {
2697         { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT,   -1, TYMED_MFPICT } },
2698         { NULL }
2699     };
2700     static const struct expected_method methods_flags_ifblank_2[] =
2701     {
2702         { "DataObject_GetData", 0, { CF_DIB,          NULL, DVASPECT_CONTENT,   -1, TYMED_HGLOBAL } },
2703         { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT,   -1, TYMED_MFPICT } },
2704         { NULL }
2705     };
2706     static const struct expected_method methods_flags_normal[] =
2707     {
2708         { "DataObject_GetData", 0, { CF_DIB,          NULL, DVASPECT_CONTENT,   -1, TYMED_HGLOBAL } },
2709         { NULL }
2710     };
2711     static const struct expected_method methods_initcache[] =
2712     {
2713         { "DataObject_GetData", 0, { CF_DIB,          NULL, DVASPECT_CONTENT,   -1, TYMED_HGLOBAL } },
2714         { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT,   -1, TYMED_MFPICT } },
2715         { NULL }
2716     };
2717     static const struct expected_method methods_empty[] =
2718     {
2719         { NULL }
2720     };
2721 
2722     static STATDATA view_cache[] =
2723     {
2724         {{ 0,          0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 0 }
2725     };
2726     static STATDATA view_cache_after_dib[] =
2727     {
2728         {{ CF_DIB,          0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 0 },
2729         {{ CF_BITMAP,       0, DVASPECT_CONTENT, -1, TYMED_GDI },     0, NULL, 0 }
2730     };
2731 
2732     static FORMATETC dib_fmt[] =
2733     {
2734         { CF_DIB,       NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
2735         { 0 }
2736     };
2737 
2738     hr = CreateDataCache( NULL, &CLSID_WineTestOld, &IID_IOleCache2, (void **)&cache );
2739     ok( hr == S_OK, "got %08x\n", hr );
2740 
2741     /* No cache slots */
2742     g_dataobject_fmts = NULL;
2743     expected_method_list = NULL;
2744 
2745     hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2746     ok( hr == S_OK, "got %08x\n", hr );
2747 
2748     /* A dib cache slot */
2749     fmt.cfFormat = CF_DIB;
2750     fmt.ptd = NULL;
2751     fmt.dwAspect = DVASPECT_CONTENT;
2752     fmt.lindex = -1;
2753     fmt.tymed = TYMED_HGLOBAL;
2754 
2755     hr = IOleCache2_Cache( cache, &fmt, 0, &conn[0] );
2756     ok( hr == S_OK, "got %08x\n", hr );
2757 
2758     expected_method_list = methods_dib;
2759 
2760     hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2761     ok( hr == CACHE_E_NOCACHE_UPDATED, "got %08x\n", hr );
2762 
2763     CHECK_NO_EXTRA_METHODS();
2764 
2765     /* Now with a dib available */
2766     g_dataobject_fmts = dib_fmt;
2767     expected_method_list = methods_dib;
2768 
2769     hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2770     ok( hr == S_OK, "got %08x\n", hr );
2771 
2772     /* Add an EMF cache slot */
2773     fmt.cfFormat = CF_ENHMETAFILE;
2774     fmt.ptd = NULL;
2775     fmt.dwAspect = DVASPECT_CONTENT;
2776     fmt.lindex = -1;
2777     fmt.tymed = TYMED_ENHMF;
2778 
2779     hr = IOleCache2_Cache( cache, &fmt, 0, &conn[1] );
2780     ok( hr == S_OK, "got %08x\n", hr );
2781 
2782     g_dataobject_fmts = dib_fmt;
2783     expected_method_list = methods_dib_emf;
2784 
2785     /* Two slots to fill, only the dib will succeed */
2786     hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2787     ok( hr == S_OK, "got %08x\n", hr );
2788 
2789     CHECK_NO_EXTRA_METHODS();
2790 
2791     /* Replace the emf slot with a wmf */
2792     hr = IOleCache2_Uncache( cache, conn[1] );
2793     ok( hr == S_OK, "got %08x\n", hr );
2794 
2795     fmt.cfFormat = CF_METAFILEPICT;
2796     fmt.ptd = NULL;
2797     fmt.dwAspect = DVASPECT_CONTENT;
2798     fmt.lindex = -1;
2799     fmt.tymed = TYMED_MFPICT;
2800 
2801     hr = IOleCache2_Cache( cache, &fmt, 0, &conn[1] );
2802     ok( hr == S_OK, "got %08x\n", hr );
2803 
2804     g_dataobject_fmts = dib_fmt;
2805     expected_method_list = methods_dib_wmf;
2806 
2807     hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2808     ok( hr == S_OK, "got %08x\n", hr );
2809 
2810     hr = IOleCache2_Uncache( cache, conn[1] );
2811     ok( hr == S_OK, "got %08x\n", hr );
2812     hr = IOleCache2_Uncache( cache, conn[0] );
2813     ok( hr == S_OK, "got %08x\n", hr );
2814 
2815     /* View caching */
2816     fmt.cfFormat = 0;
2817     fmt.ptd = NULL;
2818     fmt.dwAspect = DVASPECT_CONTENT;
2819     fmt.lindex = -1;
2820     fmt.tymed = TYMED_HGLOBAL;
2821 
2822     hr = IOleCache2_Cache( cache, &fmt, 0, &conn[0] );
2823     ok( hr == S_OK, "got %08x\n", hr );
2824     view_cache[0].dwConnection = conn[0];
2825 
2826     g_dataobject_fmts = NULL;
2827     expected_method_list = methods_viewcache;
2828 
2829     hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2830     ok( hr == CACHE_E_NOCACHE_UPDATED, "got %08x\n", hr );
2831 
2832     CHECK_NO_EXTRA_METHODS();
2833     check_enum_cache( cache, view_cache, 1 );
2834 
2835     g_dataobject_fmts = dib_fmt;
2836     expected_method_list = methods_viewcache_with_dib;
2837 
2838     hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2839     ok( hr == S_OK, "got %08x\n", hr );
2840 
2841     CHECK_NO_EXTRA_METHODS();
2842     view_cache_after_dib[0].dwConnection = view_cache_after_dib[1].dwConnection = view_cache[0].dwConnection;
2843     check_enum_cache( cache, view_cache_after_dib, 2 );
2844 
2845     hr = IOleCache2_Uncache( cache, conn[0] );
2846     ok( hr == S_OK, "got %08x\n", hr );
2847 
2848     /* Try some different flags */
2849 
2850     fmt.cfFormat = CF_DIB;
2851     fmt.ptd = NULL;
2852     fmt.dwAspect = DVASPECT_CONTENT;
2853     fmt.lindex = -1;
2854     fmt.tymed = TYMED_HGLOBAL;
2855 
2856     hr = IOleCache2_Cache( cache, &fmt, 0, &conn[0] );
2857     ok( hr == S_OK, "got %08x\n", hr );
2858 
2859     fmt.cfFormat = CF_ENHMETAFILE;
2860     fmt.ptd = NULL;
2861     fmt.dwAspect = DVASPECT_CONTENT;
2862     fmt.lindex = -1;
2863     fmt.tymed = TYMED_ENHMF;
2864 
2865     hr = IOleCache2_Cache( cache, &fmt, ADVF_NODATA, &conn[1] );
2866     ok( hr == S_OK, "got %08x\n", hr );
2867 
2868     fmt.cfFormat = CF_METAFILEPICT;
2869     fmt.ptd = NULL;
2870     fmt.dwAspect = DVASPECT_CONTENT;
2871     fmt.lindex = -1;
2872     fmt.tymed = TYMED_MFPICT;
2873 
2874     hr = IOleCache2_Cache( cache, &fmt, ADVFCACHE_ONSAVE, &conn[2] );
2875     ok( hr == S_OK, "got %08x\n", hr );
2876 
2877     g_dataobject_fmts = dib_fmt;
2878     expected_method_list = methods_flags_all;
2879 
2880     hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2881 
2882     CHECK_NO_EXTRA_METHODS();
2883 
2884     expected_method_list = methods_flags_all;
2885 
2886     hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2887     ok( hr == S_OK, "got %08x\n", hr );
2888 
2889     CHECK_NO_EXTRA_METHODS();
2890 
2891     expected_method_list = methods_flags_ifblank_1;
2892 
2893     hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_IFBLANK , NULL );
2894     ok( hr == S_OK, "got %08x\n", hr );
2895 
2896     CHECK_NO_EXTRA_METHODS();
2897 
2898     hr = IOleCache2_DiscardCache( cache, DISCARDCACHE_NOSAVE );
2899     ok( hr == S_OK, "got %08x\n", hr );
2900 
2901     expected_method_list = methods_flags_ifblank_2;
2902 
2903     hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_IFBLANK , NULL );
2904     ok( hr == S_OK, "got %08x\n", hr );
2905 
2906     CHECK_NO_EXTRA_METHODS();
2907 
2908     hr = IOleCache2_DiscardCache( cache, DISCARDCACHE_NOSAVE );
2909     ok( hr == S_OK, "got %08x\n", hr );
2910 
2911     expected_method_list = methods_flags_all;
2912 
2913     hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_IFBLANK | UPDFCACHE_NODATACACHE, NULL );
2914     ok( hr == S_OK, "got %08x\n", hr );
2915 
2916     CHECK_NO_EXTRA_METHODS();
2917 
2918     expected_method_list = methods_empty;
2919 
2920     hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ONLYIFBLANK | UPDFCACHE_NORMALCACHE, NULL );
2921     ok( hr == S_OK, "got %08x\n", hr );
2922 
2923     CHECK_NO_EXTRA_METHODS();
2924 
2925     hr = IOleCache2_DiscardCache( cache, DISCARDCACHE_NOSAVE );
2926     ok( hr == S_OK, "got %08x\n", hr );
2927 
2928     expected_method_list = methods_flags_normal;
2929 
2930     hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ONLYIFBLANK | UPDFCACHE_NORMALCACHE, NULL );
2931     ok( hr == S_OK, "got %08x\n", hr );
2932 
2933     CHECK_NO_EXTRA_METHODS();
2934 
2935     expected_method_list = methods_initcache;
2936 
2937     hr = IOleCache2_InitCache( cache, &DataObject );
2938     ok( hr == S_OK, "got %08x\n", hr );
2939 
2940     CHECK_NO_EXTRA_METHODS();
2941 
2942     IOleCache2_Release( cache );
2943 }
2944 
test_default_handler(void)2945 static void test_default_handler(void)
2946 {
2947     HRESULT hr;
2948     IOleObject *pObject;
2949     IRunnableObject *pRunnableObject;
2950     IOleClientSite *pClientSite;
2951     IDataObject *pDataObject;
2952     SIZEL sizel;
2953     DWORD dwStatus;
2954     CLSID clsid;
2955     LPOLESTR pszUserType;
2956     LOGPALETTE palette;
2957     DWORD dwAdvConn;
2958     IMoniker *pMoniker;
2959     FORMATETC fmtetc;
2960     IOleInPlaceObject *pInPlaceObj;
2961     IEnumOLEVERB *pEnumVerbs;
2962     DWORD dwRegister;
2963     static const WCHAR wszUnknown[] = {'U','n','k','n','o','w','n',0};
2964     static const WCHAR wszHostName[] = {'W','i','n','e',' ','T','e','s','t',' ','P','r','o','g','r','a','m',0};
2965     static const WCHAR wszDelim[] = {'!',0};
2966 
2967     static const struct expected_method methods_embeddinghelper[] =
2968     {
2969         { "OleObject_QueryInterface", 0 },
2970         { "OleObject_AddRef", 0 },
2971         { "OleObject_QueryInterface", 0 },
2972         { "OleObject_QueryInterface", TEST_TODO },
2973         { "OleObject_QueryInterface", 0 },
2974         { "OleObject_QueryInterface", 0 },
2975         { "OleObject_QueryInterface", TEST_OPTIONAL }, /* Win95/98/NT4 */
2976         { "OleObject_Release", TEST_TODO },
2977         { "WINE_EXTRA", TEST_OPTIONAL },
2978         { NULL, 0 }
2979     };
2980 
2981     hr = CoCreateInstance(&CLSID_WineTest, NULL, CLSCTX_INPROC_HANDLER, &IID_IOleObject, (void **)&pObject);
2982     ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance should have failed with REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2983 
2984     hr = OleCreateDefaultHandler(&CLSID_WineTest, NULL, &IID_IOleObject, (void **)&pObject);
2985     ok_ole_success(hr, "OleCreateDefaultHandler");
2986 
2987     hr = IOleObject_QueryInterface(pObject, &IID_IOleInPlaceObject, (void **)&pInPlaceObj);
2988     ok(hr == E_NOINTERFACE, "IOleObject_QueryInterface(&IID_IOleInPlaceObject) should return E_NOINTERFACE instead of 0x%08x\n", hr);
2989 
2990     hr = IOleObject_Advise(pObject, &AdviseSink, &dwAdvConn);
2991     ok_ole_success(hr, "IOleObject_Advise");
2992 
2993     hr = IOleObject_Close(pObject, OLECLOSE_NOSAVE);
2994     ok_ole_success(hr, "IOleObject_Close");
2995 
2996     /* FIXME: test IOleObject_EnumAdvise */
2997 
2998     hr = IOleObject_EnumVerbs(pObject, &pEnumVerbs);
2999     ok(hr == REGDB_E_CLASSNOTREG, "IOleObject_EnumVerbs should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
3000 
3001     hr = IOleObject_GetClientSite(pObject, &pClientSite);
3002     ok_ole_success(hr, "IOleObject_GetClientSite");
3003 
3004     hr = IOleObject_SetClientSite(pObject, pClientSite);
3005     ok_ole_success(hr, "IOleObject_SetClientSite");
3006 
3007     hr = IOleObject_GetClipboardData(pObject, 0, &pDataObject);
3008     ok(hr == OLE_E_NOTRUNNING,
3009        "IOleObject_GetClipboardData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n",
3010        hr);
3011 
3012     hr = IOleObject_GetExtent(pObject, DVASPECT_CONTENT, &sizel);
3013     ok(hr == OLE_E_BLANK, "IOleObject_GetExtent should have returned OLE_E_BLANK instead of 0x%08x\n",
3014        hr);
3015 
3016     hr = IOleObject_GetMiscStatus(pObject, DVASPECT_CONTENT, &dwStatus);
3017     ok(hr == REGDB_E_CLASSNOTREG, "IOleObject_GetMiscStatus should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
3018 
3019     hr = IOleObject_GetUserClassID(pObject, &clsid);
3020     ok_ole_success(hr, "IOleObject_GetUserClassID");
3021     ok(IsEqualCLSID(&clsid, &CLSID_WineTest), "clsid != CLSID_WineTest\n");
3022 
3023     hr = IOleObject_GetUserType(pObject, USERCLASSTYPE_FULL, &pszUserType);
3024     todo_wine {
3025     ok_ole_success(hr, "IOleObject_GetUserType");
3026     ok(!lstrcmpW(pszUserType, wszUnknown), "Retrieved user type was wrong\n");
3027     }
3028 
3029     hr = IOleObject_InitFromData(pObject, NULL, TRUE, 0);
3030     ok(hr == OLE_E_NOTRUNNING, "IOleObject_InitFromData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
3031 
3032     hr = IOleObject_IsUpToDate(pObject);
3033     ok(hr == OLE_E_NOTRUNNING, "IOleObject_IsUpToDate should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
3034 
3035     palette.palNumEntries = 1;
3036     palette.palVersion = 2;
3037     memset(&palette.palPalEntry[0], 0, sizeof(palette.palPalEntry[0]));
3038     hr = IOleObject_SetColorScheme(pObject, &palette);
3039     ok(hr == OLE_E_NOTRUNNING, "IOleObject_SetColorScheme should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
3040 
3041     sizel.cx = sizel.cy = 0;
3042     hr = IOleObject_SetExtent(pObject, DVASPECT_CONTENT, &sizel);
3043     ok(hr == OLE_E_NOTRUNNING, "IOleObject_SetExtent should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
3044 
3045     hr = IOleObject_SetHostNames(pObject, wszHostName, NULL);
3046     ok_ole_success(hr, "IOleObject_SetHostNames");
3047 
3048     hr = CreateItemMoniker(wszDelim, wszHostName, &pMoniker);
3049     ok_ole_success(hr, "CreateItemMoniker");
3050     hr = IOleObject_SetMoniker(pObject, OLEWHICHMK_CONTAINER, pMoniker);
3051     ok_ole_success(hr, "IOleObject_SetMoniker");
3052     IMoniker_Release(pMoniker);
3053 
3054     hr = IOleObject_GetMoniker(pObject, OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_CONTAINER, &pMoniker);
3055     ok(hr == E_FAIL, "IOleObject_GetMoniker should have returned E_FAIL instead of 0x%08x\n", hr);
3056 
3057     hr = IOleObject_Update(pObject);
3058     todo_wine
3059     ok(hr == REGDB_E_CLASSNOTREG, "IOleObject_Update should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
3060 
3061     hr = IOleObject_QueryInterface(pObject, &IID_IDataObject, (void **)&pDataObject);
3062     ok_ole_success(hr, "IOleObject_QueryInterface");
3063 
3064     fmtetc.cfFormat = CF_TEXT;
3065     fmtetc.ptd = NULL;
3066     fmtetc.dwAspect = DVASPECT_CONTENT;
3067     fmtetc.lindex = -1;
3068     fmtetc.tymed = TYMED_NULL;
3069     hr = IDataObject_DAdvise(pDataObject, &fmtetc, 0, &AdviseSink, &dwAdvConn);
3070     ok_ole_success(hr, "IDataObject_DAdvise");
3071 
3072     fmtetc.cfFormat = CF_ENHMETAFILE;
3073     fmtetc.ptd = NULL;
3074     fmtetc.dwAspect = DVASPECT_CONTENT;
3075     fmtetc.lindex = -1;
3076     fmtetc.tymed = TYMED_ENHMF;
3077     hr = IDataObject_DAdvise(pDataObject, &fmtetc, 0, &AdviseSink, &dwAdvConn);
3078     ok_ole_success(hr, "IDataObject_DAdvise");
3079 
3080     fmtetc.cfFormat = CF_ENHMETAFILE;
3081     fmtetc.ptd = NULL;
3082     fmtetc.dwAspect = DVASPECT_CONTENT;
3083     fmtetc.lindex = -1;
3084     fmtetc.tymed = TYMED_ENHMF;
3085     hr = IDataObject_QueryGetData(pDataObject, &fmtetc);
3086     ok(hr == OLE_E_NOTRUNNING, "IDataObject_QueryGetData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
3087 
3088     fmtetc.cfFormat = CF_TEXT;
3089     fmtetc.ptd = NULL;
3090     fmtetc.dwAspect = DVASPECT_CONTENT;
3091     fmtetc.lindex = -1;
3092     fmtetc.tymed = TYMED_NULL;
3093     hr = IDataObject_QueryGetData(pDataObject, &fmtetc);
3094     ok(hr == OLE_E_NOTRUNNING, "IDataObject_QueryGetData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
3095 
3096     hr = IOleObject_QueryInterface(pObject, &IID_IRunnableObject, (void **)&pRunnableObject);
3097     ok_ole_success(hr, "IOleObject_QueryInterface");
3098 
3099     hr = IRunnableObject_SetContainedObject(pRunnableObject, TRUE);
3100     ok_ole_success(hr, "IRunnableObject_SetContainedObject");
3101 
3102     hr = IRunnableObject_Run(pRunnableObject, NULL);
3103     ok(hr == REGDB_E_CLASSNOTREG, "IOleObject_Run should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
3104 
3105     hr = IOleObject_Close(pObject, OLECLOSE_NOSAVE);
3106     ok_ole_success(hr, "IOleObject_Close");
3107 
3108     IRunnableObject_Release(pRunnableObject);
3109     IOleObject_Release(pObject);
3110 
3111     /* Test failure propagation from delegate ::QueryInterface */
3112     hr = CoRegisterClassObject(&CLSID_WineTest, (IUnknown*)&OleObjectCF,
3113                                CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegister);
3114     ok_ole_success(hr, "CoRegisterClassObject");
3115     if(SUCCEEDED(hr))
3116     {
3117         expected_method_list = methods_embeddinghelper;
3118         hr = OleCreateEmbeddingHelper(&CLSID_WineTest, NULL, EMBDHLP_INPROC_SERVER,
3119                                       &OleObjectCF, &IID_IOleObject, (void**)&pObject);
3120         ok_ole_success(hr, "OleCreateEmbeddingHelper");
3121         if(SUCCEEDED(hr))
3122         {
3123             IUnknown *punk;
3124 
3125             g_QIFailsWith = E_FAIL;
3126             hr = IOleObject_QueryInterface(pObject, &IID_WineTest, (void**)&punk);
3127             ok(hr == E_FAIL, "Got 0x%08x\n", hr);
3128 
3129             g_QIFailsWith = E_NOINTERFACE;
3130             hr = IOleObject_QueryInterface(pObject, &IID_WineTest, (void**)&punk);
3131             ok(hr == E_NOINTERFACE, "Got 0x%08x\n", hr);
3132 
3133             g_QIFailsWith = CO_E_OBJNOTCONNECTED;
3134             hr = IOleObject_QueryInterface(pObject, &IID_WineTest, (void**)&punk);
3135             ok(hr == CO_E_OBJNOTCONNECTED, "Got 0x%08x\n", hr);
3136 
3137             g_QIFailsWith = 0x87654321;
3138             hr = IOleObject_QueryInterface(pObject, &IID_WineTest, (void**)&punk);
3139             ok(hr == 0x87654321, "Got 0x%08x\n", hr);
3140 
3141             IOleObject_Release(pObject);
3142         }
3143 
3144         CHECK_NO_EXTRA_METHODS();
3145 
3146         hr = CoRevokeClassObject(dwRegister);
3147         ok_ole_success(hr, "CoRevokeClassObject");
3148     }
3149 }
3150 
test_runnable(void)3151 static void test_runnable(void)
3152 {
3153     static const struct expected_method methods_query_runnable[] =
3154     {
3155         { "OleObject_QueryInterface", 0 },
3156         { "OleObjectRunnable_AddRef", 0 },
3157         { "OleObjectRunnable_IsRunning", 0 },
3158         { "OleObjectRunnable_Release", 0 },
3159         { NULL, 0 }
3160     };
3161 
3162     static const struct expected_method methods_no_runnable[] =
3163     {
3164         { "OleObject_QueryInterface", 0 },
3165         { NULL, 0 }
3166     };
3167 
3168     BOOL ret;
3169     IOleObject *object = &OleObject;
3170 
3171     /* null argument */
3172     ret = OleIsRunning(NULL);
3173     ok(ret == FALSE, "got %d\n", ret);
3174 
3175     expected_method_list = methods_query_runnable;
3176     ret = OleIsRunning(object);
3177     ok(ret == TRUE, "Object should be running\n");
3178     CHECK_NO_EXTRA_METHODS();
3179 
3180     g_isRunning = FALSE;
3181     expected_method_list = methods_query_runnable;
3182     ret = OleIsRunning(object);
3183     ok(ret == FALSE, "Object should not be running\n");
3184     CHECK_NO_EXTRA_METHODS();
3185 
3186     g_showRunnable = FALSE;  /* QueryInterface(IID_IRunnableObject, ...) will fail */
3187     expected_method_list = methods_no_runnable;
3188     ret = OleIsRunning(object);
3189     ok(ret == TRUE, "Object without IRunnableObject should be running\n");
3190     CHECK_NO_EXTRA_METHODS();
3191 
3192     g_isRunning = TRUE;
3193     g_showRunnable = TRUE;
3194 }
3195 
3196 
OleRun_QueryInterface(IRunnableObject * iface,REFIID riid,void ** ppv)3197 static HRESULT WINAPI OleRun_QueryInterface(IRunnableObject *iface, REFIID riid, void **ppv)
3198 {
3199     *ppv = NULL;
3200 
3201     if (IsEqualIID(riid, &IID_IUnknown) ||
3202         IsEqualIID(riid, &IID_IRunnableObject)) {
3203         *ppv = iface;
3204     }
3205 
3206     if (*ppv)
3207     {
3208         IUnknown_AddRef((IUnknown *)*ppv);
3209         return S_OK;
3210     }
3211 
3212     return E_NOINTERFACE;
3213 }
3214 
OleRun_AddRef(IRunnableObject * iface)3215 static ULONG WINAPI OleRun_AddRef(IRunnableObject *iface)
3216 {
3217     return 2;
3218 }
3219 
OleRun_Release(IRunnableObject * iface)3220 static ULONG WINAPI OleRun_Release(IRunnableObject *iface)
3221 {
3222     return 1;
3223 }
3224 
OleRun_GetRunningClass(IRunnableObject * iface,CLSID * clsid)3225 static HRESULT WINAPI OleRun_GetRunningClass(IRunnableObject *iface, CLSID *clsid)
3226 {
3227     ok(0, "unexpected\n");
3228     return E_NOTIMPL;
3229 }
3230 
OleRun_Run(IRunnableObject * iface,LPBINDCTX ctx)3231 static HRESULT WINAPI OleRun_Run(IRunnableObject *iface, LPBINDCTX ctx)
3232 {
3233     ok(ctx == NULL, "got %p\n", ctx);
3234     return 0xdeadc0de;
3235 }
3236 
OleRun_IsRunning(IRunnableObject * iface)3237 static BOOL WINAPI OleRun_IsRunning(IRunnableObject *iface)
3238 {
3239     ok(0, "unexpected\n");
3240     return FALSE;
3241 }
3242 
OleRun_LockRunning(IRunnableObject * iface,BOOL lock,BOOL last_unlock_closes)3243 static HRESULT WINAPI OleRun_LockRunning(IRunnableObject *iface, BOOL lock,
3244     BOOL last_unlock_closes)
3245 {
3246     ok(0, "unexpected\n");
3247     return E_NOTIMPL;
3248 }
3249 
OleRun_SetContainedObject(IRunnableObject * iface,BOOL contained)3250 static HRESULT WINAPI OleRun_SetContainedObject(IRunnableObject *iface, BOOL contained)
3251 {
3252     ok(0, "unexpected\n");
3253     return E_NOTIMPL;
3254 }
3255 
3256 static const IRunnableObjectVtbl oleruntestvtbl =
3257 {
3258     OleRun_QueryInterface,
3259     OleRun_AddRef,
3260     OleRun_Release,
3261     OleRun_GetRunningClass,
3262     OleRun_Run,
3263     OleRun_IsRunning,
3264     OleRun_LockRunning,
3265     OleRun_SetContainedObject
3266 };
3267 
3268 static IRunnableObject testrunnable = { &oleruntestvtbl };
3269 
test_OleRun(void)3270 static void test_OleRun(void)
3271 {
3272     HRESULT hr;
3273 
3274     /* doesn't support IRunnableObject */
3275     hr = OleRun(&unknown);
3276     ok(hr == S_OK, "OleRun failed 0x%08x\n", hr);
3277 
3278     hr = OleRun((IUnknown*)&testrunnable);
3279     ok(hr == 0xdeadc0de, "got 0x%08x\n", hr);
3280 }
3281 
test_OleLockRunning(void)3282 static void test_OleLockRunning(void)
3283 {
3284     HRESULT hr;
3285 
3286     hr = OleLockRunning(&unknown, TRUE, FALSE);
3287     ok(hr == S_OK, "OleLockRunning failed 0x%08x\n", hr);
3288 }
3289 
test_OleDraw(void)3290 static void test_OleDraw(void)
3291 {
3292     HRESULT hr;
3293     RECT rect;
3294 
3295     hr = OleDraw((IUnknown*)&viewobject, 0, (HDC)0x1, NULL);
3296     ok(hr == S_OK, "got 0x%08x\n", hr);
3297 
3298     hr = OleDraw(NULL, 0, (HDC)0x1, NULL);
3299     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3300 
3301     hr = OleDraw(NULL, 0, (HDC)0x1, &rect);
3302     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3303 }
3304 
3305 static const WCHAR olepres0W[] = {2,'O','l','e','P','r','e','s','0','0','0',0};
3306 static const WCHAR comp_objW[] = {1,'C','o','m','p','O','b','j',0};
3307 static IStream *comp_obj_stream;
3308 static IStream *ole_stream;
3309 static IStream *olepres_stream;
3310 static IStream *contents_stream;
3311 
Storage_QueryInterface(IStorage * iface,REFIID riid,void ** ppvObject)3312 static HRESULT WINAPI Storage_QueryInterface(IStorage *iface, REFIID riid, void **ppvObject)
3313 {
3314     ok(0, "unexpected call to QueryInterface\n");
3315     return E_NOTIMPL;
3316 }
3317 
Storage_AddRef(IStorage * iface)3318 static ULONG WINAPI Storage_AddRef(IStorage *iface)
3319 {
3320     ok(0, "unexpected call to AddRef\n");
3321     return 2;
3322 }
3323 
Storage_Release(IStorage * iface)3324 static ULONG WINAPI Storage_Release(IStorage *iface)
3325 {
3326     ok(0, "unexpected call to Release\n");
3327     return 1;
3328 }
3329 
Storage_CreateStream(IStorage * iface,LPCOLESTR pwcsName,DWORD grfMode,DWORD reserved1,DWORD reserved2,IStream ** ppstm)3330 static HRESULT WINAPI Storage_CreateStream(IStorage *iface, LPCOLESTR pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStream **ppstm)
3331 {
3332     ULARGE_INTEGER size = {{0}};
3333     LARGE_INTEGER pos = {{0}};
3334     HRESULT hr;
3335 
3336     if (!lstrcmpW(pwcsName, comp_objW))
3337     {
3338         CHECK_EXPECT(Storage_CreateStream_CompObj);
3339         *ppstm = comp_obj_stream;
3340 
3341         todo_wine ok(grfMode == (STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
3342     }
3343     else if (!lstrcmpW(pwcsName, olepres0W))
3344     {
3345         CHECK_EXPECT(Storage_CreateStream_OlePres);
3346         *ppstm = olepres_stream;
3347 
3348         todo_wine ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
3349     }
3350     else
3351     {
3352 todo_wine
3353         ok(0, "unexpected stream name %s\n", wine_dbgstr_w(pwcsName));
3354 #if 0   /* FIXME: return NULL once Wine is fixed */
3355         *ppstm = NULL;
3356         return E_NOTIMPL;
3357 #else
3358         *ppstm = contents_stream;
3359 #endif
3360     }
3361 
3362     ok(!reserved1, "reserved1 = %x\n", reserved1);
3363     ok(!reserved2, "reserved2 = %x\n", reserved2);
3364     ok(!!ppstm, "ppstm = NULL\n");
3365 
3366     IStream_AddRef(*ppstm);
3367     hr = IStream_Seek(*ppstm, pos, STREAM_SEEK_SET, NULL);
3368     ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3369     hr = IStream_SetSize(*ppstm, size);
3370     ok(hr == S_OK, "IStream_SetSize returned %x\n", hr);
3371     return S_OK;
3372 }
3373 
Storage_OpenStream(IStorage * iface,LPCOLESTR pwcsName,void * reserved1,DWORD grfMode,DWORD reserved2,IStream ** ppstm)3374 static HRESULT WINAPI Storage_OpenStream(IStorage *iface, LPCOLESTR pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream **ppstm)
3375 {
3376     static  const WCHAR ole1W[] = {1,'O','l','e',0};
3377 
3378     LARGE_INTEGER pos = {{0}};
3379     HRESULT hr;
3380 
3381     ok(!reserved1, "reserved1 = %p\n", reserved1);
3382     ok(!reserved2, "reserved2 = %x\n", reserved2);
3383     ok(!!ppstm, "ppstm = NULL\n");
3384 
3385     if(!lstrcmpW(pwcsName, comp_objW)) {
3386         CHECK_EXPECT2(Storage_OpenStream_CompObj);
3387         ok(grfMode == STGM_SHARE_EXCLUSIVE, "grfMode = %x\n", grfMode);
3388 
3389         *ppstm = comp_obj_stream;
3390         IStream_AddRef(comp_obj_stream);
3391         hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL);
3392         ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3393         return S_OK;
3394     }else if(!lstrcmpW(pwcsName, ole1W)) {
3395         CHECK_EXPECT(Storage_OpenStream_Ole);
3396 
3397         if (!ole_stream)
3398         {
3399             ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READ), "grfMode = %x\n", grfMode);
3400 
3401             *ppstm = NULL;
3402             return STG_E_FILENOTFOUND;
3403         }
3404 
3405         ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
3406 
3407         *ppstm = ole_stream;
3408         IStream_AddRef(ole_stream);
3409         hr = IStream_Seek(ole_stream, pos, STREAM_SEEK_SET, NULL);
3410         ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3411         return S_OK;
3412 
3413     }else if(!lstrcmpW(pwcsName, olepres0W)) {
3414         CHECK_EXPECT(Storage_OpenStream_OlePres);
3415         ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
3416 
3417         *ppstm = olepres_stream;
3418         IStream_AddRef(olepres_stream);
3419         hr = IStream_Seek(olepres_stream, pos, STREAM_SEEK_SET, NULL);
3420         ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3421         return S_OK;
3422     }
3423 
3424     ok(0, "unexpected call to OpenStream: %s\n", wine_dbgstr_w(pwcsName));
3425     return E_NOTIMPL;
3426 }
3427 
Storage_CreateStorage(IStorage * iface,LPCOLESTR pwcsName,DWORD grfMode,DWORD dwStgFmt,DWORD reserved2,IStorage ** ppstg)3428 static HRESULT WINAPI Storage_CreateStorage(IStorage *iface, LPCOLESTR pwcsName, DWORD grfMode, DWORD dwStgFmt, DWORD reserved2, IStorage **ppstg)
3429 {
3430     ok(0, "unexpected call to CreateStorage\n");
3431     return E_NOTIMPL;
3432 }
3433 
Storage_OpenStorage(IStorage * iface,LPCOLESTR pwcsName,IStorage * pstgPriority,DWORD grfMode,SNB snbExclude,DWORD reserved,IStorage ** ppstg)3434 static HRESULT WINAPI Storage_OpenStorage(IStorage *iface, LPCOLESTR pwcsName, IStorage *pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage **ppstg)
3435 {
3436     ok(0, "unexpected call to OpenStorage\n");
3437     return E_NOTIMPL;
3438 }
3439 
Storage_CopyTo(IStorage * iface,DWORD ciidExclude,const IID * rgiidExclude,SNB snbExclude,IStorage * pstgDest)3440 static HRESULT WINAPI Storage_CopyTo(IStorage *iface, DWORD ciidExclude, const IID *rgiidExclude, SNB snbExclude, IStorage *pstgDest)
3441 {
3442     ok(0, "unexpected call to CopyTo\n");
3443     return E_NOTIMPL;
3444 }
3445 
Storage_MoveElementTo(IStorage * iface,LPCOLESTR pwcsName,IStorage * pstgDest,LPCOLESTR pwcsNewName,DWORD grfFlags)3446 static HRESULT WINAPI Storage_MoveElementTo(IStorage *iface, LPCOLESTR pwcsName, IStorage *pstgDest, LPCOLESTR pwcsNewName, DWORD grfFlags)
3447 {
3448     ok(0, "unexpected call to MoveElementTo\n");
3449     return E_NOTIMPL;
3450 }
3451 
Storage_Commit(IStorage * iface,DWORD grfCommitFlags)3452 static HRESULT WINAPI Storage_Commit(IStorage *iface, DWORD grfCommitFlags)
3453 {
3454     ok(0, "unexpected call to Commit\n");
3455     return E_NOTIMPL;
3456 }
3457 
Storage_Revert(IStorage * iface)3458 static HRESULT WINAPI Storage_Revert(IStorage *iface)
3459 {
3460     ok(0, "unexpected call to Revert\n");
3461     return E_NOTIMPL;
3462 }
3463 
Storage_EnumElements(IStorage * iface,DWORD reserved1,void * reserved2,DWORD reserved3,IEnumSTATSTG ** ppenum)3464 static HRESULT WINAPI Storage_EnumElements(IStorage *iface, DWORD reserved1, void *reserved2, DWORD reserved3, IEnumSTATSTG **ppenum)
3465 {
3466     ok(0, "unexpected call to EnumElements\n");
3467     return E_NOTIMPL;
3468 }
3469 
Storage_DestroyElement(IStorage * iface,LPCOLESTR pwcsName)3470 static HRESULT WINAPI Storage_DestroyElement(IStorage *iface, LPCOLESTR pwcsName)
3471 {
3472     char name[32];
3473     int stream_n, cmp;
3474 
3475     CHECK_EXPECT2(Storage_DestroyElement);
3476     cmp = CompareStringW(LOCALE_NEUTRAL, 0, pwcsName, 8, olepres0W, 8);
3477     ok(cmp == CSTR_EQUAL,
3478        "unexpected call to DestroyElement(%s)\n", wine_dbgstr_w(pwcsName));
3479 
3480     WideCharToMultiByte(CP_ACP, 0, pwcsName, -1, name, sizeof(name), NULL, NULL);
3481     stream_n = atol(name + 8);
3482     if (stream_n <= Storage_DestroyElement_limit)
3483         return S_OK;
3484 
3485     return STG_E_FILENOTFOUND;
3486 }
3487 
Storage_RenameElement(IStorage * iface,LPCOLESTR pwcsOldName,LPCOLESTR pwcsNewName)3488 static HRESULT WINAPI Storage_RenameElement(IStorage *iface, LPCOLESTR pwcsOldName, LPCOLESTR pwcsNewName)
3489 {
3490     ok(0, "unexpected call to RenameElement\n");
3491     return E_NOTIMPL;
3492 }
3493 
Storage_SetElementTimes(IStorage * iface,LPCOLESTR pwcsName,const FILETIME * pctime,const FILETIME * patime,const FILETIME * pmtime)3494 static HRESULT WINAPI Storage_SetElementTimes(IStorage *iface, LPCOLESTR pwcsName, const FILETIME *pctime, const FILETIME *patime, const FILETIME *pmtime)
3495 {
3496     ok(0, "unexpected call to SetElementTimes\n");
3497     return E_NOTIMPL;
3498 }
3499 
Storage_SetClass(IStorage * iface,REFCLSID clsid)3500 static HRESULT WINAPI Storage_SetClass(IStorage *iface, REFCLSID clsid)
3501 {
3502     CHECK_EXPECT(Storage_SetClass);
3503     ok(IsEqualIID(clsid, Storage_SetClass_CLSID), "expected %s, got %s\n",
3504        wine_dbgstr_guid(Storage_SetClass_CLSID), wine_dbgstr_guid(clsid));
3505     return S_OK;
3506 }
3507 
Storage_SetStateBits(IStorage * iface,DWORD grfStateBits,DWORD grfMask)3508 static HRESULT WINAPI Storage_SetStateBits(IStorage *iface, DWORD grfStateBits, DWORD grfMask)
3509 {
3510     ok(0, "unexpected call to SetStateBits\n");
3511     return E_NOTIMPL;
3512 }
3513 
Storage_Stat(IStorage * iface,STATSTG * pstatstg,DWORD grfStatFlag)3514 static HRESULT WINAPI Storage_Stat(IStorage *iface, STATSTG *pstatstg, DWORD grfStatFlag)
3515 {
3516     CHECK_EXPECT2(Storage_Stat);
3517     ok(pstatstg != NULL, "pstatstg = NULL\n");
3518     ok(grfStatFlag == STATFLAG_NONAME, "grfStatFlag = %x\n", grfStatFlag);
3519 
3520     memset(pstatstg, 0, sizeof(STATSTG));
3521     pstatstg->type = STGTY_STORAGE;
3522     pstatstg->clsid = CLSID_WineTestOld;
3523     return S_OK;
3524 }
3525 
3526 static IStorageVtbl StorageVtbl =
3527 {
3528     Storage_QueryInterface,
3529     Storage_AddRef,
3530     Storage_Release,
3531     Storage_CreateStream,
3532     Storage_OpenStream,
3533     Storage_CreateStorage,
3534     Storage_OpenStorage,
3535     Storage_CopyTo,
3536     Storage_MoveElementTo,
3537     Storage_Commit,
3538     Storage_Revert,
3539     Storage_EnumElements,
3540     Storage_DestroyElement,
3541     Storage_RenameElement,
3542     Storage_SetElementTimes,
3543     Storage_SetClass,
3544     Storage_SetStateBits,
3545     Storage_Stat
3546 };
3547 
3548 static IStorage Storage = { &StorageVtbl };
3549 
test_OleDoAutoConvert(void)3550 static void test_OleDoAutoConvert(void)
3551 {
3552     static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0};
3553     static struct {
3554         DWORD reserved1;
3555         DWORD version;
3556         DWORD reserved2[5];
3557         DWORD ansi_user_type_len;
3558         DWORD ansi_clipboard_format_len;
3559         DWORD reserved3;
3560         DWORD unicode_marker;
3561         DWORD unicode_user_type_len;
3562         DWORD unicode_clipboard_format_len;
3563         DWORD reserved4;
3564     } comp_obj_data;
3565     static struct {
3566         DWORD version;
3567         DWORD flags;
3568         DWORD link_update_option;
3569         DWORD reserved1;
3570         DWORD reserved_moniker_stream_size;
3571         DWORD relative_source_moniker_stream_size;
3572         DWORD absolute_source_moniker_stream_size;
3573         DWORD clsid_indicator;
3574         CLSID clsid;
3575         DWORD reserved_display_name;
3576         DWORD reserved2;
3577         DWORD local_update_time;
3578         DWORD local_check_update_time;
3579         DWORD remote_update_time;
3580     } ole_data;
3581 
3582     LARGE_INTEGER pos = {{0}};
3583     WCHAR buf[39+6];
3584     DWORD i, ret;
3585     HKEY root;
3586     CLSID clsid;
3587     HRESULT hr;
3588 
3589     hr = CreateStreamOnHGlobal(NULL, TRUE, &comp_obj_stream);
3590     ok(hr == S_OK, "CreateStreamOnHGlobal returned %x\n", hr);
3591     hr = IStream_Write(comp_obj_stream, (char*)&comp_obj_data, sizeof(comp_obj_data), NULL);
3592     ok(hr == S_OK, "IStream_Write returned %x\n", hr);
3593 
3594     hr = CreateStreamOnHGlobal(NULL, TRUE, &ole_stream);
3595     ok(hr == S_OK, "CreateStreamOnHGlobal returned %x\n", hr);
3596     hr = IStream_Write(ole_stream, (char*)&ole_data, sizeof(ole_data), NULL);
3597     ok(hr == S_OK, "IStream_Write returned %x\n", hr);
3598 
3599     clsid = IID_WineTest;
3600     hr = OleDoAutoConvert(NULL, &clsid);
3601     ok(hr == E_INVALIDARG, "OleDoAutoConvert returned %x\n", hr);
3602     ok(IsEqualIID(&clsid, &IID_NULL), "clsid = %s\n", wine_dbgstr_guid(&clsid));
3603 
3604     if(0) /* crashes on Win7 */
3605         OleDoAutoConvert(&Storage, NULL);
3606 
3607     clsid = IID_WineTest;
3608     SET_EXPECT(Storage_Stat);
3609     hr = OleDoAutoConvert(&Storage, &clsid);
3610     ok(hr == REGDB_E_CLASSNOTREG, "OleDoAutoConvert returned %x\n", hr);
3611     CHECK_CALLED(Storage_Stat);
3612     ok(IsEqualIID(&clsid, &CLSID_WineTestOld), "clsid = %s\n", wine_dbgstr_guid(&clsid));
3613 
3614     lstrcpyW(buf, clsidW);
3615     StringFromGUID2(&CLSID_WineTestOld, buf+6, 39);
3616 
3617     ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, buf, 0, NULL, 0,
3618             KEY_READ | KEY_WRITE | KEY_CREATE_SUB_KEY, NULL, &root, NULL);
3619     if(ret != ERROR_SUCCESS) {
3620         win_skip("not enough permissions to create CLSID key (%u)\n", ret);
3621         return;
3622     }
3623 
3624     clsid = IID_WineTest;
3625     SET_EXPECT(Storage_Stat);
3626     hr = OleDoAutoConvert(&Storage, &clsid);
3627     ok(hr == REGDB_E_KEYMISSING, "OleDoAutoConvert returned %x\n", hr);
3628     CHECK_CALLED(Storage_Stat);
3629     ok(IsEqualIID(&clsid, &CLSID_WineTestOld), "clsid = %s\n", wine_dbgstr_guid(&clsid));
3630 
3631     hr = OleSetAutoConvert(&CLSID_WineTestOld, &CLSID_WineTest);
3632     ok_ole_success(hr, "OleSetAutoConvert");
3633 
3634     hr = OleGetAutoConvert(&CLSID_WineTestOld, &clsid);
3635     ok_ole_success(hr, "OleGetAutoConvert");
3636     ok(IsEqualIID(&clsid, &CLSID_WineTest), "incorrect clsid: %s\n", wine_dbgstr_guid(&clsid));
3637 
3638     clsid = IID_WineTest;
3639     SET_EXPECT(Storage_Stat);
3640     SET_EXPECT(Storage_OpenStream_CompObj);
3641     SET_EXPECT(Storage_SetClass);
3642     SET_EXPECT(Storage_CreateStream_CompObj);
3643     SET_EXPECT(Storage_OpenStream_Ole);
3644     hr = OleDoAutoConvert(&Storage, &clsid);
3645     ok(hr == S_OK, "OleDoAutoConvert returned %x\n", hr);
3646     CHECK_CALLED(Storage_Stat);
3647     CHECK_CALLED(Storage_OpenStream_CompObj);
3648     CHECK_CALLED(Storage_SetClass);
3649     CHECK_CALLED(Storage_CreateStream_CompObj);
3650     CHECK_CALLED(Storage_OpenStream_Ole);
3651     ok(IsEqualIID(&clsid, &CLSID_WineTest), "clsid = %s\n", wine_dbgstr_guid(&clsid));
3652 
3653     hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL);
3654     ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3655     hr = IStream_Read(comp_obj_stream, &comp_obj_data, sizeof(comp_obj_data), NULL);
3656     ok(hr == S_OK, "IStream_Read returned %x\n", hr);
3657     ok(comp_obj_data.reserved1 == 0xfffe0001, "reserved1 = %x\n", comp_obj_data.reserved1);
3658     ok(comp_obj_data.version == 0xa03, "version = %x\n", comp_obj_data.version);
3659     ok(comp_obj_data.reserved2[0] == -1, "reserved2[0] = %x\n", comp_obj_data.reserved2[0]);
3660     ok(IsEqualIID(comp_obj_data.reserved2+1, &CLSID_WineTestOld), "reserved2 = %s\n", wine_dbgstr_guid((CLSID*)(comp_obj_data.reserved2+1)));
3661     ok(!comp_obj_data.ansi_user_type_len, "ansi_user_type_len = %d\n", comp_obj_data.ansi_user_type_len);
3662     ok(!comp_obj_data.ansi_clipboard_format_len, "ansi_clipboard_format_len = %d\n", comp_obj_data.ansi_clipboard_format_len);
3663     ok(!comp_obj_data.reserved3, "reserved3 = %x\n", comp_obj_data.reserved3);
3664     ok(comp_obj_data.unicode_marker == 0x71b239f4, "unicode_marker = %x\n", comp_obj_data.unicode_marker);
3665     ok(!comp_obj_data.unicode_user_type_len, "unicode_user_type_len = %d\n", comp_obj_data.unicode_user_type_len);
3666     ok(!comp_obj_data.unicode_clipboard_format_len, "unicode_clipboard_format_len = %d\n", comp_obj_data.unicode_clipboard_format_len);
3667     ok(!comp_obj_data.reserved4, "reserved4 %d\n", comp_obj_data.reserved4);
3668 
3669     hr = IStream_Seek(ole_stream, pos, STREAM_SEEK_SET, NULL);
3670     ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3671     hr = IStream_Read(ole_stream, &ole_data, sizeof(ole_data), NULL);
3672     ok(hr == S_OK, "IStream_Read returned %x\n", hr);
3673     ok(ole_data.version == 0, "version = %x\n", ole_data.version);
3674     ok(ole_data.flags == 4, "flags = %x\n", ole_data.flags);
3675     for(i=2; i<sizeof(ole_data)/sizeof(DWORD); i++)
3676         ok(((DWORD*)&ole_data)[i] == 0, "ole_data[%d] = %x\n", i, ((DWORD*)&ole_data)[i]);
3677 
3678     SET_EXPECT(Storage_OpenStream_Ole);
3679     hr = SetConvertStg(&Storage, TRUE);
3680     ok(hr == S_OK, "SetConvertStg returned %x\n", hr);
3681     CHECK_CALLED(Storage_OpenStream_Ole);
3682 
3683     SET_EXPECT(Storage_OpenStream_CompObj);
3684     SET_EXPECT(Storage_Stat);
3685     SET_EXPECT(Storage_CreateStream_CompObj);
3686     hr = WriteFmtUserTypeStg(&Storage, 0, NULL);
3687     ok(hr == S_OK, "WriteFmtUserTypeStg returned %x\n", hr);
3688     todo_wine CHECK_CALLED(Storage_OpenStream_CompObj);
3689     CHECK_CALLED(Storage_Stat);
3690     CHECK_CALLED(Storage_CreateStream_CompObj);
3691     hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL);
3692     ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
3693     hr = IStream_Read(comp_obj_stream, &comp_obj_data, sizeof(comp_obj_data), NULL);
3694     ok(hr == S_OK, "IStream_Read returned %x\n", hr);
3695     ok(comp_obj_data.reserved1 == 0xfffe0001, "reserved1 = %x\n", comp_obj_data.reserved1);
3696     ok(comp_obj_data.version == 0xa03, "version = %x\n", comp_obj_data.version);
3697     ok(comp_obj_data.reserved2[0] == -1, "reserved2[0] = %x\n", comp_obj_data.reserved2[0]);
3698     ok(IsEqualIID(comp_obj_data.reserved2+1, &CLSID_WineTestOld), "reserved2 = %s\n", wine_dbgstr_guid((CLSID*)(comp_obj_data.reserved2+1)));
3699     ok(!comp_obj_data.ansi_user_type_len, "ansi_user_type_len = %d\n", comp_obj_data.ansi_user_type_len);
3700     ok(!comp_obj_data.ansi_clipboard_format_len, "ansi_clipboard_format_len = %d\n", comp_obj_data.ansi_clipboard_format_len);
3701     ok(!comp_obj_data.reserved3, "reserved3 = %x\n", comp_obj_data.reserved3);
3702     ok(comp_obj_data.unicode_marker == 0x71b239f4, "unicode_marker = %x\n", comp_obj_data.unicode_marker);
3703     ok(!comp_obj_data.unicode_user_type_len, "unicode_user_type_len = %d\n", comp_obj_data.unicode_user_type_len);
3704     ok(!comp_obj_data.unicode_clipboard_format_len, "unicode_clipboard_format_len = %d\n", comp_obj_data.unicode_clipboard_format_len);
3705     ok(!comp_obj_data.reserved4, "reserved4 %d\n", comp_obj_data.reserved4);
3706 
3707     ret = IStream_Release(comp_obj_stream);
3708     ok(!ret, "comp_obj_stream was not freed\n");
3709     ret = IStream_Release(ole_stream);
3710     ok(!ret, "ole_stream was not freed\n");
3711 
3712     ret = RegDeleteKeyA(root, "AutoConvertTo");
3713     ok(ret == ERROR_SUCCESS, "RegDeleteKey error %u\n", ret);
3714     ret = RegDeleteKeyA(root, "");
3715     ok(ret == ERROR_SUCCESS, "RegDeleteKey error %u\n", ret);
3716     RegCloseKey(root);
3717 }
3718 
3719 /* 1x1 pixel bmp */
3720 static const unsigned char bmpimage[] =
3721 {
3722     0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,
3723     0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
3724     0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
3725     0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
3726     0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,
3727     0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
3728     0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,
3729     0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
3730     0x00,0x00
3731 };
3732 
3733 static const unsigned char mf_blank_bits[] =
3734 {
3735     0x01,0x00,0x09,0x00,0x00,0x03,0x0c,0x00,
3736     0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
3737     0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00
3738 };
3739 
test_data_cache_save(void)3740 static void test_data_cache_save(void)
3741 {
3742     static const WCHAR contentsW[] = { 'C','o','n','t','e','n','t','s',0 };
3743     HRESULT hr;
3744     ILockBytes *ilb;
3745     IStorage *doc;
3746     IStream *stm;
3747     IOleCache2 *cache;
3748     IPersistStorage *stg;
3749     DWORD clipformat[2];
3750     PresentationDataHeader hdr;
3751 
3752     hr = CreateILockBytesOnHGlobal(0, TRUE, &ilb);
3753     ok(hr == S_OK, "unexpected %#x\n", hr);
3754     hr = StgCreateDocfileOnILockBytes(ilb, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0,  &doc);
3755     ok(hr == S_OK, "unexpected %#x\n", hr);
3756 
3757     ILockBytes_Release(ilb);
3758 
3759     hr = IStorage_SetClass(doc, &CLSID_WineTest);
3760     ok(hr == S_OK, "unexpected %#x\n", hr);
3761 
3762     hr = IStorage_CreateStream(doc, contentsW, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3763     ok(hr == S_OK, "unexpected %#x\n", hr);
3764     hr = IStream_Write(stm, bmpimage, sizeof(bmpimage), NULL);
3765     ok(hr == S_OK, "unexpected %#x\n", hr);
3766     IStream_Release(stm);
3767 
3768     hr = IStorage_CreateStream(doc, olepres0W, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3769     ok(hr == S_OK, "unexpected %#x\n", hr);
3770 
3771     clipformat[0] = -1;
3772     clipformat[1] = CF_METAFILEPICT;
3773     hr = IStream_Write(stm, clipformat, sizeof(clipformat), NULL);
3774     ok(hr == S_OK, "unexpected %#x\n", hr);
3775 
3776     hdr.tdSize = sizeof(hdr.tdSize);
3777     hdr.dvAspect = DVASPECT_CONTENT;
3778     hdr.lindex = -1;
3779     hdr.advf = ADVF_PRIMEFIRST;
3780     hdr.unknown7 = 0;
3781     hdr.dwObjectExtentX = 0;
3782     hdr.dwObjectExtentY = 0;
3783     hdr.dwSize = sizeof(mf_blank_bits);
3784     hr = IStream_Write(stm, &hdr, sizeof(hdr), NULL);
3785     ok(hr == S_OK, "unexpected %#x\n", hr);
3786     hr = IStream_Write(stm, mf_blank_bits, sizeof(mf_blank_bits), NULL);
3787     ok(hr == S_OK, "unexpected %#x\n", hr);
3788 
3789     IStream_Release(stm);
3790 
3791     hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IUnknown, (void **)&cache);
3792     ok(hr == S_OK, "unexpected %#x\n", hr);
3793     hr = IOleCache2_QueryInterface(cache, &IID_IPersistStorage, (void **)&stg);
3794     ok(hr == S_OK, "unexpected %#x\n", hr);
3795     hr = IPersistStorage_Load(stg, doc);
3796     ok(hr == S_OK, "unexpected %#x\n", hr);
3797 
3798     IStorage_Release(doc);
3799 
3800     hr = IPersistStorage_IsDirty(stg);
3801     ok(hr == S_FALSE, "unexpected %#x\n", hr);
3802 
3803     ole_stream = NULL;
3804     hr = CreateStreamOnHGlobal(NULL, TRUE, &olepres_stream);
3805     ok(hr == S_OK, "unexpected %#x\n", hr);
3806 
3807     /* FIXME: remove this stream once Wine is fixed */
3808     hr = CreateStreamOnHGlobal(NULL, TRUE, &contents_stream);
3809     ok(hr == S_OK, "unexpected %#x\n", hr);
3810 
3811     SET_EXPECT(Storage_CreateStream_OlePres);
3812     SET_EXPECT(Storage_OpenStream_OlePres);
3813     SET_EXPECT(Storage_OpenStream_Ole);
3814     SET_EXPECT(Storage_DestroyElement);
3815     Storage_DestroyElement_limit = 50;
3816     Storage_SetClass_CLSID = &CLSID_NULL;
3817     trace("IPersistStorage_Save:\n");
3818     hr = IPersistStorage_Save(stg, &Storage, FALSE);
3819     ok(hr == S_OK, "unexpected %#x\n", hr);
3820     CHECK_CALLED(Storage_CreateStream_OlePres);
3821 todo_wine
3822     CHECK_CALLED(Storage_OpenStream_OlePres);
3823 todo_wine
3824     CHECK_CALLED(Storage_OpenStream_Ole);
3825 todo_wine
3826     CHECK_CALLED(Storage_DestroyElement);
3827 
3828     IStream_Release(olepres_stream);
3829     IStream_Release(contents_stream);
3830 
3831     IPersistStorage_Release(stg);
3832     IOleCache2_Release(cache);
3833 }
3834 
3835 #define MAX_STREAM 16
3836 
3837 struct stream_def
3838 {
3839     const char *name;
3840     int cf;
3841     DVASPECT dvAspect;
3842     ADVF advf;
3843     const void *data;
3844     size_t data_size;
3845 };
3846 
3847 struct storage_def
3848 {
3849     const CLSID *clsid;
3850     int stream_count;
3851     struct stream_def stream[MAX_STREAM];
3852 };
3853 
3854 static const struct storage_def stg_def_0 =
3855 {
3856     &CLSID_NULL, 1,
3857     {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) }}
3858 };
3859 static const struct storage_def stg_def_0_saved =
3860 {
3861     &CLSID_NULL, 0, {{ 0 }}
3862 };
3863 static const struct storage_def stg_def_1 =
3864 {
3865     &CLSID_NULL, 2,
3866     {{ "Contents", -1, 0, 0, NULL, 0 },
3867     { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3868 };
3869 static const struct storage_def stg_def_1_saved =
3870 {
3871     &CLSID_NULL, 1,
3872     {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3873 };
3874 static const struct storage_def stg_def_2 =
3875 {
3876     &CLSID_ManualResetEvent, 2,
3877     {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3878     { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3879 };
3880 static const struct storage_def stg_def_2_saved =
3881 {
3882     &CLSID_NULL, 1,
3883     {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3884 };
3885 static const struct storage_def stg_def_3 =
3886 {
3887     &CLSID_NULL, 5,
3888     {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3889     { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3890     { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3891     { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
3892     { "MyStream", -1, 0, 0, "Hello World!", 13 }}
3893 };
3894 static const struct storage_def stg_def_3_saved =
3895 {
3896     &CLSID_NULL, 3,
3897     {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3898     { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3899     { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) }}
3900 };
3901 static const struct storage_def stg_def_4 =
3902 {
3903     &CLSID_Picture_EnhMetafile, 5,
3904     {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3905     { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3906     { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3907     { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
3908     { "MyStream", -1, 0, 0, "Hello World!", 13 }}
3909 };
3910 static const struct storage_def stg_def_4_saved =
3911 {
3912     &CLSID_NULL, 1,
3913     {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3914 };
3915 static const struct storage_def stg_def_5 =
3916 {
3917     &CLSID_Picture_Dib, 5,
3918     {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3919     { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
3920     { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3921     { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3922     { "MyStream", -1, 0, 0, "Hello World!", 13 }}
3923 };
3924 static const struct storage_def stg_def_5_saved =
3925 {
3926     &CLSID_NULL, 1,
3927     {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3928 };
3929 static const struct storage_def stg_def_6 =
3930 {
3931     &CLSID_Picture_Metafile, 5,
3932     {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
3933     { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
3934     { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
3935     { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
3936     { "MyStream", -1, 0, 0, "Hello World!", 13 }}
3937 };
3938 static const struct storage_def stg_def_6_saved =
3939 {
3940     &CLSID_NULL, 1,
3941     {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
3942 };
3943 static const struct storage_def stg_def_7 =
3944 {
3945     &CLSID_Picture_Dib, 1,
3946     {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) }}
3947 };
3948 static const struct storage_def stg_def_7_saved =
3949 {
3950     &CLSID_NULL, 0, {{ 0 }}
3951 };
3952 static const struct storage_def stg_def_8 =
3953 {
3954     &CLSID_Picture_Metafile, 1,
3955     {{ "Contents", -1, 0, 0, mf_blank_bits, sizeof(mf_blank_bits) }}
3956 };
3957 static const struct storage_def stg_def_8_saved =
3958 {
3959     &CLSID_NULL, 0, {{ 0 }}
3960 };
3961 static const struct storage_def stg_def_9 =
3962 {
3963     &CLSID_Picture_EnhMetafile, 1,
3964     {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) }}
3965 };
3966 static const struct storage_def stg_def_9_saved =
3967 {
3968     &CLSID_NULL, 0, {{ 0 }}
3969 };
3970 
read_clipformat(IStream * stream)3971 static int read_clipformat(IStream *stream)
3972 {
3973     HRESULT hr;
3974     ULONG bytes;
3975     int length, clipformat = -2;
3976 
3977     hr = IStream_Read(stream, &length, sizeof(length), &bytes);
3978     if (hr != S_OK || bytes != sizeof(length))
3979         return -2;
3980     if (length == 0)
3981         return 0;
3982     if (length == -1)
3983     {
3984         hr = IStream_Read(stream, &clipformat, sizeof(clipformat), &bytes);
3985         if (hr != S_OK || bytes != sizeof(clipformat))
3986             return -2;
3987     }
3988     else
3989         ok(0, "unhandled clipformat length %d\n", length);
3990 
3991     return clipformat;
3992 }
3993 
check_storage_contents(IStorage * stg,const struct storage_def * stg_def,int * enumerated_streams,int * matched_streams)3994 static void check_storage_contents(IStorage *stg, const struct storage_def *stg_def,
3995         int *enumerated_streams, int *matched_streams)
3996 {
3997     HRESULT hr;
3998     IEnumSTATSTG *enumstg;
3999     IStream *stream;
4000     STATSTG stat;
4001     int i, seen_stream[MAX_STREAM] = { 0 };
4002 
4003     if (winetest_debug > 1)
4004         trace("check_storage_contents:\n=============================================\n");
4005 
4006     *enumerated_streams = 0;
4007     *matched_streams = 0;
4008 
4009     hr = IStorage_Stat(stg, &stat, STATFLAG_NONAME);
4010     ok(hr == S_OK, "unexpected %#x\n", hr);
4011     ok(IsEqualCLSID(stg_def->clsid, &stat.clsid), "expected %s, got %s\n",
4012        wine_dbgstr_guid(stg_def->clsid), wine_dbgstr_guid(&stat.clsid));
4013 
4014     hr = IStorage_EnumElements(stg, 0, NULL, 0, &enumstg);
4015     ok(hr == S_OK, "unexpected %#x\n", hr);
4016 
4017     for (;;)
4018     {
4019         ULONG bytes;
4020         int clipformat = -1;
4021         PresentationDataHeader header;
4022         char name[32];
4023         BYTE data[1024];
4024 
4025         memset(&header, 0, sizeof(header));
4026 
4027         hr = IEnumSTATSTG_Next(enumstg, 1, &stat, NULL);
4028         if(hr == S_FALSE) break;
4029         ok(hr == S_OK, "unexpected %#x\n", hr);
4030 
4031         if (winetest_debug > 1)
4032             trace("name %s, type %u, size %d, clsid %s\n",
4033                 wine_dbgstr_w(stat.pwcsName), stat.type, stat.cbSize.u.LowPart, wine_dbgstr_guid(&stat.clsid));
4034 
4035         ok(stat.type == STGTY_STREAM, "unexpected %#x\n", stat.type);
4036 
4037         WideCharToMultiByte(CP_ACP, 0, stat.pwcsName, -1, name, sizeof(name), NULL, NULL);
4038 
4039         hr = IStorage_OpenStream(stg, stat.pwcsName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream);
4040         ok(hr == S_OK, "unexpected %#x\n", hr);
4041 
4042         if (!memcmp(name, "\2OlePres", 8))
4043         {
4044             ULONG header_size = sizeof(header);
4045 
4046             clipformat = read_clipformat(stream);
4047 
4048             if (clipformat == 0) /* view cache */
4049                 header_size = FIELD_OFFSET(PresentationDataHeader, unknown7);
4050 
4051             hr = IStream_Read(stream, &header, header_size, &bytes);
4052             ok(hr == S_OK, "unexpected %#x\n", hr);
4053             ok(bytes == header_size, "read %u bytes, expected %u\n", bytes, header_size);
4054 
4055             if (winetest_debug > 1)
4056                 trace("header: tdSize %#x, dvAspect %#x, lindex %#x, advf %#x, unknown7 %#x, dwObjectExtentX %#x, dwObjectExtentY %#x, dwSize %#x\n",
4057                     header.tdSize, header.dvAspect, header.lindex, header.advf, header.unknown7,
4058                     header.dwObjectExtentX, header.dwObjectExtentY, header.dwSize);
4059         }
4060 
4061         memset(data, 0, sizeof(data));
4062         hr = IStream_Read(stream, data, sizeof(data), &bytes);
4063         ok(hr == S_OK, "unexpected %#x\n", hr);
4064         if (winetest_debug > 1)
4065             trace("stream data (%u bytes): %02x %02x %02x %02x\n", bytes, data[0], data[1], data[2], data[3]);
4066 
4067         for (i = 0; i < stg_def->stream_count; i++)
4068         {
4069             if (seen_stream[i]) continue;
4070 
4071             if (winetest_debug > 1)
4072                 trace("%s/%s, %d/%d, %d/%d, %d/%d\n",
4073                     stg_def->stream[i].name, name,
4074                     stg_def->stream[i].cf, clipformat,
4075                     stg_def->stream[i].dvAspect, header.dvAspect,
4076                     stg_def->stream[i].advf, header.advf);
4077 
4078             if (!strcmp(stg_def->stream[i].name, name) &&
4079                 stg_def->stream[i].cf == clipformat &&
4080                 stg_def->stream[i].dvAspect == header.dvAspect &&
4081                 stg_def->stream[i].advf == header.advf &&
4082                 stg_def->stream[i].data_size <= bytes &&
4083                 (!stg_def->stream[i].data_size ||
4084                     (!memcmp(stg_def->stream[i].data, data, min(stg_def->stream[i].data_size, bytes)))))
4085             {
4086                 if (winetest_debug > 1)
4087                     trace("stream %d matches def stream %d\n", *enumerated_streams, i);
4088                 seen_stream[i] = 1;
4089                 *matched_streams += 1;
4090             }
4091         }
4092 
4093         CoTaskMemFree(stat.pwcsName);
4094         IStream_Release(stream);
4095 
4096         *enumerated_streams += 1;
4097     }
4098 
4099     IEnumSTATSTG_Release(enumstg);
4100 }
4101 
stgmedium_cmp(const STGMEDIUM * med1,STGMEDIUM * med2)4102 static HRESULT stgmedium_cmp(const STGMEDIUM *med1, STGMEDIUM *med2)
4103 {
4104     BYTE *data1, *data2;
4105     ULONG datasize1, datasize2;
4106 
4107     if (med1->tymed != med2->tymed)
4108         return E_FAIL;
4109 
4110     if (med1->tymed == TYMED_MFPICT)
4111     {
4112         METAFILEPICT *mfpict1 = GlobalLock(U(med1)->hMetaFilePict);
4113         METAFILEPICT *mfpict2 = GlobalLock(U(med2)->hMetaFilePict);
4114 
4115         datasize1 = GetMetaFileBitsEx(mfpict1->hMF, 0, NULL);
4116         datasize2 = GetMetaFileBitsEx(mfpict2->hMF, 0, NULL);
4117         if (datasize1 == datasize2)
4118         {
4119             data1 = HeapAlloc(GetProcessHeap(), 0, datasize1);
4120             data2 = HeapAlloc(GetProcessHeap(), 0, datasize2);
4121             GetMetaFileBitsEx(mfpict1->hMF, datasize1, data1);
4122             GetMetaFileBitsEx(mfpict2->hMF, datasize2, data2);
4123         }
4124         else return E_FAIL;
4125     }
4126     else if (med1->tymed == TYMED_ENHMF)
4127     {
4128         datasize1 = GetEnhMetaFileBits(med1->hEnhMetaFile, 0, NULL);
4129         datasize2 = GetEnhMetaFileBits(med2->hEnhMetaFile, 0, NULL);
4130         if (datasize1 == datasize2)
4131         {
4132             data1 = HeapAlloc(GetProcessHeap(), 0, datasize1);
4133             data2 = HeapAlloc(GetProcessHeap(), 0, datasize2);
4134             GetEnhMetaFileBits(med1->hEnhMetaFile, datasize1, data1);
4135             GetEnhMetaFileBits(med2->hEnhMetaFile, datasize2, data2);
4136         }
4137         else return E_FAIL;
4138     }
4139     else if (med1->tymed == TYMED_HGLOBAL)
4140     {
4141         datasize1 = GlobalSize(med1->hGlobal);
4142         datasize2 = GlobalSize(med2->hGlobal);
4143 
4144         if (datasize1 == datasize2)
4145         {
4146             data1 = GlobalLock(med1->hGlobal);
4147             data2 = GlobalLock(med2->hGlobal);
4148         }
4149         else
4150             return E_FAIL;
4151     }
4152     else
4153         return E_NOTIMPL;
4154 
4155     if (memcmp(data1, data2, datasize1) != 0)
4156         return E_FAIL;
4157 
4158     if (med1->tymed == TYMED_HGLOBAL)
4159     {
4160         GlobalUnlock(U(med1)->hGlobal);
4161         GlobalUnlock(U(med2)->hGlobal);
4162     }
4163     else if (med1->tymed == TYMED_MFPICT)
4164     {
4165         HeapFree(GetProcessHeap(), 0, data1);
4166         HeapFree(GetProcessHeap(), 0, data2);
4167         GlobalUnlock(U(med1)->hMetaFilePict);
4168         GlobalUnlock(U(med2)->hMetaFilePict);
4169     }
4170     else
4171     {
4172         HeapFree(GetProcessHeap(), 0, data1);
4173         HeapFree(GetProcessHeap(), 0, data2);
4174     }
4175 
4176     return S_OK;
4177 }
4178 
create_storage_from_def(const struct storage_def * stg_def)4179 static IStorage *create_storage_from_def(const struct storage_def *stg_def)
4180 {
4181     HRESULT hr;
4182     IStorage *stg;
4183     IStream *stm;
4184     int i;
4185 
4186     hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &stg);
4187     ok(hr == S_OK, "unexpected %#x\n", hr);
4188 
4189     hr = IStorage_SetClass(stg, stg_def->clsid);
4190     ok(hr == S_OK, "unexpected %#x\n", hr);
4191 
4192     for (i = 0; i < stg_def->stream_count; i++)
4193     {
4194         WCHAR name[32];
4195 
4196         MultiByteToWideChar(CP_ACP, 0, stg_def->stream[i].name, -1, name, 32);
4197         hr = IStorage_CreateStream(stg, name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
4198         ok(hr == S_OK, "unexpected %#x\n", hr);
4199 
4200         if (stg_def->stream[i].cf != -1)
4201         {
4202             int clipformat[2];
4203             PresentationDataHeader hdr;
4204 
4205             if (stg_def->stream[i].cf)
4206             {
4207                 clipformat[0] = -1;
4208                 clipformat[1] = stg_def->stream[i].cf;
4209                 hr = IStream_Write(stm, clipformat, sizeof(clipformat), NULL);
4210             }
4211             else
4212             {
4213                 clipformat[0] = 0;
4214                 hr = IStream_Write(stm, &clipformat[0], sizeof(clipformat[0]), NULL);
4215             }
4216             ok(hr == S_OK, "unexpected %#x\n", hr);
4217 
4218             hdr.tdSize = sizeof(hdr.tdSize);
4219             hdr.dvAspect = stg_def->stream[i].dvAspect;
4220             hdr.lindex = -1;
4221             hdr.advf = stg_def->stream[i].advf;
4222             hdr.unknown7 = 0;
4223             hdr.dwObjectExtentX = 0;
4224             hdr.dwObjectExtentY = 0;
4225             hdr.dwSize = stg_def->stream[i].data_size;
4226             hr = IStream_Write(stm, &hdr, sizeof(hdr), NULL);
4227             ok(hr == S_OK, "unexpected %#x\n", hr);
4228         }
4229 
4230         if (stg_def->stream[i].data_size)
4231         {
4232             hr = IStream_Write(stm, stg_def->stream[i].data, stg_def->stream[i].data_size, NULL);
4233             ok(hr == S_OK, "unexpected %#x\n", hr);
4234         }
4235 
4236         IStream_Release(stm);
4237     }
4238 
4239     return stg;
4240 }
4241 
4242 static const BYTE dib_inf[] =
4243 {
4244     0x42, 0x4d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
4245     0x00, 0x00, 0x36, 0x00, 0x00, 0x00
4246 };
4247 
4248 static const BYTE mf_rec[] =
4249 {
4250     0xd7, 0xcd, 0xc6, 0x9a, 0x00, 0x00, 0x00, 0x00,
4251     0x00, 0x00, 0x16, 0x00, 0x2d, 0x00, 0x40, 0x02,
4252     0x00, 0x00, 0x00, 0x00, 0x6a, 0x55
4253 };
4254 
get_stgdef(struct storage_def * stg_def,CLIPFORMAT cf,STGMEDIUM * stg_med,int stm_idx)4255 static void get_stgdef(struct storage_def *stg_def, CLIPFORMAT cf, STGMEDIUM *stg_med, int stm_idx)
4256 {
4257     BYTE *data;
4258     int data_size;
4259     METAFILEPICT *mfpict;
4260     HDC hdc;
4261 
4262     switch (cf)
4263     {
4264     case CF_DIB:
4265         data_size = sizeof(dib);
4266         if (!strcmp(stg_def->stream[stm_idx].name, "CONTENTS"))
4267         {
4268             data_size += sizeof(dib_inf);
4269             data = HeapAlloc(GetProcessHeap(), 0, data_size);
4270             memcpy(data, dib_inf, sizeof(dib_inf));
4271             memcpy(data + sizeof(dib_inf), dib, sizeof(dib));
4272         }
4273         else
4274         {
4275             data = HeapAlloc(GetProcessHeap(), 0, data_size);
4276             memcpy(data, dib, sizeof(dib));
4277         }
4278         stg_def->stream[stm_idx].data = data;
4279         stg_def->stream[stm_idx].data_size = data_size;
4280         break;
4281     case CF_METAFILEPICT:
4282         mfpict = GlobalLock(U(stg_med)->hMetaFilePict);
4283         data_size = GetMetaFileBitsEx(mfpict->hMF, 0, NULL);
4284         if (!strcmp(stg_def->stream[stm_idx].name, "CONTENTS"))
4285         {
4286             data = HeapAlloc(GetProcessHeap(), 0, data_size + sizeof(mf_rec));
4287             memcpy(data, mf_rec, sizeof(mf_rec));
4288             GetMetaFileBitsEx(mfpict->hMF, data_size, data + sizeof(mf_rec));
4289             data_size += sizeof(mf_rec);
4290         }
4291         else
4292         {
4293             data = HeapAlloc(GetProcessHeap(), 0, data_size);
4294             GetMetaFileBitsEx(mfpict->hMF, data_size, data);
4295         }
4296         GlobalUnlock(U(stg_med)->hMetaFilePict);
4297         stg_def->stream[stm_idx].data_size = data_size;
4298         stg_def->stream[stm_idx].data = data;
4299         break;
4300     case CF_ENHMETAFILE:
4301         if (!strcmp(stg_def->stream[stm_idx].name, "CONTENTS"))
4302         {
4303             data_size = GetEnhMetaFileBits(U(stg_med)->hEnhMetaFile, 0, NULL);
4304             data = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) + sizeof(ENHMETAHEADER) + data_size);
4305             *((DWORD *)data) = sizeof(ENHMETAHEADER);
4306             GetEnhMetaFileBits(U(stg_med)->hEnhMetaFile, data_size, data + sizeof(DWORD) + sizeof(ENHMETAHEADER));
4307             memcpy(data + sizeof(DWORD), data + sizeof(DWORD) + sizeof(ENHMETAHEADER), sizeof(ENHMETAHEADER));
4308             data_size += sizeof(DWORD) + sizeof(ENHMETAHEADER);
4309         }
4310         else
4311         {
4312             hdc = GetDC(NULL);
4313             data_size = GetWinMetaFileBits(U(stg_med)->hEnhMetaFile, 0, NULL, MM_ANISOTROPIC, hdc);
4314             data = HeapAlloc(GetProcessHeap(), 0, data_size);
4315             GetWinMetaFileBits(U(stg_med)->hEnhMetaFile, data_size, data, MM_ANISOTROPIC, hdc);
4316             ReleaseDC(NULL, hdc);
4317         }
4318         stg_def->stream[stm_idx].data_size = data_size;
4319         stg_def->stream[stm_idx].data = data;
4320         break;
4321     }
4322 }
4323 
get_stgmedium(CLIPFORMAT cfFormat,STGMEDIUM * stgmedium)4324 static void get_stgmedium(CLIPFORMAT cfFormat, STGMEDIUM *stgmedium)
4325 {
4326     switch (cfFormat)
4327     {
4328     case CF_DIB:
4329         create_dib(stgmedium);
4330         break;
4331     case CF_METAFILEPICT:
4332         create_mfpict(stgmedium);
4333         break;
4334     case CF_ENHMETAFILE:
4335         create_emf(stgmedium);
4336         break;
4337     default:
4338         ok(0, "cf %x not implemented\n", cfFormat);
4339     }
4340 }
4341 
4342 #define MAX_FMTS 5
test_data_cache_save_data(void)4343 static void test_data_cache_save_data(void)
4344 {
4345     HRESULT hr;
4346     STGMEDIUM stgmed;
4347     ILockBytes *ilb;
4348     IStorage *doc;
4349     IOleCache2 *cache;
4350     IPersistStorage *persist;
4351     IDataObject *odata;
4352     int enumerated_streams, matched_streams, i;
4353     DWORD dummy;
4354     STGMEDIUM stgmeds[MAX_FMTS];
4355     struct tests_data_cache
4356     {
4357         FORMATETC fmts[MAX_FMTS];
4358         int num_fmts, num_set;
4359         const CLSID *clsid;
4360         struct storage_def stg_def;
4361     };
4362 
4363     static struct tests_data_cache *pdata, data[] =
4364     {
4365         {
4366             {
4367                 { CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
4368                 { CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT },
4369                 { CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF },
4370                 { 0, 0, DVASPECT_DOCPRINT, -1, TYMED_HGLOBAL },
4371             },
4372             4, 3, &CLSID_WineTest,
4373             {
4374                 &CLSID_WineTestOld, 4, { { "\2OlePres000", CF_DIB, DVASPECT_CONTENT, 0, NULL, 0 },
4375                                          { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, 0, NULL, 0 },
4376                                          { "\2OlePres002", CF_ENHMETAFILE, DVASPECT_CONTENT, 0, NULL, 0 },
4377                                          { "\2OlePres003", 0, DVASPECT_DOCPRINT, 0, NULL, 0 } }
4378             }
4379         },
4380         /* without setting data */
4381         {
4382             {
4383                 { CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
4384                 { CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT },
4385                 { CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF },
4386             },
4387             3, 0, &CLSID_WineTest,
4388             {
4389                 &CLSID_WineTestOld, 3, { { "\2OlePres000", CF_DIB, DVASPECT_CONTENT, 0, NULL, 0 },
4390                                          { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, 0, NULL, 0 },
4391                                          { "\2OlePres002", CF_ENHMETAFILE, DVASPECT_CONTENT, 0, NULL, 0 } }
4392             }
4393         },
4394         /* static picture clsids */
4395         {
4396             {
4397                 { CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
4398             },
4399             1, 1, &CLSID_Picture_Dib,
4400             {
4401                 &CLSID_WineTestOld, 1, { { "CONTENTS", -1, 0, 0, NULL, 0 } }
4402             }
4403         },
4404         {
4405             {
4406                 { CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT },
4407             },
4408             1, 1, &CLSID_Picture_Metafile,
4409             {
4410                 &CLSID_WineTestOld, 1, { { "CONTENTS", -1, 0, 0, NULL, 0 } }
4411             }
4412         },
4413         {
4414             {
4415                 { CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF },
4416             },
4417             1, 1, &CLSID_Picture_EnhMetafile,
4418             {
4419                 &CLSID_WineTestOld, 1, { { "CONTENTS", -1, 0, 0, NULL, 0 } }
4420             }
4421         },
4422         /* static picture clsids without setting any data */
4423         {
4424             {
4425                 { CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
4426             },
4427             1, 0, &CLSID_Picture_Dib,
4428             {
4429                 &CLSID_WineTestOld, 1, { { "CONTENTS", -1, 0, 0, NULL, 0 } }
4430             }
4431         },
4432         {
4433             {
4434                 { CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT },
4435             },
4436             1, 0, &CLSID_Picture_Metafile,
4437             {
4438                 &CLSID_WineTestOld, 1, { { "CONTENTS", -1, 0, 0, NULL, 0 } }
4439             }
4440         },
4441         {
4442             {
4443                 { CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF },
4444             },
4445             1, 0, &CLSID_Picture_EnhMetafile,
4446             {
4447                 &CLSID_WineTestOld, 1, { { "CONTENTS", -1, 0, 0, NULL, 0 } }
4448             }
4449         },
4450         {
4451             {
4452                 { 0 }
4453             }
4454         }
4455     };
4456 
4457     /* test _Save after caching directly through _Cache + _SetData */
4458     for (pdata = data; pdata->clsid != NULL; pdata++)
4459     {
4460         hr = CreateDataCache(NULL, pdata->clsid, &IID_IOleCache2, (void **)&cache);
4461         ok(hr == S_OK, "unexpected %#x\n", hr);
4462 
4463         for (i = 0; i < pdata->num_fmts; i++)
4464         {
4465             hr = IOleCache2_Cache(cache, &pdata->fmts[i], 0, &dummy);
4466             ok(SUCCEEDED(hr), "unexpected %#x\n", hr);
4467             if (i < pdata->num_set)
4468             {
4469                 get_stgmedium(pdata->fmts[i].cfFormat, &stgmeds[i]);
4470                 get_stgdef(&pdata->stg_def, pdata->fmts[i].cfFormat, &stgmeds[i], i);
4471                 hr = IOleCache2_SetData(cache, &pdata->fmts[i], &stgmeds[i], FALSE);
4472                 ok(hr == S_OK, "unexpected %#x\n", hr);
4473             }
4474         }
4475 
4476         /* create Storage in memory where we'll save cache */
4477         hr = CreateILockBytesOnHGlobal(0, TRUE, &ilb);
4478         ok(hr == S_OK, "unexpected %#x\n", hr);
4479         hr = StgCreateDocfileOnILockBytes(ilb, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &doc);
4480         ok(hr == S_OK, "unexpected %#x\n", hr);
4481         ILockBytes_Release(ilb);
4482         hr = IStorage_SetClass(doc, &CLSID_WineTestOld);
4483         ok(hr == S_OK, "unexpected %#x\n", hr);
4484 
4485         hr = IOleCache2_QueryInterface(cache, &IID_IPersistStorage, (void **)&persist);
4486         ok(hr == S_OK, "unexpected %#x\n", hr);
4487 
4488         /* cache entries are dirty. test saving them to stg */
4489         trace("IPersistStorage_Save:\n");
4490         hr = IPersistStorage_Save(persist, doc, FALSE);
4491         ok(hr == S_OK, "unexpected %#x\n", hr);
4492 
4493         hr = IPersistStorage_IsDirty(persist);
4494         ok(hr == S_OK, "unexpected %#x\n", hr);
4495 
4496         check_storage_contents(doc, &pdata->stg_def, &enumerated_streams, &matched_streams);
4497         ok(enumerated_streams == matched_streams, "enumerated %d != matched %d\n",
4498            enumerated_streams, matched_streams);
4499         ok(enumerated_streams == pdata->stg_def.stream_count, "created %d != def streams %d\n",
4500            enumerated_streams, pdata->stg_def.stream_count);
4501 
4502         IPersistStorage_Release(persist);
4503         IOleCache2_Release(cache);
4504 
4505         /* now test _Load/_GetData using the storage we used for _Save */
4506         hr = CreateDataCache(NULL, pdata->clsid, &IID_IOleCache2, (void **)&cache);
4507         ok(hr == S_OK, "unexpected %#x\n", hr);
4508         hr = IOleCache2_QueryInterface(cache, &IID_IPersistStorage, (void **)&persist);
4509         ok(hr == S_OK, "unexpected %#x\n", hr);
4510 
4511         hr = IStorage_SetClass(doc, pdata->clsid);
4512         ok(hr == S_OK, "unexpected %#x\n", hr);
4513         trace("IPersistStorage_Load\n");
4514         hr = IPersistStorage_Load(persist, doc);
4515         ok(hr == S_OK, "unexpected %#x\n", hr);
4516 
4517         hr = IOleCache2_QueryInterface(cache, &IID_IDataObject, (void **)&odata);
4518         ok(hr == S_OK, "unexpected %#x\n", hr);
4519         for (i = 0; i < pdata->num_set; i++)
4520         {
4521             hr = IDataObject_GetData(odata, &pdata->fmts[i], &stgmed);
4522             ok(hr == S_OK, "unexpected %#x\n", hr);
4523 
4524             hr = stgmedium_cmp(&stgmeds[i], &stgmed);
4525             ok(hr == S_OK, "unexpected %#x\n", hr);
4526             ReleaseStgMedium(&stgmed);
4527             ReleaseStgMedium(&stgmeds[i]);
4528         }
4529 
4530         IDataObject_Release(odata);
4531         IPersistStorage_Release(persist);
4532         IStorage_Release(doc);
4533         IOleCache2_Release(cache);
4534         for (i = 0; i < pdata->num_set; i++)
4535             HeapFree(GetProcessHeap(), 0, (void *)pdata->stg_def.stream[i].data);
4536 
4537     }
4538 }
4539 
test_data_cache_contents(void)4540 static void test_data_cache_contents(void)
4541 {
4542     HRESULT hr;
4543     IStorage *doc1, *doc2;
4544     IOleCache2 *cache;
4545     IPersistStorage *stg;
4546     int i, enumerated_streams, matched_streams;
4547     static const struct
4548     {
4549         const struct storage_def *in;
4550         const struct storage_def *out;
4551     } test_data[] =
4552     {
4553         { &stg_def_0, &stg_def_0_saved },
4554         { &stg_def_1, &stg_def_1_saved },
4555         { &stg_def_2, &stg_def_2_saved },
4556         { &stg_def_3, &stg_def_3_saved },
4557         { &stg_def_4, &stg_def_4_saved },
4558         { &stg_def_5, &stg_def_5_saved },
4559         { &stg_def_6, &stg_def_6_saved },
4560         { &stg_def_7, &stg_def_7_saved },
4561         { &stg_def_8, &stg_def_8_saved },
4562         { &stg_def_9, &stg_def_9_saved },
4563     };
4564 
4565     for (i = 0; i < ARRAY_SIZE(test_data); i++)
4566     {
4567         if (winetest_debug > 1)
4568             trace("start testing storage def %d\n", i);
4569 
4570         doc1 = create_storage_from_def(test_data[i].in);
4571         if (!doc1) continue;
4572 
4573         enumerated_streams = matched_streams = -1;
4574         check_storage_contents(doc1, test_data[i].in, &enumerated_streams, &matched_streams);
4575         ok(enumerated_streams == matched_streams, "%d in: enumerated %d != matched %d\n", i,
4576            enumerated_streams, matched_streams);
4577         ok(enumerated_streams == test_data[i].in->stream_count, "%d: created %d != def streams %d\n", i,
4578            enumerated_streams, test_data[i].in->stream_count);
4579 
4580         hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IUnknown, (void **)&cache);
4581         ok(hr == S_OK, "unexpected %#x\n", hr);
4582         hr = IOleCache2_QueryInterface(cache, &IID_IPersistStorage, (void **)&stg);
4583         ok(hr == S_OK, "unexpected %#x\n", hr);
4584         hr = IPersistStorage_Load(stg, doc1);
4585         ok(hr == S_OK, "unexpected %#x\n", hr);
4586 
4587         IStorage_Release(doc1);
4588 
4589         hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &doc2);
4590         ok(hr == S_OK, "unexpected %#x\n", hr);
4591 
4592         hr = IPersistStorage_IsDirty(stg);
4593         ok(hr == S_FALSE, "%d: unexpected %#x\n", i, hr);
4594 
4595         hr = IPersistStorage_Save(stg, doc2, FALSE);
4596         ok(hr == S_OK, "unexpected %#x\n", hr);
4597 
4598         IPersistStorage_Release(stg);
4599 
4600         enumerated_streams = matched_streams = -1;
4601         check_storage_contents(doc2, test_data[i].out, &enumerated_streams, &matched_streams);
4602 todo_wine_if(!(test_data[i].in == &stg_def_0 || test_data[i].in == &stg_def_1 || test_data[i].in == &stg_def_2))
4603         ok(enumerated_streams == matched_streams, "%d out: enumerated %d != matched %d\n", i,
4604            enumerated_streams, matched_streams);
4605 todo_wine_if(!(test_data[i].in == &stg_def_0 || test_data[i].in == &stg_def_4 || test_data[i].in == &stg_def_5
4606                  || test_data[i].in == &stg_def_6))
4607         ok(enumerated_streams == test_data[i].out->stream_count, "%d: saved streams %d != def streams %d\n", i,
4608             enumerated_streams, test_data[i].out->stream_count);
4609 
4610         IStorage_Release(doc2);
4611 
4612         if (winetest_debug > 1)
4613             trace("done testing storage def %d\n", i);
4614     }
4615 }
4616 
test_OleCreateStaticFromData(void)4617 static void test_OleCreateStaticFromData(void)
4618 {
4619     HRESULT hr;
4620     IOleObject *ole_obj = NULL;
4621     IStorage *storage;
4622     ILockBytes *ilb;
4623     IPersist *persist;
4624     CLSID clsid;
4625     STATSTG statstg;
4626     int enumerated_streams, matched_streams;
4627     STGMEDIUM stgmed;
4628     static FORMATETC dib_fmt[] =
4629     {
4630         { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
4631         { 0 }
4632     };
4633     static FORMATETC emf_fmt[] =
4634     {
4635         { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF },
4636         { 0 }
4637     };
4638     static FORMATETC text_fmt[] =
4639     {
4640         { CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
4641         { 0 }
4642     };
4643     static const struct expected_method methods_create_from_dib[] =
4644     {
4645         { "DataObject_EnumFormatEtc", TEST_TODO },
4646         { "DataObject_GetDataHere", 0 },
4647         { "DataObject_QueryGetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_ISTORAGE } },
4648         { NULL }
4649     };
4650     static const struct expected_method methods_createstatic_from_dib[] =
4651     {
4652         { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
4653         { NULL }
4654     };
4655     static const struct expected_method methods_createstatic_from_emf[] =
4656     {
4657         { "DataObject_GetData", 0, { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } },
4658         { NULL }
4659     };
4660     static const struct expected_method methods_createstatic_from_text[] =
4661     {
4662         { "DataObject_GetData", 0, { CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
4663         { NULL }
4664     };
4665     static struct storage_def stg_def_dib =
4666     {
4667         &CLSID_Picture_Dib, 3,
4668         {{ "\1Ole", -1, 0, 0, NULL, 0 },
4669          { "\1CompObj", -1, 0, 0, NULL, 0 },
4670          { "CONTENTS", -1, 0, 0, NULL, 0 }}
4671     };
4672     static struct storage_def stg_def_emf =
4673     {
4674         &CLSID_Picture_EnhMetafile, 3,
4675         {{ "\1Ole", -1, 0, 0, NULL, 0 },
4676          { "\1CompObj", -1, 0, 0, NULL, 0 },
4677          { "CONTENTS", -1, 0, 0, NULL, 0 }}
4678     };
4679 
4680 
4681     hr = CreateILockBytesOnHGlobal(NULL, TRUE, &ilb);
4682     ok(hr == S_OK, "CreateILockBytesOnHGlobal failed: 0x%08x.\n", hr);
4683     hr = StgCreateDocfileOnILockBytes(ilb, STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE,
4684                                       0, &storage);
4685     ok(hr == S_OK, "StgCreateDocfileOnILockBytes failed: 0x%08x.\n", hr);
4686     ILockBytes_Release(ilb);
4687 
4688     hr = OleCreateStaticFromData(&DataObject, &IID_IOleObject, OLERENDER_FORMAT,
4689                                  dib_fmt, NULL, NULL, (void **)&ole_obj);
4690     ok(hr == E_INVALIDARG, "OleCreateStaticFromData should fail: 0x%08x.\n", hr);
4691 
4692     hr = OleCreateStaticFromData(&DataObject, &IID_IOleObject, OLERENDER_FORMAT,
4693                                  dib_fmt, NULL, storage, NULL);
4694     ok(hr == E_INVALIDARG, "OleCreateStaticFromData should fail: 0x%08x.\n", hr);
4695 
4696     /* CF_DIB */
4697     g_dataobject_fmts = dib_fmt;
4698     expected_method_list = methods_createstatic_from_dib;
4699     hr = OleCreateStaticFromData(&DataObject, &IID_IOleObject, OLERENDER_FORMAT,
4700                                  dib_fmt, NULL, storage, (void **)&ole_obj);
4701     ok(hr == S_OK, "OleCreateStaticFromData failed: 0x%08x.\n", hr);
4702     hr = IOleObject_QueryInterface(ole_obj, &IID_IPersist, (void **)&persist);
4703     ok(hr == S_OK, "IOleObject_QueryInterface failed: 0x%08x.\n", hr);
4704     hr = IPersist_GetClassID(persist, &clsid);
4705     ok(hr == S_OK, "IPersist_GetClassID failed: 0x%08x.\n", hr);
4706     ok(IsEqualCLSID(&clsid, &CLSID_Picture_Dib), "Got wrong clsid: %s, expected: %s.\n",
4707        wine_dbgstr_guid(&clsid), wine_dbgstr_guid(&CLSID_Picture_Dib));
4708     hr = IStorage_Stat(storage, &statstg, STATFLAG_NONAME);
4709     ok_ole_success(hr, "IStorage_Stat");
4710     ok(IsEqualCLSID(&CLSID_Picture_Dib, &statstg.clsid), "Wrong CLSID in storage.\n");
4711     enumerated_streams = matched_streams = -1;
4712     get_stgmedium(CF_DIB, &stgmed);
4713     get_stgdef(&stg_def_dib, CF_DIB, &stgmed, 2);
4714     check_storage_contents(storage, &stg_def_dib, &enumerated_streams, &matched_streams);
4715     ok(enumerated_streams == matched_streams, "enumerated %d != matched %d\n",
4716        enumerated_streams, matched_streams);
4717     ok(enumerated_streams == stg_def_dib.stream_count, "created %d != def streams %d\n",
4718        enumerated_streams, stg_def_dib.stream_count);
4719     ReleaseStgMedium(&stgmed);
4720     IPersist_Release(persist);
4721     IStorage_Release(storage);
4722     IOleObject_Release(ole_obj);
4723 
4724     /* CF_ENHMETAFILE */
4725     hr = CreateILockBytesOnHGlobal(NULL, TRUE, &ilb);
4726     ok(hr == S_OK, "CreateILockBytesOnHGlobal failed: 0x%08x.\n", hr);
4727     hr = StgCreateDocfileOnILockBytes(ilb, STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE,
4728                                       0, &storage);
4729     ok(hr == S_OK, "StgCreateDocfileOnILockBytes failed: 0x%08x.\n", hr);
4730     ILockBytes_Release(ilb);
4731     g_dataobject_fmts = emf_fmt;
4732     expected_method_list = methods_createstatic_from_emf;
4733     hr = OleCreateStaticFromData(&DataObject, &IID_IOleObject, OLERENDER_FORMAT,
4734                                  emf_fmt, NULL, storage, (void **)&ole_obj);
4735     ok(hr == S_OK, "OleCreateStaticFromData failed: 0x%08x.\n", hr);
4736     hr = IOleObject_QueryInterface(ole_obj, &IID_IPersist, (void **)&persist);
4737     ok(hr == S_OK, "IOleObject_QueryInterface failed: 0x%08x.\n", hr);
4738     hr = IPersist_GetClassID(persist, &clsid);
4739     ok(hr == S_OK, "IPersist_GetClassID failed: 0x%08x.\n", hr);
4740     ok(IsEqualCLSID(&clsid, &CLSID_Picture_EnhMetafile), "Got wrong clsid: %s, expected: %s.\n",
4741        wine_dbgstr_guid(&clsid), wine_dbgstr_guid(&CLSID_Picture_EnhMetafile));
4742     hr = IStorage_Stat(storage, &statstg, STATFLAG_NONAME);
4743     ok_ole_success(hr, "IStorage_Stat");
4744     ok(IsEqualCLSID(&CLSID_Picture_EnhMetafile, &statstg.clsid), "Wrong CLSID in storage.\n");
4745     enumerated_streams = matched_streams = -1;
4746     get_stgmedium(CF_ENHMETAFILE, &stgmed);
4747     get_stgdef(&stg_def_emf, CF_ENHMETAFILE, &stgmed, 2);
4748     check_storage_contents(storage, &stg_def_emf, &enumerated_streams, &matched_streams);
4749     ok(enumerated_streams == matched_streams, "enumerated %d != matched %d\n",
4750        enumerated_streams, matched_streams);
4751     ok(enumerated_streams == stg_def_emf.stream_count, "created %d != def streams %d\n",
4752        enumerated_streams, stg_def_emf.stream_count);
4753     ReleaseStgMedium(&stgmed);
4754     IPersist_Release(persist);
4755     IStorage_Release(storage);
4756     IOleObject_Release(ole_obj);
4757 
4758     /* CF_TEXT */
4759     hr = CreateILockBytesOnHGlobal(NULL, TRUE, &ilb);
4760     ok(hr == S_OK, "CreateILockBytesOnHGlobal failed: 0x%08x.\n", hr);
4761     hr = StgCreateDocfileOnILockBytes(ilb, STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE,
4762                                       0, &storage);
4763     ok(hr == S_OK, "StgCreateDocfileOnILockBytes failed: 0x%08x.\n", hr);
4764     ILockBytes_Release(ilb);
4765     g_dataobject_fmts = text_fmt;
4766     expected_method_list = methods_createstatic_from_text;
4767     hr = OleCreateStaticFromData(&DataObject, &IID_IOleObject, OLERENDER_FORMAT,
4768                                  text_fmt, NULL, storage, (void **)&ole_obj);
4769     ok(hr == DV_E_CLIPFORMAT, "OleCreateStaticFromData should fail: 0x%08x.\n", hr);
4770     IStorage_Release(storage);
4771 
4772     hr = CreateILockBytesOnHGlobal(NULL, TRUE, &ilb);
4773     ok(hr == S_OK, "CreateILockBytesOnHGlobal failed: 0x%08x.\n", hr);
4774     hr = StgCreateDocfileOnILockBytes(ilb, STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE,
4775                                       0, &storage);
4776     ok(hr == S_OK, "StgCreateDocfileOnILockBytes failed: 0x%08x.\n", hr);
4777     ILockBytes_Release(ilb);
4778     g_dataobject_fmts = dib_fmt;
4779     expected_method_list = methods_create_from_dib;
4780     hr = OleCreateFromData(&DataObject, &IID_IOleObject, OLERENDER_FORMAT, dib_fmt, NULL,
4781                            storage, (void **)&ole_obj);
4782     todo_wine ok(hr == DV_E_FORMATETC, "OleCreateFromData should failed: 0x%08x.\n", hr);
4783     IStorage_Release(storage);
4784 }
4785 
START_TEST(ole2)4786 START_TEST(ole2)
4787 {
4788     DWORD dwRegister;
4789     IStorage *pStorage;
4790     STATSTG statstg;
4791     HRESULT hr;
4792 
4793     cf_test_1 = RegisterClipboardFormatA("cf_winetest_1");
4794     cf_test_2 = RegisterClipboardFormatA("cf_winetest_2");
4795     cf_test_3 = RegisterClipboardFormatA("cf_winetest_3");
4796 
4797     CoInitialize(NULL);
4798 
4799     hr = CoRegisterClassObject(&CLSID_Equation3, (IUnknown *)&OleObjectCF, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegister);
4800     ok_ole_success(hr, "CoRegisterClassObject");
4801 
4802     hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &pStorage);
4803     ok_ole_success(hr, "StgCreateDocfile");
4804 
4805     test_OleCreate(pStorage);
4806 
4807     hr = IStorage_Stat(pStorage, &statstg, STATFLAG_NONAME);
4808     ok_ole_success(hr, "IStorage_Stat");
4809     ok(IsEqualCLSID(&CLSID_Equation3, &statstg.clsid), "Wrong CLSID in storage\n");
4810 
4811     test_OleLoad(pStorage);
4812 
4813     IStorage_Release(pStorage);
4814 
4815     hr = CoRevokeClassObject(dwRegister);
4816     ok_ole_success(hr, "CoRevokeClassObject");
4817 
4818     Storage_SetClass_CLSID = &CLSID_WineTest;
4819 
4820     test_data_cache();
4821     test_data_cache_dib_contents_stream( 0 );
4822     test_data_cache_dib_contents_stream( 1 );
4823     test_data_cache_cache();
4824     test_data_cache_init();
4825     test_data_cache_initnew();
4826     test_data_cache_updatecache();
4827     test_default_handler();
4828     test_runnable();
4829     test_OleRun();
4830     test_OleLockRunning();
4831     test_OleDraw();
4832     test_OleDoAutoConvert();
4833     test_data_cache_save();
4834     test_data_cache_save_data();
4835     test_data_cache_contents();
4836     test_OleCreateStaticFromData();
4837 
4838     CoUninitialize();
4839 }
4840