Release 0.9.39.
[wine/gsoc-2012-control.git] / dlls / oleaut32 / tests / olepicture.c
blob00027dedddd0c7fe7ce899ac86c708979dd1ec4d
1 /*
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
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <math.h>
25 #include <float.h>
26 #include <time.h>
28 #define COBJMACROS
30 #include <wine/test.h>
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winuser.h>
34 #include <wingdi.h>
35 #include <winnls.h>
36 #include <winerror.h>
37 #include <winnt.h>
39 #include <wtypes.h>
40 #include <olectl.h>
41 #include <objidl.h>
43 static HMODULE hOleaut32;
45 static HRESULT (WINAPI *pOleLoadPicture)(LPSTREAM,LONG,BOOL,REFIID,LPVOID*);
46 static HRESULT (WINAPI *pOleCreatePictureIndirect)(PICTDESC*,REFIID,BOOL,LPVOID*);
48 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
50 /* 1x1 pixel gif */
51 static const unsigned char gifimage[35] = {
52 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
53 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
54 0x01,0x00,0x3b
57 /* 1x1 pixel jpg */
58 static const unsigned char jpgimage[285] = {
59 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
60 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
61 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
62 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
63 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
64 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
65 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
66 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
67 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
68 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
69 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
70 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
71 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
72 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
73 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
74 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
75 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
76 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
79 /* 1x1 pixel png */
80 static const unsigned char pngimage[285] = {
81 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
82 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
83 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
84 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
85 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
86 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
87 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
90 /* 1x1 pixel bmp */
91 static const unsigned char bmpimage[66] = {
92 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
93 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
94 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
95 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
96 0x00,0x00
99 /* 2x2 pixel gif */
100 static const unsigned char gif4pixel[42] = {
101 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
102 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
103 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
106 struct NoStatStreamImpl
108 const IStreamVtbl *lpVtbl;
109 LONG ref;
111 HGLOBAL supportHandle;
112 ULARGE_INTEGER streamSize;
113 ULARGE_INTEGER currentPosition;
115 typedef struct NoStatStreamImpl NoStatStreamImpl;
116 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal);
118 static void
119 test_pic_with_stream(LPSTREAM stream, unsigned int imgsize)
121 IPicture* pic = NULL;
122 HRESULT hres;
123 LPVOID pvObj = NULL;
124 OLE_HANDLE handle, hPal;
125 OLE_XSIZE_HIMETRIC width;
126 OLE_YSIZE_HIMETRIC height;
127 short type;
128 DWORD attr;
129 ULONG res;
131 pvObj = NULL;
132 hres = pOleLoadPicture(stream, imgsize, TRUE, &IID_IPicture, &pvObj);
133 pic = pvObj;
135 ok(hres == S_OK,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres);
136 ok(pic != NULL,"OLP (NULL,..) returns NULL, instead of !NULL\n");
137 if (pic == NULL)
138 return;
140 pvObj = NULL;
141 hres = IPicture_QueryInterface (pic, &IID_IPicture, &pvObj);
143 ok(hres == S_OK,"IPicture_QI does not return S_OK, but 0x%08x\n", hres);
144 ok(pvObj != NULL,"IPicture_QI does return NULL, instead of a ptr\n");
146 IPicture_Release ((IPicture*)pvObj);
148 handle = 0;
149 hres = IPicture_get_Handle (pic, &handle);
150 ok(hres == S_OK,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres);
151 ok(handle != 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
153 width = 0;
154 hres = IPicture_get_Width (pic, &width);
155 ok(hres == S_OK,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres);
156 ok(width != 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
158 height = 0;
159 hres = IPicture_get_Height (pic, &height);
160 ok(hres == S_OK,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres);
161 ok(height != 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
163 type = 0;
164 hres = IPicture_get_Type (pic, &type);
165 ok(hres == S_OK,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
166 ok(type == PICTYPE_BITMAP, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type, PICTYPE_BITMAP);
168 attr = 0;
169 hres = IPicture_get_Attributes (pic, &attr);
170 ok(hres == S_OK,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres);
171 ok(attr == 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr);
173 hPal = 0;
174 hres = IPicture_get_hPal (pic, &hPal);
175 ok(hres == S_OK,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres);
176 /* a single pixel b/w image has no palette */
177 ok(hPal == 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal);
179 res = IPicture_Release (pic);
180 ok (res == 0, "refcount after release is %d, but should be 0?\n", res);
183 static void
184 test_pic(const unsigned char *imgdata, unsigned int imgsize)
186 LPSTREAM stream;
187 HGLOBAL hglob;
188 LPBYTE data;
189 HRESULT hres;
190 LARGE_INTEGER seekto;
191 ULARGE_INTEGER newpos1;
192 DWORD * header;
193 unsigned int i,j;
195 /* Let the fun begin */
196 hglob = GlobalAlloc (0, imgsize);
197 data = GlobalLock (hglob);
198 memcpy(data, imgdata, imgsize);
199 GlobalUnlock(hglob); data = NULL;
201 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
202 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
204 memset(&seekto,0,sizeof(seekto));
205 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
206 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
207 test_pic_with_stream(stream, imgsize);
209 IStream_Release(stream);
211 /* again with Non Statable and Non Seekable stream */
212 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
213 hglob = 0; /* Non-statable impl always deletes on release */
214 test_pic_with_stream(stream, 0);
216 IStream_Release(stream);
217 for (i = 1; i <= 8; i++) {
218 /* more fun!!! */
219 hglob = GlobalAlloc (0, imgsize + i * (2 * sizeof(DWORD)));
220 data = GlobalLock (hglob);
221 header = (DWORD *)data;
223 /* multiple copies of header */
224 memcpy(data,"lt\0\0",4);
225 header[1] = imgsize;
226 for (j = 2; j <= i; j++) {
227 memcpy(&(header[2 * (j - 1)]), header, 2 * sizeof(DWORD));
229 memcpy(data + i * (2 * sizeof(DWORD)), imgdata, imgsize);
230 GlobalUnlock(hglob); data = NULL;
232 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
233 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
235 memset(&seekto,0,sizeof(seekto));
236 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
237 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
238 test_pic_with_stream(stream, imgsize);
240 IStream_Release(stream);
242 /* again with Non Statable and Non Seekable stream */
243 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
244 hglob = 0; /* Non-statable impl always deletes on release */
245 test_pic_with_stream(stream, 0);
247 IStream_Release(stream);
251 static void test_empty_image(void) {
252 LPBYTE data;
253 LPSTREAM stream;
254 IPicture* pic = NULL;
255 HRESULT hres;
256 LPVOID pvObj = NULL;
257 HGLOBAL hglob;
258 OLE_HANDLE handle;
259 ULARGE_INTEGER newpos1;
260 LARGE_INTEGER seekto;
261 short type;
263 /* Empty image. Happens occasionally in VB programs. */
264 hglob = GlobalAlloc (0, 8);
265 data = GlobalLock (hglob);
266 memcpy(data,"lt\0\0",4);
267 ((DWORD*)data)[1] = 0;
268 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
269 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
271 memset(&seekto,0,sizeof(seekto));
272 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
273 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
275 pvObj = NULL;
276 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
277 pic = pvObj;
278 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
279 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
281 hres = IPicture_get_Type (pic, &type);
282 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
283 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
285 hres = IPicture_get_Handle (pic, &handle);
286 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
287 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
288 IPicture_Release (pic);
291 static void test_empty_image_2(void) {
292 LPBYTE data;
293 LPSTREAM stream;
294 IPicture* pic = NULL;
295 HRESULT hres;
296 LPVOID pvObj = NULL;
297 HGLOBAL hglob;
298 ULARGE_INTEGER newpos1;
299 LARGE_INTEGER seekto;
300 short type;
302 /* Empty image at random stream position. */
303 hglob = GlobalAlloc (0, 200);
304 data = GlobalLock (hglob);
305 data += 42;
306 memcpy(data,"lt\0\0",4);
307 ((DWORD*)data)[1] = 0;
308 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
309 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
311 memset(&seekto,0,sizeof(seekto));
312 seekto.u.LowPart = 42;
313 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
314 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
316 pvObj = NULL;
317 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
318 pic = pvObj;
319 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
320 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
322 hres = IPicture_get_Type (pic, &type);
323 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
324 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
326 IPicture_Release (pic);
329 static void test_Invoke(void)
331 IPictureDisp *picdisp;
332 HRESULT hr;
333 VARIANTARG vararg;
334 DISPPARAMS dispparams;
335 VARIANT varresult;
336 IStream *stream;
337 HGLOBAL hglob;
338 void *data;
340 hglob = GlobalAlloc (0, sizeof(gifimage));
341 data = GlobalLock(hglob);
342 memcpy(data, gifimage, sizeof(gifimage));
343 GlobalUnlock(hglob);
345 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
346 ok_ole_success(hr, "CreateStreamOnHGlobal");
348 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
349 IStream_Release(stream);
350 ok_ole_success(hr, "OleLoadPicture");
352 V_VT(&vararg) = VT_BOOL;
353 V_BOOL(&vararg) = VARIANT_FALSE;
354 dispparams.cNamedArgs = 0;
355 dispparams.rgdispidNamedArgs = NULL;
356 dispparams.cArgs = 1;
357 dispparams.rgvarg = &vararg;
358 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
359 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
360 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
361 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
363 dispparams.cArgs = 0;
364 dispparams.rgvarg = NULL;
365 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
366 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
368 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
369 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
371 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
372 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
374 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
375 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
377 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
378 ok_ole_success(hr, "IPictureDisp_Invoke");
379 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
381 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
382 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
384 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
385 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
387 dispparams.cArgs = 1;
388 dispparams.rgvarg = &vararg;
389 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
390 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
392 dispparams.cArgs = 1;
393 dispparams.rgvarg = &vararg;
394 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
395 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
397 IPictureDisp_Release(picdisp);
400 static void test_OleCreatePictureIndirect(void)
402 IPicture *pict;
403 HRESULT hr;
404 short type;
405 OLE_HANDLE handle;
407 if(!pOleCreatePictureIndirect)
409 skip("Skipping OleCreatePictureIndirect tests\n");
410 return;
413 hr = pOleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict);
414 ok(hr == S_OK, "hr %08x\n", hr);
416 hr = IPicture_get_Type(pict, &type);
417 ok(hr == S_OK, "hr %08x\n", hr);
418 ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type);
420 hr = IPicture_get_Handle(pict, &handle);
421 ok(hr == S_OK, "hr %08x\n", hr);
422 ok(handle == 0, "handle %08x\n", handle);
424 IPicture_Release(pict);
427 START_TEST(olepicture)
429 hOleaut32 = LoadLibraryA("oleaut32.dll");
430 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
431 pOleCreatePictureIndirect = (void*)GetProcAddress(hOleaut32, "OleCreatePictureIndirect");
432 if (!pOleLoadPicture)
433 return;
435 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
436 test_pic(gifimage, sizeof(gifimage));
437 test_pic(jpgimage, sizeof(jpgimage));
438 test_pic(bmpimage, sizeof(bmpimage));
439 test_pic(gif4pixel, sizeof(gif4pixel));
440 /* FIXME: No PNG support yet in Wine or in older Windows... */
441 if (0) test_pic(pngimage, sizeof(pngimage));
442 test_empty_image();
443 test_empty_image_2();
445 test_Invoke();
446 test_OleCreatePictureIndirect();
450 /* Helper functions only ... */
453 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
455 GlobalFree(This->supportHandle);
456 This->supportHandle=0;
457 HeapFree(GetProcessHeap(), 0, This);
460 static ULONG WINAPI NoStatStreamImpl_AddRef(
461 IStream* iface)
463 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
464 return InterlockedIncrement(&This->ref);
467 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
468 IStream* iface,
469 REFIID riid, /* [in] */
470 void** ppvObject) /* [iid_is][out] */
472 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
473 if (ppvObject==0) return E_INVALIDARG;
474 *ppvObject = 0;
475 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
477 *ppvObject = (IStream*)This;
479 else if (memcmp(&IID_IStream, riid, sizeof(IID_IStream)) == 0)
481 *ppvObject = (IStream*)This;
484 if ((*ppvObject)==0)
485 return E_NOINTERFACE;
486 NoStatStreamImpl_AddRef(iface);
487 return S_OK;
490 static ULONG WINAPI NoStatStreamImpl_Release(
491 IStream* iface)
493 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
494 ULONG newRef = InterlockedDecrement(&This->ref);
495 if (newRef==0)
496 NoStatStreamImpl_Destroy(This);
497 return newRef;
500 static HRESULT WINAPI NoStatStreamImpl_Read(
501 IStream* iface,
502 void* pv, /* [length_is][size_is][out] */
503 ULONG cb, /* [in] */
504 ULONG* pcbRead) /* [out] */
506 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
507 void* supportBuffer;
508 ULONG bytesReadBuffer;
509 ULONG bytesToReadFromBuffer;
511 if (pcbRead==0)
512 pcbRead = &bytesReadBuffer;
513 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
514 supportBuffer = GlobalLock(This->supportHandle);
515 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
516 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
517 *pcbRead = bytesToReadFromBuffer;
518 GlobalUnlock(This->supportHandle);
519 if(*pcbRead == cb)
520 return S_OK;
521 return S_FALSE;
524 static HRESULT WINAPI NoStatStreamImpl_Write(
525 IStream* iface,
526 const void* pv, /* [size_is][in] */
527 ULONG cb, /* [in] */
528 ULONG* pcbWritten) /* [out] */
530 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
531 void* supportBuffer;
532 ULARGE_INTEGER newSize;
533 ULONG bytesWritten = 0;
535 if (pcbWritten == 0)
536 pcbWritten = &bytesWritten;
537 if (cb == 0)
538 return S_OK;
539 newSize.u.HighPart = 0;
540 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
541 if (newSize.u.LowPart > This->streamSize.u.LowPart)
542 IStream_SetSize(iface, newSize);
544 supportBuffer = GlobalLock(This->supportHandle);
545 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
546 This->currentPosition.u.LowPart+=cb;
547 *pcbWritten = cb;
548 GlobalUnlock(This->supportHandle);
549 return S_OK;
552 static HRESULT WINAPI NoStatStreamImpl_Seek(
553 IStream* iface,
554 LARGE_INTEGER dlibMove, /* [in] */
555 DWORD dwOrigin, /* [in] */
556 ULARGE_INTEGER* plibNewPosition) /* [out] */
558 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
559 ULARGE_INTEGER newPosition;
560 switch (dwOrigin)
562 case STREAM_SEEK_SET:
563 newPosition.u.HighPart = 0;
564 newPosition.u.LowPart = 0;
565 break;
566 case STREAM_SEEK_CUR:
567 newPosition = This->currentPosition;
568 break;
569 case STREAM_SEEK_END:
570 newPosition = This->streamSize;
571 break;
572 default:
573 return STG_E_INVALIDFUNCTION;
575 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
576 return STG_E_INVALIDFUNCTION;
577 newPosition.QuadPart += dlibMove.QuadPart;
578 if (plibNewPosition) *plibNewPosition = newPosition;
579 This->currentPosition = newPosition;
580 return S_OK;
583 static HRESULT WINAPI NoStatStreamImpl_SetSize(
584 IStream* iface,
585 ULARGE_INTEGER libNewSize) /* [in] */
587 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
588 HGLOBAL supportHandle;
589 if (libNewSize.u.HighPart != 0)
590 return STG_E_INVALIDFUNCTION;
591 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
592 return S_OK;
593 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
594 if (supportHandle == 0)
595 return STG_E_MEDIUMFULL;
596 This->supportHandle = supportHandle;
597 This->streamSize.u.LowPart = libNewSize.u.LowPart;
598 return S_OK;
601 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
602 IStream* iface,
603 IStream* pstm, /* [unique][in] */
604 ULARGE_INTEGER cb, /* [in] */
605 ULARGE_INTEGER* pcbRead, /* [out] */
606 ULARGE_INTEGER* pcbWritten) /* [out] */
608 HRESULT hr = S_OK;
609 BYTE tmpBuffer[128];
610 ULONG bytesRead, bytesWritten, copySize;
611 ULARGE_INTEGER totalBytesRead;
612 ULARGE_INTEGER totalBytesWritten;
614 if ( pstm == 0 )
615 return STG_E_INVALIDPOINTER;
616 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
617 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
619 while ( cb.u.LowPart > 0 )
621 if ( cb.u.LowPart >= 128 )
622 copySize = 128;
623 else
624 copySize = cb.u.LowPart;
625 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
626 totalBytesRead.u.LowPart += bytesRead;
627 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
628 totalBytesWritten.u.LowPart += bytesWritten;
629 if (bytesRead != bytesWritten)
631 hr = STG_E_MEDIUMFULL;
632 break;
634 if (bytesRead!=copySize)
635 cb.u.LowPart = 0;
636 else
637 cb.u.LowPart -= bytesRead;
639 if (pcbRead)
641 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
642 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
645 if (pcbWritten)
647 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
648 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
650 return hr;
653 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
655 return S_OK;
657 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
659 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
660 IStream* iface,
661 ULARGE_INTEGER libOffset, /* [in] */
662 ULARGE_INTEGER cb, /* [in] */
663 DWORD dwLockType) /* [in] */
665 return S_OK;
668 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
669 IStream* iface,
670 ULARGE_INTEGER libOffset, /* [in] */
671 ULARGE_INTEGER cb, /* [in] */
672 DWORD dwLockType) /* [in] */
674 return S_OK;
677 static HRESULT WINAPI NoStatStreamImpl_Stat(
678 IStream* iface,
679 STATSTG* pstatstg, /* [out] */
680 DWORD grfStatFlag) /* [in] */
682 return E_NOTIMPL;
685 static HRESULT WINAPI NoStatStreamImpl_Clone(
686 IStream* iface,
687 IStream** ppstm) /* [out] */
689 return E_NOTIMPL;
691 static const IStreamVtbl NoStatStreamImpl_Vtbl;
694 Build an object that implements IStream, without IStream_Stat capabilities.
695 Receives a memory handle with data buffer. If memory handle is non-null,
696 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
697 In any case the object takes ownership of memory handle and will free it on
698 object release.
700 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal)
702 NoStatStreamImpl* newStream;
704 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
705 if (newStream!=0)
707 newStream->lpVtbl = &NoStatStreamImpl_Vtbl;
708 newStream->ref = 1;
709 newStream->supportHandle = hGlobal;
711 if (!newStream->supportHandle)
712 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
713 GMEM_SHARE, 0);
714 newStream->currentPosition.u.HighPart = 0;
715 newStream->currentPosition.u.LowPart = 0;
716 newStream->streamSize.u.HighPart = 0;
717 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
719 return newStream;
723 static const IStreamVtbl NoStatStreamImpl_Vtbl =
725 NoStatStreamImpl_QueryInterface,
726 NoStatStreamImpl_AddRef,
727 NoStatStreamImpl_Release,
728 NoStatStreamImpl_Read,
729 NoStatStreamImpl_Write,
730 NoStatStreamImpl_Seek,
731 NoStatStreamImpl_SetSize,
732 NoStatStreamImpl_CopyTo,
733 NoStatStreamImpl_Commit,
734 NoStatStreamImpl_Revert,
735 NoStatStreamImpl_LockRegion,
736 NoStatStreamImpl_UnlockRegion,
737 NoStatStreamImpl_Stat,
738 NoStatStreamImpl_Clone