push 337eb2e2d902d84a5d689451984c5832d7e04fc4
[wine/hacks.git] / dlls / oleaut32 / tests / olepicture.c
blobf81c419b1e6473e6a86385f0965263e928d7ef69
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>
27 #define COBJMACROS
29 #include "wine/test.h"
30 #include <windef.h>
31 #include <winbase.h>
32 #include <winuser.h>
33 #include <wingdi.h>
34 #include <winnls.h>
35 #include <winerror.h>
36 #include <winnt.h>
38 #include <wtypes.h>
39 #include <olectl.h>
40 #include <objidl.h>
42 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
44 #define ole_expect(expr, expect) { \
45 HRESULT r = expr; \
46 ok(r == (expect), #expr " returned %x, expected %s (%x)\n", r, #expect, expect); \
49 #define ole_check(expr) ole_expect(expr, S_OK);
51 static HMODULE hOleaut32;
53 static HRESULT (WINAPI *pOleLoadPicture)(LPSTREAM,LONG,BOOL,REFIID,LPVOID*);
54 static HRESULT (WINAPI *pOleCreatePictureIndirect)(PICTDESC*,REFIID,BOOL,LPVOID*);
56 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
58 /* 1x1 pixel gif */
59 static const unsigned char gifimage[35] = {
60 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
61 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
62 0x01,0x00,0x3b
65 /* 1x1 pixel jpg */
66 static const unsigned char jpgimage[285] = {
67 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
68 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
69 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
70 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
71 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
72 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
73 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
74 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
75 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
76 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
77 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
78 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
79 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
80 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
81 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
82 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
83 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
84 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
87 /* 1x1 pixel png */
88 static const unsigned char pngimage[285] = {
89 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
90 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
91 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
92 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
93 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
94 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
95 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
98 /* 1x1 pixel bmp */
99 static const unsigned char bmpimage[66] = {
100 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
101 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
102 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
103 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
104 0x00,0x00
107 /* 2x2 pixel gif */
108 static const unsigned char gif4pixel[42] = {
109 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
110 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
111 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
114 /* APM with an empty metafile with some padding zeros - looks like under Window the
115 * metafile data should be at least 20 bytes */
116 static const unsigned char apmdata[] = {
117 0xd7,0xcd,0xc6,0x9a, 0x00,0x00,0x00,0x00, 0x00,0x00,0xee,0x02, 0xb1,0x03,0xa0,0x05,
118 0x00,0x00,0x00,0x00, 0xee,0x53,0x01,0x00, 0x09,0x00,0x00,0x03, 0x13,0x00,0x00,0x00,
119 0x01,0x00,0x05,0x00, 0x00,0x00,0x00,0x00, 0x03,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
120 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
123 /* MF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
124 static const unsigned char metafile[] = {
125 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
126 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
127 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
128 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
129 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
130 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
131 0x00, 0x00
134 /* EMF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
135 static const unsigned char enhmetafile[] = {
136 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
141 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
142 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
143 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
146 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
149 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
150 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
151 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
153 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
155 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
156 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
159 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
160 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
161 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
162 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
163 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
164 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
166 0x14, 0x00, 0x00, 0x00
170 struct NoStatStreamImpl
172 const IStreamVtbl *lpVtbl;
173 LONG ref;
175 HGLOBAL supportHandle;
176 ULARGE_INTEGER streamSize;
177 ULARGE_INTEGER currentPosition;
179 typedef struct NoStatStreamImpl NoStatStreamImpl;
180 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal);
182 static void
183 test_pic_with_stream(LPSTREAM stream, unsigned int imgsize)
185 IPicture* pic = NULL;
186 HRESULT hres;
187 LPVOID pvObj = NULL;
188 OLE_HANDLE handle, hPal;
189 OLE_XSIZE_HIMETRIC width;
190 OLE_YSIZE_HIMETRIC height;
191 short type;
192 DWORD attr;
193 ULONG res;
195 pvObj = NULL;
196 hres = pOleLoadPicture(stream, imgsize, TRUE, &IID_IPicture, &pvObj);
197 pic = pvObj;
199 ok(hres == S_OK,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres);
200 ok(pic != NULL,"OLP (NULL,..) returns NULL, instead of !NULL\n");
201 if (pic == NULL)
202 return;
204 pvObj = NULL;
205 hres = IPicture_QueryInterface (pic, &IID_IPicture, &pvObj);
207 ok(hres == S_OK,"IPicture_QI does not return S_OK, but 0x%08x\n", hres);
208 ok(pvObj != NULL,"IPicture_QI does return NULL, instead of a ptr\n");
210 IPicture_Release ((IPicture*)pvObj);
212 handle = 0;
213 hres = IPicture_get_Handle (pic, &handle);
214 ok(hres == S_OK,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres);
215 ok(handle != 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
217 width = 0;
218 hres = IPicture_get_Width (pic, &width);
219 ok(hres == S_OK,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres);
220 ok(width != 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
222 height = 0;
223 hres = IPicture_get_Height (pic, &height);
224 ok(hres == S_OK,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres);
225 ok(height != 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
227 type = 0;
228 hres = IPicture_get_Type (pic, &type);
229 ok(hres == S_OK,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
230 ok(type == PICTYPE_BITMAP, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type, PICTYPE_BITMAP);
232 attr = 0;
233 hres = IPicture_get_Attributes (pic, &attr);
234 ok(hres == S_OK,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres);
235 ok(attr == 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr);
237 hPal = 0;
238 hres = IPicture_get_hPal (pic, &hPal);
239 ok(hres == S_OK,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres);
240 /* a single pixel b/w image has no palette */
241 ok(hPal == 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal);
243 res = IPicture_Release (pic);
244 ok (res == 0, "refcount after release is %d, but should be 0?\n", res);
247 static void
248 test_pic(const unsigned char *imgdata, unsigned int imgsize)
250 LPSTREAM stream;
251 HGLOBAL hglob;
252 LPBYTE data;
253 HRESULT hres;
254 LARGE_INTEGER seekto;
255 ULARGE_INTEGER newpos1;
256 DWORD * header;
257 unsigned int i,j;
259 /* Let the fun begin */
260 hglob = GlobalAlloc (0, imgsize);
261 data = GlobalLock (hglob);
262 memcpy(data, imgdata, imgsize);
263 GlobalUnlock(hglob); data = NULL;
265 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
266 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
268 memset(&seekto,0,sizeof(seekto));
269 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
270 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
271 test_pic_with_stream(stream, imgsize);
273 IStream_Release(stream);
275 /* again with Non Statable and Non Seekable stream */
276 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
277 hglob = 0; /* Non-statable impl always deletes on release */
278 test_pic_with_stream(stream, 0);
280 IStream_Release(stream);
281 for (i = 1; i <= 8; i++) {
282 /* more fun!!! */
283 hglob = GlobalAlloc (0, imgsize + i * (2 * sizeof(DWORD)));
284 data = GlobalLock (hglob);
285 header = (DWORD *)data;
287 /* multiple copies of header */
288 memcpy(data,"lt\0\0",4);
289 header[1] = imgsize;
290 for (j = 2; j <= i; j++) {
291 memcpy(&(header[2 * (j - 1)]), header, 2 * sizeof(DWORD));
293 memcpy(data + i * (2 * sizeof(DWORD)), imgdata, imgsize);
294 GlobalUnlock(hglob); data = NULL;
296 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
297 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
299 memset(&seekto,0,sizeof(seekto));
300 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
301 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
302 test_pic_with_stream(stream, imgsize);
304 IStream_Release(stream);
306 /* again with Non Statable and Non Seekable stream */
307 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
308 hglob = 0; /* Non-statable impl always deletes on release */
309 test_pic_with_stream(stream, 0);
311 IStream_Release(stream);
315 static void test_empty_image(void) {
316 LPBYTE data;
317 LPSTREAM stream;
318 IPicture* pic = NULL;
319 HRESULT hres;
320 LPVOID pvObj = NULL;
321 HGLOBAL hglob;
322 OLE_HANDLE handle;
323 ULARGE_INTEGER newpos1;
324 LARGE_INTEGER seekto;
325 short type;
327 /* Empty image. Happens occasionally in VB programs. */
328 hglob = GlobalAlloc (0, 8);
329 data = GlobalLock (hglob);
330 memcpy(data,"lt\0\0",4);
331 ((DWORD*)data)[1] = 0;
332 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
333 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
335 memset(&seekto,0,sizeof(seekto));
336 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
337 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
339 pvObj = NULL;
340 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
341 pic = pvObj;
342 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
343 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
345 hres = IPicture_get_Type (pic, &type);
346 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
347 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
349 hres = IPicture_get_Handle (pic, &handle);
350 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
351 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
352 IPicture_Release (pic);
355 static void test_empty_image_2(void) {
356 LPBYTE data;
357 LPSTREAM stream;
358 IPicture* pic = NULL;
359 HRESULT hres;
360 LPVOID pvObj = NULL;
361 HGLOBAL hglob;
362 ULARGE_INTEGER newpos1;
363 LARGE_INTEGER seekto;
364 short type;
366 /* Empty image at random stream position. */
367 hglob = GlobalAlloc (0, 200);
368 data = GlobalLock (hglob);
369 data += 42;
370 memcpy(data,"lt\0\0",4);
371 ((DWORD*)data)[1] = 0;
372 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
373 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
375 memset(&seekto,0,sizeof(seekto));
376 seekto.u.LowPart = 42;
377 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
378 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
380 pvObj = NULL;
381 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
382 pic = pvObj;
383 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
384 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
386 hres = IPicture_get_Type (pic, &type);
387 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
388 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
390 IPicture_Release (pic);
393 static void test_Invoke(void)
395 IPictureDisp *picdisp;
396 HRESULT hr;
397 VARIANTARG vararg;
398 DISPPARAMS dispparams;
399 VARIANT varresult;
400 IStream *stream;
401 HGLOBAL hglob;
402 void *data;
404 hglob = GlobalAlloc (0, sizeof(gifimage));
405 data = GlobalLock(hglob);
406 memcpy(data, gifimage, sizeof(gifimage));
407 GlobalUnlock(hglob);
409 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
410 ok_ole_success(hr, "CreateStreamOnHGlobal");
412 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
413 IStream_Release(stream);
414 ok_ole_success(hr, "OleLoadPicture");
416 V_VT(&vararg) = VT_BOOL;
417 V_BOOL(&vararg) = VARIANT_FALSE;
418 dispparams.cNamedArgs = 0;
419 dispparams.rgdispidNamedArgs = NULL;
420 dispparams.cArgs = 1;
421 dispparams.rgvarg = &vararg;
422 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
423 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
424 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
425 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
427 dispparams.cArgs = 0;
428 dispparams.rgvarg = NULL;
429 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
430 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
432 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
433 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
435 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
436 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
438 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
439 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
441 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
442 ok_ole_success(hr, "IPictureDisp_Invoke");
443 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
445 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
446 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
448 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
449 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
451 dispparams.cArgs = 1;
452 dispparams.rgvarg = &vararg;
453 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
454 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
456 dispparams.cArgs = 1;
457 dispparams.rgvarg = &vararg;
458 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
459 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
461 IPictureDisp_Release(picdisp);
464 static void test_OleCreatePictureIndirect(void)
466 IPicture *pict;
467 HRESULT hr;
468 short type;
469 OLE_HANDLE handle;
471 if(!pOleCreatePictureIndirect)
473 skip("Skipping OleCreatePictureIndirect tests\n");
474 return;
477 hr = pOleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict);
478 ok(hr == S_OK, "hr %08x\n", hr);
480 hr = IPicture_get_Type(pict, &type);
481 ok(hr == S_OK, "hr %08x\n", hr);
482 ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type);
484 hr = IPicture_get_Handle(pict, &handle);
485 ok(hr == S_OK, "hr %08x\n", hr);
486 ok(handle == 0, "handle %08x\n", handle);
488 IPicture_Release(pict);
491 static void test_apm()
493 OLE_HANDLE handle;
494 LPSTREAM stream;
495 IPicture *pict;
496 HGLOBAL hglob;
497 LPBYTE *data;
498 LONG cxy;
499 BOOL keep;
500 short type;
502 hglob = GlobalAlloc (0, sizeof(apmdata));
503 data = GlobalLock(hglob);
504 memcpy(data, apmdata, sizeof(apmdata));
506 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
507 ole_check(OleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict));
509 ole_check(IPicture_get_Handle(pict, &handle));
510 ok(handle != 0, "handle is null\n");
512 ole_check(IPicture_get_Type(pict, &type));
513 expect_eq(type, PICTYPE_METAFILE, short, "%d");
515 ole_check(IPicture_get_Height(pict, &cxy));
516 expect_eq(cxy, 1667, LONG, "%d");
518 ole_check(IPicture_get_Width(pict, &cxy));
519 expect_eq(cxy, 1323, LONG, "%d");
521 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
522 todo_wine expect_eq(keep, FALSE, LONG, "%d");
524 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL);
525 IPicture_Release(pict);
526 IStream_Release(stream);
527 GlobalUnlock(hglob);
528 GlobalFree(hglob);
531 static void test_metafile(void)
533 LPSTREAM stream;
534 IPicture *pict;
535 HGLOBAL hglob;
536 LPBYTE *data;
538 hglob = GlobalAlloc (0, sizeof(metafile));
539 data = GlobalLock(hglob);
540 memcpy(data, metafile, sizeof(metafile));
542 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
543 /* Windows does not load simple metafiles */
544 ole_expect(OleLoadPictureEx(stream, sizeof(metafile), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict), E_FAIL);
546 IStream_Release(stream);
547 GlobalUnlock(hglob);
548 GlobalFree(hglob);
551 static void test_enhmetafile(void)
553 OLE_HANDLE handle;
554 LPSTREAM stream;
555 IPicture *pict;
556 HGLOBAL hglob;
557 LPBYTE *data;
558 LONG cxy;
559 BOOL keep;
560 short type;
562 hglob = GlobalAlloc (0, sizeof(enhmetafile));
563 data = GlobalLock(hglob);
564 memcpy(data, enhmetafile, sizeof(enhmetafile));
566 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
567 ole_check(OleLoadPictureEx(stream, sizeof(enhmetafile), TRUE, &IID_IPicture, 10, 10, 0, (LPVOID *)&pict));
569 ole_check(IPicture_get_Handle(pict, &handle));
570 ok(handle != 0, "handle is null\n");
572 ole_check(IPicture_get_Type(pict, &type));
573 expect_eq(type, PICTYPE_ENHMETAFILE, short, "%d");
575 ole_check(IPicture_get_Height(pict, &cxy));
576 expect_eq(cxy, -23, LONG, "%d");
578 ole_check(IPicture_get_Width(pict, &cxy));
579 expect_eq(cxy, -25, LONG, "%d");
581 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
582 todo_wine expect_eq(keep, FALSE, LONG, "%d");
584 IPicture_Release(pict);
585 IStream_Release(stream);
586 GlobalUnlock(hglob);
587 GlobalFree(hglob);
590 START_TEST(olepicture)
592 hOleaut32 = GetModuleHandleA("oleaut32.dll");
593 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
594 pOleCreatePictureIndirect = (void*)GetProcAddress(hOleaut32, "OleCreatePictureIndirect");
595 if (!pOleLoadPicture)
597 skip("OleLoadPicture is not available\n");
598 return;
601 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
602 test_pic(gifimage, sizeof(gifimage));
603 test_pic(jpgimage, sizeof(jpgimage));
604 test_pic(bmpimage, sizeof(bmpimage));
605 test_pic(gif4pixel, sizeof(gif4pixel));
606 /* FIXME: No PNG support yet in Wine or in older Windows... */
607 if (0) test_pic(pngimage, sizeof(pngimage));
608 test_empty_image();
609 test_empty_image_2();
610 test_apm();
611 test_metafile();
612 test_enhmetafile();
614 test_Invoke();
615 test_OleCreatePictureIndirect();
619 /* Helper functions only ... */
622 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
624 GlobalFree(This->supportHandle);
625 This->supportHandle=0;
626 HeapFree(GetProcessHeap(), 0, This);
629 static ULONG WINAPI NoStatStreamImpl_AddRef(
630 IStream* iface)
632 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
633 return InterlockedIncrement(&This->ref);
636 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
637 IStream* iface,
638 REFIID riid, /* [in] */
639 void** ppvObject) /* [iid_is][out] */
641 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
642 if (ppvObject==0) return E_INVALIDARG;
643 *ppvObject = 0;
644 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
646 *ppvObject = (IStream*)This;
648 else if (memcmp(&IID_IStream, riid, sizeof(IID_IStream)) == 0)
650 *ppvObject = (IStream*)This;
653 if ((*ppvObject)==0)
654 return E_NOINTERFACE;
655 NoStatStreamImpl_AddRef(iface);
656 return S_OK;
659 static ULONG WINAPI NoStatStreamImpl_Release(
660 IStream* iface)
662 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
663 ULONG newRef = InterlockedDecrement(&This->ref);
664 if (newRef==0)
665 NoStatStreamImpl_Destroy(This);
666 return newRef;
669 static HRESULT WINAPI NoStatStreamImpl_Read(
670 IStream* iface,
671 void* pv, /* [length_is][size_is][out] */
672 ULONG cb, /* [in] */
673 ULONG* pcbRead) /* [out] */
675 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
676 void* supportBuffer;
677 ULONG bytesReadBuffer;
678 ULONG bytesToReadFromBuffer;
680 if (pcbRead==0)
681 pcbRead = &bytesReadBuffer;
682 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
683 supportBuffer = GlobalLock(This->supportHandle);
684 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
685 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
686 *pcbRead = bytesToReadFromBuffer;
687 GlobalUnlock(This->supportHandle);
688 if(*pcbRead == cb)
689 return S_OK;
690 return S_FALSE;
693 static HRESULT WINAPI NoStatStreamImpl_Write(
694 IStream* iface,
695 const void* pv, /* [size_is][in] */
696 ULONG cb, /* [in] */
697 ULONG* pcbWritten) /* [out] */
699 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
700 void* supportBuffer;
701 ULARGE_INTEGER newSize;
702 ULONG bytesWritten = 0;
704 if (pcbWritten == 0)
705 pcbWritten = &bytesWritten;
706 if (cb == 0)
707 return S_OK;
708 newSize.u.HighPart = 0;
709 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
710 if (newSize.u.LowPart > This->streamSize.u.LowPart)
711 IStream_SetSize(iface, newSize);
713 supportBuffer = GlobalLock(This->supportHandle);
714 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
715 This->currentPosition.u.LowPart+=cb;
716 *pcbWritten = cb;
717 GlobalUnlock(This->supportHandle);
718 return S_OK;
721 static HRESULT WINAPI NoStatStreamImpl_Seek(
722 IStream* iface,
723 LARGE_INTEGER dlibMove, /* [in] */
724 DWORD dwOrigin, /* [in] */
725 ULARGE_INTEGER* plibNewPosition) /* [out] */
727 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
728 ULARGE_INTEGER newPosition;
729 switch (dwOrigin)
731 case STREAM_SEEK_SET:
732 newPosition.u.HighPart = 0;
733 newPosition.u.LowPart = 0;
734 break;
735 case STREAM_SEEK_CUR:
736 newPosition = This->currentPosition;
737 break;
738 case STREAM_SEEK_END:
739 newPosition = This->streamSize;
740 break;
741 default:
742 return STG_E_INVALIDFUNCTION;
744 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
745 return STG_E_INVALIDFUNCTION;
746 newPosition.QuadPart += dlibMove.QuadPart;
747 if (plibNewPosition) *plibNewPosition = newPosition;
748 This->currentPosition = newPosition;
749 return S_OK;
752 static HRESULT WINAPI NoStatStreamImpl_SetSize(
753 IStream* iface,
754 ULARGE_INTEGER libNewSize) /* [in] */
756 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
757 HGLOBAL supportHandle;
758 if (libNewSize.u.HighPart != 0)
759 return STG_E_INVALIDFUNCTION;
760 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
761 return S_OK;
762 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
763 if (supportHandle == 0)
764 return STG_E_MEDIUMFULL;
765 This->supportHandle = supportHandle;
766 This->streamSize.u.LowPart = libNewSize.u.LowPart;
767 return S_OK;
770 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
771 IStream* iface,
772 IStream* pstm, /* [unique][in] */
773 ULARGE_INTEGER cb, /* [in] */
774 ULARGE_INTEGER* pcbRead, /* [out] */
775 ULARGE_INTEGER* pcbWritten) /* [out] */
777 HRESULT hr = S_OK;
778 BYTE tmpBuffer[128];
779 ULONG bytesRead, bytesWritten, copySize;
780 ULARGE_INTEGER totalBytesRead;
781 ULARGE_INTEGER totalBytesWritten;
783 if ( pstm == 0 )
784 return STG_E_INVALIDPOINTER;
785 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
786 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
788 while ( cb.u.LowPart > 0 )
790 if ( cb.u.LowPart >= 128 )
791 copySize = 128;
792 else
793 copySize = cb.u.LowPart;
794 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
795 totalBytesRead.u.LowPart += bytesRead;
796 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
797 totalBytesWritten.u.LowPart += bytesWritten;
798 if (bytesRead != bytesWritten)
800 hr = STG_E_MEDIUMFULL;
801 break;
803 if (bytesRead!=copySize)
804 cb.u.LowPart = 0;
805 else
806 cb.u.LowPart -= bytesRead;
808 if (pcbRead)
810 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
811 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
814 if (pcbWritten)
816 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
817 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
819 return hr;
822 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
824 return S_OK;
826 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
828 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
829 IStream* iface,
830 ULARGE_INTEGER libOffset, /* [in] */
831 ULARGE_INTEGER cb, /* [in] */
832 DWORD dwLockType) /* [in] */
834 return S_OK;
837 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
838 IStream* iface,
839 ULARGE_INTEGER libOffset, /* [in] */
840 ULARGE_INTEGER cb, /* [in] */
841 DWORD dwLockType) /* [in] */
843 return S_OK;
846 static HRESULT WINAPI NoStatStreamImpl_Stat(
847 IStream* iface,
848 STATSTG* pstatstg, /* [out] */
849 DWORD grfStatFlag) /* [in] */
851 return E_NOTIMPL;
854 static HRESULT WINAPI NoStatStreamImpl_Clone(
855 IStream* iface,
856 IStream** ppstm) /* [out] */
858 return E_NOTIMPL;
860 static const IStreamVtbl NoStatStreamImpl_Vtbl;
863 Build an object that implements IStream, without IStream_Stat capabilities.
864 Receives a memory handle with data buffer. If memory handle is non-null,
865 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
866 In any case the object takes ownership of memory handle and will free it on
867 object release.
869 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal)
871 NoStatStreamImpl* newStream;
873 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
874 if (newStream!=0)
876 newStream->lpVtbl = &NoStatStreamImpl_Vtbl;
877 newStream->ref = 1;
878 newStream->supportHandle = hGlobal;
880 if (!newStream->supportHandle)
881 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
882 GMEM_SHARE, 0);
883 newStream->currentPosition.u.HighPart = 0;
884 newStream->currentPosition.u.LowPart = 0;
885 newStream->streamSize.u.HighPart = 0;
886 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
888 return newStream;
892 static const IStreamVtbl NoStatStreamImpl_Vtbl =
894 NoStatStreamImpl_QueryInterface,
895 NoStatStreamImpl_AddRef,
896 NoStatStreamImpl_Release,
897 NoStatStreamImpl_Read,
898 NoStatStreamImpl_Write,
899 NoStatStreamImpl_Seek,
900 NoStatStreamImpl_SetSize,
901 NoStatStreamImpl_CopyTo,
902 NoStatStreamImpl_Commit,
903 NoStatStreamImpl_Revert,
904 NoStatStreamImpl_LockRegion,
905 NoStatStreamImpl_UnlockRegion,
906 NoStatStreamImpl_Stat,
907 NoStatStreamImpl_Clone