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
28 #define NONAMELESSUNION
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;
329 /* Empty image. Happens occasionally in VB programs. */
330 hglob = GlobalAlloc (0, 8);
331 data = GlobalLock (hglob);
332 memcpy(data,"lt\0\0",4);
333 ((DWORD*)data)[1] = 0;
334 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
335 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
337 memset(&seekto,0,sizeof(seekto));
338 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
339 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
342 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
344 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
345 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
347 hres = IPicture_get_Type (pic, &type);
348 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
349 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
352 hres = IPicture_get_Attributes (pic, &attr);
353 ok (hres == S_OK,"empty picture get attributes failed with hres 0x%08x\n", hres);
354 ok (attr == 0,"attr is %d, but should be 0\n", attr);
356 hres = IPicture_get_Handle (pic, &handle);
357 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
358 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
359 IPicture_Release (pic);
362 static void test_empty_image_2(void) {
365 IPicture* pic = NULL;
369 ULARGE_INTEGER newpos1;
370 LARGE_INTEGER seekto;
373 /* Empty image at random stream position. */
374 hglob = GlobalAlloc (0, 200);
375 data = GlobalLock (hglob);
377 memcpy(data,"lt\0\0",4);
378 ((DWORD*)data)[1] = 0;
379 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
380 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
382 memset(&seekto,0,sizeof(seekto));
383 seekto.u.LowPart = 42;
384 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
385 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
388 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
390 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
391 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
393 hres = IPicture_get_Type (pic, &type);
394 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
395 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
397 IPicture_Release (pic);
400 static void test_Invoke(void)
402 IPictureDisp *picdisp;
405 DISPPARAMS dispparams;
411 hglob = GlobalAlloc (0, sizeof(gifimage));
412 data = GlobalLock(hglob);
413 memcpy(data, gifimage, sizeof(gifimage));
416 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
417 ok_ole_success(hr, "CreateStreamOnHGlobal");
419 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
420 IStream_Release(stream);
421 ok_ole_success(hr, "OleLoadPicture");
423 V_VT(&vararg) = VT_BOOL;
424 V_BOOL(&vararg) = VARIANT_FALSE;
425 dispparams.cNamedArgs = 0;
426 dispparams.rgdispidNamedArgs = NULL;
427 dispparams.cArgs = 1;
428 dispparams.rgvarg = &vararg;
429 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
430 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
431 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
432 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
434 dispparams.cArgs = 0;
435 dispparams.rgvarg = NULL;
436 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
437 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
439 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, 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, NULL, NULL, NULL, NULL);
443 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
445 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
446 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
448 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
449 ok_ole_success(hr, "IPictureDisp_Invoke");
450 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
452 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
453 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
455 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
456 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
458 dispparams.cArgs = 1;
459 dispparams.rgvarg = &vararg;
460 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
461 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
463 dispparams.cArgs = 1;
464 dispparams.rgvarg = &vararg;
465 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
466 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
468 IPictureDisp_Release(picdisp);
471 static void test_OleCreatePictureIndirect(void)
478 if(!pOleCreatePictureIndirect)
480 skip("Skipping OleCreatePictureIndirect tests\n");
484 hr = pOleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict);
485 ok(hr == S_OK, "hr %08x\n", hr);
487 hr = IPicture_get_Type(pict, &type);
488 ok(hr == S_OK, "hr %08x\n", hr);
489 ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type);
491 hr = IPicture_get_Handle(pict, &handle);
492 ok(hr == S_OK, "hr %08x\n", hr);
493 ok(handle == 0, "handle %08x\n", handle);
495 IPicture_Release(pict);
498 static void test_apm(void)
509 hglob = GlobalAlloc (0, sizeof(apmdata));
510 data = GlobalLock(hglob);
511 memcpy(data, apmdata, sizeof(apmdata));
513 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
514 ole_check(OleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict));
516 ole_check(IPicture_get_Handle(pict, &handle));
517 ok(handle != 0, "handle is null\n");
519 ole_check(IPicture_get_Type(pict, &type));
520 expect_eq(type, PICTYPE_METAFILE, short, "%d");
522 ole_check(IPicture_get_Height(pict, &cxy));
523 expect_eq(cxy, 1667, LONG, "%d");
525 ole_check(IPicture_get_Width(pict, &cxy));
526 expect_eq(cxy, 1323, LONG, "%d");
528 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
529 todo_wine expect_eq(keep, FALSE, LONG, "%d");
531 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL);
532 IPicture_Release(pict);
533 IStream_Release(stream);
536 static void test_metafile(void)
543 hglob = GlobalAlloc (0, sizeof(metafile));
544 data = GlobalLock(hglob);
545 memcpy(data, metafile, sizeof(metafile));
547 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
548 /* Windows does not load simple metafiles */
549 ole_expect(OleLoadPictureEx(stream, sizeof(metafile), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict), E_FAIL);
551 IStream_Release(stream);
554 static void test_enhmetafile(void)
565 hglob = GlobalAlloc (0, sizeof(enhmetafile));
566 data = GlobalLock(hglob);
567 memcpy(data, enhmetafile, sizeof(enhmetafile));
569 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
570 ole_check(OleLoadPictureEx(stream, sizeof(enhmetafile), TRUE, &IID_IPicture, 10, 10, 0, (LPVOID *)&pict));
572 ole_check(IPicture_get_Handle(pict, &handle));
573 ok(handle != 0, "handle is null\n");
575 ole_check(IPicture_get_Type(pict, &type));
576 expect_eq(type, PICTYPE_ENHMETAFILE, short, "%d");
578 ole_check(IPicture_get_Height(pict, &cxy));
579 expect_eq(cxy, -23, LONG, "%d");
581 ole_check(IPicture_get_Width(pict, &cxy));
582 expect_eq(cxy, -25, LONG, "%d");
584 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
585 todo_wine expect_eq(keep, FALSE, LONG, "%d");
587 IPicture_Release(pict);
588 IStream_Release(stream);
591 static void test_Render(void)
599 /* test IPicture::Render return code on uninitialized picture */
600 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
601 hres = IPicture_get_Type(pic, &type);
602 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
603 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
604 /* zero dimensions */
605 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
606 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
607 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
608 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
609 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
610 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
611 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
612 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
613 hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
614 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
615 hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
616 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
617 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
618 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
619 /* nonzero dimensions, PICTYPE_UNINITIALIZED */
620 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL);
621 ole_expect(hres, S_OK);
622 IPicture_Release(pic);
624 desc.cbSizeofstruct = sizeof(PICTDESC);
625 desc.picType = PICTYPE_ICON;
626 desc.u.icon.hicon = LoadIcon(NULL, IDI_APPLICATION);
627 if(!desc.u.icon.hicon){
628 win_skip("LoadIcon failed. Skipping...\n");
629 ReleaseDC(NULL, hdc);
633 OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (VOID**)&pic);
634 /* zero dimensions, PICTYPE_ICON */
635 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
636 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
637 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
638 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
639 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
640 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
641 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
642 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
643 hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
644 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
645 hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
646 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
647 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
648 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
649 IPicture_Release(pic);
651 ReleaseDC(NULL, hdc);
654 static void test_get_Attributes(void)
661 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
662 hres = IPicture_get_Type(pic, &type);
663 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
664 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
666 hres = IPicture_get_Attributes(pic, NULL);
667 ole_expect(hres, E_POINTER);
670 hres = IPicture_get_Attributes(pic, &attr);
671 ole_expect(hres, S_OK);
672 ok(attr == 0, "IPicture_get_Attributes does not reset attr to zero, got %d\n", attr);
674 IPicture_Release(pic);
677 static void test_get_Handle(void)
682 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
684 hres = IPicture_get_Handle(pic, NULL);
685 ole_expect(hres, E_POINTER);
687 IPicture_Release(pic);
690 static void test_get_Type(void)
695 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
697 hres = IPicture_get_Type(pic, NULL);
698 ole_expect(hres, E_POINTER);
700 IPicture_Release(pic);
703 START_TEST(olepicture)
705 hOleaut32 = GetModuleHandleA("oleaut32.dll");
706 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
707 pOleCreatePictureIndirect = (void*)GetProcAddress(hOleaut32, "OleCreatePictureIndirect");
708 if (!pOleLoadPicture)
710 skip("OleLoadPicture is not available\n");
714 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
715 test_pic(gifimage, sizeof(gifimage));
716 test_pic(jpgimage, sizeof(jpgimage));
717 test_pic(bmpimage, sizeof(bmpimage));
718 test_pic(gif4pixel, sizeof(gif4pixel));
719 /* FIXME: No PNG support yet in Wine or in older Windows... */
720 if (0) test_pic(pngimage, sizeof(pngimage));
722 test_empty_image_2();
728 test_OleCreatePictureIndirect();
730 test_get_Attributes();
736 /* Helper functions only ... */
739 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
741 GlobalFree(This->supportHandle);
742 This->supportHandle=0;
743 HeapFree(GetProcessHeap(), 0, This);
746 static ULONG WINAPI NoStatStreamImpl_AddRef(
749 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
750 return InterlockedIncrement(&This->ref);
753 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
755 REFIID riid, /* [in] */
756 void** ppvObject) /* [iid_is][out] */
758 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
759 if (ppvObject==0) return E_INVALIDARG;
761 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
765 else if (memcmp(&IID_IStream, riid, sizeof(IID_IStream)) == 0)
771 return E_NOINTERFACE;
772 NoStatStreamImpl_AddRef(iface);
776 static ULONG WINAPI NoStatStreamImpl_Release(
779 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
780 ULONG newRef = InterlockedDecrement(&This->ref);
782 NoStatStreamImpl_Destroy(This);
786 static HRESULT WINAPI NoStatStreamImpl_Read(
788 void* pv, /* [length_is][size_is][out] */
790 ULONG* pcbRead) /* [out] */
792 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
794 ULONG bytesReadBuffer;
795 ULONG bytesToReadFromBuffer;
798 pcbRead = &bytesReadBuffer;
799 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
800 supportBuffer = GlobalLock(This->supportHandle);
801 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
802 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
803 *pcbRead = bytesToReadFromBuffer;
804 GlobalUnlock(This->supportHandle);
810 static HRESULT WINAPI NoStatStreamImpl_Write(
812 const void* pv, /* [size_is][in] */
814 ULONG* pcbWritten) /* [out] */
816 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
818 ULARGE_INTEGER newSize;
819 ULONG bytesWritten = 0;
822 pcbWritten = &bytesWritten;
825 newSize.u.HighPart = 0;
826 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
827 if (newSize.u.LowPart > This->streamSize.u.LowPart)
828 IStream_SetSize(iface, newSize);
830 supportBuffer = GlobalLock(This->supportHandle);
831 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
832 This->currentPosition.u.LowPart+=cb;
834 GlobalUnlock(This->supportHandle);
838 static HRESULT WINAPI NoStatStreamImpl_Seek(
840 LARGE_INTEGER dlibMove, /* [in] */
841 DWORD dwOrigin, /* [in] */
842 ULARGE_INTEGER* plibNewPosition) /* [out] */
844 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
845 ULARGE_INTEGER newPosition;
848 case STREAM_SEEK_SET:
849 newPosition.u.HighPart = 0;
850 newPosition.u.LowPart = 0;
852 case STREAM_SEEK_CUR:
853 newPosition = This->currentPosition;
855 case STREAM_SEEK_END:
856 newPosition = This->streamSize;
859 return STG_E_INVALIDFUNCTION;
861 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
862 return STG_E_INVALIDFUNCTION;
863 newPosition.QuadPart += dlibMove.QuadPart;
864 if (plibNewPosition) *plibNewPosition = newPosition;
865 This->currentPosition = newPosition;
869 static HRESULT WINAPI NoStatStreamImpl_SetSize(
871 ULARGE_INTEGER libNewSize) /* [in] */
873 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
874 HGLOBAL supportHandle;
875 if (libNewSize.u.HighPart != 0)
876 return STG_E_INVALIDFUNCTION;
877 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
879 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
880 if (supportHandle == 0)
881 return STG_E_MEDIUMFULL;
882 This->supportHandle = supportHandle;
883 This->streamSize.u.LowPart = libNewSize.u.LowPart;
887 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
889 IStream* pstm, /* [unique][in] */
890 ULARGE_INTEGER cb, /* [in] */
891 ULARGE_INTEGER* pcbRead, /* [out] */
892 ULARGE_INTEGER* pcbWritten) /* [out] */
896 ULONG bytesRead, bytesWritten, copySize;
897 ULARGE_INTEGER totalBytesRead;
898 ULARGE_INTEGER totalBytesWritten;
901 return STG_E_INVALIDPOINTER;
902 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
903 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
905 while ( cb.u.LowPart > 0 )
907 if ( cb.u.LowPart >= 128 )
910 copySize = cb.u.LowPart;
911 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
912 totalBytesRead.u.LowPart += bytesRead;
913 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
914 totalBytesWritten.u.LowPart += bytesWritten;
915 if (bytesRead != bytesWritten)
917 hr = STG_E_MEDIUMFULL;
920 if (bytesRead!=copySize)
923 cb.u.LowPart -= bytesRead;
927 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
928 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
933 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
934 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
939 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
943 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
945 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
947 ULARGE_INTEGER libOffset, /* [in] */
948 ULARGE_INTEGER cb, /* [in] */
949 DWORD dwLockType) /* [in] */
954 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
956 ULARGE_INTEGER libOffset, /* [in] */
957 ULARGE_INTEGER cb, /* [in] */
958 DWORD dwLockType) /* [in] */
963 static HRESULT WINAPI NoStatStreamImpl_Stat(
965 STATSTG* pstatstg, /* [out] */
966 DWORD grfStatFlag) /* [in] */
971 static HRESULT WINAPI NoStatStreamImpl_Clone(
973 IStream** ppstm) /* [out] */
977 static const IStreamVtbl NoStatStreamImpl_Vtbl;
980 Build an object that implements IStream, without IStream_Stat capabilities.
981 Receives a memory handle with data buffer. If memory handle is non-null,
982 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
983 In any case the object takes ownership of memory handle and will free it on
986 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal)
988 NoStatStreamImpl* newStream;
990 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
993 newStream->lpVtbl = &NoStatStreamImpl_Vtbl;
995 newStream->supportHandle = hGlobal;
997 if (!newStream->supportHandle)
998 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
1000 newStream->currentPosition.u.HighPart = 0;
1001 newStream->currentPosition.u.LowPart = 0;
1002 newStream->streamSize.u.HighPart = 0;
1003 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
1009 static const IStreamVtbl NoStatStreamImpl_Vtbl =
1011 NoStatStreamImpl_QueryInterface,
1012 NoStatStreamImpl_AddRef,
1013 NoStatStreamImpl_Release,
1014 NoStatStreamImpl_Read,
1015 NoStatStreamImpl_Write,
1016 NoStatStreamImpl_Seek,
1017 NoStatStreamImpl_SetSize,
1018 NoStatStreamImpl_CopyTo,
1019 NoStatStreamImpl_Commit,
1020 NoStatStreamImpl_Revert,
1021 NoStatStreamImpl_LockRegion,
1022 NoStatStreamImpl_UnlockRegion,
1023 NoStatStreamImpl_Stat,
1024 NoStatStreamImpl_Clone