wer: Add new stubbed wer.dll.
[wine/hramrach.git] / dlls / oleaut32 / tests / olepicture.c
blob03d47db5d1d9d0fa10ce1f997068a68789eca306
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 NONAMELESSUNION
30 #include "wine/test.h"
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winuser.h>
34 #include <wingdi.h>
35 #include <winnls.h>
36 #include <winerror.h>
37 #include <winnt.h>
39 #include <urlmon.h>
40 #include <wtypes.h>
41 #include <olectl.h>
42 #include <objidl.h>
44 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
46 #define ole_expect(expr, expect) { \
47 HRESULT r = expr; \
48 ok(r == (expect), #expr " returned %x, expected %s (%x)\n", r, #expect, expect); \
51 #define ole_check(expr) ole_expect(expr, S_OK);
53 static HMODULE hOleaut32;
55 static HRESULT (WINAPI *pOleLoadPicture)(LPSTREAM,LONG,BOOL,REFIID,LPVOID*);
56 static HRESULT (WINAPI *pOleCreatePictureIndirect)(PICTDESC*,REFIID,BOOL,LPVOID*);
58 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
60 /* 1x1 pixel gif */
61 static const unsigned char gifimage[35] = {
62 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
63 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
64 0x01,0x00,0x3b
67 /* 1x1 pixel jpg */
68 static const unsigned char jpgimage[285] = {
69 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
70 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
71 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
72 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
73 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
74 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
75 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
76 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
77 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
78 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
79 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
80 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
81 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
82 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
83 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
84 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
85 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
86 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
89 /* 1x1 pixel png */
90 static const unsigned char pngimage[285] = {
91 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
92 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
93 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
94 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
95 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
96 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
97 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
100 /* 1x1 pixel bmp */
101 static const unsigned char bmpimage[66] = {
102 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
103 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
104 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
105 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
106 0x00,0x00
109 /* 2x2 pixel gif */
110 static const unsigned char gif4pixel[42] = {
111 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
112 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
113 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
116 /* APM with an empty metafile with some padding zeros - looks like under Window the
117 * metafile data should be at least 20 bytes */
118 static const unsigned char apmdata[] = {
119 0xd7,0xcd,0xc6,0x9a, 0x00,0x00,0x00,0x00, 0x00,0x00,0xee,0x02, 0xb1,0x03,0xa0,0x05,
120 0x00,0x00,0x00,0x00, 0xee,0x53,0x01,0x00, 0x09,0x00,0x00,0x03, 0x13,0x00,0x00,0x00,
121 0x01,0x00,0x05,0x00, 0x00,0x00,0x00,0x00, 0x03,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
122 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
125 /* MF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
126 static const unsigned char metafile[] = {
127 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
128 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
129 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
130 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
131 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
132 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
133 0x00, 0x00
136 /* EMF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
137 static const unsigned char enhmetafile[] = {
138 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
143 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
144 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
145 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
148 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
151 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
152 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
153 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
155 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
156 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
157 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
158 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
161 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
162 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
163 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
164 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
165 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
166 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
167 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
168 0x14, 0x00, 0x00, 0x00
172 struct NoStatStreamImpl
174 const IStreamVtbl *lpVtbl;
175 LONG ref;
177 HGLOBAL supportHandle;
178 ULARGE_INTEGER streamSize;
179 ULARGE_INTEGER currentPosition;
181 typedef struct NoStatStreamImpl NoStatStreamImpl;
182 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal);
184 static void
185 test_pic_with_stream(LPSTREAM stream, unsigned int imgsize)
187 IPicture* pic = NULL;
188 HRESULT hres;
189 LPVOID pvObj = NULL;
190 OLE_HANDLE handle, hPal;
191 OLE_XSIZE_HIMETRIC width;
192 OLE_YSIZE_HIMETRIC height;
193 short type;
194 DWORD attr;
195 ULONG res;
197 pvObj = NULL;
198 hres = pOleLoadPicture(stream, imgsize, TRUE, &IID_IPicture, &pvObj);
199 pic = pvObj;
201 ok(hres == S_OK,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres);
202 ok(pic != NULL,"OLP (NULL,..) returns NULL, instead of !NULL\n");
203 if (pic == NULL)
204 return;
206 pvObj = NULL;
207 hres = IPicture_QueryInterface (pic, &IID_IPicture, &pvObj);
209 ok(hres == S_OK,"IPicture_QI does not return S_OK, but 0x%08x\n", hres);
210 ok(pvObj != NULL,"IPicture_QI does return NULL, instead of a ptr\n");
212 IPicture_Release ((IPicture*)pvObj);
214 handle = 0;
215 hres = IPicture_get_Handle (pic, &handle);
216 ok(hres == S_OK,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres);
217 ok(handle != 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
219 if (handle)
221 BITMAP bmp;
222 GetObject((HGDIOBJ)handle, sizeof(BITMAP), &bmp);
223 todo_wine ok(bmp.bmBits != 0, "not a dib\n");
226 width = 0;
227 hres = IPicture_get_Width (pic, &width);
228 ok(hres == S_OK,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres);
229 ok(width != 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
231 height = 0;
232 hres = IPicture_get_Height (pic, &height);
233 ok(hres == S_OK,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres);
234 ok(height != 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
236 type = 0;
237 hres = IPicture_get_Type (pic, &type);
238 ok(hres == S_OK,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
239 ok(type == PICTYPE_BITMAP, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type, PICTYPE_BITMAP);
241 attr = 0;
242 hres = IPicture_get_Attributes (pic, &attr);
243 ok(hres == S_OK,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres);
244 ok(attr == 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr);
246 hPal = 0;
247 hres = IPicture_get_hPal (pic, &hPal);
248 ok(hres == S_OK,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres);
249 /* a single pixel b/w image has no palette */
250 ok(hPal == 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal);
252 res = IPicture_Release (pic);
253 ok (res == 0, "refcount after release is %d, but should be 0?\n", res);
256 static void
257 test_pic(const unsigned char *imgdata, unsigned int imgsize)
259 LPSTREAM stream;
260 HGLOBAL hglob;
261 LPBYTE data;
262 HRESULT hres;
263 LARGE_INTEGER seekto;
264 ULARGE_INTEGER newpos1;
265 DWORD * header;
266 unsigned int i,j;
268 /* Let the fun begin */
269 hglob = GlobalAlloc (0, imgsize);
270 data = GlobalLock (hglob);
271 memcpy(data, imgdata, imgsize);
272 GlobalUnlock(hglob); data = NULL;
274 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
275 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
277 memset(&seekto,0,sizeof(seekto));
278 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
279 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
280 test_pic_with_stream(stream, imgsize);
282 IStream_Release(stream);
284 /* again with Non Statable and Non Seekable stream */
285 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
286 hglob = 0; /* Non-statable impl always deletes on release */
287 test_pic_with_stream(stream, 0);
289 IStream_Release(stream);
290 for (i = 1; i <= 8; i++) {
291 /* more fun!!! */
292 hglob = GlobalAlloc (0, imgsize + i * (2 * sizeof(DWORD)));
293 data = GlobalLock (hglob);
294 header = (DWORD *)data;
296 /* multiple copies of header */
297 memcpy(data,"lt\0\0",4);
298 header[1] = imgsize;
299 for (j = 2; j <= i; j++) {
300 memcpy(&(header[2 * (j - 1)]), header, 2 * sizeof(DWORD));
302 memcpy(data + i * (2 * sizeof(DWORD)), imgdata, imgsize);
303 GlobalUnlock(hglob); data = NULL;
305 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
306 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
308 memset(&seekto,0,sizeof(seekto));
309 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
310 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
311 test_pic_with_stream(stream, imgsize);
313 IStream_Release(stream);
315 /* again with Non Statable and Non Seekable stream */
316 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
317 hglob = 0; /* Non-statable impl always deletes on release */
318 test_pic_with_stream(stream, 0);
320 IStream_Release(stream);
324 static void test_empty_image(void) {
325 LPBYTE data;
326 LPSTREAM stream;
327 IPicture* pic = NULL;
328 HRESULT hres;
329 LPVOID pvObj = NULL;
330 HGLOBAL hglob;
331 OLE_HANDLE handle;
332 ULARGE_INTEGER newpos1;
333 LARGE_INTEGER seekto;
334 short type;
335 DWORD attr;
337 /* Empty image. Happens occasionally in VB programs. */
338 hglob = GlobalAlloc (0, 8);
339 data = GlobalLock (hglob);
340 memcpy(data,"lt\0\0",4);
341 ((DWORD*)data)[1] = 0;
342 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
343 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
345 memset(&seekto,0,sizeof(seekto));
346 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
347 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
349 pvObj = NULL;
350 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
351 pic = pvObj;
352 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
353 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
355 hres = IPicture_get_Type (pic, &type);
356 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
357 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
359 attr = 0xdeadbeef;
360 hres = IPicture_get_Attributes (pic, &attr);
361 ok (hres == S_OK,"empty picture get attributes failed with hres 0x%08x\n", hres);
362 ok (attr == 0,"attr is %d, but should be 0\n", attr);
364 hres = IPicture_get_Handle (pic, &handle);
365 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
366 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
367 IPicture_Release (pic);
368 IStream_Release (stream);
371 static void test_empty_image_2(void) {
372 LPBYTE data;
373 LPSTREAM stream;
374 IPicture* pic = NULL;
375 HRESULT hres;
376 LPVOID pvObj = NULL;
377 HGLOBAL hglob;
378 ULARGE_INTEGER newpos1;
379 LARGE_INTEGER seekto;
380 short type;
382 /* Empty image at random stream position. */
383 hglob = GlobalAlloc (0, 200);
384 data = GlobalLock (hglob);
385 data += 42;
386 memcpy(data,"lt\0\0",4);
387 ((DWORD*)data)[1] = 0;
388 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
389 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
391 memset(&seekto,0,sizeof(seekto));
392 seekto.u.LowPart = 42;
393 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
394 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
396 pvObj = NULL;
397 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
398 pic = pvObj;
399 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
400 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
402 hres = IPicture_get_Type (pic, &type);
403 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
404 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
406 IPicture_Release (pic);
407 IStream_Release (stream);
410 static void test_Invoke(void)
412 IPictureDisp *picdisp;
413 HRESULT hr;
414 VARIANTARG vararg;
415 DISPPARAMS dispparams;
416 VARIANT varresult;
417 IStream *stream;
418 HGLOBAL hglob;
419 void *data;
421 hglob = GlobalAlloc (0, sizeof(gifimage));
422 data = GlobalLock(hglob);
423 memcpy(data, gifimage, sizeof(gifimage));
424 GlobalUnlock(hglob);
426 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
427 ok_ole_success(hr, "CreateStreamOnHGlobal");
429 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
430 IStream_Release(stream);
431 GlobalFree(hglob);
432 ok_ole_success(hr, "OleLoadPicture");
434 V_VT(&vararg) = VT_BOOL;
435 V_BOOL(&vararg) = VARIANT_FALSE;
436 dispparams.cNamedArgs = 0;
437 dispparams.rgdispidNamedArgs = NULL;
438 dispparams.cArgs = 1;
439 dispparams.rgvarg = &vararg;
440 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
441 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
442 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
443 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
445 dispparams.cArgs = 0;
446 dispparams.rgvarg = NULL;
447 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
448 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
450 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
451 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
453 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
454 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
456 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
457 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
459 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
460 ok_ole_success(hr, "IPictureDisp_Invoke");
461 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
463 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
464 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
466 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
467 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
469 dispparams.cArgs = 1;
470 dispparams.rgvarg = &vararg;
471 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
472 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
474 dispparams.cArgs = 1;
475 dispparams.rgvarg = &vararg;
476 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
477 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
479 IPictureDisp_Release(picdisp);
482 static void test_OleCreatePictureIndirect(void)
484 OLE_HANDLE handle;
485 IPicture *pict;
486 HRESULT hr;
487 short type;
489 if(!pOleCreatePictureIndirect)
491 win_skip("Skipping OleCreatePictureIndirect tests\n");
492 return;
495 if (0)
497 /* crashes on native */
498 hr = pOleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, NULL);
501 hr = pOleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict);
502 ok(hr == S_OK, "hr %08x\n", hr);
504 type = PICTYPE_NONE;
505 hr = IPicture_get_Type(pict, &type);
506 ok(hr == S_OK, "hr %08x\n", hr);
507 ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type);
509 handle = 0xdeadbeef;
510 hr = IPicture_get_Handle(pict, &handle);
511 ok(hr == S_OK, "hr %08x\n", hr);
512 ok(handle == 0, "handle %08x\n", handle);
514 IPicture_Release(pict);
517 static void test_apm(void)
519 OLE_HANDLE handle;
520 LPSTREAM stream;
521 IPicture *pict;
522 HGLOBAL hglob;
523 LPBYTE *data;
524 LONG cxy;
525 BOOL keep;
526 short type;
528 hglob = GlobalAlloc (0, sizeof(apmdata));
529 data = GlobalLock(hglob);
530 memcpy(data, apmdata, sizeof(apmdata));
532 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
533 ole_check(OleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict));
535 ole_check(IPicture_get_Handle(pict, &handle));
536 ok(handle != 0, "handle is null\n");
538 ole_check(IPicture_get_Type(pict, &type));
539 expect_eq(type, PICTYPE_METAFILE, short, "%d");
541 ole_check(IPicture_get_Height(pict, &cxy));
542 expect_eq(cxy, 1667, LONG, "%d");
544 ole_check(IPicture_get_Width(pict, &cxy));
545 expect_eq(cxy, 1323, LONG, "%d");
547 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
548 todo_wine expect_eq(keep, FALSE, LONG, "%d");
550 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL);
551 IPicture_Release(pict);
552 IStream_Release(stream);
555 static void test_metafile(void)
557 LPSTREAM stream;
558 IPicture *pict;
559 HGLOBAL hglob;
560 LPBYTE *data;
562 hglob = GlobalAlloc (0, sizeof(metafile));
563 data = GlobalLock(hglob);
564 memcpy(data, metafile, sizeof(metafile));
566 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
567 /* Windows does not load simple metafiles */
568 ole_expect(OleLoadPictureEx(stream, sizeof(metafile), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict), E_FAIL);
570 IStream_Release(stream);
573 static void test_enhmetafile(void)
575 OLE_HANDLE handle;
576 LPSTREAM stream;
577 IPicture *pict;
578 HGLOBAL hglob;
579 LPBYTE *data;
580 LONG cxy;
581 BOOL keep;
582 short type;
584 hglob = GlobalAlloc (0, sizeof(enhmetafile));
585 data = GlobalLock(hglob);
586 memcpy(data, enhmetafile, sizeof(enhmetafile));
588 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
589 ole_check(OleLoadPictureEx(stream, sizeof(enhmetafile), TRUE, &IID_IPicture, 10, 10, 0, (LPVOID *)&pict));
591 ole_check(IPicture_get_Handle(pict, &handle));
592 ok(handle != 0, "handle is null\n");
594 ole_check(IPicture_get_Type(pict, &type));
595 expect_eq(type, PICTYPE_ENHMETAFILE, short, "%d");
597 ole_check(IPicture_get_Height(pict, &cxy));
598 expect_eq(cxy, -23, LONG, "%d");
600 ole_check(IPicture_get_Width(pict, &cxy));
601 expect_eq(cxy, -25, LONG, "%d");
603 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
604 todo_wine expect_eq(keep, FALSE, LONG, "%d");
606 IPicture_Release(pict);
607 IStream_Release(stream);
610 static void test_Render(void)
612 IPicture *pic;
613 HRESULT hres;
614 short type;
615 PICTDESC desc;
616 OLE_XSIZE_HIMETRIC pWidth;
617 OLE_YSIZE_HIMETRIC pHeight;
618 COLORREF result, expected;
619 HDC hdc = GetDC(0);
621 /* test IPicture::Render return code on uninitialized picture */
622 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
623 hres = IPicture_get_Type(pic, &type);
624 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
625 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
626 /* zero dimensions */
627 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
628 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
629 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
630 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
631 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
632 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
633 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
634 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
635 hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
636 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
637 hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
638 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
639 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
640 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
641 /* nonzero dimensions, PICTYPE_UNINITIALIZED */
642 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL);
643 ole_expect(hres, S_OK);
644 IPicture_Release(pic);
646 desc.cbSizeofstruct = sizeof(PICTDESC);
647 desc.picType = PICTYPE_ICON;
648 desc.u.icon.hicon = LoadIcon(NULL, IDI_APPLICATION);
649 if(!desc.u.icon.hicon){
650 win_skip("LoadIcon failed. Skipping...\n");
651 ReleaseDC(NULL, hdc);
652 return;
655 OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (VOID**)&pic);
656 /* zero dimensions, PICTYPE_ICON */
657 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
658 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
659 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
660 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
661 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
662 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
663 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
664 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
665 hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
666 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
667 hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
668 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
669 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
670 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
672 /* Check if target size and position is respected */
673 IPicture_get_Width(pic, &pWidth);
674 IPicture_get_Height(pic, &pHeight);
676 SetPixelV(hdc, 0, 0, 0x00F0F0F0);
677 SetPixelV(hdc, 5, 5, 0x00F0F0F0);
678 SetPixelV(hdc, 10, 10, 0x00F0F0F0);
679 expected = GetPixel(hdc, 0, 0);
681 hres = IPicture_Render(pic, hdc, 1, 1, 9, 9, 0, 0, pWidth, -pHeight, NULL);
682 ole_expect(hres, S_OK);
684 if(hres != S_OK) {
685 IPicture_Release(pic);
686 ReleaseDC(NULL, hdc);
687 return;
690 /* Evaluate the rendered Icon */
691 result = GetPixel(hdc, 0, 0);
692 ok(result == expected,
693 "Color at 0,0 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
694 result = GetPixel(hdc, 5, 5);
695 ok(result != expected ||
696 broken(result == expected), /* WinNT 4.0 and older may claim they drew */
697 /* the icon, even if they didn't. */
698 "Color at 5,5 should have changed, but still was 0x%06X\n", expected);
699 result = GetPixel(hdc, 10, 10);
700 ok(result == expected,
701 "Color at 10,10 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
703 IPicture_Release(pic);
704 ReleaseDC(NULL, hdc);
707 static void test_get_Attributes(void)
709 IPicture *pic;
710 HRESULT hres;
711 short type;
712 DWORD attr;
714 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
715 hres = IPicture_get_Type(pic, &type);
716 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
717 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
719 hres = IPicture_get_Attributes(pic, NULL);
720 ole_expect(hres, E_POINTER);
722 attr = 0xdeadbeef;
723 hres = IPicture_get_Attributes(pic, &attr);
724 ole_expect(hres, S_OK);
725 ok(attr == 0, "IPicture_get_Attributes does not reset attr to zero, got %d\n", attr);
727 IPicture_Release(pic);
730 static void test_get_Handle(void)
732 IPicture *pic;
733 HRESULT hres;
735 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
737 hres = IPicture_get_Handle(pic, NULL);
738 ole_expect(hres, E_POINTER);
740 IPicture_Release(pic);
743 static void test_get_Type(void)
745 IPicture *pic;
746 HRESULT hres;
748 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
750 hres = IPicture_get_Type(pic, NULL);
751 ole_expect(hres, E_POINTER);
753 IPicture_Release(pic);
756 static void test_OleLoadPicturePath(void)
758 static WCHAR emptyW[] = {0};
760 IPicture *pic;
761 HRESULT hres;
762 int i;
763 char temp_path[MAX_PATH];
764 char temp_file[MAX_PATH];
765 WCHAR temp_fileW[MAX_PATH + 5] = {'f','i','l','e',':','/','/','/'};
766 HANDLE file;
767 DWORD size;
768 WCHAR *ptr;
770 const struct
772 LPOLESTR szURLorPath;
773 REFIID riid;
774 IPicture **pic;
775 } invalid_parameters[] =
777 {NULL, NULL, NULL},
778 {NULL, NULL, &pic},
779 {NULL, &IID_IPicture, NULL},
780 {NULL, &IID_IPicture, &pic},
781 {emptyW, NULL, NULL},
782 {emptyW, &IID_IPicture, NULL},
785 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
787 pic = (IPicture *)0xdeadbeef;
788 hres = OleLoadPicturePath(invalid_parameters[i].szURLorPath, NULL, 0, 0,
789 invalid_parameters[i].riid,
790 (void **)invalid_parameters[i].pic);
791 ok(hres == E_INVALIDARG,
792 "[%d] Expected OleLoadPicturePath to return E_INVALIDARG, got 0x%08x\n", i, hres);
793 ok(pic == (IPicture *)0xdeadbeef,
794 "[%d] Expected output pointer to be 0xdeadbeef, got %p\n", i, pic);
797 pic = (IPicture *)0xdeadbeef;
798 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, NULL, (void **)&pic);
799 todo_wine
800 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
801 hres == E_UNEXPECTED || /* NT4/Win95 */
802 hres == E_FAIL || /* Win95 OSR2 */
803 hres == E_OUTOFMEMORY, /* Win98/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 hres == E_UNEXPECTED || /* NT4/Win95 */
813 hres == E_FAIL || /* Win95 OSR2 */
814 hres == E_OUTOFMEMORY, /* Win98/Win2k/Win2k3 */
815 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
816 ok(pic == NULL,
817 "Expected the output interface pointer to be NULL, got %p\n", pic);
819 /* Create a local temporary image file for testing. */
820 GetTempPathA(sizeof(temp_path), temp_path);
821 GetTempFileNameA(temp_path, "bmp", 0, temp_file);
822 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
823 FILE_ATTRIBUTE_NORMAL, NULL);
824 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
825 CloseHandle(file);
827 MultiByteToWideChar(CP_ACP, 0, temp_file, -1, temp_fileW + 8, sizeof(temp_fileW)/sizeof(WCHAR) - 8);
829 /* Try a normal DOS path. */
830 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
831 ok(hres == S_OK ||
832 broken(hres == E_UNEXPECTED), /* NT4/Win95 */
833 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
834 if (pic)
835 IPicture_Release(pic);
837 /* Try a DOS path with tacked on "file:". */
838 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
839 ok(hres == S_OK ||
840 broken(hres == E_UNEXPECTED), /* NT4/Win95 */
841 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
842 if (pic)
843 IPicture_Release(pic);
845 DeleteFileA(temp_file);
847 /* Try with a nonexistent file. */
848 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
849 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
850 hres == E_UNEXPECTED || /* NT4/Win95 */
851 hres == E_FAIL, /* Win9x/Win2k */
852 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
854 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
855 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
856 hres == E_UNEXPECTED || /* NT4/Win95 */
857 hres == E_FAIL, /* Win9x/Win2k */
858 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
860 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
861 FILE_ATTRIBUTE_NORMAL, NULL);
862 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
863 CloseHandle(file);
865 /* Try a "file:" URL with slash separators. */
866 ptr = temp_fileW + 8;
867 while (*ptr)
869 if (*ptr == '\\')
870 *ptr = '/';
871 ptr++;
874 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
875 ok(hres == S_OK ||
876 broken(hres == E_UNEXPECTED), /* NT4/Win95 */
877 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
878 if (pic)
879 IPicture_Release(pic);
881 DeleteFileA(temp_file);
883 /* Try with a nonexistent file. */
884 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
885 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
886 hres == E_UNEXPECTED || /* NT4/Win95 */
887 hres == E_FAIL, /* Win9x/Win2k */
888 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
891 static void test_himetric(void)
893 static const BYTE bmp_bits[1024];
894 OLE_XSIZE_HIMETRIC cx;
895 OLE_YSIZE_HIMETRIC cy;
896 IPicture *pic;
897 PICTDESC desc;
898 HBITMAP bmp;
899 HRESULT hr;
900 HICON icon;
901 HDC hdc;
902 INT d;
904 if (!pOleCreatePictureIndirect)
906 win_skip("OleCreatePictureIndirect not available\n");
907 return;
910 desc.cbSizeofstruct = sizeof(desc);
911 desc.picType = PICTYPE_BITMAP;
912 desc.u.bmp.hpal = NULL;
914 hdc = CreateCompatibleDC(0);
916 bmp = CreateBitmap(1.9 * GetDeviceCaps(hdc, LOGPIXELSX),
917 1.9 * GetDeviceCaps(hdc, LOGPIXELSY), 1, 1, NULL);
919 desc.u.bmp.hbitmap = bmp;
921 /* size in himetric units reported rounded up to next integer value */
922 hr = pOleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
923 ok(hr == S_OK, "got 0x%08x\n", hr);
925 cx = 0;
926 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSX)), 2540, GetDeviceCaps(hdc, LOGPIXELSX));
927 hr = IPicture_get_Width(pic, &cx);
928 ok(hr == S_OK, "got 0x%08x\n", hr);
929 ok(cx == d, "got %d, expected %d\n", cx, d);
931 cy = 0;
932 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSY)), 2540, GetDeviceCaps(hdc, LOGPIXELSY));
933 hr = IPicture_get_Height(pic, &cy);
934 ok(hr == S_OK, "got 0x%08x\n", hr);
935 ok(cy == d, "got %d, expected %d\n", cy, d);
937 DeleteObject(bmp);
938 IPicture_Release(pic);
940 /* same thing with icon */
941 icon = CreateIcon(NULL, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
942 1, 1, bmp_bits, bmp_bits);
943 ok(icon != NULL, "failed to create icon\n");
945 desc.picType = PICTYPE_ICON;
946 desc.u.icon.hicon = icon;
948 hr = pOleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
949 ok(hr == S_OK, "got 0x%08x\n", hr);
951 cx = 0;
952 d = MulDiv(GetSystemMetrics(SM_CXICON), 2540, GetDeviceCaps(hdc, LOGPIXELSX));
953 hr = IPicture_get_Width(pic, &cx);
954 ok(hr == S_OK, "got 0x%08x\n", hr);
955 ok(cx == d, "got %d, expected %d\n", cx, d);
957 cy = 0;
958 d = MulDiv(GetSystemMetrics(SM_CYICON), 2540, GetDeviceCaps(hdc, LOGPIXELSY));
959 hr = IPicture_get_Height(pic, &cy);
960 ok(hr == S_OK, "got 0x%08x\n", hr);
961 ok(cy == d, "got %d, expected %d\n", cy, d);
963 IPicture_Release(pic);
964 DestroyIcon(icon);
966 DeleteDC(hdc);
969 START_TEST(olepicture)
971 hOleaut32 = GetModuleHandleA("oleaut32.dll");
972 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
973 pOleCreatePictureIndirect = (void*)GetProcAddress(hOleaut32, "OleCreatePictureIndirect");
974 if (!pOleLoadPicture)
976 win_skip("OleLoadPicture is not available\n");
977 return;
980 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
981 test_pic(gifimage, sizeof(gifimage));
982 test_pic(jpgimage, sizeof(jpgimage));
983 test_pic(bmpimage, sizeof(bmpimage));
984 test_pic(gif4pixel, sizeof(gif4pixel));
985 /* FIXME: No PNG support in Windows... */
986 if (0) test_pic(pngimage, sizeof(pngimage));
987 test_empty_image();
988 test_empty_image_2();
989 test_apm();
990 test_metafile();
991 test_enhmetafile();
993 test_Invoke();
994 test_OleCreatePictureIndirect();
995 test_Render();
996 test_get_Attributes();
997 test_get_Handle();
998 test_get_Type();
999 test_OleLoadPicturePath();
1000 test_himetric();
1004 /* Helper functions only ... */
1007 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
1009 GlobalFree(This->supportHandle);
1010 This->supportHandle=0;
1011 HeapFree(GetProcessHeap(), 0, This);
1014 static ULONG WINAPI NoStatStreamImpl_AddRef(
1015 IStream* iface)
1017 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
1018 return InterlockedIncrement(&This->ref);
1021 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
1022 IStream* iface,
1023 REFIID riid, /* [in] */
1024 void** ppvObject) /* [iid_is][out] */
1026 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
1027 if (ppvObject==0) return E_INVALIDARG;
1028 *ppvObject = 0;
1029 if (IsEqualIID(&IID_IUnknown, riid))
1031 *ppvObject = This;
1033 else if (IsEqualIID(&IID_IStream, riid))
1035 *ppvObject = This;
1038 if ((*ppvObject)==0)
1039 return E_NOINTERFACE;
1040 NoStatStreamImpl_AddRef(iface);
1041 return S_OK;
1044 static ULONG WINAPI NoStatStreamImpl_Release(
1045 IStream* iface)
1047 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
1048 ULONG newRef = InterlockedDecrement(&This->ref);
1049 if (newRef==0)
1050 NoStatStreamImpl_Destroy(This);
1051 return newRef;
1054 static HRESULT WINAPI NoStatStreamImpl_Read(
1055 IStream* iface,
1056 void* pv, /* [length_is][size_is][out] */
1057 ULONG cb, /* [in] */
1058 ULONG* pcbRead) /* [out] */
1060 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
1061 void* supportBuffer;
1062 ULONG bytesReadBuffer;
1063 ULONG bytesToReadFromBuffer;
1065 if (pcbRead==0)
1066 pcbRead = &bytesReadBuffer;
1067 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
1068 supportBuffer = GlobalLock(This->supportHandle);
1069 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
1070 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
1071 *pcbRead = bytesToReadFromBuffer;
1072 GlobalUnlock(This->supportHandle);
1073 if(*pcbRead == cb)
1074 return S_OK;
1075 return S_FALSE;
1078 static HRESULT WINAPI NoStatStreamImpl_Write(
1079 IStream* iface,
1080 const void* pv, /* [size_is][in] */
1081 ULONG cb, /* [in] */
1082 ULONG* pcbWritten) /* [out] */
1084 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
1085 void* supportBuffer;
1086 ULARGE_INTEGER newSize;
1087 ULONG bytesWritten = 0;
1089 if (pcbWritten == 0)
1090 pcbWritten = &bytesWritten;
1091 if (cb == 0)
1092 return S_OK;
1093 newSize.u.HighPart = 0;
1094 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
1095 if (newSize.u.LowPart > This->streamSize.u.LowPart)
1096 IStream_SetSize(iface, newSize);
1098 supportBuffer = GlobalLock(This->supportHandle);
1099 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
1100 This->currentPosition.u.LowPart+=cb;
1101 *pcbWritten = cb;
1102 GlobalUnlock(This->supportHandle);
1103 return S_OK;
1106 static HRESULT WINAPI NoStatStreamImpl_Seek(
1107 IStream* iface,
1108 LARGE_INTEGER dlibMove, /* [in] */
1109 DWORD dwOrigin, /* [in] */
1110 ULARGE_INTEGER* plibNewPosition) /* [out] */
1112 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
1113 ULARGE_INTEGER newPosition;
1114 switch (dwOrigin)
1116 case STREAM_SEEK_SET:
1117 newPosition.u.HighPart = 0;
1118 newPosition.u.LowPart = 0;
1119 break;
1120 case STREAM_SEEK_CUR:
1121 newPosition = This->currentPosition;
1122 break;
1123 case STREAM_SEEK_END:
1124 newPosition = This->streamSize;
1125 break;
1126 default:
1127 return STG_E_INVALIDFUNCTION;
1129 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
1130 return STG_E_INVALIDFUNCTION;
1131 newPosition.QuadPart += dlibMove.QuadPart;
1132 if (plibNewPosition) *plibNewPosition = newPosition;
1133 This->currentPosition = newPosition;
1134 return S_OK;
1137 static HRESULT WINAPI NoStatStreamImpl_SetSize(
1138 IStream* iface,
1139 ULARGE_INTEGER libNewSize) /* [in] */
1141 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
1142 HGLOBAL supportHandle;
1143 if (libNewSize.u.HighPart != 0)
1144 return STG_E_INVALIDFUNCTION;
1145 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
1146 return S_OK;
1147 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
1148 if (supportHandle == 0)
1149 return STG_E_MEDIUMFULL;
1150 This->supportHandle = supportHandle;
1151 This->streamSize.u.LowPart = libNewSize.u.LowPart;
1152 return S_OK;
1155 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
1156 IStream* iface,
1157 IStream* pstm, /* [unique][in] */
1158 ULARGE_INTEGER cb, /* [in] */
1159 ULARGE_INTEGER* pcbRead, /* [out] */
1160 ULARGE_INTEGER* pcbWritten) /* [out] */
1162 HRESULT hr = S_OK;
1163 BYTE tmpBuffer[128];
1164 ULONG bytesRead, bytesWritten, copySize;
1165 ULARGE_INTEGER totalBytesRead;
1166 ULARGE_INTEGER totalBytesWritten;
1168 if ( pstm == 0 )
1169 return STG_E_INVALIDPOINTER;
1170 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
1171 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
1173 while ( cb.u.LowPart > 0 )
1175 if ( cb.u.LowPart >= 128 )
1176 copySize = 128;
1177 else
1178 copySize = cb.u.LowPart;
1179 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
1180 totalBytesRead.u.LowPart += bytesRead;
1181 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
1182 totalBytesWritten.u.LowPart += bytesWritten;
1183 if (bytesRead != bytesWritten)
1185 hr = STG_E_MEDIUMFULL;
1186 break;
1188 if (bytesRead!=copySize)
1189 cb.u.LowPart = 0;
1190 else
1191 cb.u.LowPart -= bytesRead;
1193 if (pcbRead)
1195 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
1196 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
1199 if (pcbWritten)
1201 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
1202 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
1204 return hr;
1207 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
1209 return S_OK;
1211 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
1213 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
1214 IStream* iface,
1215 ULARGE_INTEGER libOffset, /* [in] */
1216 ULARGE_INTEGER cb, /* [in] */
1217 DWORD dwLockType) /* [in] */
1219 return S_OK;
1222 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
1223 IStream* iface,
1224 ULARGE_INTEGER libOffset, /* [in] */
1225 ULARGE_INTEGER cb, /* [in] */
1226 DWORD dwLockType) /* [in] */
1228 return S_OK;
1231 static HRESULT WINAPI NoStatStreamImpl_Stat(
1232 IStream* iface,
1233 STATSTG* pstatstg, /* [out] */
1234 DWORD grfStatFlag) /* [in] */
1236 return E_NOTIMPL;
1239 static HRESULT WINAPI NoStatStreamImpl_Clone(
1240 IStream* iface,
1241 IStream** ppstm) /* [out] */
1243 return E_NOTIMPL;
1245 static const IStreamVtbl NoStatStreamImpl_Vtbl;
1248 Build an object that implements IStream, without IStream_Stat capabilities.
1249 Receives a memory handle with data buffer. If memory handle is non-null,
1250 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
1251 In any case the object takes ownership of memory handle and will free it on
1252 object release.
1254 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal)
1256 NoStatStreamImpl* newStream;
1258 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
1259 if (newStream!=0)
1261 newStream->lpVtbl = &NoStatStreamImpl_Vtbl;
1262 newStream->ref = 1;
1263 newStream->supportHandle = hGlobal;
1265 if (!newStream->supportHandle)
1266 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
1267 GMEM_SHARE, 0);
1268 newStream->currentPosition.u.HighPart = 0;
1269 newStream->currentPosition.u.LowPart = 0;
1270 newStream->streamSize.u.HighPart = 0;
1271 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
1273 return newStream;
1277 static const IStreamVtbl NoStatStreamImpl_Vtbl =
1279 NoStatStreamImpl_QueryInterface,
1280 NoStatStreamImpl_AddRef,
1281 NoStatStreamImpl_Release,
1282 NoStatStreamImpl_Read,
1283 NoStatStreamImpl_Write,
1284 NoStatStreamImpl_Seek,
1285 NoStatStreamImpl_SetSize,
1286 NoStatStreamImpl_CopyTo,
1287 NoStatStreamImpl_Commit,
1288 NoStatStreamImpl_Revert,
1289 NoStatStreamImpl_LockRegion,
1290 NoStatStreamImpl_UnlockRegion,
1291 NoStatStreamImpl_Stat,
1292 NoStatStreamImpl_Clone