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