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 struct NoStatStreamImpl
126 const IStreamVtbl *lpVtbl;
129 HGLOBAL supportHandle;
130 ULARGE_INTEGER streamSize;
131 ULARGE_INTEGER currentPosition;
133 typedef struct NoStatStreamImpl NoStatStreamImpl;
134 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal);
137 test_pic_with_stream(LPSTREAM stream, unsigned int imgsize)
139 IPicture* pic = NULL;
142 OLE_HANDLE handle, hPal;
143 OLE_XSIZE_HIMETRIC width;
144 OLE_YSIZE_HIMETRIC height;
150 hres = pOleLoadPicture(stream, imgsize, TRUE, &IID_IPicture, &pvObj);
153 ok(hres == S_OK,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres);
154 ok(pic != NULL,"OLP (NULL,..) returns NULL, instead of !NULL\n");
159 hres = IPicture_QueryInterface (pic, &IID_IPicture, &pvObj);
161 ok(hres == S_OK,"IPicture_QI does not return S_OK, but 0x%08x\n", hres);
162 ok(pvObj != NULL,"IPicture_QI does return NULL, instead of a ptr\n");
164 IPicture_Release ((IPicture*)pvObj);
167 hres = IPicture_get_Handle (pic, &handle);
168 ok(hres == S_OK,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres);
169 ok(handle != 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
172 hres = IPicture_get_Width (pic, &width);
173 ok(hres == S_OK,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres);
174 ok(width != 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
177 hres = IPicture_get_Height (pic, &height);
178 ok(hres == S_OK,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres);
179 ok(height != 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
182 hres = IPicture_get_Type (pic, &type);
183 ok(hres == S_OK,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
184 ok(type == PICTYPE_BITMAP, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type, PICTYPE_BITMAP);
187 hres = IPicture_get_Attributes (pic, &attr);
188 ok(hres == S_OK,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres);
189 ok(attr == 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr);
192 hres = IPicture_get_hPal (pic, &hPal);
193 ok(hres == S_OK,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres);
194 /* a single pixel b/w image has no palette */
195 ok(hPal == 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal);
197 res = IPicture_Release (pic);
198 ok (res == 0, "refcount after release is %d, but should be 0?\n", res);
202 test_pic(const unsigned char *imgdata, unsigned int imgsize)
208 LARGE_INTEGER seekto;
209 ULARGE_INTEGER newpos1;
213 /* Let the fun begin */
214 hglob = GlobalAlloc (0, imgsize);
215 data = GlobalLock (hglob);
216 memcpy(data, imgdata, imgsize);
217 GlobalUnlock(hglob); data = NULL;
219 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
220 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
222 memset(&seekto,0,sizeof(seekto));
223 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
224 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
225 test_pic_with_stream(stream, imgsize);
227 IStream_Release(stream);
229 /* again with Non Statable and Non Seekable stream */
230 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
231 hglob = 0; /* Non-statable impl always deletes on release */
232 test_pic_with_stream(stream, 0);
234 IStream_Release(stream);
235 for (i = 1; i <= 8; i++) {
237 hglob = GlobalAlloc (0, imgsize + i * (2 * sizeof(DWORD)));
238 data = GlobalLock (hglob);
239 header = (DWORD *)data;
241 /* multiple copies of header */
242 memcpy(data,"lt\0\0",4);
244 for (j = 2; j <= i; j++) {
245 memcpy(&(header[2 * (j - 1)]), header, 2 * sizeof(DWORD));
247 memcpy(data + i * (2 * sizeof(DWORD)), imgdata, imgsize);
248 GlobalUnlock(hglob); data = NULL;
250 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
251 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
253 memset(&seekto,0,sizeof(seekto));
254 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
255 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
256 test_pic_with_stream(stream, imgsize);
258 IStream_Release(stream);
260 /* again with Non Statable and Non Seekable stream */
261 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
262 hglob = 0; /* Non-statable impl always deletes on release */
263 test_pic_with_stream(stream, 0);
265 IStream_Release(stream);
269 static void test_empty_image(void) {
272 IPicture* pic = NULL;
277 ULARGE_INTEGER newpos1;
278 LARGE_INTEGER seekto;
281 /* Empty image. Happens occasionally in VB programs. */
282 hglob = GlobalAlloc (0, 8);
283 data = GlobalLock (hglob);
284 memcpy(data,"lt\0\0",4);
285 ((DWORD*)data)[1] = 0;
286 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
287 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
289 memset(&seekto,0,sizeof(seekto));
290 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
291 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
294 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
296 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
297 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
299 hres = IPicture_get_Type (pic, &type);
300 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
301 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
303 hres = IPicture_get_Handle (pic, &handle);
304 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
305 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
306 IPicture_Release (pic);
309 static void test_empty_image_2(void) {
312 IPicture* pic = NULL;
316 ULARGE_INTEGER newpos1;
317 LARGE_INTEGER seekto;
320 /* Empty image at random stream position. */
321 hglob = GlobalAlloc (0, 200);
322 data = GlobalLock (hglob);
324 memcpy(data,"lt\0\0",4);
325 ((DWORD*)data)[1] = 0;
326 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
327 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
329 memset(&seekto,0,sizeof(seekto));
330 seekto.u.LowPart = 42;
331 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
332 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
335 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
337 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
338 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
340 hres = IPicture_get_Type (pic, &type);
341 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
342 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
344 IPicture_Release (pic);
347 static void test_Invoke(void)
349 IPictureDisp *picdisp;
352 DISPPARAMS dispparams;
358 hglob = GlobalAlloc (0, sizeof(gifimage));
359 data = GlobalLock(hglob);
360 memcpy(data, gifimage, sizeof(gifimage));
363 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
364 ok_ole_success(hr, "CreateStreamOnHGlobal");
366 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
367 IStream_Release(stream);
368 ok_ole_success(hr, "OleLoadPicture");
370 V_VT(&vararg) = VT_BOOL;
371 V_BOOL(&vararg) = VARIANT_FALSE;
372 dispparams.cNamedArgs = 0;
373 dispparams.rgdispidNamedArgs = NULL;
374 dispparams.cArgs = 1;
375 dispparams.rgvarg = &vararg;
376 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
377 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
378 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
379 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
381 dispparams.cArgs = 0;
382 dispparams.rgvarg = NULL;
383 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
384 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
386 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
387 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
389 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
390 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
392 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
393 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
395 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
396 ok_ole_success(hr, "IPictureDisp_Invoke");
397 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
399 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
400 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
402 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
403 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
405 dispparams.cArgs = 1;
406 dispparams.rgvarg = &vararg;
407 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
408 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
410 dispparams.cArgs = 1;
411 dispparams.rgvarg = &vararg;
412 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
413 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
415 IPictureDisp_Release(picdisp);
418 static void test_OleCreatePictureIndirect(void)
425 if(!pOleCreatePictureIndirect)
427 skip("Skipping OleCreatePictureIndirect tests\n");
431 hr = pOleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict);
432 ok(hr == S_OK, "hr %08x\n", hr);
434 hr = IPicture_get_Type(pict, &type);
435 ok(hr == S_OK, "hr %08x\n", hr);
436 ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type);
438 hr = IPicture_get_Handle(pict, &handle);
439 ok(hr == S_OK, "hr %08x\n", hr);
440 ok(handle == 0, "handle %08x\n", handle);
442 IPicture_Release(pict);
445 static void test_apm()
456 hglob = GlobalAlloc (0, sizeof(apmdata));
457 data = GlobalLock(hglob);
458 memcpy(data, apmdata, sizeof(apmdata));
460 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
461 ole_check(OleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict));
463 ole_check(IPicture_get_Handle(pict, &handle));
464 ok(handle != 0, "handle is null\n");
466 ole_check(IPicture_get_Type(pict, &type));
467 expect_eq(type, PICTYPE_METAFILE, short, "%d");
469 ole_check(IPicture_get_Height(pict, &cxy));
470 expect_eq(cxy, 1667, LONG, "%d");
472 ole_check(IPicture_get_Width(pict, &cxy));
473 expect_eq(cxy, 1323, LONG, "%d");
475 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
476 todo_wine expect_eq(keep, FALSE, LONG, "%d");
478 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL);
479 IPicture_Release(pict);
480 IStream_Release(stream);
483 START_TEST(olepicture)
485 hOleaut32 = GetModuleHandleA("oleaut32.dll");
486 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
487 pOleCreatePictureIndirect = (void*)GetProcAddress(hOleaut32, "OleCreatePictureIndirect");
488 if (!pOleLoadPicture)
490 skip("OleLoadPicture is not available\n");
494 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
495 test_pic(gifimage, sizeof(gifimage));
496 test_pic(jpgimage, sizeof(jpgimage));
497 test_pic(bmpimage, sizeof(bmpimage));
498 test_pic(gif4pixel, sizeof(gif4pixel));
499 /* FIXME: No PNG support yet in Wine or in older Windows... */
500 if (0) test_pic(pngimage, sizeof(pngimage));
502 test_empty_image_2();
506 test_OleCreatePictureIndirect();
510 /* Helper functions only ... */
513 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
515 GlobalFree(This->supportHandle);
516 This->supportHandle=0;
517 HeapFree(GetProcessHeap(), 0, This);
520 static ULONG WINAPI NoStatStreamImpl_AddRef(
523 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
524 return InterlockedIncrement(&This->ref);
527 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
529 REFIID riid, /* [in] */
530 void** ppvObject) /* [iid_is][out] */
532 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
533 if (ppvObject==0) return E_INVALIDARG;
535 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
537 *ppvObject = (IStream*)This;
539 else if (memcmp(&IID_IStream, riid, sizeof(IID_IStream)) == 0)
541 *ppvObject = (IStream*)This;
545 return E_NOINTERFACE;
546 NoStatStreamImpl_AddRef(iface);
550 static ULONG WINAPI NoStatStreamImpl_Release(
553 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
554 ULONG newRef = InterlockedDecrement(&This->ref);
556 NoStatStreamImpl_Destroy(This);
560 static HRESULT WINAPI NoStatStreamImpl_Read(
562 void* pv, /* [length_is][size_is][out] */
564 ULONG* pcbRead) /* [out] */
566 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
568 ULONG bytesReadBuffer;
569 ULONG bytesToReadFromBuffer;
572 pcbRead = &bytesReadBuffer;
573 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
574 supportBuffer = GlobalLock(This->supportHandle);
575 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
576 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
577 *pcbRead = bytesToReadFromBuffer;
578 GlobalUnlock(This->supportHandle);
584 static HRESULT WINAPI NoStatStreamImpl_Write(
586 const void* pv, /* [size_is][in] */
588 ULONG* pcbWritten) /* [out] */
590 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
592 ULARGE_INTEGER newSize;
593 ULONG bytesWritten = 0;
596 pcbWritten = &bytesWritten;
599 newSize.u.HighPart = 0;
600 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
601 if (newSize.u.LowPart > This->streamSize.u.LowPart)
602 IStream_SetSize(iface, newSize);
604 supportBuffer = GlobalLock(This->supportHandle);
605 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
606 This->currentPosition.u.LowPart+=cb;
608 GlobalUnlock(This->supportHandle);
612 static HRESULT WINAPI NoStatStreamImpl_Seek(
614 LARGE_INTEGER dlibMove, /* [in] */
615 DWORD dwOrigin, /* [in] */
616 ULARGE_INTEGER* plibNewPosition) /* [out] */
618 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
619 ULARGE_INTEGER newPosition;
622 case STREAM_SEEK_SET:
623 newPosition.u.HighPart = 0;
624 newPosition.u.LowPart = 0;
626 case STREAM_SEEK_CUR:
627 newPosition = This->currentPosition;
629 case STREAM_SEEK_END:
630 newPosition = This->streamSize;
633 return STG_E_INVALIDFUNCTION;
635 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
636 return STG_E_INVALIDFUNCTION;
637 newPosition.QuadPart += dlibMove.QuadPart;
638 if (plibNewPosition) *plibNewPosition = newPosition;
639 This->currentPosition = newPosition;
643 static HRESULT WINAPI NoStatStreamImpl_SetSize(
645 ULARGE_INTEGER libNewSize) /* [in] */
647 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
648 HGLOBAL supportHandle;
649 if (libNewSize.u.HighPart != 0)
650 return STG_E_INVALIDFUNCTION;
651 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
653 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
654 if (supportHandle == 0)
655 return STG_E_MEDIUMFULL;
656 This->supportHandle = supportHandle;
657 This->streamSize.u.LowPart = libNewSize.u.LowPart;
661 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
663 IStream* pstm, /* [unique][in] */
664 ULARGE_INTEGER cb, /* [in] */
665 ULARGE_INTEGER* pcbRead, /* [out] */
666 ULARGE_INTEGER* pcbWritten) /* [out] */
670 ULONG bytesRead, bytesWritten, copySize;
671 ULARGE_INTEGER totalBytesRead;
672 ULARGE_INTEGER totalBytesWritten;
675 return STG_E_INVALIDPOINTER;
676 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
677 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
679 while ( cb.u.LowPart > 0 )
681 if ( cb.u.LowPart >= 128 )
684 copySize = cb.u.LowPart;
685 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
686 totalBytesRead.u.LowPart += bytesRead;
687 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
688 totalBytesWritten.u.LowPart += bytesWritten;
689 if (bytesRead != bytesWritten)
691 hr = STG_E_MEDIUMFULL;
694 if (bytesRead!=copySize)
697 cb.u.LowPart -= bytesRead;
701 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
702 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
707 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
708 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
713 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
717 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
719 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
721 ULARGE_INTEGER libOffset, /* [in] */
722 ULARGE_INTEGER cb, /* [in] */
723 DWORD dwLockType) /* [in] */
728 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
730 ULARGE_INTEGER libOffset, /* [in] */
731 ULARGE_INTEGER cb, /* [in] */
732 DWORD dwLockType) /* [in] */
737 static HRESULT WINAPI NoStatStreamImpl_Stat(
739 STATSTG* pstatstg, /* [out] */
740 DWORD grfStatFlag) /* [in] */
745 static HRESULT WINAPI NoStatStreamImpl_Clone(
747 IStream** ppstm) /* [out] */
751 static const IStreamVtbl NoStatStreamImpl_Vtbl;
754 Build an object that implements IStream, without IStream_Stat capabilities.
755 Receives a memory handle with data buffer. If memory handle is non-null,
756 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
757 In any case the object takes ownership of memory handle and will free it on
760 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal)
762 NoStatStreamImpl* newStream;
764 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
767 newStream->lpVtbl = &NoStatStreamImpl_Vtbl;
769 newStream->supportHandle = hGlobal;
771 if (!newStream->supportHandle)
772 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
774 newStream->currentPosition.u.HighPart = 0;
775 newStream->currentPosition.u.LowPart = 0;
776 newStream->streamSize.u.HighPart = 0;
777 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
783 static const IStreamVtbl NoStatStreamImpl_Vtbl =
785 NoStatStreamImpl_QueryInterface,
786 NoStatStreamImpl_AddRef,
787 NoStatStreamImpl_Release,
788 NoStatStreamImpl_Read,
789 NoStatStreamImpl_Write,
790 NoStatStreamImpl_Seek,
791 NoStatStreamImpl_SetSize,
792 NoStatStreamImpl_CopyTo,
793 NoStatStreamImpl_Commit,
794 NoStatStreamImpl_Revert,
795 NoStatStreamImpl_LockRegion,
796 NoStatStreamImpl_UnlockRegion,
797 NoStatStreamImpl_Stat,
798 NoStatStreamImpl_Clone