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