2 * OLEPICTURE test program
4 * Copyright 2005 Marcus Meissner
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "wine/test.h"
42 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
44 #define ole_expect(expr, expect) { \
46 ok(r == (expect), #expr " returned %x, expected %s (%x)\n", r, #expect, expect); \
49 #define ole_check(expr) ole_expect(expr, S_OK);
51 static HMODULE hOleaut32
;
53 static HRESULT (WINAPI
*pOleLoadPicture
)(LPSTREAM
,LONG
,BOOL
,REFIID
,LPVOID
*);
54 static HRESULT (WINAPI
*pOleCreatePictureIndirect
)(PICTDESC
*,REFIID
,BOOL
,LPVOID
*);
56 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
59 static const unsigned char gifimage
[35] = {
60 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
61 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
66 static const unsigned char jpgimage
[285] = {
67 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
68 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
69 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
70 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
71 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
72 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
73 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
74 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
75 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
76 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
77 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
78 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
79 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
80 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
81 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
82 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
83 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
84 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
88 static const unsigned char pngimage
[285] = {
89 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
90 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
91 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
92 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
93 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
94 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
95 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
99 static const unsigned char bmpimage
[66] = {
100 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
101 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
102 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
103 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
108 static const unsigned char gif4pixel
[42] = {
109 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
110 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
111 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
114 /* APM with an empty metafile with some padding zeros - looks like under Window the
115 * metafile data should be at least 20 bytes */
116 static const unsigned char apmdata
[] = {
117 0xd7,0xcd,0xc6,0x9a, 0x00,0x00,0x00,0x00, 0x00,0x00,0xee,0x02, 0xb1,0x03,0xa0,0x05,
118 0x00,0x00,0x00,0x00, 0xee,0x53,0x01,0x00, 0x09,0x00,0x00,0x03, 0x13,0x00,0x00,0x00,
119 0x01,0x00,0x05,0x00, 0x00,0x00,0x00,0x00, 0x03,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
120 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
123 /* MF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
124 static const unsigned char metafile
[] = {
125 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
126 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
127 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
128 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
129 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
130 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
134 /* EMF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
135 static const unsigned char enhmetafile
[] = {
136 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
141 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
142 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
143 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
146 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
149 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
150 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
151 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
153 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
155 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
156 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
159 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
160 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
161 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
162 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
163 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
164 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
166 0x14, 0x00, 0x00, 0x00
170 struct NoStatStreamImpl
172 const IStreamVtbl
*lpVtbl
;
175 HGLOBAL supportHandle
;
176 ULARGE_INTEGER streamSize
;
177 ULARGE_INTEGER currentPosition
;
179 typedef struct NoStatStreamImpl NoStatStreamImpl
;
180 static NoStatStreamImpl
* NoStatStreamImpl_Construct(HGLOBAL hGlobal
);
183 test_pic_with_stream(LPSTREAM stream
, unsigned int imgsize
)
185 IPicture
* pic
= NULL
;
188 OLE_HANDLE handle
, hPal
;
189 OLE_XSIZE_HIMETRIC width
;
190 OLE_YSIZE_HIMETRIC height
;
196 hres
= pOleLoadPicture(stream
, imgsize
, TRUE
, &IID_IPicture
, &pvObj
);
199 ok(hres
== S_OK
,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres
);
200 ok(pic
!= NULL
,"OLP (NULL,..) returns NULL, instead of !NULL\n");
205 hres
= IPicture_QueryInterface (pic
, &IID_IPicture
, &pvObj
);
207 ok(hres
== S_OK
,"IPicture_QI does not return S_OK, but 0x%08x\n", hres
);
208 ok(pvObj
!= NULL
,"IPicture_QI does return NULL, instead of a ptr\n");
210 IPicture_Release ((IPicture
*)pvObj
);
213 hres
= IPicture_get_Handle (pic
, &handle
);
214 ok(hres
== S_OK
,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres
);
215 ok(handle
!= 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
218 hres
= IPicture_get_Width (pic
, &width
);
219 ok(hres
== S_OK
,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres
);
220 ok(width
!= 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
223 hres
= IPicture_get_Height (pic
, &height
);
224 ok(hres
== S_OK
,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres
);
225 ok(height
!= 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
228 hres
= IPicture_get_Type (pic
, &type
);
229 ok(hres
== S_OK
,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres
);
230 ok(type
== PICTYPE_BITMAP
, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type
, PICTYPE_BITMAP
);
233 hres
= IPicture_get_Attributes (pic
, &attr
);
234 ok(hres
== S_OK
,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres
);
235 ok(attr
== 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr
);
238 hres
= IPicture_get_hPal (pic
, &hPal
);
239 ok(hres
== S_OK
,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres
);
240 /* a single pixel b/w image has no palette */
241 ok(hPal
== 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal
);
243 res
= IPicture_Release (pic
);
244 ok (res
== 0, "refcount after release is %d, but should be 0?\n", res
);
248 test_pic(const unsigned char *imgdata
, unsigned int imgsize
)
254 LARGE_INTEGER seekto
;
255 ULARGE_INTEGER newpos1
;
259 /* Let the fun begin */
260 hglob
= GlobalAlloc (0, imgsize
);
261 data
= GlobalLock (hglob
);
262 memcpy(data
, imgdata
, imgsize
);
263 GlobalUnlock(hglob
); data
= NULL
;
265 hres
= CreateStreamOnHGlobal (hglob
, FALSE
, &stream
);
266 ok (hres
== S_OK
, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres
);
268 memset(&seekto
,0,sizeof(seekto
));
269 hres
= IStream_Seek(stream
,seekto
,SEEK_CUR
,&newpos1
);
270 ok (hres
== S_OK
, "istream seek failed? doubt it... hres 0x%08x\n", hres
);
271 test_pic_with_stream(stream
, imgsize
);
273 IStream_Release(stream
);
275 /* again with Non Statable and Non Seekable stream */
276 stream
= (LPSTREAM
)NoStatStreamImpl_Construct(hglob
);
277 hglob
= 0; /* Non-statable impl always deletes on release */
278 test_pic_with_stream(stream
, 0);
280 IStream_Release(stream
);
281 for (i
= 1; i
<= 8; i
++) {
283 hglob
= GlobalAlloc (0, imgsize
+ i
* (2 * sizeof(DWORD
)));
284 data
= GlobalLock (hglob
);
285 header
= (DWORD
*)data
;
287 /* multiple copies of header */
288 memcpy(data
,"lt\0\0",4);
290 for (j
= 2; j
<= i
; j
++) {
291 memcpy(&(header
[2 * (j
- 1)]), header
, 2 * sizeof(DWORD
));
293 memcpy(data
+ i
* (2 * sizeof(DWORD
)), imgdata
, imgsize
);
294 GlobalUnlock(hglob
); data
= NULL
;
296 hres
= CreateStreamOnHGlobal (hglob
, FALSE
, &stream
);
297 ok (hres
== S_OK
, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres
);
299 memset(&seekto
,0,sizeof(seekto
));
300 hres
= IStream_Seek(stream
,seekto
,SEEK_CUR
,&newpos1
);
301 ok (hres
== S_OK
, "istream seek failed? doubt it... hres 0x%08x\n", hres
);
302 test_pic_with_stream(stream
, imgsize
);
304 IStream_Release(stream
);
306 /* again with Non Statable and Non Seekable stream */
307 stream
= (LPSTREAM
)NoStatStreamImpl_Construct(hglob
);
308 hglob
= 0; /* Non-statable impl always deletes on release */
309 test_pic_with_stream(stream
, 0);
311 IStream_Release(stream
);
315 static void test_empty_image(void) {
318 IPicture
* pic
= NULL
;
323 ULARGE_INTEGER newpos1
;
324 LARGE_INTEGER seekto
;
327 /* Empty image. Happens occasionally in VB programs. */
328 hglob
= GlobalAlloc (0, 8);
329 data
= GlobalLock (hglob
);
330 memcpy(data
,"lt\0\0",4);
331 ((DWORD
*)data
)[1] = 0;
332 hres
= CreateStreamOnHGlobal (hglob
, TRUE
, &stream
);
333 ok (hres
== S_OK
, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres
);
335 memset(&seekto
,0,sizeof(seekto
));
336 hres
= IStream_Seek(stream
,seekto
,SEEK_CUR
,&newpos1
);
337 ok (hres
== S_OK
, "istream seek failed? doubt it... hres 0x%08x\n", hres
);
340 hres
= pOleLoadPicture(stream
, 8, TRUE
, &IID_IPicture
, &pvObj
);
342 ok(hres
== S_OK
,"empty picture not loaded, hres 0x%08x\n", hres
);
343 ok(pic
!= NULL
,"empty picture not loaded, pic is NULL\n");
345 hres
= IPicture_get_Type (pic
, &type
);
346 ok (hres
== S_OK
,"empty picture get type failed with hres 0x%08x\n", hres
);
347 ok (type
== PICTYPE_NONE
,"type is %d, but should be PICTYPE_NONE(0)\n", type
);
349 hres
= IPicture_get_Handle (pic
, &handle
);
350 ok (hres
== S_OK
,"empty picture get handle failed with hres 0x%08x\n", hres
);
351 ok (handle
== 0, "empty picture get handle did not return 0, but 0x%08x\n", handle
);
352 IPicture_Release (pic
);
355 static void test_empty_image_2(void) {
358 IPicture
* pic
= NULL
;
362 ULARGE_INTEGER newpos1
;
363 LARGE_INTEGER seekto
;
366 /* Empty image at random stream position. */
367 hglob
= GlobalAlloc (0, 200);
368 data
= GlobalLock (hglob
);
370 memcpy(data
,"lt\0\0",4);
371 ((DWORD
*)data
)[1] = 0;
372 hres
= CreateStreamOnHGlobal (hglob
, TRUE
, &stream
);
373 ok (hres
== S_OK
, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres
);
375 memset(&seekto
,0,sizeof(seekto
));
376 seekto
.u
.LowPart
= 42;
377 hres
= IStream_Seek(stream
,seekto
,SEEK_CUR
,&newpos1
);
378 ok (hres
== S_OK
, "istream seek failed? doubt it... hres 0x%08x\n", hres
);
381 hres
= pOleLoadPicture(stream
, 8, TRUE
, &IID_IPicture
, &pvObj
);
383 ok(hres
== S_OK
,"empty picture not loaded, hres 0x%08x\n", hres
);
384 ok(pic
!= NULL
,"empty picture not loaded, pic is NULL\n");
386 hres
= IPicture_get_Type (pic
, &type
);
387 ok (hres
== S_OK
,"empty picture get type failed with hres 0x%08x\n", hres
);
388 ok (type
== PICTYPE_NONE
,"type is %d, but should be PICTYPE_NONE(0)\n", type
);
390 IPicture_Release (pic
);
393 static void test_Invoke(void)
395 IPictureDisp
*picdisp
;
398 DISPPARAMS dispparams
;
404 hglob
= GlobalAlloc (0, sizeof(gifimage
));
405 data
= GlobalLock(hglob
);
406 memcpy(data
, gifimage
, sizeof(gifimage
));
409 hr
= CreateStreamOnHGlobal (hglob
, FALSE
, &stream
);
410 ok_ole_success(hr
, "CreateStreamOnHGlobal");
412 hr
= pOleLoadPicture(stream
, sizeof(gifimage
), TRUE
, &IID_IPictureDisp
, (void **)&picdisp
);
413 IStream_Release(stream
);
414 ok_ole_success(hr
, "OleLoadPicture");
416 V_VT(&vararg
) = VT_BOOL
;
417 V_BOOL(&vararg
) = VARIANT_FALSE
;
418 dispparams
.cNamedArgs
= 0;
419 dispparams
.rgdispidNamedArgs
= NULL
;
420 dispparams
.cArgs
= 1;
421 dispparams
.rgvarg
= &vararg
;
422 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_IPictureDisp
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
423 ok(hr
== DISP_E_UNKNOWNNAME
, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr
);
424 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_IUnknown
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
425 ok(hr
== DISP_E_UNKNOWNNAME
, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr
);
427 dispparams
.cArgs
= 0;
428 dispparams
.rgvarg
= NULL
;
429 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
430 ok(hr
== DISP_E_BADPARAMCOUNT
, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr
);
432 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYPUT
, NULL
, NULL
, NULL
, NULL
);
433 ok(hr
== DISP_E_PARAMNOTOPTIONAL
, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr
);
435 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, NULL
, NULL
, NULL
, NULL
);
436 ok(hr
== DISP_E_PARAMNOTOPTIONAL
, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr
);
438 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, NULL
, &varresult
, NULL
, NULL
);
439 ok(hr
== DISP_E_PARAMNOTOPTIONAL
, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr
);
441 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
442 ok_ole_success(hr
, "IPictureDisp_Invoke");
443 ok(V_VT(&varresult
) == VT_I4
, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult
));
445 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_METHOD
, &dispparams
, &varresult
, NULL
, NULL
);
446 ok(hr
== DISP_E_MEMBERNOTFOUND
, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr
);
448 hr
= IPictureDisp_Invoke(picdisp
, 0xdeadbeef, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
449 ok(hr
== DISP_E_MEMBERNOTFOUND
, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr
);
451 dispparams
.cArgs
= 1;
452 dispparams
.rgvarg
= &vararg
;
453 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
454 ok(hr
== DISP_E_BADPARAMCOUNT
, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr
);
456 dispparams
.cArgs
= 1;
457 dispparams
.rgvarg
= &vararg
;
458 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
459 ok(hr
== DISP_E_BADPARAMCOUNT
, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr
);
461 IPictureDisp_Release(picdisp
);
464 static void test_OleCreatePictureIndirect(void)
471 if(!pOleCreatePictureIndirect
)
473 skip("Skipping OleCreatePictureIndirect tests\n");
477 hr
= pOleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (void**)&pict
);
478 ok(hr
== S_OK
, "hr %08x\n", hr
);
480 hr
= IPicture_get_Type(pict
, &type
);
481 ok(hr
== S_OK
, "hr %08x\n", hr
);
482 ok(type
== PICTYPE_UNINITIALIZED
, "type %d\n", type
);
484 hr
= IPicture_get_Handle(pict
, &handle
);
485 ok(hr
== S_OK
, "hr %08x\n", hr
);
486 ok(handle
== 0, "handle %08x\n", handle
);
488 IPicture_Release(pict
);
491 static void test_apm()
502 hglob
= GlobalAlloc (0, sizeof(apmdata
));
503 data
= GlobalLock(hglob
);
504 memcpy(data
, apmdata
, sizeof(apmdata
));
506 ole_check(CreateStreamOnHGlobal(hglob
, TRUE
, &stream
));
507 ole_check(OleLoadPictureEx(stream
, sizeof(apmdata
), TRUE
, &IID_IPicture
, 100, 100, 0, (LPVOID
*)&pict
));
509 ole_check(IPicture_get_Handle(pict
, &handle
));
510 ok(handle
!= 0, "handle is null\n");
512 ole_check(IPicture_get_Type(pict
, &type
));
513 expect_eq(type
, PICTYPE_METAFILE
, short, "%d");
515 ole_check(IPicture_get_Height(pict
, &cxy
));
516 expect_eq(cxy
, 1667, LONG
, "%d");
518 ole_check(IPicture_get_Width(pict
, &cxy
));
519 expect_eq(cxy
, 1323, LONG
, "%d");
521 ole_check(IPicture_get_KeepOriginalFormat(pict
, &keep
));
522 todo_wine
expect_eq(keep
, FALSE
, LONG
, "%d");
524 ole_expect(IPicture_get_hPal(pict
, &handle
), E_FAIL
);
525 IPicture_Release(pict
);
526 IStream_Release(stream
);
531 static void test_metafile(void)
538 hglob
= GlobalAlloc (0, sizeof(metafile
));
539 data
= GlobalLock(hglob
);
540 memcpy(data
, metafile
, sizeof(metafile
));
542 ole_check(CreateStreamOnHGlobal(hglob
, TRUE
, &stream
));
543 /* Windows does not load simple metafiles */
544 ole_expect(OleLoadPictureEx(stream
, sizeof(metafile
), TRUE
, &IID_IPicture
, 100, 100, 0, (LPVOID
*)&pict
), E_FAIL
);
546 IStream_Release(stream
);
551 static void test_enhmetafile(void)
562 hglob
= GlobalAlloc (0, sizeof(enhmetafile
));
563 data
= GlobalLock(hglob
);
564 memcpy(data
, enhmetafile
, sizeof(enhmetafile
));
566 ole_check(CreateStreamOnHGlobal(hglob
, TRUE
, &stream
));
567 ole_check(OleLoadPictureEx(stream
, sizeof(enhmetafile
), TRUE
, &IID_IPicture
, 10, 10, 0, (LPVOID
*)&pict
));
569 ole_check(IPicture_get_Handle(pict
, &handle
));
570 ok(handle
!= 0, "handle is null\n");
572 ole_check(IPicture_get_Type(pict
, &type
));
573 expect_eq(type
, PICTYPE_ENHMETAFILE
, short, "%d");
575 ole_check(IPicture_get_Height(pict
, &cxy
));
576 expect_eq(cxy
, -23, LONG
, "%d");
578 ole_check(IPicture_get_Width(pict
, &cxy
));
579 expect_eq(cxy
, -25, LONG
, "%d");
581 ole_check(IPicture_get_KeepOriginalFormat(pict
, &keep
));
582 todo_wine
expect_eq(keep
, FALSE
, LONG
, "%d");
584 IPicture_Release(pict
);
585 IStream_Release(stream
);
590 START_TEST(olepicture
)
592 hOleaut32
= GetModuleHandleA("oleaut32.dll");
593 pOleLoadPicture
= (void*)GetProcAddress(hOleaut32
, "OleLoadPicture");
594 pOleCreatePictureIndirect
= (void*)GetProcAddress(hOleaut32
, "OleCreatePictureIndirect");
595 if (!pOleLoadPicture
)
597 skip("OleLoadPicture is not available\n");
601 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
602 test_pic(gifimage
, sizeof(gifimage
));
603 test_pic(jpgimage
, sizeof(jpgimage
));
604 test_pic(bmpimage
, sizeof(bmpimage
));
605 test_pic(gif4pixel
, sizeof(gif4pixel
));
606 /* FIXME: No PNG support yet in Wine or in older Windows... */
607 if (0) test_pic(pngimage
, sizeof(pngimage
));
609 test_empty_image_2();
615 test_OleCreatePictureIndirect();
619 /* Helper functions only ... */
622 static void NoStatStreamImpl_Destroy(NoStatStreamImpl
* This
)
624 GlobalFree(This
->supportHandle
);
625 This
->supportHandle
=0;
626 HeapFree(GetProcessHeap(), 0, This
);
629 static ULONG WINAPI
NoStatStreamImpl_AddRef(
632 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
633 return InterlockedIncrement(&This
->ref
);
636 static HRESULT WINAPI
NoStatStreamImpl_QueryInterface(
638 REFIID riid
, /* [in] */
639 void** ppvObject
) /* [iid_is][out] */
641 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
642 if (ppvObject
==0) return E_INVALIDARG
;
644 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
646 *ppvObject
= (IStream
*)This
;
648 else if (memcmp(&IID_IStream
, riid
, sizeof(IID_IStream
)) == 0)
650 *ppvObject
= (IStream
*)This
;
654 return E_NOINTERFACE
;
655 NoStatStreamImpl_AddRef(iface
);
659 static ULONG WINAPI
NoStatStreamImpl_Release(
662 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
663 ULONG newRef
= InterlockedDecrement(&This
->ref
);
665 NoStatStreamImpl_Destroy(This
);
669 static HRESULT WINAPI
NoStatStreamImpl_Read(
671 void* pv
, /* [length_is][size_is][out] */
673 ULONG
* pcbRead
) /* [out] */
675 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
677 ULONG bytesReadBuffer
;
678 ULONG bytesToReadFromBuffer
;
681 pcbRead
= &bytesReadBuffer
;
682 bytesToReadFromBuffer
= min( This
->streamSize
.u
.LowPart
- This
->currentPosition
.u
.LowPart
, cb
);
683 supportBuffer
= GlobalLock(This
->supportHandle
);
684 memcpy(pv
, (char *) supportBuffer
+This
->currentPosition
.u
.LowPart
, bytesToReadFromBuffer
);
685 This
->currentPosition
.u
.LowPart
+=bytesToReadFromBuffer
;
686 *pcbRead
= bytesToReadFromBuffer
;
687 GlobalUnlock(This
->supportHandle
);
693 static HRESULT WINAPI
NoStatStreamImpl_Write(
695 const void* pv
, /* [size_is][in] */
697 ULONG
* pcbWritten
) /* [out] */
699 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
701 ULARGE_INTEGER newSize
;
702 ULONG bytesWritten
= 0;
705 pcbWritten
= &bytesWritten
;
708 newSize
.u
.HighPart
= 0;
709 newSize
.u
.LowPart
= This
->currentPosition
.u
.LowPart
+ cb
;
710 if (newSize
.u
.LowPart
> This
->streamSize
.u
.LowPart
)
711 IStream_SetSize(iface
, newSize
);
713 supportBuffer
= GlobalLock(This
->supportHandle
);
714 memcpy((char *) supportBuffer
+This
->currentPosition
.u
.LowPart
, pv
, cb
);
715 This
->currentPosition
.u
.LowPart
+=cb
;
717 GlobalUnlock(This
->supportHandle
);
721 static HRESULT WINAPI
NoStatStreamImpl_Seek(
723 LARGE_INTEGER dlibMove
, /* [in] */
724 DWORD dwOrigin
, /* [in] */
725 ULARGE_INTEGER
* plibNewPosition
) /* [out] */
727 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
728 ULARGE_INTEGER newPosition
;
731 case STREAM_SEEK_SET
:
732 newPosition
.u
.HighPart
= 0;
733 newPosition
.u
.LowPart
= 0;
735 case STREAM_SEEK_CUR
:
736 newPosition
= This
->currentPosition
;
738 case STREAM_SEEK_END
:
739 newPosition
= This
->streamSize
;
742 return STG_E_INVALIDFUNCTION
;
744 if (dlibMove
.QuadPart
< 0 && newPosition
.QuadPart
< -dlibMove
.QuadPart
)
745 return STG_E_INVALIDFUNCTION
;
746 newPosition
.QuadPart
+= dlibMove
.QuadPart
;
747 if (plibNewPosition
) *plibNewPosition
= newPosition
;
748 This
->currentPosition
= newPosition
;
752 static HRESULT WINAPI
NoStatStreamImpl_SetSize(
754 ULARGE_INTEGER libNewSize
) /* [in] */
756 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
757 HGLOBAL supportHandle
;
758 if (libNewSize
.u
.HighPart
!= 0)
759 return STG_E_INVALIDFUNCTION
;
760 if (This
->streamSize
.u
.LowPart
== libNewSize
.u
.LowPart
)
762 supportHandle
= GlobalReAlloc(This
->supportHandle
, libNewSize
.u
.LowPart
, 0);
763 if (supportHandle
== 0)
764 return STG_E_MEDIUMFULL
;
765 This
->supportHandle
= supportHandle
;
766 This
->streamSize
.u
.LowPart
= libNewSize
.u
.LowPart
;
770 static HRESULT WINAPI
NoStatStreamImpl_CopyTo(
772 IStream
* pstm
, /* [unique][in] */
773 ULARGE_INTEGER cb
, /* [in] */
774 ULARGE_INTEGER
* pcbRead
, /* [out] */
775 ULARGE_INTEGER
* pcbWritten
) /* [out] */
779 ULONG bytesRead
, bytesWritten
, copySize
;
780 ULARGE_INTEGER totalBytesRead
;
781 ULARGE_INTEGER totalBytesWritten
;
784 return STG_E_INVALIDPOINTER
;
785 totalBytesRead
.u
.LowPart
= totalBytesRead
.u
.HighPart
= 0;
786 totalBytesWritten
.u
.LowPart
= totalBytesWritten
.u
.HighPart
= 0;
788 while ( cb
.u
.LowPart
> 0 )
790 if ( cb
.u
.LowPart
>= 128 )
793 copySize
= cb
.u
.LowPart
;
794 IStream_Read(iface
, tmpBuffer
, copySize
, &bytesRead
);
795 totalBytesRead
.u
.LowPart
+= bytesRead
;
796 IStream_Write(pstm
, tmpBuffer
, bytesRead
, &bytesWritten
);
797 totalBytesWritten
.u
.LowPart
+= bytesWritten
;
798 if (bytesRead
!= bytesWritten
)
800 hr
= STG_E_MEDIUMFULL
;
803 if (bytesRead
!=copySize
)
806 cb
.u
.LowPart
-= bytesRead
;
810 pcbRead
->u
.LowPart
= totalBytesRead
.u
.LowPart
;
811 pcbRead
->u
.HighPart
= totalBytesRead
.u
.HighPart
;
816 pcbWritten
->u
.LowPart
= totalBytesWritten
.u
.LowPart
;
817 pcbWritten
->u
.HighPart
= totalBytesWritten
.u
.HighPart
;
822 static HRESULT WINAPI
NoStatStreamImpl_Commit(IStream
* iface
,DWORD grfCommitFlags
)
826 static HRESULT WINAPI
NoStatStreamImpl_Revert(IStream
* iface
) { return S_OK
; }
828 static HRESULT WINAPI
NoStatStreamImpl_LockRegion(
830 ULARGE_INTEGER libOffset
, /* [in] */
831 ULARGE_INTEGER cb
, /* [in] */
832 DWORD dwLockType
) /* [in] */
837 static HRESULT WINAPI
NoStatStreamImpl_UnlockRegion(
839 ULARGE_INTEGER libOffset
, /* [in] */
840 ULARGE_INTEGER cb
, /* [in] */
841 DWORD dwLockType
) /* [in] */
846 static HRESULT WINAPI
NoStatStreamImpl_Stat(
848 STATSTG
* pstatstg
, /* [out] */
849 DWORD grfStatFlag
) /* [in] */
854 static HRESULT WINAPI
NoStatStreamImpl_Clone(
856 IStream
** ppstm
) /* [out] */
860 static const IStreamVtbl NoStatStreamImpl_Vtbl
;
863 Build an object that implements IStream, without IStream_Stat capabilities.
864 Receives a memory handle with data buffer. If memory handle is non-null,
865 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
866 In any case the object takes ownership of memory handle and will free it on
869 static NoStatStreamImpl
* NoStatStreamImpl_Construct(HGLOBAL hGlobal
)
871 NoStatStreamImpl
* newStream
;
873 newStream
= HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl
));
876 newStream
->lpVtbl
= &NoStatStreamImpl_Vtbl
;
878 newStream
->supportHandle
= hGlobal
;
880 if (!newStream
->supportHandle
)
881 newStream
->supportHandle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_NODISCARD
|
883 newStream
->currentPosition
.u
.HighPart
= 0;
884 newStream
->currentPosition
.u
.LowPart
= 0;
885 newStream
->streamSize
.u
.HighPart
= 0;
886 newStream
->streamSize
.u
.LowPart
= GlobalSize(newStream
->supportHandle
);
892 static const IStreamVtbl NoStatStreamImpl_Vtbl
=
894 NoStatStreamImpl_QueryInterface
,
895 NoStatStreamImpl_AddRef
,
896 NoStatStreamImpl_Release
,
897 NoStatStreamImpl_Read
,
898 NoStatStreamImpl_Write
,
899 NoStatStreamImpl_Seek
,
900 NoStatStreamImpl_SetSize
,
901 NoStatStreamImpl_CopyTo
,
902 NoStatStreamImpl_Commit
,
903 NoStatStreamImpl_Revert
,
904 NoStatStreamImpl_LockRegion
,
905 NoStatStreamImpl_UnlockRegion
,
906 NoStatStreamImpl_Stat
,
907 NoStatStreamImpl_Clone