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