Release 1.6-rc2.
[wine/testsucceed.git] / dlls / oleaut32 / tests / olepicture.c
blobdb10baafe579e0712ee3feb3f66a733309b4f42d
1 /*
2 * OLEPICTURE test program
4 * Copyright 2005 Marcus Meissner
5 * Copyright 2012 Dmitry Timoshkov
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
28 #define CONST_VTABLE
29 #define NONAMELESSUNION
31 #include "wine/test.h"
32 #include <windef.h>
33 #include <winbase.h>
34 #include <winuser.h>
35 #include <wingdi.h>
36 #include <winnls.h>
37 #include <winerror.h>
38 #include <winnt.h>
40 #include <urlmon.h>
41 #include <wtypes.h>
42 #include <olectl.h>
43 #include <objidl.h>
45 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
47 #define ole_expect(expr, expect) { \
48 HRESULT r = expr; \
49 ok(r == (expect), #expr " returned %x, expected %s (%x)\n", r, #expect, expect); \
52 #define ole_check(expr) ole_expect(expr, S_OK);
54 static HMODULE hOleaut32;
56 static HRESULT (WINAPI *pOleLoadPicture)(LPSTREAM,LONG,BOOL,REFIID,LPVOID*);
57 static HRESULT (WINAPI *pOleLoadPictureEx)(LPSTREAM,LONG,BOOL,REFIID,DWORD,DWORD,DWORD,LPVOID*);
59 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
61 /* 1x1 pixel gif */
62 static const unsigned char gifimage[35] = {
63 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
64 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
65 0x01,0x00,0x3b
68 /* 1x1 pixel jpg */
69 static const unsigned char jpgimage[285] = {
70 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
71 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
72 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
73 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
74 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
75 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
76 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
77 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
78 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
79 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
80 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
81 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
82 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
83 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
84 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
85 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
86 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
87 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
90 /* 1x1 pixel png */
91 static const unsigned char pngimage[285] = {
92 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
93 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
94 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
95 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
96 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
97 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
98 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
101 /* 1x1 pixel bmp */
102 static const unsigned char bmpimage[66] = {
103 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
104 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
105 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
106 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
107 0x00,0x00
110 /* 2x2 pixel gif */
111 static const unsigned char gif4pixel[42] = {
112 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
113 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
114 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
117 /* APM with an empty metafile with some padding zeros - looks like under Window the
118 * metafile data should be at least 20 bytes */
119 static const unsigned char apmdata[] = {
120 0xd7,0xcd,0xc6,0x9a, 0x00,0x00,0x00,0x00, 0x00,0x00,0xee,0x02, 0xb1,0x03,0xa0,0x05,
121 0x00,0x00,0x00,0x00, 0xee,0x53,0x01,0x00, 0x09,0x00,0x00,0x03, 0x13,0x00,0x00,0x00,
122 0x01,0x00,0x05,0x00, 0x00,0x00,0x00,0x00, 0x03,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
123 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
126 /* MF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
127 static const unsigned char metafile[] = {
128 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
129 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
131 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
132 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
133 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
134 0x00, 0x00
137 /* EMF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
138 static const unsigned char enhmetafile[] = {
139 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
144 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
145 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
146 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
149 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
152 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
153 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
154 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
156 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
158 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
159 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
162 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
163 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
164 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
165 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
166 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
167 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
168 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
169 0x14, 0x00, 0x00, 0x00
173 typedef struct NoStatStreamImpl
175 IStream IStream_iface;
176 LONG ref;
178 HGLOBAL supportHandle;
179 ULARGE_INTEGER streamSize;
180 ULARGE_INTEGER currentPosition;
181 } NoStatStreamImpl;
183 static IStream* NoStatStream_Construct(HGLOBAL hGlobal);
185 static void
186 test_pic_with_stream(LPSTREAM stream, unsigned int imgsize)
188 IPicture* pic = NULL;
189 HRESULT hres;
190 LPVOID pvObj = NULL;
191 OLE_HANDLE handle, hPal;
192 OLE_XSIZE_HIMETRIC width;
193 OLE_YSIZE_HIMETRIC height;
194 short type;
195 DWORD attr;
196 ULONG res;
198 pvObj = NULL;
199 hres = pOleLoadPicture(stream, imgsize, TRUE, &IID_IPicture, &pvObj);
200 pic = pvObj;
202 ok(hres == S_OK,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres);
203 ok(pic != NULL,"OLP (NULL,..) returns NULL, instead of !NULL\n");
204 if (pic == NULL)
205 return;
207 pvObj = NULL;
208 hres = IPicture_QueryInterface (pic, &IID_IPicture, &pvObj);
210 ok(hres == S_OK,"IPicture_QI does not return S_OK, but 0x%08x\n", hres);
211 ok(pvObj != NULL,"IPicture_QI does return NULL, instead of a ptr\n");
213 IPicture_Release ((IPicture*)pvObj);
215 handle = 0;
216 hres = IPicture_get_Handle (pic, &handle);
217 ok(hres == S_OK,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres);
218 ok(handle != 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
220 if (handle)
222 BITMAP bmp;
223 GetObject(UlongToHandle(handle), sizeof(BITMAP), &bmp);
224 todo_wine ok(bmp.bmBits != 0, "not a dib\n");
227 width = 0;
228 hres = IPicture_get_Width (pic, &width);
229 ok(hres == S_OK,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres);
230 ok(width != 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
232 height = 0;
233 hres = IPicture_get_Height (pic, &height);
234 ok(hres == S_OK,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres);
235 ok(height != 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
237 type = 0;
238 hres = IPicture_get_Type (pic, &type);
239 ok(hres == S_OK,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
240 ok(type == PICTYPE_BITMAP, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type, PICTYPE_BITMAP);
242 attr = 0;
243 hres = IPicture_get_Attributes (pic, &attr);
244 ok(hres == S_OK,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres);
245 ok(attr == 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr);
247 hPal = 0;
248 hres = IPicture_get_hPal (pic, &hPal);
249 ok(hres == S_OK,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres);
250 /* a single pixel b/w image has no palette */
251 ok(hPal == 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal);
253 res = IPicture_Release (pic);
254 ok (res == 0, "refcount after release is %d, but should be 0?\n", res);
257 static void
258 test_pic(const unsigned char *imgdata, unsigned int imgsize)
260 LPSTREAM stream;
261 HGLOBAL hglob;
262 LPBYTE data;
263 HRESULT hres;
264 LARGE_INTEGER seekto;
265 ULARGE_INTEGER newpos1;
266 DWORD * header;
267 unsigned int i,j;
269 /* Let the fun begin */
270 hglob = GlobalAlloc (0, imgsize);
271 data = GlobalLock (hglob);
272 memcpy(data, imgdata, imgsize);
273 GlobalUnlock(hglob); data = NULL;
275 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
276 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
278 memset(&seekto,0,sizeof(seekto));
279 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
280 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
281 test_pic_with_stream(stream, imgsize);
283 IStream_Release(stream);
285 /* again with Non Statable and Non Seekable stream */
286 stream = NoStatStream_Construct(hglob);
287 hglob = 0; /* Non-statable impl always deletes on release */
288 test_pic_with_stream(stream, 0);
290 IStream_Release(stream);
291 for (i = 1; i <= 8; i++) {
292 /* more fun!!! */
293 hglob = GlobalAlloc (0, imgsize + i * (2 * sizeof(DWORD)));
294 data = GlobalLock (hglob);
295 header = (DWORD *)data;
297 /* multiple copies of header */
298 memcpy(data,"lt\0\0",4);
299 header[1] = imgsize;
300 for (j = 2; j <= i; j++) {
301 memcpy(&(header[2 * (j - 1)]), header, 2 * sizeof(DWORD));
303 memcpy(data + i * (2 * sizeof(DWORD)), imgdata, imgsize);
304 GlobalUnlock(hglob); data = NULL;
306 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
307 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
309 memset(&seekto,0,sizeof(seekto));
310 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
311 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
312 test_pic_with_stream(stream, imgsize);
314 IStream_Release(stream);
316 /* again with Non Statable and Non Seekable stream */
317 stream = NoStatStream_Construct(hglob);
318 hglob = 0; /* Non-statable impl always deletes on release */
319 test_pic_with_stream(stream, 0);
321 IStream_Release(stream);
325 static void test_empty_image(void) {
326 LPBYTE data;
327 LPSTREAM stream;
328 IPicture* pic = NULL;
329 HRESULT hres;
330 LPVOID pvObj = NULL;
331 HGLOBAL hglob;
332 OLE_HANDLE handle;
333 ULARGE_INTEGER newpos1;
334 LARGE_INTEGER seekto;
335 short type;
336 DWORD attr;
338 /* Empty image. Happens occasionally in VB programs. */
339 hglob = GlobalAlloc (0, 8);
340 data = GlobalLock (hglob);
341 memcpy(data,"lt\0\0",4);
342 ((DWORD*)data)[1] = 0;
343 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
344 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
346 memset(&seekto,0,sizeof(seekto));
347 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
348 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
350 pvObj = NULL;
351 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
352 pic = pvObj;
353 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
354 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
356 hres = IPicture_get_Type (pic, &type);
357 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
358 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
360 attr = 0xdeadbeef;
361 hres = IPicture_get_Attributes (pic, &attr);
362 ok (hres == S_OK,"empty picture get attributes failed with hres 0x%08x\n", hres);
363 ok (attr == 0,"attr is %d, but should be 0\n", attr);
365 hres = IPicture_get_Handle (pic, &handle);
366 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
367 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
368 IPicture_Release (pic);
369 IStream_Release (stream);
372 static void test_empty_image_2(void) {
373 LPBYTE data;
374 LPSTREAM stream;
375 IPicture* pic = NULL;
376 HRESULT hres;
377 LPVOID pvObj = NULL;
378 HGLOBAL hglob;
379 ULARGE_INTEGER newpos1;
380 LARGE_INTEGER seekto;
381 short type;
383 /* Empty image at random stream position. */
384 hglob = GlobalAlloc (0, 200);
385 data = GlobalLock (hglob);
386 data += 42;
387 memcpy(data,"lt\0\0",4);
388 ((DWORD*)data)[1] = 0;
389 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
390 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
392 memset(&seekto,0,sizeof(seekto));
393 seekto.u.LowPart = 42;
394 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
395 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
397 pvObj = NULL;
398 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
399 pic = pvObj;
400 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
401 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
403 hres = IPicture_get_Type (pic, &type);
404 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
405 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
407 IPicture_Release (pic);
408 IStream_Release (stream);
411 static void test_Invoke(void)
413 IPictureDisp *picdisp;
414 HRESULT hr;
415 VARIANTARG vararg;
416 DISPPARAMS dispparams;
417 VARIANT varresult;
418 IStream *stream;
419 HGLOBAL hglob;
420 void *data;
422 hglob = GlobalAlloc (0, sizeof(gifimage));
423 data = GlobalLock(hglob);
424 memcpy(data, gifimage, sizeof(gifimage));
425 GlobalUnlock(hglob);
427 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
428 ok_ole_success(hr, "CreateStreamOnHGlobal");
430 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
431 IStream_Release(stream);
432 GlobalFree(hglob);
433 ok_ole_success(hr, "OleLoadPicture");
435 V_VT(&vararg) = VT_BOOL;
436 V_BOOL(&vararg) = VARIANT_FALSE;
437 dispparams.cNamedArgs = 0;
438 dispparams.rgdispidNamedArgs = NULL;
439 dispparams.cArgs = 1;
440 dispparams.rgvarg = &vararg;
441 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
442 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
443 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
444 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
446 dispparams.cArgs = 0;
447 dispparams.rgvarg = NULL;
448 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
449 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
451 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
452 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
454 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
455 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
457 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
458 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
460 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
461 ok_ole_success(hr, "IPictureDisp_Invoke");
462 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
464 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
465 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
467 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
468 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
470 dispparams.cArgs = 1;
471 dispparams.rgvarg = &vararg;
472 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
473 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
475 dispparams.cArgs = 1;
476 dispparams.rgvarg = &vararg;
477 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
478 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
480 IPictureDisp_Release(picdisp);
483 static void test_OleCreatePictureIndirect(void)
485 OLE_HANDLE handle;
486 IPicture *pict;
487 HRESULT hr;
488 short type;
490 if (0)
492 /* crashes on native */
493 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, NULL);
496 hr = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict);
497 ok(hr == S_OK, "hr %08x\n", hr);
499 type = PICTYPE_NONE;
500 hr = IPicture_get_Type(pict, &type);
501 ok(hr == S_OK, "hr %08x\n", hr);
502 ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type);
504 handle = 0xdeadbeef;
505 hr = IPicture_get_Handle(pict, &handle);
506 ok(hr == S_OK, "hr %08x\n", hr);
507 ok(handle == 0, "handle %08x\n", handle);
509 IPicture_Release(pict);
512 static void test_apm(void)
514 OLE_HANDLE handle;
515 LPSTREAM stream;
516 IPicture *pict;
517 HGLOBAL hglob;
518 LPBYTE *data;
519 LONG cxy;
520 BOOL keep;
521 short type;
523 hglob = GlobalAlloc (0, sizeof(apmdata));
524 data = GlobalLock(hglob);
525 memcpy(data, apmdata, sizeof(apmdata));
527 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
528 ole_check(pOleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict));
530 ole_check(IPicture_get_Handle(pict, &handle));
531 ok(handle != 0, "handle is null\n");
533 ole_check(IPicture_get_Type(pict, &type));
534 expect_eq(type, PICTYPE_METAFILE, short, "%d");
536 ole_check(IPicture_get_Height(pict, &cxy));
537 expect_eq(cxy, 1667, LONG, "%d");
539 ole_check(IPicture_get_Width(pict, &cxy));
540 expect_eq(cxy, 1323, LONG, "%d");
542 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
543 todo_wine expect_eq(keep, FALSE, LONG, "%d");
545 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL);
546 IPicture_Release(pict);
547 IStream_Release(stream);
550 static void test_metafile(void)
552 LPSTREAM stream;
553 IPicture *pict;
554 HGLOBAL hglob;
555 LPBYTE *data;
557 hglob = GlobalAlloc (0, sizeof(metafile));
558 data = GlobalLock(hglob);
559 memcpy(data, metafile, sizeof(metafile));
561 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
562 /* Windows does not load simple metafiles */
563 ole_expect(pOleLoadPictureEx(stream, sizeof(metafile), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict), E_FAIL);
565 IStream_Release(stream);
568 static void test_enhmetafile(void)
570 OLE_HANDLE handle;
571 LPSTREAM stream;
572 IPicture *pict;
573 HGLOBAL hglob;
574 LPBYTE *data;
575 LONG cxy;
576 BOOL keep;
577 short type;
579 hglob = GlobalAlloc (0, sizeof(enhmetafile));
580 data = GlobalLock(hglob);
581 memcpy(data, enhmetafile, sizeof(enhmetafile));
583 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
584 ole_check(pOleLoadPictureEx(stream, sizeof(enhmetafile), TRUE, &IID_IPicture, 10, 10, 0, (LPVOID *)&pict));
586 ole_check(IPicture_get_Handle(pict, &handle));
587 ok(handle != 0, "handle is null\n");
589 ole_check(IPicture_get_Type(pict, &type));
590 expect_eq(type, PICTYPE_ENHMETAFILE, short, "%d");
592 ole_check(IPicture_get_Height(pict, &cxy));
593 expect_eq(cxy, -23, LONG, "%d");
595 ole_check(IPicture_get_Width(pict, &cxy));
596 expect_eq(cxy, -25, LONG, "%d");
598 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
599 todo_wine expect_eq(keep, FALSE, LONG, "%d");
601 IPicture_Release(pict);
602 IStream_Release(stream);
605 static void test_Render(void)
607 IPicture *pic;
608 HRESULT hres;
609 short type;
610 PICTDESC desc;
611 OLE_XSIZE_HIMETRIC pWidth;
612 OLE_YSIZE_HIMETRIC pHeight;
613 COLORREF result, expected;
614 HDC hdc = GetDC(0);
616 /* test IPicture::Render return code on uninitialized picture */
617 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
618 hres = IPicture_get_Type(pic, &type);
619 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
620 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
621 /* zero dimensions */
622 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
623 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
624 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
625 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
626 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
627 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
628 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
629 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
630 hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
631 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
632 hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
633 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
634 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
635 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
636 /* nonzero dimensions, PICTYPE_UNINITIALIZED */
637 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL);
638 ole_expect(hres, S_OK);
639 IPicture_Release(pic);
641 desc.cbSizeofstruct = sizeof(PICTDESC);
642 desc.picType = PICTYPE_ICON;
643 desc.u.icon.hicon = LoadIcon(NULL, IDI_APPLICATION);
644 if(!desc.u.icon.hicon){
645 win_skip("LoadIcon failed. Skipping...\n");
646 ReleaseDC(NULL, hdc);
647 return;
650 OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (VOID**)&pic);
651 /* zero dimensions, PICTYPE_ICON */
652 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
653 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
654 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
655 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
656 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
657 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
658 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
659 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
660 hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
661 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
662 hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
663 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
664 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
665 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
667 /* Check if target size and position is respected */
668 IPicture_get_Width(pic, &pWidth);
669 IPicture_get_Height(pic, &pHeight);
671 SetPixelV(hdc, 0, 0, 0x00223344);
672 SetPixelV(hdc, 5, 5, 0x00223344);
673 SetPixelV(hdc, 10, 10, 0x00223344);
674 expected = GetPixel(hdc, 0, 0);
676 hres = IPicture_Render(pic, hdc, 1, 1, 9, 9, 0, 0, pWidth, -pHeight, NULL);
677 ole_expect(hres, S_OK);
679 if(hres != S_OK) {
680 IPicture_Release(pic);
681 ReleaseDC(NULL, hdc);
682 return;
685 /* Evaluate the rendered Icon */
686 result = GetPixel(hdc, 0, 0);
687 ok(result == expected,
688 "Color at 0,0 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
689 result = GetPixel(hdc, 5, 5);
690 ok(result != expected ||
691 broken(result == expected), /* WinNT 4.0 and older may claim they drew */
692 /* the icon, even if they didn't. */
693 "Color at 5,5 should have changed, but still was 0x%06X\n", expected);
694 result = GetPixel(hdc, 10, 10);
695 ok(result == expected,
696 "Color at 10,10 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
698 IPicture_Release(pic);
699 ReleaseDC(NULL, hdc);
702 static void test_get_Attributes(void)
704 IPicture *pic;
705 HRESULT hres;
706 short type;
707 DWORD attr;
709 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
710 hres = IPicture_get_Type(pic, &type);
711 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
712 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
714 hres = IPicture_get_Attributes(pic, NULL);
715 ole_expect(hres, E_POINTER);
717 attr = 0xdeadbeef;
718 hres = IPicture_get_Attributes(pic, &attr);
719 ole_expect(hres, S_OK);
720 ok(attr == 0, "IPicture_get_Attributes does not reset attr to zero, got %d\n", attr);
722 IPicture_Release(pic);
725 static void test_get_Handle(void)
727 IPicture *pic;
728 HRESULT hres;
730 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
732 hres = IPicture_get_Handle(pic, NULL);
733 ole_expect(hres, E_POINTER);
735 IPicture_Release(pic);
738 static void test_get_Type(void)
740 IPicture *pic;
741 HRESULT hres;
743 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
745 hres = IPicture_get_Type(pic, NULL);
746 ole_expect(hres, E_POINTER);
748 IPicture_Release(pic);
751 static void test_OleLoadPicturePath(void)
753 static WCHAR emptyW[] = {0};
755 IPicture *pic;
756 HRESULT hres;
757 int i;
758 char temp_path[MAX_PATH];
759 char temp_file[MAX_PATH];
760 WCHAR temp_fileW[MAX_PATH + 5] = {'f','i','l','e',':','/','/','/'};
761 HANDLE file;
762 DWORD size;
763 WCHAR *ptr;
765 const struct
767 LPOLESTR szURLorPath;
768 REFIID riid;
769 IPicture **pic;
770 } invalid_parameters[] =
772 {NULL, NULL, NULL},
773 {NULL, NULL, &pic},
774 {NULL, &IID_IPicture, NULL},
775 {NULL, &IID_IPicture, &pic},
776 {emptyW, NULL, NULL},
777 {emptyW, &IID_IPicture, NULL},
780 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
782 pic = (IPicture *)0xdeadbeef;
783 hres = OleLoadPicturePath(invalid_parameters[i].szURLorPath, NULL, 0, 0,
784 invalid_parameters[i].riid,
785 (void **)invalid_parameters[i].pic);
786 ok(hres == E_INVALIDARG,
787 "[%d] Expected OleLoadPicturePath to return E_INVALIDARG, got 0x%08x\n", i, hres);
788 ok(pic == (IPicture *)0xdeadbeef,
789 "[%d] Expected output pointer to be 0xdeadbeef, got %p\n", i, pic);
792 pic = (IPicture *)0xdeadbeef;
793 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, NULL, (void **)&pic);
794 todo_wine
795 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
796 broken(hres == E_UNEXPECTED) || /* NT4 */
797 broken(hres == E_OUTOFMEMORY), /* Win2k/Win2k3 */
798 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
799 ok(pic == NULL,
800 "Expected the output interface pointer to be NULL, got %p\n", pic);
802 pic = (IPicture *)0xdeadbeef;
803 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
804 todo_wine
805 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
806 broken(hres == E_UNEXPECTED) || /* NT4 */
807 broken(hres == E_OUTOFMEMORY), /* Win2k/Win2k3 */
808 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
809 ok(pic == NULL,
810 "Expected the output interface pointer to be NULL, got %p\n", pic);
812 /* Create a local temporary image file for testing. */
813 GetTempPathA(sizeof(temp_path), temp_path);
814 GetTempFileNameA(temp_path, "bmp", 0, temp_file);
815 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
816 FILE_ATTRIBUTE_NORMAL, NULL);
817 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
818 CloseHandle(file);
820 MultiByteToWideChar(CP_ACP, 0, temp_file, -1, temp_fileW + 8, sizeof(temp_fileW)/sizeof(WCHAR) - 8);
822 /* Try a normal DOS path. */
823 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
824 ok(hres == S_OK ||
825 broken(hres == E_UNEXPECTED), /* NT4 */
826 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
827 if (pic)
828 IPicture_Release(pic);
830 /* Try a DOS path with tacked on "file:". */
831 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
832 ok(hres == S_OK ||
833 broken(hres == E_UNEXPECTED), /* NT4 */
834 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
835 if (pic)
836 IPicture_Release(pic);
838 DeleteFileA(temp_file);
840 /* Try with a nonexistent file. */
841 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
842 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
843 broken(hres == E_UNEXPECTED) || /* NT4 */
844 broken(hres == E_FAIL), /*Win2k */
845 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
847 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
848 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
849 broken(hres == E_UNEXPECTED) || /* NT4 */
850 broken(hres == E_FAIL), /* Win2k */
851 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
853 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
854 FILE_ATTRIBUTE_NORMAL, NULL);
855 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
856 CloseHandle(file);
858 /* Try a "file:" URL with slash separators. */
859 ptr = temp_fileW + 8;
860 while (*ptr)
862 if (*ptr == '\\')
863 *ptr = '/';
864 ptr++;
867 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
868 ok(hres == S_OK ||
869 broken(hres == E_UNEXPECTED), /* NT4 */
870 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
871 if (pic)
872 IPicture_Release(pic);
874 DeleteFileA(temp_file);
876 /* Try with a nonexistent file. */
877 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
878 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
879 broken(hres == E_UNEXPECTED) || /* NT4 */
880 broken(hres == E_FAIL), /* Win2k */
881 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
884 static void test_himetric(void)
886 static const BYTE bmp_bits[1024];
887 OLE_XSIZE_HIMETRIC cx;
888 OLE_YSIZE_HIMETRIC cy;
889 IPicture *pic;
890 PICTDESC desc;
891 HBITMAP bmp;
892 HRESULT hr;
893 HICON icon;
894 HDC hdc;
895 INT d;
897 desc.cbSizeofstruct = sizeof(desc);
898 desc.picType = PICTYPE_BITMAP;
899 desc.u.bmp.hpal = NULL;
901 hdc = CreateCompatibleDC(0);
903 bmp = CreateBitmap(1.9 * GetDeviceCaps(hdc, LOGPIXELSX),
904 1.9 * GetDeviceCaps(hdc, LOGPIXELSY), 1, 1, NULL);
906 desc.u.bmp.hbitmap = bmp;
908 /* size in himetric units reported rounded up to next integer value */
909 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
910 ok(hr == S_OK, "got 0x%08x\n", hr);
912 cx = 0;
913 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSX)), 2540, GetDeviceCaps(hdc, LOGPIXELSX));
914 hr = IPicture_get_Width(pic, &cx);
915 ok(hr == S_OK, "got 0x%08x\n", hr);
916 ok(cx == d, "got %d, expected %d\n", cx, d);
918 cy = 0;
919 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSY)), 2540, GetDeviceCaps(hdc, LOGPIXELSY));
920 hr = IPicture_get_Height(pic, &cy);
921 ok(hr == S_OK, "got 0x%08x\n", hr);
922 ok(cy == d, "got %d, expected %d\n", cy, d);
924 DeleteObject(bmp);
925 IPicture_Release(pic);
927 /* same thing with icon */
928 icon = CreateIcon(NULL, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
929 1, 1, bmp_bits, bmp_bits);
930 ok(icon != NULL, "failed to create icon\n");
932 desc.picType = PICTYPE_ICON;
933 desc.u.icon.hicon = icon;
935 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
936 ok(hr == S_OK, "got 0x%08x\n", hr);
938 cx = 0;
939 d = MulDiv(GetSystemMetrics(SM_CXICON), 2540, GetDeviceCaps(hdc, LOGPIXELSX));
940 hr = IPicture_get_Width(pic, &cx);
941 ok(hr == S_OK, "got 0x%08x\n", hr);
942 ok(cx == d, "got %d, expected %d\n", cx, d);
944 cy = 0;
945 d = MulDiv(GetSystemMetrics(SM_CYICON), 2540, GetDeviceCaps(hdc, LOGPIXELSY));
946 hr = IPicture_get_Height(pic, &cy);
947 ok(hr == S_OK, "got 0x%08x\n", hr);
948 ok(cy == d, "got %d, expected %d\n", cy, d);
950 IPicture_Release(pic);
951 DestroyIcon(icon);
953 DeleteDC(hdc);
956 static void test_load_save_bmp(void)
958 IPicture *pic;
959 PICTDESC desc;
960 short type;
961 OLE_HANDLE handle;
962 HGLOBAL hmem;
963 DWORD *mem;
964 IPersistStream *src_stream;
965 IStream *dst_stream;
966 HRESULT hr;
968 desc.cbSizeofstruct = sizeof(desc);
969 desc.picType = PICTYPE_BITMAP;
970 desc.u.bmp.hpal = 0;
971 desc.u.bmp.hbitmap = CreateBitmap(1, 1, 1, 1, NULL);
972 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
973 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
975 type = -1;
976 hr = IPicture_get_Type(pic, &type);
977 ok(hr == S_OK,"get_Type error %#8x\n", hr);
978 ok(type == PICTYPE_BITMAP,"expected picture type PICTYPE_BITMAP, got %d\n", type);
980 hr = IPicture_get_Handle(pic, &handle);
981 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
982 ok(IntToPtr(handle) == desc.u.bmp.hbitmap, "get_Handle returned wrong handle %#x\n", handle);
984 hmem = GlobalAlloc(GMEM_ZEROINIT, 4096);
985 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
986 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr);
988 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
989 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
991 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
992 ok(hr == S_OK, "Save error %#x\n", hr);
994 IPersistStream_Release(src_stream);
995 IStream_Release(dst_stream);
997 mem = GlobalLock(hmem);
998 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
999 ok(mem[1] == 66, "expected stream size 66, got %u\n", mem[1]);
1000 ok(!memcmp(&mem[2], "BM", 2), "got wrong bmp header %04x\n", mem[2]);
1002 GlobalUnlock(hmem);
1003 GlobalFree(hmem);
1005 DeleteObject(desc.u.bmp.hbitmap);
1006 IPicture_Release(pic);
1009 static void test_load_save_icon(void)
1011 IPicture *pic;
1012 PICTDESC desc;
1013 short type;
1014 OLE_HANDLE handle;
1015 HGLOBAL hmem;
1016 DWORD *mem;
1017 IPersistStream *src_stream;
1018 IStream *dst_stream;
1019 HRESULT hr;
1021 desc.cbSizeofstruct = sizeof(desc);
1022 desc.picType = PICTYPE_ICON;
1023 desc.u.icon.hicon = LoadIcon(0, IDI_APPLICATION);
1024 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1025 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1027 type = -1;
1028 hr = IPicture_get_Type(pic, &type);
1029 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1030 ok(type == PICTYPE_ICON,"expected picture type PICTYPE_ICON, got %d\n", type);
1032 hr = IPicture_get_Handle(pic, &handle);
1033 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1034 ok(IntToPtr(handle) == desc.u.icon.hicon, "get_Handle returned wrong handle %#x\n", handle);
1036 hmem = GlobalAlloc(GMEM_ZEROINIT, 8192);
1037 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1038 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
1040 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1041 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1043 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1044 ok(hr == S_OK, "Saveerror %#x\n", hr);
1046 IPersistStream_Release(src_stream);
1047 IStream_Release(dst_stream);
1049 mem = GlobalLock(hmem);
1050 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1051 todo_wine
1052 ok(mem[1] == 766, "expected stream size 766, got %u\n", mem[1]);
1053 ok(mem[2] == 0x00010000, "got wrong icon header %04x\n", mem[2]);
1055 GlobalUnlock(hmem);
1056 GlobalFree(hmem);
1058 DestroyIcon(desc.u.icon.hicon);
1059 IPicture_Release(pic);
1062 static void test_load_save_empty_picture(void)
1064 IPicture *pic;
1065 PICTDESC desc;
1066 short type;
1067 OLE_HANDLE handle;
1068 HGLOBAL hmem;
1069 DWORD *mem;
1070 IPersistStream *src_stream;
1071 IStream *dst_stream;
1072 HRESULT hr;
1074 memset(&pic, 0, sizeof(pic));
1075 desc.cbSizeofstruct = sizeof(desc);
1076 desc.picType = PICTYPE_NONE;
1077 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void **)&pic);
1078 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1080 type = -1;
1081 hr = IPicture_get_Type(pic, &type);
1082 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1083 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
1085 handle = (OLE_HANDLE)0xdeadbeef;
1086 hr = IPicture_get_Handle(pic, &handle);
1087 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1088 ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
1090 hmem = GlobalAlloc(GMEM_ZEROINIT, 4096);
1091 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1092 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr);
1094 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1095 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1097 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1098 ok(hr == S_OK, "Save error %#x\n", hr);
1100 mem = GlobalLock(hmem);
1101 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1102 ok(mem[1] == 0, "expected stream size 0, got %u\n", mem[1]);
1103 GlobalUnlock(hmem);
1105 IPersistStream_Release(src_stream);
1106 IStream_Release(dst_stream);
1108 GlobalFree(hmem);
1109 IPicture_Release(pic);
1112 START_TEST(olepicture)
1114 hOleaut32 = GetModuleHandleA("oleaut32.dll");
1115 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
1116 pOleLoadPictureEx = (void*)GetProcAddress(hOleaut32, "OleLoadPictureEx");
1117 if (!pOleLoadPicture)
1119 win_skip("OleLoadPicture is not available\n");
1120 return;
1123 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
1124 test_pic(gifimage, sizeof(gifimage));
1125 test_pic(jpgimage, sizeof(jpgimage));
1126 test_pic(bmpimage, sizeof(bmpimage));
1127 test_pic(gif4pixel, sizeof(gif4pixel));
1128 /* FIXME: No PNG support in Windows... */
1129 if (0) test_pic(pngimage, sizeof(pngimage));
1130 test_empty_image();
1131 test_empty_image_2();
1132 if (pOleLoadPictureEx)
1134 test_apm();
1135 test_metafile();
1136 test_enhmetafile();
1138 else
1139 win_skip("OleLoadPictureEx is not available\n");
1140 test_Invoke();
1141 test_OleCreatePictureIndirect();
1142 test_Render();
1143 test_get_Attributes();
1144 test_get_Handle();
1145 test_get_Type();
1146 test_OleLoadPicturePath();
1147 test_himetric();
1148 test_load_save_bmp();
1149 test_load_save_icon();
1150 test_load_save_empty_picture();
1154 /* Helper functions only ... */
1157 static inline NoStatStreamImpl *impl_from_IStream(IStream *iface)
1159 return CONTAINING_RECORD(iface, NoStatStreamImpl, IStream_iface);
1162 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
1164 GlobalFree(This->supportHandle);
1165 This->supportHandle=0;
1166 HeapFree(GetProcessHeap(), 0, This);
1169 static ULONG WINAPI NoStatStreamImpl_AddRef(
1170 IStream* iface)
1172 NoStatStreamImpl* const This = impl_from_IStream(iface);
1173 return InterlockedIncrement(&This->ref);
1176 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
1177 IStream* iface,
1178 REFIID riid, /* [in] */
1179 void** ppvObject) /* [iid_is][out] */
1181 NoStatStreamImpl* const This = impl_from_IStream(iface);
1182 if (ppvObject==0) return E_INVALIDARG;
1183 *ppvObject = 0;
1184 if (IsEqualIID(&IID_IUnknown, riid))
1186 *ppvObject = This;
1188 else if (IsEqualIID(&IID_IStream, riid))
1190 *ppvObject = This;
1193 if ((*ppvObject)==0)
1194 return E_NOINTERFACE;
1195 NoStatStreamImpl_AddRef(iface);
1196 return S_OK;
1199 static ULONG WINAPI NoStatStreamImpl_Release(
1200 IStream* iface)
1202 NoStatStreamImpl* const This = impl_from_IStream(iface);
1203 ULONG newRef = InterlockedDecrement(&This->ref);
1204 if (newRef==0)
1205 NoStatStreamImpl_Destroy(This);
1206 return newRef;
1209 static HRESULT WINAPI NoStatStreamImpl_Read(
1210 IStream* iface,
1211 void* pv, /* [length_is][size_is][out] */
1212 ULONG cb, /* [in] */
1213 ULONG* pcbRead) /* [out] */
1215 NoStatStreamImpl* const This = impl_from_IStream(iface);
1216 void* supportBuffer;
1217 ULONG bytesReadBuffer;
1218 ULONG bytesToReadFromBuffer;
1220 if (pcbRead==0)
1221 pcbRead = &bytesReadBuffer;
1222 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
1223 supportBuffer = GlobalLock(This->supportHandle);
1224 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
1225 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
1226 *pcbRead = bytesToReadFromBuffer;
1227 GlobalUnlock(This->supportHandle);
1228 if(*pcbRead == cb)
1229 return S_OK;
1230 return S_FALSE;
1233 static HRESULT WINAPI NoStatStreamImpl_Write(
1234 IStream* iface,
1235 const void* pv, /* [size_is][in] */
1236 ULONG cb, /* [in] */
1237 ULONG* pcbWritten) /* [out] */
1239 NoStatStreamImpl* const This = impl_from_IStream(iface);
1240 void* supportBuffer;
1241 ULARGE_INTEGER newSize;
1242 ULONG bytesWritten = 0;
1244 if (pcbWritten == 0)
1245 pcbWritten = &bytesWritten;
1246 if (cb == 0)
1247 return S_OK;
1248 newSize.u.HighPart = 0;
1249 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
1250 if (newSize.u.LowPart > This->streamSize.u.LowPart)
1251 IStream_SetSize(iface, newSize);
1253 supportBuffer = GlobalLock(This->supportHandle);
1254 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
1255 This->currentPosition.u.LowPart+=cb;
1256 *pcbWritten = cb;
1257 GlobalUnlock(This->supportHandle);
1258 return S_OK;
1261 static HRESULT WINAPI NoStatStreamImpl_Seek(
1262 IStream* iface,
1263 LARGE_INTEGER dlibMove, /* [in] */
1264 DWORD dwOrigin, /* [in] */
1265 ULARGE_INTEGER* plibNewPosition) /* [out] */
1267 NoStatStreamImpl* const This = impl_from_IStream(iface);
1268 ULARGE_INTEGER newPosition;
1269 switch (dwOrigin)
1271 case STREAM_SEEK_SET:
1272 newPosition.u.HighPart = 0;
1273 newPosition.u.LowPart = 0;
1274 break;
1275 case STREAM_SEEK_CUR:
1276 newPosition = This->currentPosition;
1277 break;
1278 case STREAM_SEEK_END:
1279 newPosition = This->streamSize;
1280 break;
1281 default:
1282 return STG_E_INVALIDFUNCTION;
1284 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
1285 return STG_E_INVALIDFUNCTION;
1286 newPosition.QuadPart += dlibMove.QuadPart;
1287 if (plibNewPosition) *plibNewPosition = newPosition;
1288 This->currentPosition = newPosition;
1289 return S_OK;
1292 static HRESULT WINAPI NoStatStreamImpl_SetSize(
1293 IStream* iface,
1294 ULARGE_INTEGER libNewSize) /* [in] */
1296 NoStatStreamImpl* const This = impl_from_IStream(iface);
1297 HGLOBAL supportHandle;
1298 if (libNewSize.u.HighPart != 0)
1299 return STG_E_INVALIDFUNCTION;
1300 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
1301 return S_OK;
1302 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
1303 if (supportHandle == 0)
1304 return STG_E_MEDIUMFULL;
1305 This->supportHandle = supportHandle;
1306 This->streamSize.u.LowPart = libNewSize.u.LowPart;
1307 return S_OK;
1310 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
1311 IStream* iface,
1312 IStream* pstm, /* [unique][in] */
1313 ULARGE_INTEGER cb, /* [in] */
1314 ULARGE_INTEGER* pcbRead, /* [out] */
1315 ULARGE_INTEGER* pcbWritten) /* [out] */
1317 HRESULT hr = S_OK;
1318 BYTE tmpBuffer[128];
1319 ULONG bytesRead, bytesWritten, copySize;
1320 ULARGE_INTEGER totalBytesRead;
1321 ULARGE_INTEGER totalBytesWritten;
1323 if ( pstm == 0 )
1324 return STG_E_INVALIDPOINTER;
1325 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
1326 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
1328 while ( cb.u.LowPart > 0 )
1330 if ( cb.u.LowPart >= 128 )
1331 copySize = 128;
1332 else
1333 copySize = cb.u.LowPart;
1334 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
1335 totalBytesRead.u.LowPart += bytesRead;
1336 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
1337 totalBytesWritten.u.LowPart += bytesWritten;
1338 if (bytesRead != bytesWritten)
1340 hr = STG_E_MEDIUMFULL;
1341 break;
1343 if (bytesRead!=copySize)
1344 cb.u.LowPart = 0;
1345 else
1346 cb.u.LowPart -= bytesRead;
1348 if (pcbRead)
1350 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
1351 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
1354 if (pcbWritten)
1356 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
1357 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
1359 return hr;
1362 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
1364 return S_OK;
1366 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
1368 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
1369 IStream* iface,
1370 ULARGE_INTEGER libOffset, /* [in] */
1371 ULARGE_INTEGER cb, /* [in] */
1372 DWORD dwLockType) /* [in] */
1374 return S_OK;
1377 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
1378 IStream* iface,
1379 ULARGE_INTEGER libOffset, /* [in] */
1380 ULARGE_INTEGER cb, /* [in] */
1381 DWORD dwLockType) /* [in] */
1383 return S_OK;
1386 static HRESULT WINAPI NoStatStreamImpl_Stat(
1387 IStream* iface,
1388 STATSTG* pstatstg, /* [out] */
1389 DWORD grfStatFlag) /* [in] */
1391 return E_NOTIMPL;
1394 static HRESULT WINAPI NoStatStreamImpl_Clone(
1395 IStream* iface,
1396 IStream** ppstm) /* [out] */
1398 return E_NOTIMPL;
1400 static const IStreamVtbl NoStatStreamImpl_Vtbl;
1403 Build an object that implements IStream, without IStream_Stat capabilities.
1404 Receives a memory handle with data buffer. If memory handle is non-null,
1405 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
1406 In any case the object takes ownership of memory handle and will free it on
1407 object release.
1409 static IStream* NoStatStream_Construct(HGLOBAL hGlobal)
1411 NoStatStreamImpl* newStream;
1413 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
1414 if (newStream!=0)
1416 newStream->IStream_iface.lpVtbl = &NoStatStreamImpl_Vtbl;
1417 newStream->ref = 1;
1418 newStream->supportHandle = hGlobal;
1420 if (!newStream->supportHandle)
1421 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
1422 GMEM_SHARE, 0);
1423 newStream->currentPosition.u.HighPart = 0;
1424 newStream->currentPosition.u.LowPart = 0;
1425 newStream->streamSize.u.HighPart = 0;
1426 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
1428 return &newStream->IStream_iface;
1432 static const IStreamVtbl NoStatStreamImpl_Vtbl =
1434 NoStatStreamImpl_QueryInterface,
1435 NoStatStreamImpl_AddRef,
1436 NoStatStreamImpl_Release,
1437 NoStatStreamImpl_Read,
1438 NoStatStreamImpl_Write,
1439 NoStatStreamImpl_Seek,
1440 NoStatStreamImpl_SetSize,
1441 NoStatStreamImpl_CopyTo,
1442 NoStatStreamImpl_Commit,
1443 NoStatStreamImpl_Revert,
1444 NoStatStreamImpl_LockRegion,
1445 NoStatStreamImpl_UnlockRegion,
1446 NoStatStreamImpl_Stat,
1447 NoStatStreamImpl_Clone