[OLE32_WINETEST] Sync with Wine Staging 4.0. CORE-15682
[reactos.git] / modules / rostests / winetests / ole32 / ole2.c
1 /*
2 * Object Linking and Embedding Tests
3 *
4 * Copyright 2005 Robert Shearman
5 * Copyright 2017 Dmitry Timoshkov
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #define COBJMACROS
23 #define CONST_VTABLE
24 #define WIN32_LEAN_AND_MEAN
25
26 #include <stdarg.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "objbase.h"
32 #include "shlguid.h"
33
34 #include "wine/test.h"
35
36 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
37
38 #define DEFINE_EXPECT(func) \
39 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
40
41 #define SET_EXPECT(func) \
42 expect_ ## func = TRUE
43
44 #define CHECK_EXPECT2(func) \
45 do { \
46 ok(expect_ ##func, "unexpected call " #func "\n"); \
47 called_ ## func = TRUE; \
48 }while(0)
49
50 #define CHECK_EXPECT(func) \
51 do { \
52 CHECK_EXPECT2(func); \
53 expect_ ## func = FALSE; \
54 }while(0)
55
56 #define CHECK_CALLED(func) \
57 do { \
58 ok(called_ ## func, "expected " #func "\n"); \
59 expect_ ## func = called_ ## func = FALSE; \
60 }while(0)
61
62 DEFINE_EXPECT(Storage_Stat);
63 DEFINE_EXPECT(Storage_OpenStream_CompObj);
64 DEFINE_EXPECT(Storage_OpenStream_OlePres);
65 DEFINE_EXPECT(Storage_SetClass);
66 DEFINE_EXPECT(Storage_CreateStream_CompObj);
67 DEFINE_EXPECT(Storage_CreateStream_OlePres);
68 DEFINE_EXPECT(Storage_OpenStream_Ole);
69 DEFINE_EXPECT(Storage_DestroyElement);
70
71 static const CLSID *Storage_SetClass_CLSID;
72 static int Storage_DestroyElement_limit;
73
74 static IPersistStorage OleObjectPersistStg;
75 static IOleCache *cache;
76 static IRunnableObject *runnable;
77
78 static const CLSID CLSID_WineTestOld =
79 { /* 9474ba1a-258b-490b-bc13-516e9239acd0 */
80 0x9474ba1a,
81 0x258b,
82 0x490b,
83 {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xd0}
84 };
85
86 static const CLSID CLSID_WineTest =
87 { /* 9474ba1a-258b-490b-bc13-516e9239ace0 */
88 0x9474ba1a,
89 0x258b,
90 0x490b,
91 {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xe0}
92 };
93
94 static const IID IID_WineTest =
95 { /* 9474ba1a-258b-490b-bc13-516e9239ace1 */
96 0x9474ba1a,
97 0x258b,
98 0x490b,
99 {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xe1}
100 };
101
102 #define TEST_OPTIONAL 0x1
103 #define TEST_TODO 0x2
104
105 struct expected_method
106 {
107 const char *method;
108 unsigned int flags;
109 FORMATETC fmt;
110 };
111
112 static const struct expected_method *expected_method_list;
113 static FORMATETC *g_expected_fetc = NULL;
114
115 static BOOL g_showRunnable = TRUE;
116 static BOOL g_isRunning = TRUE;
117 static HRESULT g_GetMiscStatusFailsWith = S_OK;
118 static HRESULT g_QIFailsWith;
119
120 static UINT cf_test_1, cf_test_2, cf_test_3;
121
122 static FORMATETC *g_dataobject_fmts;
123
124 /****************************************************************************
125 * PresentationDataHeader
126 *
127 * This structure represents the header of the \002OlePresXXX stream in
128 * the OLE object storage.
129 */
130 typedef struct PresentationDataHeader
131 {
132 /* clipformat:
133 * - standard clipformat:
134 * DWORD length = 0xffffffff;
135 * DWORD cfFormat;
136 * - or custom clipformat:
137 * DWORD length;
138 * CHAR format_name[length]; (null-terminated)
139 */
140 DWORD tdSize; /* This is actually a truncated DVTARGETDEVICE, if tdSize > sizeof(DWORD)
141 then there are tdSize - sizeof(DWORD) more bytes before dvAspect */
142 DVASPECT dvAspect;
143 DWORD lindex;
144 DWORD advf;
145 DWORD unknown7; /* 0 */
146 DWORD dwObjectExtentX;
147 DWORD dwObjectExtentY;
148 DWORD dwSize;
149 } PresentationDataHeader;
150
151 #ifdef __REACTOS__
152 static inline void check_expected_method_fmt(const char *method_name, const FORMATETC *fmt)
153 #else
154 static void inline check_expected_method_fmt(const char *method_name, const FORMATETC *fmt)
155 #endif
156 {
157 trace("%s\n", method_name);
158 ok(expected_method_list->method != NULL, "Extra method %s called\n", method_name);
159 if (!strcmp(expected_method_list->method, "WINE_EXTRA"))
160 {
161 todo_wine ok(0, "Too many method calls.\n");
162 return;
163 }
164 if (expected_method_list->method)
165 {
166 while (expected_method_list->flags & TEST_OPTIONAL &&
167 strcmp(expected_method_list->method, method_name) != 0)
168 expected_method_list++;
169 todo_wine_if (expected_method_list->flags & TEST_TODO)
170 {
171 ok(!strcmp(expected_method_list->method, method_name),
172 "Expected %s to be called instead of %s\n",
173 expected_method_list->method, method_name);
174 if (fmt)
175 {
176 ok(fmt->cfFormat == expected_method_list->fmt.cfFormat, "got cf %04x vs %04x\n",
177 fmt->cfFormat, expected_method_list->fmt.cfFormat );
178 ok(fmt->dwAspect == expected_method_list->fmt.dwAspect, "got aspect %d vs %d\n",
179 fmt->dwAspect, expected_method_list->fmt.dwAspect );
180 ok(fmt->lindex == expected_method_list->fmt.lindex, "got lindex %d vs %d\n",
181 fmt->lindex, expected_method_list->fmt.lindex );
182 ok(fmt->tymed == expected_method_list->fmt.tymed, "got tymed %d vs %d\n",
183 fmt->tymed, expected_method_list->fmt.tymed );
184 }
185 }
186 expected_method_list++;
187 }
188 }
189
190 #define CHECK_EXPECTED_METHOD(method_name) check_expected_method_fmt(method_name, NULL)
191 #define CHECK_EXPECTED_METHOD_FMT(method_name, fmt) check_expected_method_fmt(method_name, fmt)
192
193 #define CHECK_NO_EXTRA_METHODS() \
194 do { \
195 while (expected_method_list->flags & TEST_OPTIONAL) \
196 expected_method_list++; \
197 ok(!expected_method_list->method, "Method sequence starting from %s not called\n", expected_method_list->method); \
198 } while (0)
199
200 /* 2 x 1 x 32 bpp dib. PelsPerMeter = 200x400 */
201 static const BYTE dib[] =
202 {
203 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
204 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206 0xc8, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
209 };
210
211 static void create_dib( STGMEDIUM *med )
212 {
213 void *ptr;
214
215 med->tymed = TYMED_HGLOBAL;
216 U(med)->hGlobal = GlobalAlloc( GMEM_MOVEABLE, sizeof(dib) );
217 ptr = GlobalLock( U(med)->hGlobal );
218 memcpy( ptr, dib, sizeof(dib) );
219 GlobalUnlock( U(med)->hGlobal );
220 med->pUnkForRelease = NULL;
221 }
222
223 static void create_bitmap( STGMEDIUM *med )
224 {
225 med->tymed = TYMED_GDI;
226 U(med)->hBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
227 med->pUnkForRelease = NULL;
228 }
229
230 static void create_emf(STGMEDIUM *med)
231 {
232 HDC hdc = CreateEnhMetaFileW(NULL, NULL, NULL, NULL);
233
234 Rectangle(hdc, 0, 0, 150, 300);
235 med->tymed = TYMED_ENHMF;
236 U(med)->hEnhMetaFile = CloseEnhMetaFile(hdc);
237 med->pUnkForRelease = NULL;
238 }
239
240 static void create_mfpict(STGMEDIUM *med)
241 {
242 METAFILEPICT *mf;
243 HDC hdc = CreateMetaFileW(NULL);
244
245 Rectangle(hdc, 0, 0, 100, 200);
246
247 med->tymed = TYMED_MFPICT;
248 U(med)->hMetaFilePict = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT));
249 mf = GlobalLock(U(med)->hMetaFilePict);
250 mf->mm = MM_ANISOTROPIC;
251 mf->xExt = 100;
252 mf->yExt = 200;
253 mf->hMF = CloseMetaFile(hdc);
254 GlobalUnlock(U(med)->hMetaFilePict);
255 med->pUnkForRelease = NULL;
256 }
257
258 static void create_text(STGMEDIUM *med)
259 {
260 HGLOBAL handle;
261 char *p;
262
263 handle = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5);
264 p = GlobalLock(handle);
265 strcpy(p, "test");
266 GlobalUnlock(handle);
267
268 med->tymed = TYMED_HGLOBAL;
269 U(med)->hGlobal = handle;
270 med->pUnkForRelease = NULL;
271 }
272
273 static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, void **ppv)
274 {
275 CHECK_EXPECTED_METHOD("OleObject_QueryInterface");
276
277 *ppv = NULL;
278
279 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IOleObject))
280 *ppv = iface;
281 else if (IsEqualIID(riid, &IID_IPersistStorage))
282 *ppv = &OleObjectPersistStg;
283 else if (IsEqualIID(riid, &IID_IOleCache))
284 *ppv = cache;
285 else if (IsEqualIID(riid, &IID_IRunnableObject) && g_showRunnable)
286 *ppv = runnable;
287 else if (IsEqualIID(riid, &IID_WineTest))
288 return g_QIFailsWith;
289
290 if(*ppv) {
291 IUnknown_AddRef((IUnknown*)*ppv);
292 return S_OK;
293 }
294
295 trace("OleObject_QueryInterface: returning E_NOINTERFACE\n");
296 return E_NOINTERFACE;
297 }
298
299 static ULONG WINAPI OleObject_AddRef(IOleObject *iface)
300 {
301 CHECK_EXPECTED_METHOD("OleObject_AddRef");
302 return 2;
303 }
304
305 static ULONG WINAPI OleObject_Release(IOleObject *iface)
306 {
307 CHECK_EXPECTED_METHOD("OleObject_Release");
308 return 1;
309 }
310
311 static HRESULT WINAPI OleObject_SetClientSite
312 (
313 IOleObject *iface,
314 IOleClientSite *pClientSite
315 )
316 {
317 CHECK_EXPECTED_METHOD("OleObject_SetClientSite");
318 return S_OK;
319 }
320
321 static HRESULT WINAPI OleObject_GetClientSite
322 (
323 IOleObject *iface,
324 IOleClientSite **ppClientSite
325 )
326 {
327 CHECK_EXPECTED_METHOD("OleObject_GetClientSite");
328 return E_NOTIMPL;
329 }
330
331 static HRESULT WINAPI OleObject_SetHostNames
332 (
333 IOleObject *iface,
334 LPCOLESTR szContainerApp,
335 LPCOLESTR szContainerObj
336 )
337 {
338 CHECK_EXPECTED_METHOD("OleObject_SetHostNames");
339 return S_OK;
340 }
341
342 static HRESULT WINAPI OleObject_Close
343 (
344 IOleObject *iface,
345 DWORD dwSaveOption
346 )
347 {
348 CHECK_EXPECTED_METHOD("OleObject_Close");
349 return S_OK;
350 }
351
352 static HRESULT WINAPI OleObject_SetMoniker
353 (
354 IOleObject *iface,
355 DWORD dwWhichMoniker,
356 IMoniker *pmk
357 )
358 {
359 CHECK_EXPECTED_METHOD("OleObject_SetMoniker");
360 return S_OK;
361 }
362
363 static HRESULT WINAPI OleObject_GetMoniker
364 (
365 IOleObject *iface,
366 DWORD dwAssign,
367 DWORD dwWhichMoniker,
368 IMoniker **ppmk
369 )
370 {
371 CHECK_EXPECTED_METHOD("OleObject_GetMoniker");
372 return S_OK;
373 }
374
375 static HRESULT WINAPI OleObject_InitFromData
376 (
377 IOleObject *iface,
378 IDataObject *pDataObject,
379 BOOL fCreation,
380 DWORD dwReserved
381 )
382 {
383 CHECK_EXPECTED_METHOD("OleObject_InitFromData");
384 return S_OK;
385 }
386
387 static HRESULT WINAPI OleObject_GetClipboardData
388 (
389 IOleObject *iface,
390 DWORD dwReserved,
391 IDataObject **ppDataObject
392 )
393 {
394 CHECK_EXPECTED_METHOD("OleObject_GetClipboardData");
395 return E_NOTIMPL;
396 }
397
398 static HRESULT WINAPI OleObject_DoVerb
399 (
400 IOleObject *iface,
401 LONG iVerb,
402 LPMSG lpmsg,
403 IOleClientSite *pActiveSite,
404 LONG lindex,
405 HWND hwndParent,
406 LPCRECT lprcPosRect
407 )
408 {
409 CHECK_EXPECTED_METHOD("OleObject_DoVerb");
410 return S_OK;
411 }
412
413 static HRESULT WINAPI OleObject_EnumVerbs
414 (
415 IOleObject *iface,
416 IEnumOLEVERB **ppEnumOleVerb
417 )
418 {
419 CHECK_EXPECTED_METHOD("OleObject_EnumVerbs");
420 return E_NOTIMPL;
421 }
422
423 static HRESULT WINAPI OleObject_Update
424 (
425 IOleObject *iface
426 )
427 {
428 CHECK_EXPECTED_METHOD("OleObject_Update");
429 return S_OK;
430 }
431
432 static HRESULT WINAPI OleObject_IsUpToDate
433 (
434 IOleObject *iface
435 )
436 {
437 CHECK_EXPECTED_METHOD("OleObject_IsUpToDate");
438 return S_OK;
439 }
440
441 static HRESULT WINAPI OleObject_GetUserClassID
442 (
443 IOleObject *iface,
444 CLSID *pClsid
445 )
446 {
447 CHECK_EXPECTED_METHOD("OleObject_GetUserClassID");
448 return E_NOTIMPL;
449 }
450
451 static HRESULT WINAPI OleObject_GetUserType
452 (
453 IOleObject *iface,
454 DWORD dwFormOfType,
455 LPOLESTR *pszUserType
456 )
457 {
458 CHECK_EXPECTED_METHOD("OleObject_GetUserType");
459 return E_NOTIMPL;
460 }
461
462 static HRESULT WINAPI OleObject_SetExtent
463 (
464 IOleObject *iface,
465 DWORD dwDrawAspect,
466 SIZEL *psizel
467 )
468 {
469 CHECK_EXPECTED_METHOD("OleObject_SetExtent");
470 return S_OK;
471 }
472
473 static HRESULT WINAPI OleObject_GetExtent
474 (
475 IOleObject *iface,
476 DWORD dwDrawAspect,
477 SIZEL *psizel
478 )
479 {
480 CHECK_EXPECTED_METHOD("OleObject_GetExtent");
481 return E_NOTIMPL;
482 }
483
484 static HRESULT WINAPI OleObject_Advise
485 (
486 IOleObject *iface,
487 IAdviseSink *pAdvSink,
488 DWORD *pdwConnection
489 )
490 {
491 CHECK_EXPECTED_METHOD("OleObject_Advise");
492 return S_OK;
493 }
494
495 static HRESULT WINAPI OleObject_Unadvise
496 (
497 IOleObject *iface,
498 DWORD dwConnection
499 )
500 {
501 CHECK_EXPECTED_METHOD("OleObject_Unadvise");
502 return S_OK;
503 }
504
505 static HRESULT WINAPI OleObject_EnumAdvise
506 (
507 IOleObject *iface,
508 IEnumSTATDATA **ppenumAdvise
509 )
510 {
511 CHECK_EXPECTED_METHOD("OleObject_EnumAdvise");
512 return E_NOTIMPL;
513 }
514
515 static HRESULT WINAPI OleObject_GetMiscStatus
516 (
517 IOleObject *iface,
518 DWORD aspect,
519 DWORD *pdwStatus
520 )
521 {
522 CHECK_EXPECTED_METHOD("OleObject_GetMiscStatus");
523
524 ok(aspect == DVASPECT_CONTENT, "got aspect %d\n", aspect);
525
526 if (g_GetMiscStatusFailsWith == S_OK)
527 {
528 *pdwStatus = OLEMISC_RECOMPOSEONRESIZE;
529 return S_OK;
530 }
531 else
532 {
533 *pdwStatus = 0x1234;
534 return g_GetMiscStatusFailsWith;
535 }
536 }
537
538 static HRESULT WINAPI OleObject_SetColorScheme
539 (
540 IOleObject *iface,
541 LOGPALETTE *pLogpal
542 )
543 {
544 CHECK_EXPECTED_METHOD("OleObject_SetColorScheme");
545 return E_NOTIMPL;
546 }
547
548 static const IOleObjectVtbl OleObjectVtbl =
549 {
550 OleObject_QueryInterface,
551 OleObject_AddRef,
552 OleObject_Release,
553 OleObject_SetClientSite,
554 OleObject_GetClientSite,
555 OleObject_SetHostNames,
556 OleObject_Close,
557 OleObject_SetMoniker,
558 OleObject_GetMoniker,
559 OleObject_InitFromData,
560 OleObject_GetClipboardData,
561 OleObject_DoVerb,
562 OleObject_EnumVerbs,
563 OleObject_Update,
564 OleObject_IsUpToDate,
565 OleObject_GetUserClassID,
566 OleObject_GetUserType,
567 OleObject_SetExtent,
568 OleObject_GetExtent,
569 OleObject_Advise,
570 OleObject_Unadvise,
571 OleObject_EnumAdvise,
572 OleObject_GetMiscStatus,
573 OleObject_SetColorScheme
574 };
575
576 static IOleObject OleObject = { &OleObjectVtbl };
577
578 static HRESULT WINAPI OleObjectPersistStg_QueryInterface(IPersistStorage *iface, REFIID riid, void **ppv)
579 {
580 trace("OleObjectPersistStg_QueryInterface\n");
581 return IOleObject_QueryInterface(&OleObject, riid, ppv);
582 }
583
584 static ULONG WINAPI OleObjectPersistStg_AddRef(IPersistStorage *iface)
585 {
586 CHECK_EXPECTED_METHOD("OleObjectPersistStg_AddRef");
587 return 2;
588 }
589
590 static ULONG WINAPI OleObjectPersistStg_Release(IPersistStorage *iface)
591 {
592 CHECK_EXPECTED_METHOD("OleObjectPersistStg_Release");
593 return 1;
594 }
595
596 static HRESULT WINAPI OleObjectPersistStg_GetClassId(IPersistStorage *iface, CLSID *clsid)
597 {
598 CHECK_EXPECTED_METHOD("OleObjectPersistStg_GetClassId");
599 return E_NOTIMPL;
600 }
601
602 static HRESULT WINAPI OleObjectPersistStg_IsDirty
603 (
604 IPersistStorage *iface
605 )
606 {
607 CHECK_EXPECTED_METHOD("OleObjectPersistStg_IsDirty");
608 return S_OK;
609 }
610
611 static HRESULT WINAPI OleObjectPersistStg_InitNew
612 (
613 IPersistStorage *iface,
614 IStorage *pStg
615 )
616 {
617 CHECK_EXPECTED_METHOD("OleObjectPersistStg_InitNew");
618 return S_OK;
619 }
620
621 static HRESULT WINAPI OleObjectPersistStg_Load
622 (
623 IPersistStorage *iface,
624 IStorage *pStg
625 )
626 {
627 CHECK_EXPECTED_METHOD("OleObjectPersistStg_Load");
628 return S_OK;
629 }
630
631 static HRESULT WINAPI OleObjectPersistStg_Save
632 (
633 IPersistStorage *iface,
634 IStorage *pStgSave,
635 BOOL fSameAsLoad
636 )
637 {
638 CHECK_EXPECTED_METHOD("OleObjectPersistStg_Save");
639 return S_OK;
640 }
641
642 static HRESULT WINAPI OleObjectPersistStg_SaveCompleted
643 (
644 IPersistStorage *iface,
645 IStorage *pStgNew
646 )
647 {
648 CHECK_EXPECTED_METHOD("OleObjectPersistStg_SaveCompleted");
649 return S_OK;
650 }
651
652 static HRESULT WINAPI OleObjectPersistStg_HandsOffStorage
653 (
654 IPersistStorage *iface
655 )
656 {
657 CHECK_EXPECTED_METHOD("OleObjectPersistStg_HandsOffStorage");
658 return S_OK;
659 }
660
661 static const IPersistStorageVtbl OleObjectPersistStgVtbl =
662 {
663 OleObjectPersistStg_QueryInterface,
664 OleObjectPersistStg_AddRef,
665 OleObjectPersistStg_Release,
666 OleObjectPersistStg_GetClassId,
667 OleObjectPersistStg_IsDirty,
668 OleObjectPersistStg_InitNew,
669 OleObjectPersistStg_Load,
670 OleObjectPersistStg_Save,
671 OleObjectPersistStg_SaveCompleted,
672 OleObjectPersistStg_HandsOffStorage
673 };
674
675 static IPersistStorage OleObjectPersistStg = { &OleObjectPersistStgVtbl };
676
677 static HRESULT WINAPI OleObjectCache_QueryInterface(IOleCache *iface, REFIID riid, void **ppv)
678 {
679 return IOleObject_QueryInterface(&OleObject, riid, ppv);
680 }
681
682 static ULONG WINAPI OleObjectCache_AddRef(IOleCache *iface)
683 {
684 CHECK_EXPECTED_METHOD("OleObjectCache_AddRef");
685 return 2;
686 }
687
688 static ULONG WINAPI OleObjectCache_Release(IOleCache *iface)
689 {
690 CHECK_EXPECTED_METHOD("OleObjectCache_Release");
691 return 1;
692 }
693
694 static HRESULT WINAPI OleObjectCache_Cache
695 (
696 IOleCache *iface,
697 FORMATETC *pformatetc,
698 DWORD advf,
699 DWORD *pdwConnection
700 )
701 {
702 CHECK_EXPECTED_METHOD("OleObjectCache_Cache");
703 if (g_expected_fetc) {
704 ok(pformatetc != NULL, "pformatetc should not be NULL\n");
705 if (pformatetc) {
706 ok(pformatetc->cfFormat == g_expected_fetc->cfFormat,
707 "cfFormat: %x\n", pformatetc->cfFormat);
708 ok((pformatetc->ptd != NULL) == (g_expected_fetc->ptd != NULL),
709 "ptd: %p\n", pformatetc->ptd);
710 ok(pformatetc->dwAspect == g_expected_fetc->dwAspect,
711 "dwAspect: %x\n", pformatetc->dwAspect);
712 ok(pformatetc->lindex == g_expected_fetc->lindex,
713 "lindex: %x\n", pformatetc->lindex);
714 ok(pformatetc->tymed == g_expected_fetc->tymed,
715 "tymed: %x\n", pformatetc->tymed);
716 }
717 } else
718 ok(pformatetc == NULL, "pformatetc should be NULL\n");
719 return S_OK;
720 }
721
722 static HRESULT WINAPI OleObjectCache_Uncache
723 (
724 IOleCache *iface,
725 DWORD dwConnection
726 )
727 {
728 CHECK_EXPECTED_METHOD("OleObjectCache_Uncache");
729 return S_OK;
730 }
731
732 static HRESULT WINAPI OleObjectCache_EnumCache
733 (
734 IOleCache *iface,
735 IEnumSTATDATA **ppenumSTATDATA
736 )
737 {
738 CHECK_EXPECTED_METHOD("OleObjectCache_EnumCache");
739 return S_OK;
740 }
741
742
743 static HRESULT WINAPI OleObjectCache_InitCache
744 (
745 IOleCache *iface,
746 IDataObject *pDataObject
747 )
748 {
749 CHECK_EXPECTED_METHOD("OleObjectCache_InitCache");
750 return S_OK;
751 }
752
753
754 static HRESULT WINAPI OleObjectCache_SetData
755 (
756 IOleCache *iface,
757 FORMATETC *pformatetc,
758 STGMEDIUM *pmedium,
759 BOOL fRelease
760 )
761 {
762 CHECK_EXPECTED_METHOD("OleObjectCache_SetData");
763 return S_OK;
764 }
765
766
767 static const IOleCacheVtbl OleObjectCacheVtbl =
768 {
769 OleObjectCache_QueryInterface,
770 OleObjectCache_AddRef,
771 OleObjectCache_Release,
772 OleObjectCache_Cache,
773 OleObjectCache_Uncache,
774 OleObjectCache_EnumCache,
775 OleObjectCache_InitCache,
776 OleObjectCache_SetData
777 };
778
779 static IOleCache OleObjectCache = { &OleObjectCacheVtbl };
780
781 static HRESULT WINAPI OleObjectCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
782 {
783 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
784 {
785 *ppv = iface;
786 IClassFactory_AddRef(iface);
787 return S_OK;
788 }
789 *ppv = NULL;
790 return E_NOINTERFACE;
791 }
792
793 static ULONG WINAPI OleObjectCF_AddRef(IClassFactory *iface)
794 {
795 return 2;
796 }
797
798 static ULONG WINAPI OleObjectCF_Release(IClassFactory *iface)
799 {
800 return 1;
801 }
802
803 static HRESULT WINAPI OleObjectCF_CreateInstance(IClassFactory *iface, IUnknown *punkOuter, REFIID riid, void **ppv)
804 {
805 return IOleObject_QueryInterface(&OleObject, riid, ppv);
806 }
807
808 static HRESULT WINAPI OleObjectCF_LockServer(IClassFactory *iface, BOOL lock)
809 {
810 return S_OK;
811 }
812
813 static const IClassFactoryVtbl OleObjectCFVtbl =
814 {
815 OleObjectCF_QueryInterface,
816 OleObjectCF_AddRef,
817 OleObjectCF_Release,
818 OleObjectCF_CreateInstance,
819 OleObjectCF_LockServer
820 };
821
822 static IClassFactory OleObjectCF = { &OleObjectCFVtbl };
823
824 static HRESULT WINAPI OleObjectRunnable_QueryInterface(IRunnableObject *iface, REFIID riid, void **ppv)
825 {
826 return IOleObject_QueryInterface(&OleObject, riid, ppv);
827 }
828
829 static ULONG WINAPI OleObjectRunnable_AddRef(IRunnableObject *iface)
830 {
831 CHECK_EXPECTED_METHOD("OleObjectRunnable_AddRef");
832 return 2;
833 }
834
835 static ULONG WINAPI OleObjectRunnable_Release(IRunnableObject *iface)
836 {
837 CHECK_EXPECTED_METHOD("OleObjectRunnable_Release");
838 return 1;
839 }
840
841 static HRESULT WINAPI OleObjectRunnable_GetRunningClass(
842 IRunnableObject *iface,
843 LPCLSID lpClsid)
844 {
845 CHECK_EXPECTED_METHOD("OleObjectRunnable_GetRunningClass");
846 return E_NOTIMPL;
847 }
848
849 static HRESULT WINAPI OleObjectRunnable_Run(
850 IRunnableObject *iface,
851 LPBINDCTX pbc)
852 {
853 CHECK_EXPECTED_METHOD("OleObjectRunnable_Run");
854 return S_OK;
855 }
856
857 static BOOL WINAPI OleObjectRunnable_IsRunning(IRunnableObject *iface)
858 {
859 CHECK_EXPECTED_METHOD("OleObjectRunnable_IsRunning");
860 return g_isRunning;
861 }
862
863 static HRESULT WINAPI OleObjectRunnable_LockRunning(
864 IRunnableObject *iface,
865 BOOL fLock,
866 BOOL fLastUnlockCloses)
867 {
868 CHECK_EXPECTED_METHOD("OleObjectRunnable_LockRunning");
869 return S_OK;
870 }
871
872 static HRESULT WINAPI OleObjectRunnable_SetContainedObject(
873 IRunnableObject *iface,
874 BOOL fContained)
875 {
876 CHECK_EXPECTED_METHOD("OleObjectRunnable_SetContainedObject");
877 return S_OK;
878 }
879
880 static const IRunnableObjectVtbl OleObjectRunnableVtbl =
881 {
882 OleObjectRunnable_QueryInterface,
883 OleObjectRunnable_AddRef,
884 OleObjectRunnable_Release,
885 OleObjectRunnable_GetRunningClass,
886 OleObjectRunnable_Run,
887 OleObjectRunnable_IsRunning,
888 OleObjectRunnable_LockRunning,
889 OleObjectRunnable_SetContainedObject
890 };
891
892 static IRunnableObject OleObjectRunnable = { &OleObjectRunnableVtbl };
893
894 static const CLSID CLSID_Equation3 = {0x0002CE02, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
895
896 static HRESULT WINAPI viewobject_QueryInterface(IViewObject *iface, REFIID riid, void **obj)
897 {
898 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IViewObject))
899 {
900 *obj = iface;
901 return S_OK;
902 }
903
904 *obj = NULL;
905 return E_NOINTERFACE;
906 }
907
908 static ULONG WINAPI viewobject_AddRef(IViewObject *iface)
909 {
910 return 2;
911 }
912
913 static ULONG WINAPI viewobject_Release(IViewObject *iface)
914 {
915 return 1;
916 }
917
918 static HRESULT WINAPI viewobject_Draw(IViewObject *iface, DWORD aspect, LONG index,
919 void *paspect, DVTARGETDEVICE *ptd, HDC hdcTargetDev, HDC hdcDraw,
920 LPCRECTL bounds, LPCRECTL wbounds, BOOL (STDMETHODCALLTYPE *pfnContinue)(ULONG_PTR dwContinue),
921 ULONG_PTR dwContinue)
922 {
923 ok(index == -1, "index=%d\n", index);
924 return S_OK;
925 }
926
927 static HRESULT WINAPI viewobject_GetColorSet(IViewObject *iface, DWORD draw_aspect, LONG index,
928 void *aspect, DVTARGETDEVICE *ptd, HDC hicTargetDev, LOGPALETTE **colorset)
929 {
930 ok(0, "unexpected call GetColorSet\n");
931 return E_NOTIMPL;
932 }
933
934 static HRESULT WINAPI viewobject_Freeze(IViewObject *iface, DWORD draw_aspect, LONG index,
935 void *aspect, DWORD *freeze)
936 {
937 ok(0, "unexpected call Freeze\n");
938 return E_NOTIMPL;
939 }
940
941 static HRESULT WINAPI viewobject_Unfreeze(IViewObject *iface, DWORD freeze)
942 {
943 ok(0, "unexpected call Unfreeze\n");
944 return E_NOTIMPL;
945 }
946
947 static HRESULT WINAPI viewobject_SetAdvise(IViewObject *iface, DWORD aspects, DWORD advf, IAdviseSink *sink)
948 {
949 ok(0, "unexpected call SetAdvise\n");
950 return E_NOTIMPL;
951 }
952
953 static HRESULT WINAPI viewobject_GetAdvise(IViewObject *iface, DWORD *aspects, DWORD *advf,
954 IAdviseSink **sink)
955 {
956 ok(0, "unexpected call GetAdvise\n");
957 return E_NOTIMPL;
958 }
959
960 static const struct IViewObjectVtbl viewobjectvtbl = {
961 viewobject_QueryInterface,
962 viewobject_AddRef,
963 viewobject_Release,
964 viewobject_Draw,
965 viewobject_GetColorSet,
966 viewobject_Freeze,
967 viewobject_Unfreeze,
968 viewobject_SetAdvise,
969 viewobject_GetAdvise
970 };
971
972 static IViewObject viewobject = { &viewobjectvtbl };
973
974 static void test_OleCreate(IStorage *pStorage)
975 {
976 HRESULT hr;
977 IOleObject *pObject;
978 FORMATETC formatetc;
979 static const struct expected_method methods_olerender_none[] =
980 {
981 { "OleObject_QueryInterface", 0 },
982 { "OleObject_AddRef", 0 },
983 { "OleObject_QueryInterface", 0 },
984 { "OleObject_AddRef", TEST_OPTIONAL },
985 { "OleObject_Release", TEST_OPTIONAL },
986 { "OleObject_QueryInterface", TEST_OPTIONAL },
987 { "OleObjectPersistStg_AddRef", 0 },
988 { "OleObjectPersistStg_InitNew", 0 },
989 { "OleObjectPersistStg_Release", 0 },
990 { "OleObject_Release", 0 },
991 { "OleObject_Release", TEST_OPTIONAL },
992 { NULL, 0 }
993 };
994 static const struct expected_method methods_olerender_draw[] =
995 {
996 { "OleObject_QueryInterface", 0 },
997 { "OleObject_AddRef", 0 },
998 { "OleObject_QueryInterface", 0 },
999 { "OleObject_AddRef", TEST_OPTIONAL /* NT4 only */ },
1000 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1001 { "OleObject_QueryInterface", TEST_OPTIONAL /* NT4 only */ },
1002 { "OleObjectPersistStg_AddRef", 0 },
1003 { "OleObjectPersistStg_InitNew", 0 },
1004 { "OleObjectPersistStg_Release", 0 },
1005 { "OleObject_QueryInterface", 0 },
1006 { "OleObjectRunnable_AddRef", 0 },
1007 { "OleObjectRunnable_Run", 0 },
1008 { "OleObjectRunnable_Release", 0 },
1009 { "OleObject_QueryInterface", 0 },
1010 { "OleObjectCache_AddRef", 0 },
1011 { "OleObjectCache_Cache", 0 },
1012 { "OleObjectCache_Release", 0 },
1013 { "OleObject_Release", 0 },
1014 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1015 { NULL, 0 }
1016 };
1017 static const struct expected_method methods_olerender_draw_with_site[] =
1018 {
1019 { "OleObject_QueryInterface", 0 },
1020 { "OleObject_AddRef", 0 },
1021 { "OleObject_QueryInterface", 0 },
1022 { "OleObject_AddRef", 0 },
1023 { "OleObject_GetMiscStatus", 0 },
1024 { "OleObject_QueryInterface", 0 },
1025 { "OleObjectPersistStg_AddRef", 0 },
1026 { "OleObjectPersistStg_InitNew", 0 },
1027 { "OleObjectPersistStg_Release", 0 },
1028 { "OleObject_SetClientSite", 0 },
1029 { "OleObject_Release", 0 },
1030 { "OleObject_QueryInterface", 0 },
1031 { "OleObjectRunnable_AddRef", 0 },
1032 { "OleObjectRunnable_Run", 0 },
1033 { "OleObjectRunnable_Release", 0 },
1034 { "OleObject_QueryInterface", 0 },
1035 { "OleObjectCache_AddRef", 0 },
1036 { "OleObjectCache_Cache", 0 },
1037 { "OleObjectCache_Release", 0 },
1038 { "OleObject_Release", 0 },
1039 { NULL, 0 }
1040 };
1041 static const struct expected_method methods_olerender_format[] =
1042 {
1043 { "OleObject_QueryInterface", 0 },
1044 { "OleObject_AddRef", 0 },
1045 { "OleObject_QueryInterface", 0 },
1046 { "OleObject_AddRef", 0 },
1047 { "OleObject_GetMiscStatus", 0 },
1048 { "OleObject_QueryInterface", 0 },
1049 { "OleObjectPersistStg_AddRef", 0 },
1050 { "OleObjectPersistStg_InitNew", 0 },
1051 { "OleObjectPersistStg_Release", 0 },
1052 { "OleObject_SetClientSite", 0 },
1053 { "OleObject_Release", 0 },
1054 { "OleObject_QueryInterface", 0 },
1055 { "OleObjectRunnable_AddRef", 0 },
1056 { "OleObjectRunnable_Run", 0 },
1057 { "OleObjectRunnable_Release", 0 },
1058 { "OleObject_QueryInterface", 0 },
1059 { "OleObjectCache_AddRef", 0 },
1060 { "OleObjectCache_Cache", 0 },
1061 { "OleObjectCache_Release", 0 },
1062 { "OleObject_Release", 0 },
1063 { NULL, 0 }
1064 };
1065 static const struct expected_method methods_olerender_asis[] =
1066 {
1067 { "OleObject_QueryInterface", 0 },
1068 { "OleObject_AddRef", 0 },
1069 { "OleObject_QueryInterface", 0 },
1070 { "OleObject_AddRef", TEST_OPTIONAL /* NT4 only */ },
1071 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1072 { "OleObject_QueryInterface", TEST_OPTIONAL /* NT4 only */ },
1073 { "OleObjectPersistStg_AddRef", 0 },
1074 { "OleObjectPersistStg_InitNew", 0 },
1075 { "OleObjectPersistStg_Release", 0 },
1076 { "OleObject_Release", 0 },
1077 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1078 { NULL, 0 }
1079 };
1080 static const struct expected_method methods_olerender_draw_no_runnable[] =
1081 {
1082 { "OleObject_QueryInterface", 0 },
1083 { "OleObject_AddRef", 0 },
1084 { "OleObject_QueryInterface", 0 },
1085 { "OleObject_AddRef", TEST_OPTIONAL /* NT4 only */ },
1086 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1087 { "OleObject_QueryInterface", TEST_OPTIONAL /* NT4 only */ },
1088 { "OleObjectPersistStg_AddRef", 0 },
1089 { "OleObjectPersistStg_InitNew", 0 },
1090 { "OleObjectPersistStg_Release", 0 },
1091 { "OleObject_QueryInterface", 0 },
1092 { "OleObject_QueryInterface", 0 },
1093 { "OleObjectCache_AddRef", 0 },
1094 { "OleObjectCache_Cache", 0 },
1095 { "OleObjectCache_Release", 0 },
1096 { "OleObject_Release", 0 },
1097 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1098 { NULL, 0 },
1099 };
1100 static const struct expected_method methods_olerender_draw_no_cache[] =
1101 {
1102 { "OleObject_QueryInterface", 0 },
1103 { "OleObject_AddRef", 0 },
1104 { "OleObject_QueryInterface", 0 },
1105 { "OleObject_AddRef", TEST_OPTIONAL /* NT4 only */ },
1106 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1107 { "OleObject_QueryInterface", TEST_OPTIONAL /* NT4 only */ },
1108 { "OleObjectPersistStg_AddRef", 0 },
1109 { "OleObjectPersistStg_InitNew", 0 },
1110 { "OleObjectPersistStg_Release", 0 },
1111 { "OleObject_QueryInterface", 0 },
1112 { "OleObjectRunnable_AddRef", 0 },
1113 { "OleObjectRunnable_Run", 0 },
1114 { "OleObjectRunnable_Release", 0 },
1115 { "OleObject_QueryInterface", 0 },
1116 { "OleObject_Release", 0 },
1117 { "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
1118 { NULL, 0 }
1119 };
1120
1121 g_expected_fetc = &formatetc;
1122 formatetc.cfFormat = 0;
1123 formatetc.ptd = NULL;
1124 formatetc.dwAspect = DVASPECT_CONTENT;
1125 formatetc.lindex = -1;
1126 formatetc.tymed = TYMED_NULL;
1127 runnable = &OleObjectRunnable;
1128 cache = &OleObjectCache;
1129 expected_method_list = methods_olerender_none;
1130 trace("OleCreate with OLERENDER_NONE:\n");
1131 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_NONE, NULL, NULL, pStorage, (void **)&pObject);
1132 ok_ole_success(hr, "OleCreate");
1133 IOleObject_Release(pObject);
1134 CHECK_NO_EXTRA_METHODS();
1135
1136 expected_method_list = methods_olerender_draw;
1137 trace("OleCreate with OLERENDER_DRAW:\n");
1138 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, NULL, pStorage, (void **)&pObject);
1139 ok_ole_success(hr, "OleCreate");
1140 IOleObject_Release(pObject);
1141 CHECK_NO_EXTRA_METHODS();
1142
1143 expected_method_list = methods_olerender_draw_with_site;
1144 trace("OleCreate with OLERENDER_DRAW, with site:\n");
1145 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, (IOleClientSite*)0xdeadbeef, pStorage, (void **)&pObject);
1146 ok_ole_success(hr, "OleCreate");
1147 IOleObject_Release(pObject);
1148 CHECK_NO_EXTRA_METHODS();
1149
1150 /* GetMiscStatus fails */
1151 g_GetMiscStatusFailsWith = 0x8fafefaf;
1152 expected_method_list = methods_olerender_draw_with_site;
1153 trace("OleCreate with OLERENDER_DRAW, with site:\n");
1154 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, (IOleClientSite*)0xdeadbeef, pStorage, (void **)&pObject);
1155 ok_ole_success(hr, "OleCreate");
1156 IOleObject_Release(pObject);
1157 CHECK_NO_EXTRA_METHODS();
1158 g_GetMiscStatusFailsWith = S_OK;
1159
1160 formatetc.cfFormat = CF_TEXT;
1161 formatetc.ptd = NULL;
1162 formatetc.dwAspect = DVASPECT_CONTENT;
1163 formatetc.lindex = -1;
1164 formatetc.tymed = TYMED_HGLOBAL;
1165 expected_method_list = methods_olerender_format;
1166 trace("OleCreate with OLERENDER_FORMAT:\n");
1167 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_FORMAT, &formatetc, (IOleClientSite *)0xdeadbeef, pStorage, (void **)&pObject);
1168 ok(hr == S_OK ||
1169 broken(hr == E_INVALIDARG), /* win2k */
1170 "OleCreate failed with error 0x%08x\n", hr);
1171 if (pObject)
1172 {
1173 IOleObject_Release(pObject);
1174 CHECK_NO_EXTRA_METHODS();
1175 }
1176
1177 expected_method_list = methods_olerender_asis;
1178 trace("OleCreate with OLERENDER_ASIS:\n");
1179 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_ASIS, NULL, NULL, pStorage, (void **)&pObject);
1180 ok_ole_success(hr, "OleCreate");
1181 IOleObject_Release(pObject);
1182 CHECK_NO_EXTRA_METHODS();
1183
1184 formatetc.cfFormat = 0;
1185 formatetc.tymed = TYMED_NULL;
1186 runnable = NULL;
1187 expected_method_list = methods_olerender_draw_no_runnable;
1188 trace("OleCreate with OLERENDER_DRAW (no IRunnableObject):\n");
1189 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, NULL, pStorage, (void **)&pObject);
1190 ok_ole_success(hr, "OleCreate");
1191 IOleObject_Release(pObject);
1192 CHECK_NO_EXTRA_METHODS();
1193
1194 runnable = &OleObjectRunnable;
1195 cache = NULL;
1196 expected_method_list = methods_olerender_draw_no_cache;
1197 trace("OleCreate with OLERENDER_DRAW (no IOleCache):\n");
1198 hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, NULL, pStorage, (void **)&pObject);
1199 ok_ole_success(hr, "OleCreate");
1200 IOleObject_Release(pObject);
1201 CHECK_NO_EXTRA_METHODS();
1202 trace("end\n");
1203 g_expected_fetc = NULL;
1204 }
1205
1206 static void test_OleLoad(IStorage *pStorage)
1207 {
1208 HRESULT hr;
1209 IOleObject *pObject;
1210 DWORD fmt;
1211
1212 static const struct expected_method methods_oleload[] =
1213 {
1214 { "OleObject_QueryInterface", 0 },
1215 { "OleObject_AddRef", 0 },
1216 { "OleObject_QueryInterface", 0 },
1217 { "OleObject_AddRef", 0 },
1218 { "OleObject_GetMiscStatus", 0 },
1219 { "OleObject_QueryInterface", 0 },
1220 { "OleObjectPersistStg_AddRef", 0 },
1221 { "OleObjectPersistStg_Load", 0 },
1222 { "OleObjectPersistStg_Release", 0 },
1223 { "OleObject_SetClientSite", 0 },
1224 { "OleObject_Release", 0 },
1225 { "OleObject_QueryInterface", 0 },
1226 { "OleObject_GetMiscStatus", 0 },
1227 { "OleObject_Release", 0 },
1228 { NULL, 0 }
1229 };
1230
1231 /* Test once with IOleObject_GetMiscStatus failing */
1232 expected_method_list = methods_oleload;
1233 g_GetMiscStatusFailsWith = E_FAIL;
1234 trace("OleLoad:\n");
1235 hr = OleLoad(pStorage, &IID_IOleObject, (IOleClientSite *)0xdeadbeef, (void **)&pObject);
1236 ok(hr == S_OK ||
1237 broken(hr == E_INVALIDARG), /* win98 and win2k */
1238 "OleLoad failed with error 0x%08x\n", hr);
1239 if(pObject)
1240 {
1241 DWORD dwStatus = 0xdeadbeef;
1242 hr = IOleObject_GetMiscStatus(pObject, DVASPECT_CONTENT, &dwStatus);
1243 ok(hr == E_FAIL, "Got 0x%08x\n", hr);
1244 ok(dwStatus == 0x1234, "Got 0x%08x\n", dwStatus);
1245
1246 IOleObject_Release(pObject);
1247 CHECK_NO_EXTRA_METHODS();
1248 }
1249 g_GetMiscStatusFailsWith = S_OK;
1250
1251 /* Test again, let IOleObject_GetMiscStatus succeed. */
1252 expected_method_list = methods_oleload;
1253 trace("OleLoad:\n");
1254 hr = OleLoad(pStorage, &IID_IOleObject, (IOleClientSite *)0xdeadbeef, (void **)&pObject);
1255 ok(hr == S_OK ||
1256 broken(hr == E_INVALIDARG), /* win98 and win2k */
1257 "OleLoad failed with error 0x%08x\n", hr);
1258 if (pObject)
1259 {
1260 DWORD dwStatus = 0xdeadbeef;
1261 hr = IOleObject_GetMiscStatus(pObject, DVASPECT_CONTENT, &dwStatus);
1262 ok(hr == S_OK, "Got 0x%08x\n", hr);
1263 ok(dwStatus == 1, "Got 0x%08x\n", dwStatus);
1264
1265 IOleObject_Release(pObject);
1266 CHECK_NO_EXTRA_METHODS();
1267 }
1268
1269 for (fmt = CF_TEXT; fmt < CF_MAX; fmt++)
1270 {
1271 static const WCHAR olrepres[] = { 2,'O','l','e','P','r','e','s','0','0','0',0 };
1272 IStorage *stg;
1273 IStream *stream;
1274 IUnknown *obj;
1275 DWORD data, i, data_size;
1276 PresentationDataHeader header;
1277 HDC hdc;
1278 HGDIOBJ hobj;
1279 RECT rc;
1280 char buf[256];
1281
1282 for (i = 0; i < 7; i++)
1283 {
1284 hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &stg);
1285 ok(hr == S_OK, "StgCreateDocfile error %#x\n", hr);
1286
1287 hr = IStorage_SetClass(stg, &CLSID_WineTest);
1288 ok(hr == S_OK, "SetClass error %#x\n", hr);
1289
1290 hr = IStorage_CreateStream(stg, olrepres, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, &stream);
1291 ok(hr == S_OK, "CreateStream error %#x\n", hr);
1292
1293 data = ~0;
1294 hr = IStream_Write(stream, &data, sizeof(data), NULL);
1295 ok(hr == S_OK, "Write error %#x\n", hr);
1296
1297 data = fmt;
1298 hr = IStream_Write(stream, &data, sizeof(data), NULL);
1299 ok(hr == S_OK, "Write error %#x\n", hr);
1300
1301 switch (fmt)
1302 {
1303 case CF_BITMAP:
1304 /* FIXME: figure out stream format */
1305 hobj = CreateBitmap(1, 1, 1, 1, NULL);
1306 data_size = GetBitmapBits(hobj, sizeof(buf), buf);
1307 DeleteObject(hobj);
1308 break;
1309
1310 case CF_METAFILEPICT:
1311 case CF_ENHMETAFILE:
1312 hdc = CreateMetaFileA(NULL);
1313 hobj = CloseMetaFile(hdc);
1314 data_size = GetMetaFileBitsEx(hobj, sizeof(buf), buf);
1315 DeleteMetaFile(hobj);
1316 break;
1317
1318 default:
1319 data_size = sizeof(buf);
1320 memset(buf, 'A', sizeof(buf));
1321 break;
1322 }
1323
1324 header.tdSize = sizeof(header.tdSize);
1325 header.dvAspect = DVASPECT_CONTENT;
1326 header.lindex = -1;
1327 header.advf = 1 << i;
1328 header.unknown7 = 0;
1329 header.dwObjectExtentX = 1;
1330 header.dwObjectExtentY = 1;
1331 header.dwSize = data_size;
1332 hr = IStream_Write(stream, &header, sizeof(header), NULL);
1333 ok(hr == S_OK, "Write error %#x\n", hr);
1334
1335 hr = IStream_Write(stream, buf, data_size, NULL);
1336 ok(hr == S_OK, "Write error %#x\n", hr);
1337
1338 IStream_Release(stream);
1339
1340 hr = OleLoad(stg, &IID_IUnknown, NULL, (void **)&obj);
1341 /* FIXME: figure out stream format */
1342 if (fmt == CF_BITMAP && hr != S_OK)
1343 {
1344 IStorage_Release(stg);
1345 continue;
1346 }
1347 ok(hr == S_OK, "OleLoad error %#x: cfFormat = %u, advf = %#x\n", hr, fmt, header.advf);
1348
1349 hdc = CreateCompatibleDC(0);
1350 SetRect(&rc, 0, 0, 100, 100);
1351 hr = OleDraw(obj, DVASPECT_CONTENT, hdc, &rc);
1352 DeleteDC(hdc);
1353 if (fmt == CF_METAFILEPICT)
1354 ok(hr == S_OK, "OleDraw error %#x: cfFormat = %u, advf = %#x\n", hr, fmt, header.advf);
1355 else if (fmt == CF_ENHMETAFILE)
1356 todo_wine
1357 ok(hr == S_OK, "OleDraw error %#x: cfFormat = %u, advf = %#x\n", hr, fmt, header.advf);
1358 else
1359 ok(hr == OLE_E_BLANK || hr == OLE_E_NOTRUNNING || hr == E_FAIL, "OleDraw should fail: %#x, cfFormat = %u, advf = %#x\n", hr, fmt, header.advf);
1360
1361 IUnknown_Release(obj);
1362 IStorage_Release(stg);
1363 }
1364 }
1365 }
1366
1367 static BOOL STDMETHODCALLTYPE draw_continue(ULONG_PTR param)
1368 {
1369 CHECK_EXPECTED_METHOD("draw_continue");
1370 return TRUE;
1371 }
1372
1373 static BOOL STDMETHODCALLTYPE draw_continue_false(ULONG_PTR param)
1374 {
1375 CHECK_EXPECTED_METHOD("draw_continue_false");
1376 return FALSE;
1377 }
1378
1379 static HRESULT WINAPI AdviseSink_QueryInterface(IAdviseSink *iface, REFIID riid, void **ppv)
1380 {
1381 if (IsEqualIID(riid, &IID_IAdviseSink) || IsEqualIID(riid, &IID_IUnknown))
1382 {
1383 *ppv = iface;
1384 IAdviseSink_AddRef(iface);
1385 return S_OK;
1386 }
1387 *ppv = NULL;
1388 return E_NOINTERFACE;
1389 }
1390
1391 static ULONG WINAPI AdviseSink_AddRef(IAdviseSink *iface)
1392 {
1393 return 2;
1394 }
1395
1396 static ULONG WINAPI AdviseSink_Release(IAdviseSink *iface)
1397 {
1398 return 1;
1399 }
1400
1401
1402 static void WINAPI AdviseSink_OnDataChange(
1403 IAdviseSink *iface,
1404 FORMATETC *pFormatetc,
1405 STGMEDIUM *pStgmed)
1406 {
1407 CHECK_EXPECTED_METHOD("AdviseSink_OnDataChange");
1408 }
1409
1410 static void WINAPI AdviseSink_OnViewChange(
1411 IAdviseSink *iface,
1412 DWORD dwAspect,
1413 LONG lindex)
1414 {
1415 CHECK_EXPECTED_METHOD("AdviseSink_OnViewChange");
1416 }
1417
1418 static void WINAPI AdviseSink_OnRename(
1419 IAdviseSink *iface,
1420 IMoniker *pmk)
1421 {
1422 CHECK_EXPECTED_METHOD("AdviseSink_OnRename");
1423 }
1424
1425 static void WINAPI AdviseSink_OnSave(IAdviseSink *iface)
1426 {
1427 CHECK_EXPECTED_METHOD("AdviseSink_OnSave");
1428 }
1429
1430 static void WINAPI AdviseSink_OnClose(IAdviseSink *iface)
1431 {
1432 CHECK_EXPECTED_METHOD("AdviseSink_OnClose");
1433 }
1434
1435 static const IAdviseSinkVtbl AdviseSinkVtbl =
1436 {
1437 AdviseSink_QueryInterface,
1438 AdviseSink_AddRef,
1439 AdviseSink_Release,
1440 AdviseSink_OnDataChange,
1441 AdviseSink_OnViewChange,
1442 AdviseSink_OnRename,
1443 AdviseSink_OnSave,
1444 AdviseSink_OnClose
1445 };
1446
1447 static IAdviseSink AdviseSink = { &AdviseSinkVtbl };
1448
1449 static HRESULT WINAPI DataObject_QueryInterface(
1450 IDataObject* iface,
1451 REFIID riid,
1452 void** ppvObject)
1453 {
1454 CHECK_EXPECTED_METHOD("DataObject_QueryInterface");
1455
1456 if (IsEqualIID(riid, &IID_IDataObject) || IsEqualIID(riid, &IID_IUnknown))
1457 {
1458 *ppvObject = iface;
1459 return S_OK;
1460 }
1461 *ppvObject = NULL;
1462 return S_OK;
1463 }
1464
1465 static ULONG WINAPI DataObject_AddRef(
1466 IDataObject* iface)
1467 {
1468 CHECK_EXPECTED_METHOD("DataObject_AddRef");
1469 return 2;
1470 }
1471
1472 static ULONG WINAPI DataObject_Release(
1473 IDataObject* iface)
1474 {
1475 CHECK_EXPECTED_METHOD("DataObject_Release");
1476 return 1;
1477 }
1478
1479 static inline BOOL fmtetc_equal( const FORMATETC *a, const FORMATETC *b )
1480 {
1481 /* FIXME ptd */
1482 return a->cfFormat == b->cfFormat && a->dwAspect == b->dwAspect &&
1483 a->lindex == b->lindex && a->tymed == b->tymed;
1484
1485 }
1486
1487 static HRESULT WINAPI DataObject_GetData( IDataObject *iface, FORMATETC *fmt_in,
1488 STGMEDIUM *med )
1489 {
1490 FORMATETC *fmt;
1491
1492 CHECK_EXPECTED_METHOD_FMT("DataObject_GetData", fmt_in);
1493
1494 for (fmt = g_dataobject_fmts; fmt && fmt->cfFormat != 0; fmt++)
1495 {
1496 if (fmtetc_equal( fmt_in, fmt ))
1497 {
1498 switch (fmt->cfFormat)
1499 {
1500 case CF_DIB:
1501 create_dib( med );
1502 return S_OK;
1503 case CF_BITMAP:
1504 create_bitmap( med );
1505 return S_OK;
1506 case CF_ENHMETAFILE:
1507 create_emf( med );
1508 return S_OK;
1509 case CF_TEXT:
1510 create_text( med );
1511 return S_OK;
1512 default:
1513 trace( "unhandled fmt %d\n", fmt->cfFormat );
1514 }
1515 }
1516 }
1517
1518 return S_FALSE;
1519 }
1520
1521 static HRESULT WINAPI DataObject_GetDataHere(
1522 IDataObject* iface,
1523 LPFORMATETC pformatetc,
1524 STGMEDIUM* pmedium)
1525 {
1526 CHECK_EXPECTED_METHOD("DataObject_GetDataHere");
1527 return E_NOTIMPL;
1528 }
1529
1530 static HRESULT WINAPI DataObject_QueryGetData( IDataObject *iface, FORMATETC *fmt_in )
1531 {
1532 FORMATETC *fmt;
1533
1534 CHECK_EXPECTED_METHOD_FMT("DataObject_QueryGetData", fmt_in);
1535
1536 for (fmt = g_dataobject_fmts; fmt && fmt->cfFormat != 0; fmt++)
1537 if (fmtetc_equal( fmt_in, fmt )) return S_OK;
1538
1539 return S_FALSE;
1540 }
1541
1542 static HRESULT WINAPI DataObject_GetCanonicalFormatEtc(
1543 IDataObject* iface,
1544 LPFORMATETC pformatectIn,
1545 LPFORMATETC pformatetcOut)
1546 {
1547 CHECK_EXPECTED_METHOD("DataObject_GetCanonicalFormatEtc");
1548 return E_NOTIMPL;
1549 }
1550
1551 static HRESULT WINAPI DataObject_SetData(
1552 IDataObject* iface,
1553 LPFORMATETC pformatetc,
1554 STGMEDIUM* pmedium,
1555 BOOL fRelease)
1556 {
1557 CHECK_EXPECTED_METHOD("DataObject_SetData");
1558 return E_NOTIMPL;
1559 }
1560
1561 static HRESULT WINAPI DataObject_EnumFormatEtc(
1562 IDataObject* iface,
1563 DWORD dwDirection,
1564 IEnumFORMATETC** ppenumFormatEtc)
1565 {
1566 CHECK_EXPECTED_METHOD("DataObject_EnumFormatEtc");
1567 return E_NOTIMPL;
1568 }
1569
1570 static HRESULT WINAPI DataObject_DAdvise(
1571 IDataObject* iface,
1572 FORMATETC* pformatetc,
1573 DWORD advf,
1574 IAdviseSink* pAdvSink,
1575 DWORD* pdwConnection)
1576 {
1577 STGMEDIUM stgmedium;
1578
1579 CHECK_EXPECTED_METHOD("DataObject_DAdvise");
1580 *pdwConnection = 1;
1581
1582 if(advf & ADVF_PRIMEFIRST)
1583 {
1584 ok(pformatetc->cfFormat == cf_test_2, "got %04x\n", pformatetc->cfFormat);
1585 stgmedium.tymed = TYMED_HGLOBAL;
1586 U(stgmedium).hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 4);
1587 stgmedium.pUnkForRelease = NULL;
1588 IAdviseSink_OnDataChange(pAdvSink, pformatetc, &stgmedium);
1589 }
1590
1591 return S_OK;
1592 }
1593
1594 static HRESULT WINAPI DataObject_DUnadvise(
1595 IDataObject* iface,
1596 DWORD dwConnection)
1597 {
1598 CHECK_EXPECTED_METHOD("DataObject_DUnadvise");
1599 return S_OK;
1600 }
1601
1602 static HRESULT WINAPI DataObject_EnumDAdvise(
1603 IDataObject* iface,
1604 IEnumSTATDATA** ppenumAdvise)
1605 {
1606 CHECK_EXPECTED_METHOD("DataObject_EnumDAdvise");
1607 return OLE_E_ADVISENOTSUPPORTED;
1608 }
1609
1610 static IDataObjectVtbl DataObjectVtbl =
1611 {
1612 DataObject_QueryInterface,
1613 DataObject_AddRef,
1614 DataObject_Release,
1615 DataObject_GetData,
1616 DataObject_GetDataHere,
1617 DataObject_QueryGetData,
1618 DataObject_GetCanonicalFormatEtc,
1619 DataObject_SetData,
1620 DataObject_EnumFormatEtc,
1621 DataObject_DAdvise,
1622 DataObject_DUnadvise,
1623 DataObject_EnumDAdvise
1624 };
1625
1626 static IDataObject DataObject = { &DataObjectVtbl };
1627
1628 static HRESULT WINAPI Unknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1629 {
1630 *ppv = NULL;
1631 if (IsEqualIID(riid, &IID_IUnknown)) *ppv = iface;
1632 if (*ppv)
1633 {
1634 IUnknown_AddRef((IUnknown *)*ppv);
1635 return S_OK;
1636 }
1637 return E_NOINTERFACE;
1638 }
1639
1640 static ULONG WINAPI Unknown_AddRef(IUnknown *iface)
1641 {
1642 return 2;
1643 }
1644
1645 static ULONG WINAPI Unknown_Release(IUnknown *iface)
1646 {
1647 return 1;
1648 }
1649
1650 static const IUnknownVtbl UnknownVtbl =
1651 {
1652 Unknown_QueryInterface,
1653 Unknown_AddRef,
1654 Unknown_Release
1655 };
1656
1657 static IUnknown unknown = { &UnknownVtbl };
1658
1659 static void check_enum_cache(IOleCache2 *cache, const STATDATA *expect, int num)
1660 {
1661 IEnumSTATDATA *enum_stat;
1662 STATDATA stat;
1663 HRESULT hr;
1664
1665 hr = IOleCache2_EnumCache( cache, &enum_stat );
1666 ok( hr == S_OK, "got %08x\n", hr );
1667
1668 while (IEnumSTATDATA_Next(enum_stat, 1, &stat, NULL) == S_OK)
1669 {
1670 ok( stat.formatetc.cfFormat == expect->formatetc.cfFormat, "got %d expect %d\n",
1671 stat.formatetc.cfFormat, expect->formatetc.cfFormat );
1672 ok( !stat.formatetc.ptd == !expect->formatetc.ptd, "got %p expect %p\n",
1673 stat.formatetc.ptd, expect->formatetc.ptd );
1674 ok( stat.formatetc.dwAspect == expect->formatetc.dwAspect, "got %d expect %d\n",
1675 stat.formatetc.dwAspect, expect->formatetc.dwAspect );
1676 ok( stat.formatetc.lindex == expect->formatetc.lindex, "got %d expect %d\n",
1677 stat.formatetc.lindex, expect->formatetc.lindex );
1678 ok( stat.formatetc.tymed == expect->formatetc.tymed, "got %d expect %d\n",
1679 stat.formatetc.tymed, expect->formatetc.tymed );
1680 ok( stat.advf == expect->advf, "got %d expect %d\n", stat.advf, expect->advf );
1681 ok( stat.pAdvSink == 0, "got %p\n", stat.pAdvSink );
1682 ok( stat.dwConnection == expect->dwConnection, "got %d expect %d\n", stat.dwConnection, expect->dwConnection );
1683 num--;
1684 expect++;
1685 }
1686
1687 ok( num == 0, "incorrect number. num %d\n", num );
1688
1689 IEnumSTATDATA_Release( enum_stat );
1690 }
1691
1692 static void test_data_cache(void)
1693 {
1694 HRESULT hr;
1695 IOleCache2 *pOleCache;
1696 IOleCache *olecache;
1697 IStorage *pStorage;
1698 IUnknown *unk, *unk2;
1699 IPersistStorage *pPS;
1700 IViewObject *pViewObject;
1701 IOleCacheControl *pOleCacheControl;
1702 IDataObject *pCacheDataObject;
1703 FORMATETC fmtetc;
1704 STGMEDIUM stgmedium;
1705 DWORD dwConnection;
1706 DWORD dwFreeze;
1707 RECTL rcBounds;
1708 HDC hdcMem;
1709 CLSID clsid;
1710 char szSystemDir[MAX_PATH];
1711 WCHAR wszPath[MAX_PATH];
1712 static const WCHAR wszShell32[] = {'\\','s','h','e','l','l','3','2','.','d','l','l',0};
1713
1714 static const struct expected_method methods_cacheinitnew[] =
1715 {
1716 { "AdviseSink_OnViewChange", 0 },
1717 { "AdviseSink_OnViewChange", 0 },
1718 { "draw_continue", 1 },
1719 { "draw_continue_false", 1 },
1720 { "DataObject_DAdvise", 0 },
1721 { "DataObject_DAdvise", 0 },
1722 { "DataObject_DUnadvise", 0 },
1723 { "DataObject_DUnadvise", 0 },
1724 { NULL, 0 }
1725 };
1726 static const struct expected_method methods_cacheload[] =
1727 {
1728 { "AdviseSink_OnViewChange", 0 },
1729 { "draw_continue", 1 },
1730 { "draw_continue", 1 },
1731 { "draw_continue", 1 },
1732 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_THUMBNAIL, -1, TYMED_HGLOBAL} },
1733 { "DataObject_GetData", 0, { CF_BITMAP, NULL, DVASPECT_THUMBNAIL, -1, TYMED_GDI} },
1734 { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_ICON, -1, TYMED_MFPICT} },
1735 { NULL, 0 }
1736 };
1737 static const struct expected_method methods_cachethenrun[] =
1738 {
1739 { "DataObject_DAdvise", 0 },
1740 { "DataObject_DAdvise", 0 },
1741 { "DataObject_DAdvise", 0 },
1742 { "DataObject_DAdvise", 0 },
1743 { "DataObject_DUnadvise", 0 },
1744 { "DataObject_DUnadvise", 0 },
1745 { "DataObject_DUnadvise", 0 },
1746 { "DataObject_DUnadvise", 0 },
1747 { NULL, 0 }
1748 };
1749
1750 GetSystemDirectoryA(szSystemDir, ARRAY_SIZE(szSystemDir));
1751
1752 expected_method_list = methods_cacheinitnew;
1753
1754 fmtetc.cfFormat = CF_METAFILEPICT;
1755 fmtetc.dwAspect = DVASPECT_ICON;
1756 fmtetc.lindex = -1;
1757 fmtetc.ptd = NULL;
1758 fmtetc.tymed = TYMED_MFPICT;
1759
1760 hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &pStorage);
1761 ok_ole_success(hr, "StgCreateDocfile");
1762
1763 /* aggregation */
1764
1765 /* requested is not IUnknown */
1766 hr = CreateDataCache(&unknown, &CLSID_NULL, &IID_IOleCache2, (void**)&pOleCache);
1767 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1768
1769 hr = CreateDataCache(&unknown, &CLSID_NULL, &IID_IUnknown, (void**)&unk);
1770 ok(hr == S_OK, "got 0x%08x\n", hr);
1771
1772 hr = IUnknown_QueryInterface(unk, &IID_IOleCache, (void**)&olecache);
1773 ok(hr == S_OK, "got 0x%08x\n", hr);
1774 hr = IUnknown_QueryInterface(unk, &IID_IOleCache2, (void**)&pOleCache);
1775 ok(hr == S_OK, "got 0x%08x\n", hr);
1776 ok(unk != (IUnknown*)olecache, "got %p, expected %p\n", olecache, unk);
1777 ok(unk != (IUnknown*)pOleCache, "got %p, expected %p\n", pOleCache, unk);
1778 IOleCache2_Release(pOleCache);
1779 IOleCache_Release(olecache);
1780 IUnknown_Release(unk);
1781
1782 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IUnknown, (void**)&unk);
1783 ok(hr == S_OK, "got 0x%08x\n", hr);
1784 hr = IUnknown_QueryInterface(unk, &IID_IOleCache, (void**)&olecache);
1785 ok(hr == S_OK, "got 0x%08x\n", hr);
1786 hr = IUnknown_QueryInterface(unk, &IID_IOleCache2, (void**)&pOleCache);
1787 ok(hr == S_OK, "got 0x%08x\n", hr);
1788 hr = IUnknown_QueryInterface(unk, &IID_IUnknown, (void**)&unk2);
1789 ok(hr == S_OK, "got 0x%08x\n", hr);
1790 ok(unk == (IUnknown*)olecache, "got %p, expected %p\n", olecache, unk);
1791 ok(unk == (IUnknown*)pOleCache, "got %p, expected %p\n", pOleCache, unk);
1792 ok(unk == unk2, "got %p, expected %p\n", unk2, unk);
1793 IUnknown_Release(unk2);
1794 IOleCache2_Release(pOleCache);
1795 IOleCache_Release(olecache);
1796 IUnknown_Release(unk);
1797
1798 /* Test with new data */
1799
1800 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IOleCache2, (LPVOID *)&pOleCache);
1801 ok_ole_success(hr, "CreateDataCache");
1802
1803 hr = IOleCache2_QueryInterface(pOleCache, &IID_IPersistStorage, (LPVOID *)&pPS);
1804 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IPersistStorage)");
1805 hr = IOleCache2_QueryInterface(pOleCache, &IID_IViewObject, (LPVOID *)&pViewObject);
1806 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IViewObject)");
1807 hr = IOleCache2_QueryInterface(pOleCache, &IID_IOleCacheControl, (LPVOID *)&pOleCacheControl);
1808 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IOleCacheControl)");
1809
1810 hr = IViewObject_SetAdvise(pViewObject, DVASPECT_ICON, ADVF_PRIMEFIRST, &AdviseSink);
1811 ok_ole_success(hr, "IViewObject_SetAdvise");
1812
1813 hr = IPersistStorage_InitNew(pPS, pStorage);
1814 ok_ole_success(hr, "IPersistStorage_InitNew");
1815
1816 hr = IPersistStorage_IsDirty(pPS);
1817 ok_ole_success(hr, "IPersistStorage_IsDirty");
1818
1819 hr = IPersistStorage_GetClassID(pPS, &clsid);
1820 ok_ole_success(hr, "IPersistStorage_GetClassID");
1821 ok(IsEqualCLSID(&clsid, &IID_NULL), "clsid should be blank\n");
1822
1823 hr = IOleCache2_Uncache(pOleCache, 0xdeadbeef);
1824 ok(hr == OLE_E_NOCONNECTION, "IOleCache_Uncache with invalid value should return OLE_E_NOCONNECTION instead of 0x%x\n", hr);
1825
1826 /* Both tests crash on NT4 and below. StgCreatePropSetStg is only available on w2k and above. */
1827 if (GetProcAddress(GetModuleHandleA("ole32.dll"), "StgCreatePropSetStg"))
1828 {
1829 hr = IOleCache2_Cache(pOleCache, NULL, 0, &dwConnection);
1830 ok(hr == E_INVALIDARG, "IOleCache_Cache with NULL fmtetc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1831
1832 hr = IOleCache2_Cache(pOleCache, NULL, 0, NULL);
1833 ok(hr == E_INVALIDARG, "IOleCache_Cache with NULL pdwConnection should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1834 }
1835 else
1836 {
1837 skip("tests with NULL parameters will crash on NT4 and below\n");
1838 }
1839
1840 for (fmtetc.cfFormat = CF_TEXT; fmtetc.cfFormat < CF_MAX; fmtetc.cfFormat++)
1841 {
1842 int i;
1843 fmtetc.dwAspect = DVASPECT_THUMBNAIL;
1844 for (i = 0; i < 7; i++)
1845 {
1846 fmtetc.tymed = 1 << i;
1847 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1848 if ((fmtetc.cfFormat == CF_METAFILEPICT && fmtetc.tymed == TYMED_MFPICT) ||
1849 (fmtetc.cfFormat == CF_BITMAP && fmtetc.tymed == TYMED_GDI) ||
1850 (fmtetc.cfFormat == CF_DIB && fmtetc.tymed == TYMED_HGLOBAL) ||
1851 (fmtetc.cfFormat == CF_ENHMETAFILE && fmtetc.tymed == TYMED_ENHMF))
1852 ok(hr == S_OK, "IOleCache_Cache cfFormat = %d, tymed = %d should have returned S_OK instead of 0x%08x\n",
1853 fmtetc.cfFormat, fmtetc.tymed, hr);
1854 else if (fmtetc.tymed == TYMED_HGLOBAL)
1855 ok(hr == CACHE_S_FORMATETC_NOTSUPPORTED ||
1856 broken(hr == S_OK && fmtetc.cfFormat == CF_BITMAP) /* Win9x & NT4 */,
1857 "IOleCache_Cache cfFormat = %d, tymed = %d should have returned CACHE_S_FORMATETC_NOTSUPPORTED instead of 0x%08x\n",
1858 fmtetc.cfFormat, fmtetc.tymed, hr);
1859 else
1860 ok(hr == DV_E_TYMED, "IOleCache_Cache cfFormat = %d, tymed = %d should have returned DV_E_TYMED instead of 0x%08x\n",
1861 fmtetc.cfFormat, fmtetc.tymed, hr);
1862 if (SUCCEEDED(hr))
1863 {
1864 hr = IOleCache2_Uncache(pOleCache, dwConnection);
1865 ok_ole_success(hr, "IOleCache_Uncache");
1866 }
1867 }
1868 }
1869
1870 fmtetc.cfFormat = CF_BITMAP;
1871 fmtetc.dwAspect = DVASPECT_THUMBNAIL;
1872 fmtetc.tymed = TYMED_GDI;
1873 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1874 ok_ole_success(hr, "IOleCache_Cache");
1875
1876 fmtetc.cfFormat = 0;
1877 fmtetc.dwAspect = DVASPECT_ICON;
1878 fmtetc.tymed = TYMED_MFPICT;
1879 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1880 ok_ole_success(hr, "IOleCache_Cache");
1881
1882 MultiByteToWideChar(CP_ACP, 0, szSystemDir, -1, wszPath, ARRAY_SIZE(wszPath));
1883 memcpy(wszPath+lstrlenW(wszPath), wszShell32, sizeof(wszShell32));
1884
1885 fmtetc.cfFormat = CF_METAFILEPICT;
1886 stgmedium.tymed = TYMED_MFPICT;
1887 U(stgmedium).hMetaFilePict = OleMetafilePictFromIconAndLabel(
1888 LoadIconA(NULL, (LPSTR)IDI_APPLICATION), wszPath, wszPath, 0);
1889 stgmedium.pUnkForRelease = NULL;
1890
1891 fmtetc.dwAspect = DVASPECT_CONTENT;
1892 hr = IOleCache2_SetData(pOleCache, &fmtetc, &stgmedium, FALSE);
1893 ok(hr == OLE_E_BLANK, "IOleCache_SetData for aspect not in cache should have return OLE_E_BLANK instead of 0x%08x\n", hr);
1894
1895 fmtetc.dwAspect = DVASPECT_ICON;
1896 hr = IOleCache2_SetData(pOleCache, &fmtetc, &stgmedium, FALSE);
1897 ok_ole_success(hr, "IOleCache_SetData");
1898 ReleaseStgMedium(&stgmedium);
1899
1900 hr = IViewObject_Freeze(pViewObject, DVASPECT_ICON, -1, NULL, &dwFreeze);
1901 todo_wine {
1902 ok_ole_success(hr, "IViewObject_Freeze");
1903 hr = IViewObject_Freeze(pViewObject, DVASPECT_CONTENT, -1, NULL, &dwFreeze);
1904 ok(hr == OLE_E_BLANK, "IViewObject_Freeze with uncached aspect should have returned OLE_E_BLANK instead of 0x%08x\n", hr);
1905 }
1906
1907 rcBounds.left = 0;
1908 rcBounds.top = 0;
1909 rcBounds.right = 100;
1910 rcBounds.bottom = 100;
1911 hdcMem = CreateCompatibleDC(NULL);
1912
1913 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1914 ok_ole_success(hr, "IViewObject_Draw");
1915
1916 hr = IViewObject_Draw(pViewObject, DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1917 ok(hr == OLE_E_BLANK, "IViewObject_Draw with uncached aspect should have returned OLE_E_BLANK instead of 0x%08x\n", hr);
1918
1919 /* a NULL draw_continue fn ptr */
1920 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, NULL, 0xdeadbeef);
1921 ok_ole_success(hr, "IViewObject_Draw");
1922
1923 /* draw_continue that returns FALSE to abort drawing */
1924 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue_false, 0xdeadbeef);
1925 ok(hr == E_ABORT ||
1926 broken(hr == S_OK), /* win9x may skip the callbacks */
1927 "IViewObject_Draw with draw_continue_false returns 0x%08x\n", hr);
1928
1929 DeleteDC(hdcMem);
1930
1931 hr = IOleCacheControl_OnRun(pOleCacheControl, &DataObject);
1932 ok_ole_success(hr, "IOleCacheControl_OnRun");
1933
1934 hr = IPersistStorage_Save(pPS, pStorage, TRUE);
1935 ok_ole_success(hr, "IPersistStorage_Save");
1936
1937 hr = IPersistStorage_SaveCompleted(pPS, NULL);
1938 ok_ole_success(hr, "IPersistStorage_SaveCompleted");
1939
1940 hr = IPersistStorage_IsDirty(pPS);
1941 ok(hr == S_FALSE, "IPersistStorage_IsDirty should have returned S_FALSE instead of 0x%x\n", hr);
1942
1943 IPersistStorage_Release(pPS);
1944 IViewObject_Release(pViewObject);
1945 IOleCache2_Release(pOleCache);
1946 IOleCacheControl_Release(pOleCacheControl);
1947
1948 CHECK_NO_EXTRA_METHODS();
1949
1950 /* Test with loaded data */
1951 trace("Testing loaded data with CreateDataCache:\n");
1952 expected_method_list = methods_cacheload;
1953
1954 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IOleCache2, (LPVOID *)&pOleCache);
1955 ok_ole_success(hr, "CreateDataCache");
1956
1957 hr = IOleCache2_QueryInterface(pOleCache, &IID_IPersistStorage, (LPVOID *)&pPS);
1958 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IPersistStorage)");
1959 hr = IOleCache2_QueryInterface(pOleCache, &IID_IViewObject, (LPVOID *)&pViewObject);
1960 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IViewObject)");
1961
1962 hr = IViewObject_SetAdvise(pViewObject, DVASPECT_ICON, ADVF_PRIMEFIRST, &AdviseSink);
1963 ok_ole_success(hr, "IViewObject_SetAdvise");
1964
1965 hr = IPersistStorage_Load(pPS, pStorage);
1966 ok_ole_success(hr, "IPersistStorage_Load");
1967
1968 hr = IPersistStorage_IsDirty(pPS);
1969 ok(hr == S_FALSE, "IPersistStorage_IsDirty should have returned S_FALSE instead of 0x%x\n", hr);
1970
1971 fmtetc.cfFormat = 0;
1972 fmtetc.dwAspect = DVASPECT_ICON;
1973 fmtetc.lindex = -1;
1974 fmtetc.ptd = NULL;
1975 fmtetc.tymed = TYMED_MFPICT;
1976 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
1977 ok(hr == CACHE_S_SAMECACHE, "IOleCache_Cache with already loaded data format type should return CACHE_S_SAMECACHE instead of 0x%x\n", hr);
1978
1979 rcBounds.left = 0;
1980 rcBounds.top = 0;
1981 rcBounds.right = 100;
1982 rcBounds.bottom = 100;
1983 hdcMem = CreateCompatibleDC(NULL);
1984
1985 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1986 ok_ole_success(hr, "IViewObject_Draw");
1987
1988 hr = IViewObject_Draw(pViewObject, DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1989 ok(hr == OLE_E_BLANK, "IViewObject_Draw with uncached aspect should have returned OLE_E_BLANK instead of 0x%08x\n", hr);
1990
1991 /* unload the cached storage object, causing it to be reloaded */
1992 hr = IOleCache2_DiscardCache(pOleCache, DISCARDCACHE_NOSAVE);
1993 ok_ole_success(hr, "IOleCache2_DiscardCache");
1994 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
1995 ok_ole_success(hr, "IViewObject_Draw");
1996
1997 /* unload the cached storage object, but don't allow it to be reloaded */
1998 hr = IPersistStorage_HandsOffStorage(pPS);
1999 ok_ole_success(hr, "IPersistStorage_HandsOffStorage");
2000 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
2001 ok_ole_success(hr, "IViewObject_Draw");
2002 hr = IOleCache2_DiscardCache(pOleCache, DISCARDCACHE_NOSAVE);
2003 ok_ole_success(hr, "IOleCache2_DiscardCache");
2004 hr = IViewObject_Draw(pViewObject, DVASPECT_ICON, -1, NULL, NULL, NULL, hdcMem, &rcBounds, NULL, draw_continue, 0xdeadbeef);
2005 ok(hr == OLE_E_BLANK, "IViewObject_Draw with uncached aspect should have returned OLE_E_BLANK instead of 0x%08x\n", hr);
2006
2007 DeleteDC(hdcMem);
2008
2009 hr = IOleCache2_InitCache(pOleCache, &DataObject);
2010 ok(hr == CACHE_E_NOCACHE_UPDATED, "IOleCache_InitCache should have returned CACHE_E_NOCACHE_UPDATED instead of 0x%08x\n", hr);
2011
2012 IPersistStorage_Release(pPS);
2013 IViewObject_Release(pViewObject);
2014 IOleCache2_Release(pOleCache);
2015
2016 CHECK_NO_EXTRA_METHODS();
2017
2018 hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IOleCache2, (LPVOID *)&pOleCache);
2019 ok_ole_success(hr, "CreateDataCache");
2020
2021 expected_method_list = methods_cachethenrun;
2022
2023 hr = IOleCache2_QueryInterface(pOleCache, &IID_IDataObject, (LPVOID *)&pCacheDataObject);
2024 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IDataObject)");
2025 hr = IOleCache2_QueryInterface(pOleCache, &IID_IOleCacheControl, (LPVOID *)&pOleCacheControl);
2026 ok_ole_success(hr, "IOleCache_QueryInterface(IID_IOleCacheControl)");
2027
2028 fmtetc.cfFormat = CF_METAFILEPICT;
2029 fmtetc.dwAspect = DVASPECT_CONTENT;
2030 fmtetc.tymed = TYMED_MFPICT;
2031
2032 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
2033 ok_ole_success(hr, "IOleCache_Cache");
2034
2035 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2036 ok(hr == OLE_E_BLANK, "got %08x\n", hr);
2037
2038 fmtetc.cfFormat = cf_test_1;
2039 fmtetc.dwAspect = DVASPECT_CONTENT;
2040 fmtetc.tymed = TYMED_HGLOBAL;
2041
2042 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
2043 ok(hr == CACHE_S_FORMATETC_NOTSUPPORTED, "got %08x\n", hr);
2044
2045 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2046 ok(hr == OLE_E_BLANK, "got %08x\n", hr);
2047
2048 fmtetc.cfFormat = cf_test_2;
2049 hr = IOleCache2_Cache(pOleCache, &fmtetc, ADVF_PRIMEFIRST, &dwConnection);
2050 ok(hr == CACHE_S_FORMATETC_NOTSUPPORTED, "got %08x\n", hr);
2051
2052 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2053 ok(hr == OLE_E_BLANK, "got %08x\n", hr);
2054
2055 hr = IOleCacheControl_OnRun(pOleCacheControl, &DataObject);
2056 ok_ole_success(hr, "IOleCacheControl_OnRun");
2057
2058 fmtetc.cfFormat = cf_test_3;
2059 hr = IOleCache2_Cache(pOleCache, &fmtetc, 0, &dwConnection);
2060 ok(hr == CACHE_S_FORMATETC_NOTSUPPORTED, "got %08x\n", hr);
2061
2062 fmtetc.cfFormat = cf_test_1;
2063 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2064 ok(hr == OLE_E_BLANK, "got %08x\n", hr);
2065
2066 fmtetc.cfFormat = cf_test_2;
2067 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2068 ok(hr == S_OK, "got %08x\n", hr);
2069 ReleaseStgMedium(&stgmedium);
2070
2071 fmtetc.cfFormat = cf_test_3;
2072 hr = IDataObject_GetData(pCacheDataObject, &fmtetc, &stgmedium);
2073 ok(hr == OLE_E_BLANK, "got %08x\n", hr);
2074
2075 IOleCacheControl_Release(pOleCacheControl);
2076 IDataObject_Release(pCacheDataObject);
2077 IOleCache2_Release(pOleCache);
2078
2079 CHECK_NO_EXTRA_METHODS();
2080
2081 IStorage_Release(pStorage);
2082 }
2083
2084 static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0};
2085
2086 /* 2 x 1 x 32 bpp dib. PelsPerMeter = 200x400 */
2087 static BYTE file_dib[] =
2088 {
2089 0x42, 0x4d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
2090 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
2091 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00,
2092 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
2093 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00,
2094 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00,
2095 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
2096 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
2097 };
2098
2099 static IStorage *create_storage( int num )
2100 {
2101 IStorage *stg;
2102 IStream *stm;
2103 HRESULT hr;
2104 ULONG written;
2105
2106 hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg );
2107 ok( hr == S_OK, "got %08x\n", hr);
2108 hr = IStorage_SetClass( stg, &CLSID_Picture_Dib );
2109 ok( hr == S_OK, "got %08x\n", hr);
2110 hr = IStorage_CreateStream( stg, CONTENTS, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, &stm );
2111 ok( hr == S_OK, "got %08x\n", hr);
2112 if (num == 1) /* Set biXPelsPerMeter = 0 */
2113 {
2114 file_dib[0x26] = 0;
2115 file_dib[0x27] = 0;
2116 }
2117 hr = IStream_Write( stm, file_dib, sizeof(file_dib), &written );
2118 ok( hr == S_OK, "got %08x\n", hr);
2119 IStream_Release( stm );
2120 return stg;
2121 }
2122
2123 static void test_data_cache_dib_contents_stream(int num)
2124 {
2125 HRESULT hr;
2126 IUnknown *unk;
2127 IPersistStorage *persist;
2128 IDataObject *data;
2129 IViewObject2 *view;
2130 IStorage *stg;
2131 IOleCache2 *cache;
2132 FORMATETC fmt = {CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
2133 STGMEDIUM med;
2134 CLSID cls;
2135 SIZEL sz;
2136 BYTE *ptr;
2137 BITMAPINFOHEADER expect_info;
2138 STATDATA enum_expect[] =
2139 {
2140 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2141 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 },
2142 };
2143
2144 hr = CreateDataCache( NULL, &CLSID_Picture_Metafile, &IID_IUnknown, (void **)&unk );
2145 ok( SUCCEEDED(hr), "got %08x\n", hr );
2146 hr = IUnknown_QueryInterface( unk, &IID_IPersistStorage, (void **)&persist );
2147 ok( SUCCEEDED(hr), "got %08x\n", hr );
2148 hr = IUnknown_QueryInterface( unk, &IID_IDataObject, (void **)&data );
2149 ok( SUCCEEDED(hr), "got %08x\n", hr );
2150 hr = IUnknown_QueryInterface( unk, &IID_IViewObject2, (void **)&view );
2151 ok( SUCCEEDED(hr), "got %08x\n", hr );
2152 hr = IUnknown_QueryInterface( unk, &IID_IOleCache2, (void **)&cache );
2153 ok( SUCCEEDED(hr), "got %08x\n", hr );
2154
2155 stg = create_storage( num );
2156
2157 hr = IPersistStorage_Load( persist, stg );
2158 ok( SUCCEEDED(hr), "got %08x\n", hr );
2159 IStorage_Release( stg );
2160
2161 hr = IPersistStorage_GetClassID( persist, &cls );
2162 ok( SUCCEEDED(hr), "got %08x\n", hr );
2163 ok( IsEqualCLSID( &cls, &CLSID_Picture_Dib ), "class id mismatch\n" );
2164
2165 hr = IDataObject_GetData( data, &fmt, &med );
2166 ok( SUCCEEDED(hr), "got %08x\n", hr );
2167 ok( med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed );
2168 ok( GlobalSize( U(med).hGlobal ) >= sizeof(dib) - sizeof(BITMAPFILEHEADER),
2169 "got %lu\n", GlobalSize( U(med).hGlobal ) );
2170 ptr = GlobalLock( U(med).hGlobal );
2171
2172 expect_info = *(BITMAPINFOHEADER *)(file_dib + sizeof(BITMAPFILEHEADER));
2173 if (expect_info.biXPelsPerMeter == 0 || expect_info.biYPelsPerMeter == 0)
2174 {
2175 HDC hdc = GetDC( 0 );
2176 expect_info.biXPelsPerMeter = MulDiv( GetDeviceCaps( hdc, LOGPIXELSX ), 10000, 254 );
2177 expect_info.biYPelsPerMeter = MulDiv( GetDeviceCaps( hdc, LOGPIXELSY ), 10000, 254 );
2178 ReleaseDC( 0, hdc );
2179 }
2180 ok( !memcmp( ptr, &expect_info, sizeof(expect_info) ), "mismatch\n" );
2181 ok( !memcmp( ptr + sizeof(expect_info), file_dib + sizeof(BITMAPFILEHEADER) + sizeof(expect_info),
2182 sizeof(file_dib) - sizeof(BITMAPFILEHEADER) - sizeof(expect_info) ), "mismatch\n" );
2183 GlobalUnlock( U(med).hGlobal );
2184 ReleaseStgMedium( &med );
2185
2186 check_enum_cache( cache, enum_expect, 2 );
2187
2188 hr = IViewObject2_GetExtent( view, DVASPECT_CONTENT, -1, NULL, &sz );
2189 ok( SUCCEEDED(hr), "got %08x\n", hr );
2190 if (num == 0)
2191 {
2192 ok( sz.cx == 1000, "got %d\n", sz.cx );
2193 ok( sz.cy == 250, "got %d\n", sz.cy );
2194 }
2195 else
2196 {
2197 HDC hdc = GetDC( 0 );
2198 LONG x = 2 * 2540 / GetDeviceCaps( hdc, LOGPIXELSX );
2199 LONG y = 1 * 2540 / GetDeviceCaps( hdc, LOGPIXELSY );
2200 ok( sz.cx == x, "got %d %d\n", sz.cx, x );
2201 ok( sz.cy == y, "got %d %d\n", sz.cy, y );
2202
2203 ReleaseDC( 0, hdc );
2204 }
2205
2206 IOleCache2_Release( cache );
2207 IViewObject2_Release( view );
2208 IDataObject_Release( data );
2209 IPersistStorage_Release( persist );
2210 IUnknown_Release( unk );
2211 }
2212
2213 static void check_bitmap_size( HBITMAP h, int cx, int cy )
2214 {
2215 BITMAP bm;
2216
2217 GetObjectW( h, sizeof(bm), &bm );
2218 ok( bm.bmWidth == cx, "got %d expect %d\n", bm.bmWidth, cx );
2219 ok( bm.bmHeight == cy, "got %d expect %d\n", bm.bmHeight, cy );
2220 }
2221
2222 static void check_dib_size( HGLOBAL h, int cx, int cy )
2223 {
2224 BITMAPINFO *info;
2225
2226 info = GlobalLock( h );
2227 ok( info->bmiHeader.biWidth == cx, "got %d expect %d\n", info->bmiHeader.biWidth, cx );
2228 ok( info->bmiHeader.biHeight == cy, "got %d expect %d\n", info->bmiHeader.biHeight, cy );
2229 GlobalUnlock( h );
2230 }
2231
2232 static void test_data_cache_cache(void)
2233 {
2234 HRESULT hr;
2235 IOleCache2 *cache;
2236 IDataObject *data;
2237 FORMATETC fmt;
2238 DWORD conn;
2239 STGMEDIUM med;
2240 STATDATA expect[] =
2241 {
2242 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 0 },
2243 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 0 },
2244 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 0 },
2245 {{ CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF }, 0, NULL, 0 }
2246 };
2247 STATDATA view_caching[] =
2248 {
2249 {{ 0, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF }, 0, NULL, 0 },
2250 {{ 0, 0, DVASPECT_THUMBNAIL, -1, TYMED_HGLOBAL }, 0, NULL, 0 },
2251 {{ 0, 0, DVASPECT_DOCPRINT, -1, TYMED_HGLOBAL }, 0, NULL, 0 },
2252 {{ CF_METAFILEPICT, 0, DVASPECT_ICON, -1, TYMED_MFPICT }, 0, NULL, 0 }
2253 };
2254
2255 hr = CreateDataCache( NULL, &CLSID_NULL, &IID_IOleCache2, (void **)&cache );
2256 ok( hr == S_OK, "got %08x\n", hr );
2257
2258 /* create a dib entry which will also create a bitmap entry too */
2259 fmt.cfFormat = CF_DIB;
2260 fmt.ptd = NULL;
2261 fmt.dwAspect = DVASPECT_CONTENT;
2262 fmt.lindex = -1;
2263 fmt.tymed = TYMED_HGLOBAL;
2264
2265 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2266 ok( hr == S_OK, "got %08x\n", hr );
2267 ok( conn == 2, "got %d\n", conn );
2268 expect[0].dwConnection = conn;
2269 expect[1].dwConnection = conn;
2270
2271 check_enum_cache( cache, expect, 2 );
2272
2273 /* now try to add a bitmap */
2274 fmt.cfFormat = CF_BITMAP;
2275 fmt.tymed = TYMED_GDI;
2276
2277 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2278 ok( hr == CACHE_S_SAMECACHE, "got %08x\n", hr );
2279
2280 /* metafile */
2281 fmt.cfFormat = CF_METAFILEPICT;
2282 fmt.tymed = TYMED_MFPICT;
2283
2284 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2285 ok( hr == S_OK, "got %08x\n", hr );
2286 ok( conn == 3, "got %d\n", conn );
2287 expect[2].dwConnection = conn;
2288
2289 check_enum_cache( cache, expect, 3);
2290
2291 /* enhmetafile */
2292 fmt.cfFormat = CF_ENHMETAFILE;
2293 fmt.tymed = TYMED_ENHMF;
2294
2295 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2296 ok( hr == S_OK, "got %08x\n", hr );
2297 ok( conn == 4, "got %d\n", conn );
2298 expect[3].dwConnection = conn;
2299
2300 check_enum_cache( cache, expect, 4 );
2301
2302 /* uncache everything */
2303 hr = IOleCache2_Uncache( cache, expect[3].dwConnection );
2304 ok( hr == S_OK, "got %08x\n", hr );
2305 hr = IOleCache2_Uncache( cache, expect[2].dwConnection );
2306 ok( hr == S_OK, "got %08x\n", hr );
2307 hr = IOleCache2_Uncache( cache, expect[0].dwConnection );
2308 ok( hr == S_OK, "got %08x\n", hr );
2309 hr = IOleCache2_Uncache( cache, expect[0].dwConnection );
2310 ok( hr == OLE_E_NOCONNECTION, "got %08x\n", hr );
2311
2312 check_enum_cache( cache, expect, 0 );
2313
2314 /* just create a bitmap entry which again adds both dib and bitmap */
2315 fmt.cfFormat = CF_BITMAP;
2316 fmt.tymed = TYMED_GDI;
2317
2318 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2319 ok( hr == S_OK, "got %08x\n", hr );
2320
2321 expect[0].dwConnection = conn;
2322 expect[1].dwConnection = conn;
2323
2324 check_enum_cache( cache, expect, 2 );
2325
2326 /* Try setting a 1x1 bitmap */
2327 hr = IOleCache2_QueryInterface( cache, &IID_IDataObject, (void **) &data );
2328 ok( hr == S_OK, "got %08x\n", hr );
2329
2330 create_bitmap( &med );
2331
2332 hr = IOleCache2_SetData( cache, &fmt, &med, TRUE );
2333 ok( hr == S_OK, "got %08x\n", hr );
2334
2335 hr = IDataObject_GetData( data, &fmt, &med );
2336 ok( hr == S_OK, "got %08x\n", hr );
2337 ok( med.tymed == TYMED_GDI, "got %d\n", med.tymed );
2338 check_bitmap_size( U(med).hBitmap, 1, 1 );
2339 ReleaseStgMedium( &med );
2340
2341 fmt.cfFormat = CF_DIB;
2342 fmt.tymed = TYMED_HGLOBAL;
2343 hr = IDataObject_GetData( data, &fmt, &med );
2344 ok( hr == S_OK, "got %08x\n", hr );
2345 ok( med.tymed == TYMED_HGLOBAL, "got %d\n", med.tymed );
2346 check_dib_size( U(med).hGlobal, 1, 1 );
2347 ReleaseStgMedium( &med );
2348
2349 /* Now set a 2x1 dib */
2350 fmt.cfFormat = CF_DIB;
2351 fmt.tymed = TYMED_HGLOBAL;
2352 create_dib( &med );
2353
2354 hr = IOleCache2_SetData( cache, &fmt, &med, TRUE );
2355 ok( hr == S_OK, "got %08x\n", hr );
2356
2357 fmt.cfFormat = CF_BITMAP;
2358 fmt.tymed = TYMED_GDI;
2359 hr = IDataObject_GetData( data, &fmt, &med );
2360 ok( hr == S_OK, "got %08x\n", hr );
2361 ok( med.tymed == TYMED_GDI, "got %d\n", med.tymed );
2362 check_bitmap_size( U(med).hBitmap, 2, 1 );
2363 ReleaseStgMedium( &med );
2364
2365 fmt.cfFormat = CF_DIB;
2366 fmt.tymed = TYMED_HGLOBAL;
2367 hr = IDataObject_GetData( data, &fmt, &med );
2368 ok( hr == S_OK, "got %08x\n", hr );
2369 ok( med.tymed == TYMED_HGLOBAL, "got %d\n", med.tymed );
2370 check_dib_size( U(med).hGlobal, 2, 1 );
2371 ReleaseStgMedium( &med );
2372
2373 /* uncache everything */
2374 hr = IOleCache2_Uncache( cache, conn );
2375 ok( hr == S_OK, "got %08x\n", hr );
2376
2377 /* view caching */
2378 fmt.cfFormat = 0;
2379 fmt.tymed = TYMED_ENHMF;
2380 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2381 ok( hr == S_OK, "got %08x\n", hr );
2382 view_caching[0].dwConnection = conn;
2383
2384 fmt.tymed = TYMED_HGLOBAL;
2385 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2386 ok( hr == CACHE_S_SAMECACHE, "got %08x\n", hr );
2387
2388 fmt.dwAspect = DVASPECT_THUMBNAIL;
2389 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2390 ok( hr == S_OK, "got %08x\n", hr );
2391 view_caching[1].dwConnection = conn;
2392
2393 fmt.dwAspect = DVASPECT_DOCPRINT;
2394 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2395 ok( hr == S_OK, "got %08x\n", hr );
2396 view_caching[2].dwConnection = conn;
2397
2398 /* DVASPECT_ICON view cache gets mapped to CF_METAFILEPICT */
2399 fmt.dwAspect = DVASPECT_ICON;
2400 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2401 ok( hr == S_OK, "got %08x\n", hr );
2402 view_caching[3].dwConnection = conn;
2403
2404 check_enum_cache( cache, view_caching, 4 );
2405
2406 /* uncache everything */
2407 hr = IOleCache2_Uncache( cache, view_caching[3].dwConnection );
2408 ok( hr == S_OK, "got %08x\n", hr );
2409 hr = IOleCache2_Uncache( cache, view_caching[2].dwConnection );
2410 ok( hr == S_OK, "got %08x\n", hr );
2411 hr = IOleCache2_Uncache( cache, view_caching[1].dwConnection );
2412 ok( hr == S_OK, "got %08x\n", hr );
2413 hr = IOleCache2_Uncache( cache, view_caching[0].dwConnection );
2414 ok( hr == S_OK, "got %08x\n", hr );
2415
2416 /* Only able to set cfFormat == CF_METAFILEPICT (or == 0, see above) for DVASPECT_ICON */
2417 fmt.dwAspect = DVASPECT_ICON;
2418 fmt.cfFormat = CF_DIB;
2419 fmt.tymed = TYMED_HGLOBAL;
2420 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2421 ok( hr == DV_E_FORMATETC, "got %08x\n", hr );
2422 fmt.cfFormat = CF_BITMAP;
2423 fmt.tymed = TYMED_GDI;
2424 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2425 ok( hr == DV_E_FORMATETC, "got %08x\n", hr );
2426 fmt.cfFormat = CF_ENHMETAFILE;
2427 fmt.tymed = TYMED_ENHMF;
2428 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2429 ok( hr == DV_E_FORMATETC, "got %08x\n", hr );
2430 fmt.cfFormat = CF_METAFILEPICT;
2431 fmt.tymed = TYMED_MFPICT;
2432 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2433 ok( hr == S_OK, "got %08x\n", hr );
2434
2435 /* uncache everything */
2436 hr = IOleCache2_Uncache( cache, conn );
2437 ok( hr == S_OK, "got %08x\n", hr );
2438
2439 /* tymed == 0 */
2440 fmt.cfFormat = CF_ENHMETAFILE;
2441 fmt.dwAspect = DVASPECT_CONTENT;
2442 fmt.tymed = 0;
2443 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2444 ok( hr == DV_E_TYMED, "got %08x\n", hr );
2445
2446 IDataObject_Release( data );
2447 IOleCache2_Release( cache );
2448
2449 /* tests for a static class cache */
2450 hr = CreateDataCache( NULL, &CLSID_Picture_Dib, &IID_IOleCache2, (void **)&cache );
2451
2452 fmt.cfFormat = CF_DIB;
2453 fmt.dwAspect = DVASPECT_CONTENT;
2454 fmt.tymed = TYMED_HGLOBAL;
2455 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2456 ok( hr == CACHE_S_SAMECACHE, "got %08x\n", hr );
2457
2458 /* aspect other than DVASPECT_CONTENT should fail */
2459 fmt.dwAspect = DVASPECT_THUMBNAIL;
2460 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2461 ok( FAILED(hr), "got %08x\n", hr );
2462
2463 fmt.dwAspect = DVASPECT_DOCPRINT;
2464 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2465 ok( FAILED(hr), "got %08x\n", hr );
2466
2467 /* try caching another clip format */
2468 fmt.cfFormat = CF_METAFILEPICT;
2469 fmt.dwAspect = DVASPECT_CONTENT;
2470 fmt.tymed = TYMED_MFPICT;
2471 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2472 ok( FAILED(hr), "got %08x\n", hr );
2473
2474 /* As an exception, it's possible to add an icon aspect */
2475 fmt.cfFormat = CF_METAFILEPICT;
2476 fmt.dwAspect = DVASPECT_ICON;
2477 fmt.tymed = TYMED_MFPICT;
2478 hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
2479 ok( hr == S_OK, "got %08x\n", hr );
2480
2481 IOleCache2_Release( cache );
2482 }
2483
2484 /* The CLSID_Picture_ classes automatically create appropriate cache entries */
2485 static void test_data_cache_init(void)
2486 {
2487 HRESULT hr;
2488 IOleCache2 *cache;
2489 IPersistStorage *persist;
2490 int i;
2491 CLSID clsid;
2492 static const STATDATA enum_expect[] =
2493 {
2494 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2495 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 },
2496 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 1 },
2497 {{ CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF }, 0, NULL, 1 }
2498 };
2499 static const struct
2500 {
2501 const CLSID *clsid;
2502 int enum_start, enum_num;
2503 } data[] =
2504 {
2505 { &CLSID_NULL, 0, 0 },
2506 { &CLSID_WineTestOld, 0, 0 },
2507 { &CLSID_Picture_Dib, 0, 2 },
2508 { &CLSID_Picture_Metafile, 2, 1 },
2509 { &CLSID_Picture_EnhMetafile, 3, 1 }
2510 };
2511
2512 for (i = 0; i < ARRAY_SIZE(data); i++)
2513 {
2514 hr = CreateDataCache( NULL, data[i].clsid, &IID_IOleCache2, (void **)&cache );
2515 ok( hr == S_OK, "got %08x\n", hr );
2516
2517 check_enum_cache( cache, enum_expect + data[i].enum_start , data[i].enum_num );
2518
2519 IOleCache2_QueryInterface( cache, &IID_IPersistStorage, (void **) &persist );
2520 hr = IPersistStorage_GetClassID( persist, &clsid );
2521 ok( hr == S_OK, "got %08x\n", hr );
2522 ok( IsEqualCLSID( &clsid, data[i].clsid ), "class id mismatch %s %s\n", wine_dbgstr_guid( &clsid ),
2523 wine_dbgstr_guid( data[i].clsid ) );
2524
2525 IPersistStorage_Release( persist );
2526 IOleCache2_Release( cache );
2527 }
2528 }
2529
2530 static void test_data_cache_initnew(void)
2531 {
2532 HRESULT hr;
2533 IOleCache2 *cache;
2534 IPersistStorage *persist;
2535 IStorage *stg_dib, *stg_mf, *stg_wine;
2536 CLSID clsid;
2537 static const STATDATA initnew_expect[] =
2538 {
2539 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2540 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 },
2541 };
2542 static const STATDATA initnew2_expect[] =
2543 {
2544 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 1 },
2545 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 2 },
2546 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 2 },
2547 };
2548 static const STATDATA initnew3_expect[] =
2549 {
2550 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
2551 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 },
2552 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 2 },
2553 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 2 },
2554 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 3 },
2555 };
2556 static const STATDATA initnew4_expect[] =
2557 {
2558 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 2 },
2559 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 2 },
2560 {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 3 },
2561 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 4 },
2562 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 4 },
2563 };
2564
2565 hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg_dib );
2566 ok( hr == S_OK, "got %08x\n", hr);
2567 hr = IStorage_SetClass( stg_dib, &CLSID_Picture_Dib );
2568 ok( hr == S_OK, "got %08x\n", hr);
2569
2570 hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg_mf );
2571 ok( hr == S_OK, "got %08x\n", hr);
2572 hr = IStorage_SetClass( stg_mf, &CLSID_Picture_Metafile );
2573 ok( hr == S_OK, "got %08x\n", hr);
2574
2575 hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg_wine );
2576 ok( hr == S_OK, "got %08x\n", hr);
2577 hr = IStorage_SetClass( stg_wine, &CLSID_WineTestOld );
2578 ok( hr == S_OK, "got %08x\n", hr);
2579
2580 hr = CreateDataCache( NULL, &CLSID_WineTestOld, &IID_IOleCache2, (void **)&cache );
2581 ok( hr == S_OK, "got %08x\n", hr );
2582 IOleCache2_QueryInterface( cache, &IID_IPersistStorage, (void **) &persist );
2583
2584 hr = IPersistStorage_InitNew( persist, stg_dib );
2585 ok( hr == S_OK, "got %08x\n", hr);
2586
2587 hr = IPersistStorage_GetClassID( persist, &clsid );
2588 ok( hr == S_OK, "got %08x\n", hr );
2589 ok( IsEqualCLSID( &clsid, &CLSID_Picture_Dib ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2590
2591 check_enum_cache( cache, initnew_expect, 2 );
2592
2593 hr = IPersistStorage_InitNew( persist, stg_mf );
2594 ok( hr == CO_E_ALREADYINITIALIZED, "got %08x\n", hr);
2595
2596 hr = IPersistStorage_HandsOffStorage( persist );
2597 ok( hr == S_OK, "got %08x\n", hr);
2598
2599 hr = IPersistStorage_GetClassID( persist, &clsid );
2600 ok( hr == S_OK, "got %08x\n", hr );
2601 ok( IsEqualCLSID( &clsid, &CLSID_Picture_Dib ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2602
2603 hr = IPersistStorage_InitNew( persist, stg_mf );
2604 ok( hr == S_OK, "got %08x\n", hr);
2605
2606 hr = IPersistStorage_GetClassID( persist, &clsid );
2607 ok( hr == S_OK, "got %08x\n", hr );
2608 ok( IsEqualCLSID( &clsid, &CLSID_Picture_Metafile ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2609
2610 check_enum_cache( cache, initnew2_expect, 3 );
2611
2612 hr = IPersistStorage_HandsOffStorage( persist );
2613 ok( hr == S_OK, "got %08x\n", hr);
2614
2615 hr = IPersistStorage_InitNew( persist, stg_dib );
2616 ok( hr == S_OK, "got %08x\n", hr);
2617
2618 hr = IPersistStorage_GetClassID( persist, &clsid );
2619 ok( hr == S_OK, "got %08x\n", hr );
2620 ok( IsEqualCLSID( &clsid, &CLSID_Picture_Dib ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2621
2622 check_enum_cache( cache, initnew3_expect, 5 );
2623
2624 hr = IPersistStorage_HandsOffStorage( persist );
2625 ok( hr == S_OK, "got %08x\n", hr);
2626
2627 hr = IPersistStorage_InitNew( persist, stg_wine );
2628 ok( hr == S_OK, "got %08x\n", hr);
2629
2630 hr = IPersistStorage_GetClassID( persist, &clsid );
2631 ok( hr == S_OK, "got %08x\n", hr );
2632 ok( IsEqualCLSID( &clsid, &CLSID_WineTestOld ), "got %s\n", wine_dbgstr_guid( &clsid ) );
2633
2634 check_enum_cache( cache, initnew4_expect, 5 );
2635
2636 IStorage_Release( stg_wine );
2637 IStorage_Release( stg_mf );
2638 IStorage_Release( stg_dib );
2639
2640 IPersistStorage_Release( persist );
2641 IOleCache2_Release( cache );
2642 }
2643
2644 static void test_data_cache_updatecache( void )
2645 {
2646 HRESULT hr;
2647 IOleCache2 *cache;
2648 FORMATETC fmt;
2649 DWORD conn[4];
2650
2651 static const struct expected_method methods_dib[] =
2652 {
2653 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2654 { "DataObject_GetData", 0, { CF_BITMAP, NULL, DVASPECT_CONTENT, -1, TYMED_GDI } },
2655 { NULL }
2656 };
2657
2658 static const struct expected_method methods_dib_emf[] =
2659 {
2660 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2661 { "DataObject_GetData", 0, { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } },
2662 { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2663 { NULL }
2664 };
2665 static const struct expected_method methods_dib_wmf[] =
2666 {
2667 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2668 { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2669 { NULL }
2670 };
2671 static const struct expected_method methods_viewcache[] =
2672 {
2673 { "DataObject_QueryGetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2674 { "DataObject_QueryGetData", 0, { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } },
2675 { "DataObject_QueryGetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2676 { "DataObject_QueryGetData", 0, { CF_BITMAP, NULL, DVASPECT_CONTENT, -1, TYMED_GDI } },
2677 { NULL }
2678 };
2679 static const struct expected_method methods_viewcache_with_dib[] =
2680 {
2681 { "DataObject_QueryGetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2682 { "DataObject_QueryGetData", 0, { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } },
2683 { "DataObject_QueryGetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2684 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2685 { NULL }
2686 };
2687 static const struct expected_method methods_flags_all[] =
2688 {
2689 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2690 { "DataObject_GetData", 0, { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } },
2691 { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2692 { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2693 { NULL }
2694 };
2695 static const struct expected_method methods_flags_ifblank_1[] =
2696 {
2697 { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2698 { NULL }
2699 };
2700 static const struct expected_method methods_flags_ifblank_2[] =
2701 {
2702 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2703 { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2704 { NULL }
2705 };
2706 static const struct expected_method methods_flags_normal[] =
2707 {
2708 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2709 { NULL }
2710 };
2711 static const struct expected_method methods_initcache[] =
2712 {
2713 { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
2714 { "DataObject_GetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
2715 { NULL }
2716 };
2717 static const struct expected_method methods_empty[] =
2718 {
2719 { NULL }
2720 };
2721
2722 static STATDATA view_cache[] =
2723 {
2724 {{ 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 0 }
2725 };
2726 static STATDATA view_cache_after_dib[] =
2727 {
2728 {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 0 },
2729 {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 0 }
2730 };
2731
2732 static FORMATETC dib_fmt[] =
2733 {
2734 { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
2735 { 0 }
2736 };
2737
2738 hr = CreateDataCache( NULL, &CLSID_WineTestOld, &IID_IOleCache2, (void **)&cache );
2739 ok( hr == S_OK, "got %08x\n", hr );
2740
2741 /* No cache slots */
2742 g_dataobject_fmts = NULL;
2743 expected_method_list = NULL;
2744
2745 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2746 ok( hr == S_OK, "got %08x\n", hr );
2747
2748 /* A dib cache slot */
2749 fmt.cfFormat = CF_DIB;
2750 fmt.ptd = NULL;
2751 fmt.dwAspect = DVASPECT_CONTENT;
2752 fmt.lindex = -1;
2753 fmt.tymed = TYMED_HGLOBAL;
2754
2755 hr = IOleCache2_Cache( cache, &fmt, 0, &conn[0] );
2756 ok( hr == S_OK, "got %08x\n", hr );
2757
2758 expected_method_list = methods_dib;
2759
2760 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2761 ok( hr == CACHE_E_NOCACHE_UPDATED, "got %08x\n", hr );
2762
2763 CHECK_NO_EXTRA_METHODS();
2764
2765 /* Now with a dib available */
2766 g_dataobject_fmts = dib_fmt;
2767 expected_method_list = methods_dib;
2768
2769 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2770 ok( hr == S_OK, "got %08x\n", hr );
2771
2772 /* Add an EMF cache slot */
2773 fmt.cfFormat = CF_ENHMETAFILE;
2774 fmt.ptd = NULL;
2775 fmt.dwAspect = DVASPECT_CONTENT;
2776 fmt.lindex = -1;
2777 fmt.tymed = TYMED_ENHMF;
2778
2779 hr = IOleCache2_Cache( cache, &fmt, 0, &conn[1] );
2780 ok( hr == S_OK, "got %08x\n", hr );
2781
2782 g_dataobject_fmts = dib_fmt;
2783 expected_method_list = methods_dib_emf;
2784
2785 /* Two slots to fill, only the dib will succeed */
2786 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2787 ok( hr == S_OK, "got %08x\n", hr );
2788
2789 CHECK_NO_EXTRA_METHODS();
2790
2791 /* Replace the emf slot with a wmf */
2792 hr = IOleCache2_Uncache( cache, conn[1] );
2793 ok( hr == S_OK, "got %08x\n", hr );
2794
2795 fmt.cfFormat = CF_METAFILEPICT;
2796 fmt.ptd = NULL;
2797 fmt.dwAspect = DVASPECT_CONTENT;
2798 fmt.lindex = -1;
2799 fmt.tymed = TYMED_MFPICT;
2800
2801 hr = IOleCache2_Cache( cache, &fmt, 0, &conn[1] );
2802 ok( hr == S_OK, "got %08x\n", hr );
2803
2804 g_dataobject_fmts = dib_fmt;
2805 expected_method_list = methods_dib_wmf;
2806
2807 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2808 ok( hr == S_OK, "got %08x\n", hr );
2809
2810 hr = IOleCache2_Uncache( cache, conn[1] );
2811 ok( hr == S_OK, "got %08x\n", hr );
2812 hr = IOleCache2_Uncache( cache, conn[0] );
2813 ok( hr == S_OK, "got %08x\n", hr );
2814
2815 /* View caching */
2816 fmt.cfFormat = 0;
2817 fmt.ptd = NULL;
2818 fmt.dwAspect = DVASPECT_CONTENT;
2819 fmt.lindex = -1;
2820 fmt.tymed = TYMED_HGLOBAL;
2821
2822 hr = IOleCache2_Cache( cache, &fmt, 0, &conn[0] );
2823 ok( hr == S_OK, "got %08x\n", hr );
2824 view_cache[0].dwConnection = conn[0];
2825
2826 g_dataobject_fmts = NULL;
2827 expected_method_list = methods_viewcache;
2828
2829 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2830 ok( hr == CACHE_E_NOCACHE_UPDATED, "got %08x\n", hr );
2831
2832 CHECK_NO_EXTRA_METHODS();
2833 check_enum_cache( cache, view_cache, 1 );
2834
2835 g_dataobject_fmts = dib_fmt;
2836 expected_method_list = methods_viewcache_with_dib;
2837
2838 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2839 ok( hr == S_OK, "got %08x\n", hr );
2840
2841 CHECK_NO_EXTRA_METHODS();
2842 view_cache_after_dib[0].dwConnection = view_cache_after_dib[1].dwConnection = view_cache[0].dwConnection;
2843 check_enum_cache( cache, view_cache_after_dib, 2 );
2844
2845 hr = IOleCache2_Uncache( cache, conn[0] );
2846 ok( hr == S_OK, "got %08x\n", hr );
2847
2848 /* Try some different flags */
2849
2850 fmt.cfFormat = CF_DIB;
2851 fmt.ptd = NULL;
2852 fmt.dwAspect = DVASPECT_CONTENT;
2853 fmt.lindex = -1;
2854 fmt.tymed = TYMED_HGLOBAL;
2855
2856 hr = IOleCache2_Cache( cache, &fmt, 0, &conn[0] );
2857 ok( hr == S_OK, "got %08x\n", hr );
2858
2859 fmt.cfFormat = CF_ENHMETAFILE;
2860 fmt.ptd = NULL;
2861 fmt.dwAspect = DVASPECT_CONTENT;
2862 fmt.lindex = -1;
2863 fmt.tymed = TYMED_ENHMF;
2864
2865 hr = IOleCache2_Cache( cache, &fmt, ADVF_NODATA, &conn[1] );
2866 ok( hr == S_OK, "got %08x\n", hr );
2867
2868 fmt.cfFormat = CF_METAFILEPICT;
2869 fmt.ptd = NULL;
2870 fmt.dwAspect = DVASPECT_CONTENT;
2871 fmt.lindex = -1;
2872 fmt.tymed = TYMED_MFPICT;
2873
2874 hr = IOleCache2_Cache( cache, &fmt, ADVFCACHE_ONSAVE, &conn[2] );
2875 ok( hr == S_OK, "got %08x\n", hr );
2876
2877 g_dataobject_fmts = dib_fmt;
2878 expected_method_list = methods_flags_all;
2879
2880 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2881
2882 CHECK_NO_EXTRA_METHODS();
2883
2884 expected_method_list = methods_flags_all;
2885
2886 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ALL, NULL );
2887 ok( hr == S_OK, "got %08x\n", hr );
2888
2889 CHECK_NO_EXTRA_METHODS();
2890
2891 expected_method_list = methods_flags_ifblank_1;
2892
2893 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_IFBLANK , NULL );
2894 ok( hr == S_OK, "got %08x\n", hr );
2895
2896 CHECK_NO_EXTRA_METHODS();
2897
2898 hr = IOleCache2_DiscardCache( cache, DISCARDCACHE_NOSAVE );
2899 ok( hr == S_OK, "got %08x\n", hr );
2900
2901 expected_method_list = methods_flags_ifblank_2;
2902
2903 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_IFBLANK , NULL );
2904 ok( hr == S_OK, "got %08x\n", hr );
2905
2906 CHECK_NO_EXTRA_METHODS();
2907
2908 hr = IOleCache2_DiscardCache( cache, DISCARDCACHE_NOSAVE );
2909 ok( hr == S_OK, "got %08x\n", hr );
2910
2911 expected_method_list = methods_flags_all;
2912
2913 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_IFBLANK | UPDFCACHE_NODATACACHE, NULL );
2914 ok( hr == S_OK, "got %08x\n", hr );
2915
2916 CHECK_NO_EXTRA_METHODS();
2917
2918 expected_method_list = methods_empty;
2919
2920 hr = IOleCache2_UpdateCache( cache, &DataObject, UPDFCACHE_ONLYIFBLANK | UPDFCACHE_NORMALCACHE, NULL );
2921 ok( hr == S_OK, "got %08x\n", hr );
2922
2923 CHECK_NO_EXTRA_METHODS();