po: Update Polish translation.
[wine/multimedia.git] / dlls / oleaut32 / tests / olepicture.c
blob54de1cbe8497d18807168974a4b09d2e75191c8b
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
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 *pOleCreatePictureIndirect)(PICTDESC*,REFIID,BOOL,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(!pOleCreatePictureIndirect)
492 win_skip("Skipping OleCreatePictureIndirect tests\n");
493 return;
496 if (0)
498 /* crashes on native */
499 pOleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, NULL);
502 hr = pOleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict);
503 ok(hr == S_OK, "hr %08x\n", hr);
505 type = PICTYPE_NONE;
506 hr = IPicture_get_Type(pict, &type);
507 ok(hr == S_OK, "hr %08x\n", hr);
508 ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type);
510 handle = 0xdeadbeef;
511 hr = IPicture_get_Handle(pict, &handle);
512 ok(hr == S_OK, "hr %08x\n", hr);
513 ok(handle == 0, "handle %08x\n", handle);
515 IPicture_Release(pict);
518 static void test_apm(void)
520 OLE_HANDLE handle;
521 LPSTREAM stream;
522 IPicture *pict;
523 HGLOBAL hglob;
524 LPBYTE *data;
525 LONG cxy;
526 BOOL keep;
527 short type;
529 hglob = GlobalAlloc (0, sizeof(apmdata));
530 data = GlobalLock(hglob);
531 memcpy(data, apmdata, sizeof(apmdata));
533 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
534 ole_check(OleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict));
536 ole_check(IPicture_get_Handle(pict, &handle));
537 ok(handle != 0, "handle is null\n");
539 ole_check(IPicture_get_Type(pict, &type));
540 expect_eq(type, PICTYPE_METAFILE, short, "%d");
542 ole_check(IPicture_get_Height(pict, &cxy));
543 expect_eq(cxy, 1667, LONG, "%d");
545 ole_check(IPicture_get_Width(pict, &cxy));
546 expect_eq(cxy, 1323, LONG, "%d");
548 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
549 todo_wine expect_eq(keep, FALSE, LONG, "%d");
551 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL);
552 IPicture_Release(pict);
553 IStream_Release(stream);
556 static void test_metafile(void)
558 LPSTREAM stream;
559 IPicture *pict;
560 HGLOBAL hglob;
561 LPBYTE *data;
563 hglob = GlobalAlloc (0, sizeof(metafile));
564 data = GlobalLock(hglob);
565 memcpy(data, metafile, sizeof(metafile));
567 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
568 /* Windows does not load simple metafiles */
569 ole_expect(OleLoadPictureEx(stream, sizeof(metafile), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict), E_FAIL);
571 IStream_Release(stream);
574 static void test_enhmetafile(void)
576 OLE_HANDLE handle;
577 LPSTREAM stream;
578 IPicture *pict;
579 HGLOBAL hglob;
580 LPBYTE *data;
581 LONG cxy;
582 BOOL keep;
583 short type;
585 hglob = GlobalAlloc (0, sizeof(enhmetafile));
586 data = GlobalLock(hglob);
587 memcpy(data, enhmetafile, sizeof(enhmetafile));
589 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
590 ole_check(OleLoadPictureEx(stream, sizeof(enhmetafile), TRUE, &IID_IPicture, 10, 10, 0, (LPVOID *)&pict));
592 ole_check(IPicture_get_Handle(pict, &handle));
593 ok(handle != 0, "handle is null\n");
595 ole_check(IPicture_get_Type(pict, &type));
596 expect_eq(type, PICTYPE_ENHMETAFILE, short, "%d");
598 ole_check(IPicture_get_Height(pict, &cxy));
599 expect_eq(cxy, -23, LONG, "%d");
601 ole_check(IPicture_get_Width(pict, &cxy));
602 expect_eq(cxy, -25, LONG, "%d");
604 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
605 todo_wine expect_eq(keep, FALSE, LONG, "%d");
607 IPicture_Release(pict);
608 IStream_Release(stream);
611 static void test_Render(void)
613 IPicture *pic;
614 HRESULT hres;
615 short type;
616 PICTDESC desc;
617 OLE_XSIZE_HIMETRIC pWidth;
618 OLE_YSIZE_HIMETRIC pHeight;
619 COLORREF result, expected;
620 HDC hdc = GetDC(0);
622 /* test IPicture::Render return code on uninitialized picture */
623 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
624 hres = IPicture_get_Type(pic, &type);
625 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
626 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
627 /* zero dimensions */
628 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
629 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
630 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
631 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
632 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
633 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
634 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
635 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
636 hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
637 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
638 hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
639 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
640 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
641 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
642 /* nonzero dimensions, PICTYPE_UNINITIALIZED */
643 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL);
644 ole_expect(hres, S_OK);
645 IPicture_Release(pic);
647 desc.cbSizeofstruct = sizeof(PICTDESC);
648 desc.picType = PICTYPE_ICON;
649 desc.u.icon.hicon = LoadIcon(NULL, IDI_APPLICATION);
650 if(!desc.u.icon.hicon){
651 win_skip("LoadIcon failed. Skipping...\n");
652 ReleaseDC(NULL, hdc);
653 return;
656 OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (VOID**)&pic);
657 /* zero dimensions, PICTYPE_ICON */
658 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
659 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
660 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
661 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
662 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
663 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
664 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
665 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
666 hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
667 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
668 hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
669 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
670 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
671 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
673 /* Check if target size and position is respected */
674 IPicture_get_Width(pic, &pWidth);
675 IPicture_get_Height(pic, &pHeight);
677 SetPixelV(hdc, 0, 0, 0x00F0F0F0);
678 SetPixelV(hdc, 5, 5, 0x00F0F0F0);
679 SetPixelV(hdc, 10, 10, 0x00F0F0F0);
680 expected = GetPixel(hdc, 0, 0);
682 hres = IPicture_Render(pic, hdc, 1, 1, 9, 9, 0, 0, pWidth, -pHeight, NULL);
683 ole_expect(hres, S_OK);
685 if(hres != S_OK) {
686 IPicture_Release(pic);
687 ReleaseDC(NULL, hdc);
688 return;
691 /* Evaluate the rendered Icon */
692 result = GetPixel(hdc, 0, 0);
693 ok(result == expected,
694 "Color at 0,0 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
695 result = GetPixel(hdc, 5, 5);
696 ok(result != expected ||
697 broken(result == expected), /* WinNT 4.0 and older may claim they drew */
698 /* the icon, even if they didn't. */
699 "Color at 5,5 should have changed, but still was 0x%06X\n", expected);
700 result = GetPixel(hdc, 10, 10);
701 ok(result == expected,
702 "Color at 10,10 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
704 IPicture_Release(pic);
705 ReleaseDC(NULL, hdc);
708 static void test_get_Attributes(void)
710 IPicture *pic;
711 HRESULT hres;
712 short type;
713 DWORD attr;
715 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
716 hres = IPicture_get_Type(pic, &type);
717 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
718 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
720 hres = IPicture_get_Attributes(pic, NULL);
721 ole_expect(hres, E_POINTER);
723 attr = 0xdeadbeef;
724 hres = IPicture_get_Attributes(pic, &attr);
725 ole_expect(hres, S_OK);
726 ok(attr == 0, "IPicture_get_Attributes does not reset attr to zero, got %d\n", attr);
728 IPicture_Release(pic);
731 static void test_get_Handle(void)
733 IPicture *pic;
734 HRESULT hres;
736 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
738 hres = IPicture_get_Handle(pic, NULL);
739 ole_expect(hres, E_POINTER);
741 IPicture_Release(pic);
744 static void test_get_Type(void)
746 IPicture *pic;
747 HRESULT hres;
749 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
751 hres = IPicture_get_Type(pic, NULL);
752 ole_expect(hres, E_POINTER);
754 IPicture_Release(pic);
757 static void test_OleLoadPicturePath(void)
759 static WCHAR emptyW[] = {0};
761 IPicture *pic;
762 HRESULT hres;
763 int i;
764 char temp_path[MAX_PATH];
765 char temp_file[MAX_PATH];
766 WCHAR temp_fileW[MAX_PATH + 5] = {'f','i','l','e',':','/','/','/'};
767 HANDLE file;
768 DWORD size;
769 WCHAR *ptr;
771 const struct
773 LPOLESTR szURLorPath;
774 REFIID riid;
775 IPicture **pic;
776 } invalid_parameters[] =
778 {NULL, NULL, NULL},
779 {NULL, NULL, &pic},
780 {NULL, &IID_IPicture, NULL},
781 {NULL, &IID_IPicture, &pic},
782 {emptyW, NULL, NULL},
783 {emptyW, &IID_IPicture, NULL},
786 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
788 pic = (IPicture *)0xdeadbeef;
789 hres = OleLoadPicturePath(invalid_parameters[i].szURLorPath, NULL, 0, 0,
790 invalid_parameters[i].riid,
791 (void **)invalid_parameters[i].pic);
792 ok(hres == E_INVALIDARG,
793 "[%d] Expected OleLoadPicturePath to return E_INVALIDARG, got 0x%08x\n", i, hres);
794 ok(pic == (IPicture *)0xdeadbeef,
795 "[%d] Expected output pointer to be 0xdeadbeef, got %p\n", i, pic);
798 pic = (IPicture *)0xdeadbeef;
799 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, NULL, (void **)&pic);
800 todo_wine
801 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
802 broken(hres == E_UNEXPECTED) || /* NT4 */
803 broken(hres == E_OUTOFMEMORY), /* Win2k/Win2k3 */
804 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
805 ok(pic == NULL,
806 "Expected the output interface pointer to be NULL, got %p\n", pic);
808 pic = (IPicture *)0xdeadbeef;
809 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
810 todo_wine
811 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
812 broken(hres == E_UNEXPECTED) || /* NT4 */
813 broken(hres == E_OUTOFMEMORY), /* Win2k/Win2k3 */
814 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
815 ok(pic == NULL,
816 "Expected the output interface pointer to be NULL, got %p\n", pic);
818 /* Create a local temporary image file for testing. */
819 GetTempPathA(sizeof(temp_path), temp_path);
820 GetTempFileNameA(temp_path, "bmp", 0, temp_file);
821 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
822 FILE_ATTRIBUTE_NORMAL, NULL);
823 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
824 CloseHandle(file);
826 MultiByteToWideChar(CP_ACP, 0, temp_file, -1, temp_fileW + 8, sizeof(temp_fileW)/sizeof(WCHAR) - 8);
828 /* Try a normal DOS path. */
829 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
830 ok(hres == S_OK ||
831 broken(hres == E_UNEXPECTED), /* NT4 */
832 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
833 if (pic)
834 IPicture_Release(pic);
836 /* Try a DOS path with tacked on "file:". */
837 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
838 ok(hres == S_OK ||
839 broken(hres == E_UNEXPECTED), /* NT4 */
840 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
841 if (pic)
842 IPicture_Release(pic);
844 DeleteFileA(temp_file);
846 /* Try with a nonexistent file. */
847 hres = OleLoadPicturePath(temp_fileW + 8, 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 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
854 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
855 broken(hres == E_UNEXPECTED) || /* NT4 */
856 broken(hres == E_FAIL), /* Win2k */
857 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
859 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
860 FILE_ATTRIBUTE_NORMAL, NULL);
861 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
862 CloseHandle(file);
864 /* Try a "file:" URL with slash separators. */
865 ptr = temp_fileW + 8;
866 while (*ptr)
868 if (*ptr == '\\')
869 *ptr = '/';
870 ptr++;
873 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
874 ok(hres == S_OK ||
875 broken(hres == E_UNEXPECTED), /* NT4 */
876 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
877 if (pic)
878 IPicture_Release(pic);
880 DeleteFileA(temp_file);
882 /* Try with a nonexistent file. */
883 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
884 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
885 broken(hres == E_UNEXPECTED) || /* NT4 */
886 broken(hres == E_FAIL), /* Win2k */
887 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
890 static void test_himetric(void)
892 static const BYTE bmp_bits[1024];
893 OLE_XSIZE_HIMETRIC cx;
894 OLE_YSIZE_HIMETRIC cy;
895 IPicture *pic;
896 PICTDESC desc;
897 HBITMAP bmp;
898 HRESULT hr;
899 HICON icon;
900 HDC hdc;
901 INT d;
903 if (!pOleCreatePictureIndirect)
905 win_skip("OleCreatePictureIndirect not available\n");
906 return;
909 desc.cbSizeofstruct = sizeof(desc);
910 desc.picType = PICTYPE_BITMAP;
911 desc.u.bmp.hpal = NULL;
913 hdc = CreateCompatibleDC(0);
915 bmp = CreateBitmap(1.9 * GetDeviceCaps(hdc, LOGPIXELSX),
916 1.9 * GetDeviceCaps(hdc, LOGPIXELSY), 1, 1, NULL);
918 desc.u.bmp.hbitmap = bmp;
920 /* size in himetric units reported rounded up to next integer value */
921 hr = pOleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
922 ok(hr == S_OK, "got 0x%08x\n", hr);
924 cx = 0;
925 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSX)), 2540, GetDeviceCaps(hdc, LOGPIXELSX));
926 hr = IPicture_get_Width(pic, &cx);
927 ok(hr == S_OK, "got 0x%08x\n", hr);
928 ok(cx == d, "got %d, expected %d\n", cx, d);
930 cy = 0;
931 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSY)), 2540, GetDeviceCaps(hdc, LOGPIXELSY));
932 hr = IPicture_get_Height(pic, &cy);
933 ok(hr == S_OK, "got 0x%08x\n", hr);
934 ok(cy == d, "got %d, expected %d\n", cy, d);
936 DeleteObject(bmp);
937 IPicture_Release(pic);
939 /* same thing with icon */
940 icon = CreateIcon(NULL, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
941 1, 1, bmp_bits, bmp_bits);
942 ok(icon != NULL, "failed to create icon\n");
944 desc.picType = PICTYPE_ICON;
945 desc.u.icon.hicon = icon;
947 hr = pOleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
948 ok(hr == S_OK, "got 0x%08x\n", hr);
950 cx = 0;
951 d = MulDiv(GetSystemMetrics(SM_CXICON), 2540, GetDeviceCaps(hdc, LOGPIXELSX));
952 hr = IPicture_get_Width(pic, &cx);
953 ok(hr == S_OK, "got 0x%08x\n", hr);
954 ok(cx == d, "got %d, expected %d\n", cx, d);
956 cy = 0;
957 d = MulDiv(GetSystemMetrics(SM_CYICON), 2540, GetDeviceCaps(hdc, LOGPIXELSY));
958 hr = IPicture_get_Height(pic, &cy);
959 ok(hr == S_OK, "got 0x%08x\n", hr);
960 ok(cy == d, "got %d, expected %d\n", cy, d);
962 IPicture_Release(pic);
963 DestroyIcon(icon);
965 DeleteDC(hdc);
968 START_TEST(olepicture)
970 hOleaut32 = GetModuleHandleA("oleaut32.dll");
971 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
972 pOleCreatePictureIndirect = (void*)GetProcAddress(hOleaut32, "OleCreatePictureIndirect");
973 if (!pOleLoadPicture)
975 win_skip("OleLoadPicture is not available\n");
976 return;
979 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
980 test_pic(gifimage, sizeof(gifimage));
981 test_pic(jpgimage, sizeof(jpgimage));
982 test_pic(bmpimage, sizeof(bmpimage));
983 test_pic(gif4pixel, sizeof(gif4pixel));
984 /* FIXME: No PNG support in Windows... */
985 if (0) test_pic(pngimage, sizeof(pngimage));
986 test_empty_image();
987 test_empty_image_2();
988 test_apm();
989 test_metafile();
990 test_enhmetafile();
992 test_Invoke();
993 test_OleCreatePictureIndirect();
994 test_Render();
995 test_get_Attributes();
996 test_get_Handle();
997 test_get_Type();
998 test_OleLoadPicturePath();
999 test_himetric();
1003 /* Helper functions only ... */
1006 static inline NoStatStreamImpl *impl_from_IStream(IStream *iface)
1008 return CONTAINING_RECORD(iface, NoStatStreamImpl, IStream_iface);
1011 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
1013 GlobalFree(This->supportHandle);
1014 This->supportHandle=0;
1015 HeapFree(GetProcessHeap(), 0, This);
1018 static ULONG WINAPI NoStatStreamImpl_AddRef(
1019 IStream* iface)
1021 NoStatStreamImpl* const This = impl_from_IStream(iface);
1022 return InterlockedIncrement(&This->ref);
1025 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
1026 IStream* iface,
1027 REFIID riid, /* [in] */
1028 void** ppvObject) /* [iid_is][out] */
1030 NoStatStreamImpl* const This = impl_from_IStream(iface);
1031 if (ppvObject==0) return E_INVALIDARG;
1032 *ppvObject = 0;
1033 if (IsEqualIID(&IID_IUnknown, riid))
1035 *ppvObject = This;
1037 else if (IsEqualIID(&IID_IStream, riid))
1039 *ppvObject = This;
1042 if ((*ppvObject)==0)
1043 return E_NOINTERFACE;
1044 NoStatStreamImpl_AddRef(iface);
1045 return S_OK;
1048 static ULONG WINAPI NoStatStreamImpl_Release(
1049 IStream* iface)
1051 NoStatStreamImpl* const This = impl_from_IStream(iface);
1052 ULONG newRef = InterlockedDecrement(&This->ref);
1053 if (newRef==0)
1054 NoStatStreamImpl_Destroy(This);
1055 return newRef;
1058 static HRESULT WINAPI NoStatStreamImpl_Read(
1059 IStream* iface,
1060 void* pv, /* [length_is][size_is][out] */
1061 ULONG cb, /* [in] */
1062 ULONG* pcbRead) /* [out] */
1064 NoStatStreamImpl* const This = impl_from_IStream(iface);
1065 void* supportBuffer;
1066 ULONG bytesReadBuffer;
1067 ULONG bytesToReadFromBuffer;
1069 if (pcbRead==0)
1070 pcbRead = &bytesReadBuffer;
1071 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
1072 supportBuffer = GlobalLock(This->supportHandle);
1073 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
1074 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
1075 *pcbRead = bytesToReadFromBuffer;
1076 GlobalUnlock(This->supportHandle);
1077 if(*pcbRead == cb)
1078 return S_OK;
1079 return S_FALSE;
1082 static HRESULT WINAPI NoStatStreamImpl_Write(
1083 IStream* iface,
1084 const void* pv, /* [size_is][in] */
1085 ULONG cb, /* [in] */
1086 ULONG* pcbWritten) /* [out] */
1088 NoStatStreamImpl* const This = impl_from_IStream(iface);
1089 void* supportBuffer;
1090 ULARGE_INTEGER newSize;
1091 ULONG bytesWritten = 0;
1093 if (pcbWritten == 0)
1094 pcbWritten = &bytesWritten;
1095 if (cb == 0)
1096 return S_OK;
1097 newSize.u.HighPart = 0;
1098 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
1099 if (newSize.u.LowPart > This->streamSize.u.LowPart)
1100 IStream_SetSize(iface, newSize);
1102 supportBuffer = GlobalLock(This->supportHandle);
1103 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
1104 This->currentPosition.u.LowPart+=cb;
1105 *pcbWritten = cb;
1106 GlobalUnlock(This->supportHandle);
1107 return S_OK;
1110 static HRESULT WINAPI NoStatStreamImpl_Seek(
1111 IStream* iface,
1112 LARGE_INTEGER dlibMove, /* [in] */
1113 DWORD dwOrigin, /* [in] */
1114 ULARGE_INTEGER* plibNewPosition) /* [out] */
1116 NoStatStreamImpl* const This = impl_from_IStream(iface);
1117 ULARGE_INTEGER newPosition;
1118 switch (dwOrigin)
1120 case STREAM_SEEK_SET:
1121 newPosition.u.HighPart = 0;
1122 newPosition.u.LowPart = 0;
1123 break;
1124 case STREAM_SEEK_CUR:
1125 newPosition = This->currentPosition;
1126 break;
1127 case STREAM_SEEK_END:
1128 newPosition = This->streamSize;
1129 break;
1130 default:
1131 return STG_E_INVALIDFUNCTION;
1133 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
1134 return STG_E_INVALIDFUNCTION;
1135 newPosition.QuadPart += dlibMove.QuadPart;
1136 if (plibNewPosition) *plibNewPosition = newPosition;
1137 This->currentPosition = newPosition;
1138 return S_OK;
1141 static HRESULT WINAPI NoStatStreamImpl_SetSize(
1142 IStream* iface,
1143 ULARGE_INTEGER libNewSize) /* [in] */
1145 NoStatStreamImpl* const This = impl_from_IStream(iface);
1146 HGLOBAL supportHandle;
1147 if (libNewSize.u.HighPart != 0)
1148 return STG_E_INVALIDFUNCTION;
1149 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
1150 return S_OK;
1151 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
1152 if (supportHandle == 0)
1153 return STG_E_MEDIUMFULL;
1154 This->supportHandle = supportHandle;
1155 This->streamSize.u.LowPart = libNewSize.u.LowPart;
1156 return S_OK;
1159 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
1160 IStream* iface,
1161 IStream* pstm, /* [unique][in] */
1162 ULARGE_INTEGER cb, /* [in] */
1163 ULARGE_INTEGER* pcbRead, /* [out] */
1164 ULARGE_INTEGER* pcbWritten) /* [out] */
1166 HRESULT hr = S_OK;
1167 BYTE tmpBuffer[128];
1168 ULONG bytesRead, bytesWritten, copySize;
1169 ULARGE_INTEGER totalBytesRead;
1170 ULARGE_INTEGER totalBytesWritten;
1172 if ( pstm == 0 )
1173 return STG_E_INVALIDPOINTER;
1174 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
1175 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
1177 while ( cb.u.LowPart > 0 )
1179 if ( cb.u.LowPart >= 128 )
1180 copySize = 128;
1181 else
1182 copySize = cb.u.LowPart;
1183 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
1184 totalBytesRead.u.LowPart += bytesRead;
1185 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
1186 totalBytesWritten.u.LowPart += bytesWritten;
1187 if (bytesRead != bytesWritten)
1189 hr = STG_E_MEDIUMFULL;
1190 break;
1192 if (bytesRead!=copySize)
1193 cb.u.LowPart = 0;
1194 else
1195 cb.u.LowPart -= bytesRead;
1197 if (pcbRead)
1199 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
1200 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
1203 if (pcbWritten)
1205 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
1206 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
1208 return hr;
1211 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
1213 return S_OK;
1215 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
1217 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
1218 IStream* iface,
1219 ULARGE_INTEGER libOffset, /* [in] */
1220 ULARGE_INTEGER cb, /* [in] */
1221 DWORD dwLockType) /* [in] */
1223 return S_OK;
1226 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
1227 IStream* iface,
1228 ULARGE_INTEGER libOffset, /* [in] */
1229 ULARGE_INTEGER cb, /* [in] */
1230 DWORD dwLockType) /* [in] */
1232 return S_OK;
1235 static HRESULT WINAPI NoStatStreamImpl_Stat(
1236 IStream* iface,
1237 STATSTG* pstatstg, /* [out] */
1238 DWORD grfStatFlag) /* [in] */
1240 return E_NOTIMPL;
1243 static HRESULT WINAPI NoStatStreamImpl_Clone(
1244 IStream* iface,
1245 IStream** ppstm) /* [out] */
1247 return E_NOTIMPL;
1249 static const IStreamVtbl NoStatStreamImpl_Vtbl;
1252 Build an object that implements IStream, without IStream_Stat capabilities.
1253 Receives a memory handle with data buffer. If memory handle is non-null,
1254 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
1255 In any case the object takes ownership of memory handle and will free it on
1256 object release.
1258 static IStream* NoStatStream_Construct(HGLOBAL hGlobal)
1260 NoStatStreamImpl* newStream;
1262 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
1263 if (newStream!=0)
1265 newStream->IStream_iface.lpVtbl = &NoStatStreamImpl_Vtbl;
1266 newStream->ref = 1;
1267 newStream->supportHandle = hGlobal;
1269 if (!newStream->supportHandle)
1270 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
1271 GMEM_SHARE, 0);
1272 newStream->currentPosition.u.HighPart = 0;
1273 newStream->currentPosition.u.LowPart = 0;
1274 newStream->streamSize.u.HighPart = 0;
1275 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
1277 return &newStream->IStream_iface;
1281 static const IStreamVtbl NoStatStreamImpl_Vtbl =
1283 NoStatStreamImpl_QueryInterface,
1284 NoStatStreamImpl_AddRef,
1285 NoStatStreamImpl_Release,
1286 NoStatStreamImpl_Read,
1287 NoStatStreamImpl_Write,
1288 NoStatStreamImpl_Seek,
1289 NoStatStreamImpl_SetSize,
1290 NoStatStreamImpl_CopyTo,
1291 NoStatStreamImpl_Commit,
1292 NoStatStreamImpl_Revert,
1293 NoStatStreamImpl_LockRegion,
1294 NoStatStreamImpl_UnlockRegion,
1295 NoStatStreamImpl_Stat,
1296 NoStatStreamImpl_Clone