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
30 #include "wine/test.h"
43 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
45 #define ole_expect(expr, expect) { \
47 ok(r == (expect), #expr " returned %x, expected %s (%x)\n", r, #expect, expect); \
50 #define ole_check(expr) ole_expect(expr, S_OK);
52 static HMODULE hOleaut32
;
54 static HRESULT (WINAPI
*pOleLoadPicture
)(LPSTREAM
,LONG
,BOOL
,REFIID
,LPVOID
*);
55 static HRESULT (WINAPI
*pOleCreatePictureIndirect
)(PICTDESC
*,REFIID
,BOOL
,LPVOID
*);
57 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
60 static const unsigned char gifimage
[35] = {
61 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
62 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
67 static const unsigned char jpgimage
[285] = {
68 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
69 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
70 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
71 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
72 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
73 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
74 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,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,0x1e,0x1e,
77 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
78 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
79 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
80 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
81 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
82 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
83 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
84 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
85 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
89 static const unsigned char pngimage
[285] = {
90 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
91 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
92 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
93 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
94 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
95 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
96 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
100 static const unsigned char bmpimage
[66] = {
101 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
102 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
103 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
104 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
109 static const unsigned char gif4pixel
[42] = {
110 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
111 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
112 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
115 /* APM with an empty metafile with some padding zeros - looks like under Window the
116 * metafile data should be at least 20 bytes */
117 static const unsigned char apmdata
[] = {
118 0xd7,0xcd,0xc6,0x9a, 0x00,0x00,0x00,0x00, 0x00,0x00,0xee,0x02, 0xb1,0x03,0xa0,0x05,
119 0x00,0x00,0x00,0x00, 0xee,0x53,0x01,0x00, 0x09,0x00,0x00,0x03, 0x13,0x00,0x00,0x00,
120 0x01,0x00,0x05,0x00, 0x00,0x00,0x00,0x00, 0x03,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
121 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
124 /* MF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
125 static const unsigned char metafile
[] = {
126 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
127 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
128 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
129 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
130 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
131 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
135 /* EMF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
136 static const unsigned char enhmetafile
[] = {
137 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
142 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
143 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
144 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
147 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
150 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
151 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
152 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
154 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
156 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
157 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
160 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
161 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
162 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
163 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
164 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
165 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
166 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
167 0x14, 0x00, 0x00, 0x00
171 struct NoStatStreamImpl
173 const IStreamVtbl
*lpVtbl
;
176 HGLOBAL supportHandle
;
177 ULARGE_INTEGER streamSize
;
178 ULARGE_INTEGER currentPosition
;
180 typedef struct NoStatStreamImpl NoStatStreamImpl
;
181 static NoStatStreamImpl
* NoStatStreamImpl_Construct(HGLOBAL hGlobal
);
184 test_pic_with_stream(LPSTREAM stream
, unsigned int imgsize
)
186 IPicture
* pic
= NULL
;
189 OLE_HANDLE handle
, hPal
;
190 OLE_XSIZE_HIMETRIC width
;
191 OLE_YSIZE_HIMETRIC height
;
197 hres
= pOleLoadPicture(stream
, imgsize
, TRUE
, &IID_IPicture
, &pvObj
);
200 ok(hres
== S_OK
,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres
);
201 ok(pic
!= NULL
,"OLP (NULL,..) returns NULL, instead of !NULL\n");
206 hres
= IPicture_QueryInterface (pic
, &IID_IPicture
, &pvObj
);
208 ok(hres
== S_OK
,"IPicture_QI does not return S_OK, but 0x%08x\n", hres
);
209 ok(pvObj
!= NULL
,"IPicture_QI does return NULL, instead of a ptr\n");
211 IPicture_Release ((IPicture
*)pvObj
);
214 hres
= IPicture_get_Handle (pic
, &handle
);
215 ok(hres
== S_OK
,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres
);
216 ok(handle
!= 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
219 hres
= IPicture_get_Width (pic
, &width
);
220 ok(hres
== S_OK
,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres
);
221 ok(width
!= 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
224 hres
= IPicture_get_Height (pic
, &height
);
225 ok(hres
== S_OK
,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres
);
226 ok(height
!= 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
229 hres
= IPicture_get_Type (pic
, &type
);
230 ok(hres
== S_OK
,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres
);
231 ok(type
== PICTYPE_BITMAP
, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type
, PICTYPE_BITMAP
);
234 hres
= IPicture_get_Attributes (pic
, &attr
);
235 ok(hres
== S_OK
,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres
);
236 ok(attr
== 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr
);
239 hres
= IPicture_get_hPal (pic
, &hPal
);
240 ok(hres
== S_OK
,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres
);
241 /* a single pixel b/w image has no palette */
242 ok(hPal
== 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal
);
244 res
= IPicture_Release (pic
);
245 ok (res
== 0, "refcount after release is %d, but should be 0?\n", res
);
249 test_pic(const unsigned char *imgdata
, unsigned int imgsize
)
255 LARGE_INTEGER seekto
;
256 ULARGE_INTEGER newpos1
;
260 /* Let the fun begin */
261 hglob
= GlobalAlloc (0, imgsize
);
262 data
= GlobalLock (hglob
);
263 memcpy(data
, imgdata
, imgsize
);
264 GlobalUnlock(hglob
); data
= NULL
;
266 hres
= CreateStreamOnHGlobal (hglob
, FALSE
, &stream
);
267 ok (hres
== S_OK
, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres
);
269 memset(&seekto
,0,sizeof(seekto
));
270 hres
= IStream_Seek(stream
,seekto
,SEEK_CUR
,&newpos1
);
271 ok (hres
== S_OK
, "istream seek failed? doubt it... hres 0x%08x\n", hres
);
272 test_pic_with_stream(stream
, imgsize
);
274 IStream_Release(stream
);
276 /* again with Non Statable and Non Seekable stream */
277 stream
= (LPSTREAM
)NoStatStreamImpl_Construct(hglob
);
278 hglob
= 0; /* Non-statable impl always deletes on release */
279 test_pic_with_stream(stream
, 0);
281 IStream_Release(stream
);
282 for (i
= 1; i
<= 8; i
++) {
284 hglob
= GlobalAlloc (0, imgsize
+ i
* (2 * sizeof(DWORD
)));
285 data
= GlobalLock (hglob
);
286 header
= (DWORD
*)data
;
288 /* multiple copies of header */
289 memcpy(data
,"lt\0\0",4);
291 for (j
= 2; j
<= i
; j
++) {
292 memcpy(&(header
[2 * (j
- 1)]), header
, 2 * sizeof(DWORD
));
294 memcpy(data
+ i
* (2 * sizeof(DWORD
)), imgdata
, imgsize
);
295 GlobalUnlock(hglob
); data
= NULL
;
297 hres
= CreateStreamOnHGlobal (hglob
, FALSE
, &stream
);
298 ok (hres
== S_OK
, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres
);
300 memset(&seekto
,0,sizeof(seekto
));
301 hres
= IStream_Seek(stream
,seekto
,SEEK_CUR
,&newpos1
);
302 ok (hres
== S_OK
, "istream seek failed? doubt it... hres 0x%08x\n", hres
);
303 test_pic_with_stream(stream
, imgsize
);
305 IStream_Release(stream
);
307 /* again with Non Statable and Non Seekable stream */
308 stream
= (LPSTREAM
)NoStatStreamImpl_Construct(hglob
);
309 hglob
= 0; /* Non-statable impl always deletes on release */
310 test_pic_with_stream(stream
, 0);
312 IStream_Release(stream
);
316 static void test_empty_image(void) {
319 IPicture
* pic
= NULL
;
324 ULARGE_INTEGER newpos1
;
325 LARGE_INTEGER seekto
;
328 /* Empty image. Happens occasionally in VB programs. */
329 hglob
= GlobalAlloc (0, 8);
330 data
= GlobalLock (hglob
);
331 memcpy(data
,"lt\0\0",4);
332 ((DWORD
*)data
)[1] = 0;
333 hres
= CreateStreamOnHGlobal (hglob
, TRUE
, &stream
);
334 ok (hres
== S_OK
, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres
);
336 memset(&seekto
,0,sizeof(seekto
));
337 hres
= IStream_Seek(stream
,seekto
,SEEK_CUR
,&newpos1
);
338 ok (hres
== S_OK
, "istream seek failed? doubt it... hres 0x%08x\n", hres
);
341 hres
= pOleLoadPicture(stream
, 8, TRUE
, &IID_IPicture
, &pvObj
);
343 ok(hres
== S_OK
,"empty picture not loaded, hres 0x%08x\n", hres
);
344 ok(pic
!= NULL
,"empty picture not loaded, pic is NULL\n");
346 hres
= IPicture_get_Type (pic
, &type
);
347 ok (hres
== S_OK
,"empty picture get type failed with hres 0x%08x\n", hres
);
348 ok (type
== PICTYPE_NONE
,"type is %d, but should be PICTYPE_NONE(0)\n", type
);
350 hres
= IPicture_get_Handle (pic
, &handle
);
351 ok (hres
== S_OK
,"empty picture get handle failed with hres 0x%08x\n", hres
);
352 ok (handle
== 0, "empty picture get handle did not return 0, but 0x%08x\n", handle
);
353 IPicture_Release (pic
);
356 static void test_empty_image_2(void) {
359 IPicture
* pic
= NULL
;
363 ULARGE_INTEGER newpos1
;
364 LARGE_INTEGER seekto
;
367 /* Empty image at random stream position. */
368 hglob
= GlobalAlloc (0, 200);
369 data
= GlobalLock (hglob
);
371 memcpy(data
,"lt\0\0",4);
372 ((DWORD
*)data
)[1] = 0;
373 hres
= CreateStreamOnHGlobal (hglob
, TRUE
, &stream
);
374 ok (hres
== S_OK
, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres
);
376 memset(&seekto
,0,sizeof(seekto
));
377 seekto
.u
.LowPart
= 42;
378 hres
= IStream_Seek(stream
,seekto
,SEEK_CUR
,&newpos1
);
379 ok (hres
== S_OK
, "istream seek failed? doubt it... hres 0x%08x\n", hres
);
382 hres
= pOleLoadPicture(stream
, 8, TRUE
, &IID_IPicture
, &pvObj
);
384 ok(hres
== S_OK
,"empty picture not loaded, hres 0x%08x\n", hres
);
385 ok(pic
!= NULL
,"empty picture not loaded, pic is NULL\n");
387 hres
= IPicture_get_Type (pic
, &type
);
388 ok (hres
== S_OK
,"empty picture get type failed with hres 0x%08x\n", hres
);
389 ok (type
== PICTYPE_NONE
,"type is %d, but should be PICTYPE_NONE(0)\n", type
);
391 IPicture_Release (pic
);
394 static void test_Invoke(void)
396 IPictureDisp
*picdisp
;
399 DISPPARAMS dispparams
;
405 hglob
= GlobalAlloc (0, sizeof(gifimage
));
406 data
= GlobalLock(hglob
);
407 memcpy(data
, gifimage
, sizeof(gifimage
));
410 hr
= CreateStreamOnHGlobal (hglob
, FALSE
, &stream
);
411 ok_ole_success(hr
, "CreateStreamOnHGlobal");
413 hr
= pOleLoadPicture(stream
, sizeof(gifimage
), TRUE
, &IID_IPictureDisp
, (void **)&picdisp
);
414 IStream_Release(stream
);
415 ok_ole_success(hr
, "OleLoadPicture");
417 V_VT(&vararg
) = VT_BOOL
;
418 V_BOOL(&vararg
) = VARIANT_FALSE
;
419 dispparams
.cNamedArgs
= 0;
420 dispparams
.rgdispidNamedArgs
= NULL
;
421 dispparams
.cArgs
= 1;
422 dispparams
.rgvarg
= &vararg
;
423 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_IPictureDisp
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
424 ok(hr
== DISP_E_UNKNOWNNAME
, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr
);
425 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_IUnknown
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
426 ok(hr
== DISP_E_UNKNOWNNAME
, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr
);
428 dispparams
.cArgs
= 0;
429 dispparams
.rgvarg
= NULL
;
430 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
431 ok(hr
== DISP_E_BADPARAMCOUNT
, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr
);
433 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYPUT
, NULL
, NULL
, NULL
, NULL
);
434 ok(hr
== DISP_E_PARAMNOTOPTIONAL
, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr
);
436 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, NULL
, NULL
, NULL
, NULL
);
437 ok(hr
== DISP_E_PARAMNOTOPTIONAL
, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr
);
439 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, NULL
, &varresult
, NULL
, NULL
);
440 ok(hr
== DISP_E_PARAMNOTOPTIONAL
, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr
);
442 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
443 ok_ole_success(hr
, "IPictureDisp_Invoke");
444 ok(V_VT(&varresult
) == VT_I4
, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult
));
446 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_METHOD
, &dispparams
, &varresult
, NULL
, NULL
);
447 ok(hr
== DISP_E_MEMBERNOTFOUND
, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr
);
449 hr
= IPictureDisp_Invoke(picdisp
, 0xdeadbeef, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
450 ok(hr
== DISP_E_MEMBERNOTFOUND
, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr
);
452 dispparams
.cArgs
= 1;
453 dispparams
.rgvarg
= &vararg
;
454 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
455 ok(hr
== DISP_E_BADPARAMCOUNT
, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr
);
457 dispparams
.cArgs
= 1;
458 dispparams
.rgvarg
= &vararg
;
459 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
460 ok(hr
== DISP_E_BADPARAMCOUNT
, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr
);
462 IPictureDisp_Release(picdisp
);
465 static void test_OleCreatePictureIndirect(void)
472 if(!pOleCreatePictureIndirect
)
474 skip("Skipping OleCreatePictureIndirect tests\n");
478 hr
= pOleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (void**)&pict
);
479 ok(hr
== S_OK
, "hr %08x\n", hr
);
481 hr
= IPicture_get_Type(pict
, &type
);
482 ok(hr
== S_OK
, "hr %08x\n", hr
);
483 ok(type
== PICTYPE_UNINITIALIZED
, "type %d\n", type
);
485 hr
= IPicture_get_Handle(pict
, &handle
);
486 ok(hr
== S_OK
, "hr %08x\n", hr
);
487 ok(handle
== 0, "handle %08x\n", handle
);
489 IPicture_Release(pict
);
492 static void test_apm()
503 hglob
= GlobalAlloc (0, sizeof(apmdata
));
504 data
= GlobalLock(hglob
);
505 memcpy(data
, apmdata
, sizeof(apmdata
));
507 ole_check(CreateStreamOnHGlobal(hglob
, TRUE
, &stream
));
508 ole_check(OleLoadPictureEx(stream
, sizeof(apmdata
), TRUE
, &IID_IPicture
, 100, 100, 0, (LPVOID
*)&pict
));
510 ole_check(IPicture_get_Handle(pict
, &handle
));
511 ok(handle
!= 0, "handle is null\n");
513 ole_check(IPicture_get_Type(pict
, &type
));
514 expect_eq(type
, PICTYPE_METAFILE
, short, "%d");
516 ole_check(IPicture_get_Height(pict
, &cxy
));
517 expect_eq(cxy
, 1667, LONG
, "%d");
519 ole_check(IPicture_get_Width(pict
, &cxy
));
520 expect_eq(cxy
, 1323, LONG
, "%d");
522 ole_check(IPicture_get_KeepOriginalFormat(pict
, &keep
));
523 todo_wine
expect_eq(keep
, FALSE
, LONG
, "%d");
525 ole_expect(IPicture_get_hPal(pict
, &handle
), E_FAIL
);
526 IPicture_Release(pict
);
527 IStream_Release(stream
);
532 static void test_metafile(void)
539 hglob
= GlobalAlloc (0, sizeof(metafile
));
540 data
= GlobalLock(hglob
);
541 memcpy(data
, metafile
, sizeof(metafile
));
543 ole_check(CreateStreamOnHGlobal(hglob
, TRUE
, &stream
));
544 /* Windows does not load simple metafiles */
545 ole_expect(OleLoadPictureEx(stream
, sizeof(metafile
), TRUE
, &IID_IPicture
, 100, 100, 0, (LPVOID
*)&pict
), E_FAIL
);
547 IStream_Release(stream
);
552 static void test_enhmetafile(void)
563 hglob
= GlobalAlloc (0, sizeof(enhmetafile
));
564 data
= GlobalLock(hglob
);
565 memcpy(data
, enhmetafile
, sizeof(enhmetafile
));
567 ole_check(CreateStreamOnHGlobal(hglob
, TRUE
, &stream
));
568 ole_check(OleLoadPictureEx(stream
, sizeof(enhmetafile
), TRUE
, &IID_IPicture
, 10, 10, 0, (LPVOID
*)&pict
));
570 ole_check(IPicture_get_Handle(pict
, &handle
));
571 ok(handle
!= 0, "handle is null\n");
573 ole_check(IPicture_get_Type(pict
, &type
));
574 expect_eq(type
, PICTYPE_ENHMETAFILE
, short, "%d");
576 ole_check(IPicture_get_Height(pict
, &cxy
));
577 expect_eq(cxy
, -23, LONG
, "%d");
579 ole_check(IPicture_get_Width(pict
, &cxy
));
580 expect_eq(cxy
, -25, LONG
, "%d");
582 ole_check(IPicture_get_KeepOriginalFormat(pict
, &keep
));
583 todo_wine
expect_eq(keep
, FALSE
, LONG
, "%d");
585 IPicture_Release(pict
);
586 IStream_Release(stream
);
591 START_TEST(olepicture
)
593 hOleaut32
= GetModuleHandleA("oleaut32.dll");
594 pOleLoadPicture
= (void*)GetProcAddress(hOleaut32
, "OleLoadPicture");
595 pOleCreatePictureIndirect
= (void*)GetProcAddress(hOleaut32
, "OleCreatePictureIndirect");
596 if (!pOleLoadPicture
)
598 skip("OleLoadPicture is not available\n");
602 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
603 test_pic(gifimage
, sizeof(gifimage
));
604 test_pic(jpgimage
, sizeof(jpgimage
));
605 test_pic(bmpimage
, sizeof(bmpimage
));
606 test_pic(gif4pixel
, sizeof(gif4pixel
));
607 /* FIXME: No PNG support yet in Wine or in older Windows... */
608 if (0) test_pic(pngimage
, sizeof(pngimage
));
610 test_empty_image_2();
616 test_OleCreatePictureIndirect();
620 /* Helper functions only ... */
623 static void NoStatStreamImpl_Destroy(NoStatStreamImpl
* This
)
625 GlobalFree(This
->supportHandle
);
626 This
->supportHandle
=0;
627 HeapFree(GetProcessHeap(), 0, This
);
630 static ULONG WINAPI
NoStatStreamImpl_AddRef(
633 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
634 return InterlockedIncrement(&This
->ref
);
637 static HRESULT WINAPI
NoStatStreamImpl_QueryInterface(
639 REFIID riid
, /* [in] */
640 void** ppvObject
) /* [iid_is][out] */
642 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
643 if (ppvObject
==0) return E_INVALIDARG
;
645 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
647 *ppvObject
= (IStream
*)This
;
649 else if (memcmp(&IID_IStream
, riid
, sizeof(IID_IStream
)) == 0)
651 *ppvObject
= (IStream
*)This
;
655 return E_NOINTERFACE
;
656 NoStatStreamImpl_AddRef(iface
);
660 static ULONG WINAPI
NoStatStreamImpl_Release(
663 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
664 ULONG newRef
= InterlockedDecrement(&This
->ref
);
666 NoStatStreamImpl_Destroy(This
);
670 static HRESULT WINAPI
NoStatStreamImpl_Read(
672 void* pv
, /* [length_is][size_is][out] */
674 ULONG
* pcbRead
) /* [out] */
676 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
678 ULONG bytesReadBuffer
;
679 ULONG bytesToReadFromBuffer
;
682 pcbRead
= &bytesReadBuffer
;
683 bytesToReadFromBuffer
= min( This
->streamSize
.u
.LowPart
- This
->currentPosition
.u
.LowPart
, cb
);
684 supportBuffer
= GlobalLock(This
->supportHandle
);
685 memcpy(pv
, (char *) supportBuffer
+This
->currentPosition
.u
.LowPart
, bytesToReadFromBuffer
);
686 This
->currentPosition
.u
.LowPart
+=bytesToReadFromBuffer
;
687 *pcbRead
= bytesToReadFromBuffer
;
688 GlobalUnlock(This
->supportHandle
);
694 static HRESULT WINAPI
NoStatStreamImpl_Write(
696 const void* pv
, /* [size_is][in] */
698 ULONG
* pcbWritten
) /* [out] */
700 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
702 ULARGE_INTEGER newSize
;
703 ULONG bytesWritten
= 0;
706 pcbWritten
= &bytesWritten
;
709 newSize
.u
.HighPart
= 0;
710 newSize
.u
.LowPart
= This
->currentPosition
.u
.LowPart
+ cb
;
711 if (newSize
.u
.LowPart
> This
->streamSize
.u
.LowPart
)
712 IStream_SetSize(iface
, newSize
);
714 supportBuffer
= GlobalLock(This
->supportHandle
);
715 memcpy((char *) supportBuffer
+This
->currentPosition
.u
.LowPart
, pv
, cb
);
716 This
->currentPosition
.u
.LowPart
+=cb
;
718 GlobalUnlock(This
->supportHandle
);
722 static HRESULT WINAPI
NoStatStreamImpl_Seek(
724 LARGE_INTEGER dlibMove
, /* [in] */
725 DWORD dwOrigin
, /* [in] */
726 ULARGE_INTEGER
* plibNewPosition
) /* [out] */
728 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
729 ULARGE_INTEGER newPosition
;
732 case STREAM_SEEK_SET
:
733 newPosition
.u
.HighPart
= 0;
734 newPosition
.u
.LowPart
= 0;
736 case STREAM_SEEK_CUR
:
737 newPosition
= This
->currentPosition
;
739 case STREAM_SEEK_END
:
740 newPosition
= This
->streamSize
;
743 return STG_E_INVALIDFUNCTION
;
745 if (dlibMove
.QuadPart
< 0 && newPosition
.QuadPart
< -dlibMove
.QuadPart
)
746 return STG_E_INVALIDFUNCTION
;
747 newPosition
.QuadPart
+= dlibMove
.QuadPart
;
748 if (plibNewPosition
) *plibNewPosition
= newPosition
;
749 This
->currentPosition
= newPosition
;
753 static HRESULT WINAPI
NoStatStreamImpl_SetSize(
755 ULARGE_INTEGER libNewSize
) /* [in] */
757 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
758 HGLOBAL supportHandle
;
759 if (libNewSize
.u
.HighPart
!= 0)
760 return STG_E_INVALIDFUNCTION
;
761 if (This
->streamSize
.u
.LowPart
== libNewSize
.u
.LowPart
)
763 supportHandle
= GlobalReAlloc(This
->supportHandle
, libNewSize
.u
.LowPart
, 0);
764 if (supportHandle
== 0)
765 return STG_E_MEDIUMFULL
;
766 This
->supportHandle
= supportHandle
;
767 This
->streamSize
.u
.LowPart
= libNewSize
.u
.LowPart
;
771 static HRESULT WINAPI
NoStatStreamImpl_CopyTo(
773 IStream
* pstm
, /* [unique][in] */
774 ULARGE_INTEGER cb
, /* [in] */
775 ULARGE_INTEGER
* pcbRead
, /* [out] */
776 ULARGE_INTEGER
* pcbWritten
) /* [out] */
780 ULONG bytesRead
, bytesWritten
, copySize
;
781 ULARGE_INTEGER totalBytesRead
;
782 ULARGE_INTEGER totalBytesWritten
;
785 return STG_E_INVALIDPOINTER
;
786 totalBytesRead
.u
.LowPart
= totalBytesRead
.u
.HighPart
= 0;
787 totalBytesWritten
.u
.LowPart
= totalBytesWritten
.u
.HighPart
= 0;
789 while ( cb
.u
.LowPart
> 0 )
791 if ( cb
.u
.LowPart
>= 128 )
794 copySize
= cb
.u
.LowPart
;
795 IStream_Read(iface
, tmpBuffer
, copySize
, &bytesRead
);
796 totalBytesRead
.u
.LowPart
+= bytesRead
;
797 IStream_Write(pstm
, tmpBuffer
, bytesRead
, &bytesWritten
);
798 totalBytesWritten
.u
.LowPart
+= bytesWritten
;
799 if (bytesRead
!= bytesWritten
)
801 hr
= STG_E_MEDIUMFULL
;
804 if (bytesRead
!=copySize
)
807 cb
.u
.LowPart
-= bytesRead
;
811 pcbRead
->u
.LowPart
= totalBytesRead
.u
.LowPart
;
812 pcbRead
->u
.HighPart
= totalBytesRead
.u
.HighPart
;
817 pcbWritten
->u
.LowPart
= totalBytesWritten
.u
.LowPart
;
818 pcbWritten
->u
.HighPart
= totalBytesWritten
.u
.HighPart
;
823 static HRESULT WINAPI
NoStatStreamImpl_Commit(IStream
* iface
,DWORD grfCommitFlags
)
827 static HRESULT WINAPI
NoStatStreamImpl_Revert(IStream
* iface
) { return S_OK
; }
829 static HRESULT WINAPI
NoStatStreamImpl_LockRegion(
831 ULARGE_INTEGER libOffset
, /* [in] */
832 ULARGE_INTEGER cb
, /* [in] */
833 DWORD dwLockType
) /* [in] */
838 static HRESULT WINAPI
NoStatStreamImpl_UnlockRegion(
840 ULARGE_INTEGER libOffset
, /* [in] */
841 ULARGE_INTEGER cb
, /* [in] */
842 DWORD dwLockType
) /* [in] */
847 static HRESULT WINAPI
NoStatStreamImpl_Stat(
849 STATSTG
* pstatstg
, /* [out] */
850 DWORD grfStatFlag
) /* [in] */
855 static HRESULT WINAPI
NoStatStreamImpl_Clone(
857 IStream
** ppstm
) /* [out] */
861 static const IStreamVtbl NoStatStreamImpl_Vtbl
;
864 Build an object that implements IStream, without IStream_Stat capabilities.
865 Receives a memory handle with data buffer. If memory handle is non-null,
866 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
867 In any case the object takes ownership of memory handle and will free it on
870 static NoStatStreamImpl
* NoStatStreamImpl_Construct(HGLOBAL hGlobal
)
872 NoStatStreamImpl
* newStream
;
874 newStream
= HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl
));
877 newStream
->lpVtbl
= &NoStatStreamImpl_Vtbl
;
879 newStream
->supportHandle
= hGlobal
;
881 if (!newStream
->supportHandle
)
882 newStream
->supportHandle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_NODISCARD
|
884 newStream
->currentPosition
.u
.HighPart
= 0;
885 newStream
->currentPosition
.u
.LowPart
= 0;
886 newStream
->streamSize
.u
.HighPart
= 0;
887 newStream
->streamSize
.u
.LowPart
= GlobalSize(newStream
->supportHandle
);
893 static const IStreamVtbl NoStatStreamImpl_Vtbl
=
895 NoStatStreamImpl_QueryInterface
,
896 NoStatStreamImpl_AddRef
,
897 NoStatStreamImpl_Release
,
898 NoStatStreamImpl_Read
,
899 NoStatStreamImpl_Write
,
900 NoStatStreamImpl_Seek
,
901 NoStatStreamImpl_SetSize
,
902 NoStatStreamImpl_CopyTo
,
903 NoStatStreamImpl_Commit
,
904 NoStatStreamImpl_Revert
,
905 NoStatStreamImpl_LockRegion
,
906 NoStatStreamImpl_UnlockRegion
,
907 NoStatStreamImpl_Stat
,
908 NoStatStreamImpl_Clone