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