1 /*
2 * OLEPICTURE test program
3 *
4 * Copyright 2005 Marcus Meissner
5 * Copyright 2012 Dmitry Timoshkov
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <math.h>
25 #include <float.h>
26
27 #define COBJMACROS
28 #define CONST_VTABLE
29 #ifndef __REACTOS__
30 #define NONAMELESSUNION
31 #endif
32
33 #include "wine/test.h"
34 #include <windef.h>
35 #include <winbase.h>
36 #include <winuser.h>
37 #include <wingdi.h>
38 #include <winnls.h>
39 #include <winerror.h>
40 #include <winnt.h>
41
42 #include <urlmon.h>
43 #include <wtypes.h>
44 #include <olectl.h>
45 #include <objidl.h>
46
47 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
48
49 #define ole_expect(expr, expect) { \
50 HRESULT r = expr; \
51 ok(r == (expect), #expr " returned %x, expected %s (%x)\n", r, #expect, expect); \
52 }
53
54 #define ole_check(expr) ole_expect(expr, S_OK);
55
56 static HMODULE hOleaut32;
57
58 static HRESULT (WINAPI *pOleLoadPicture)(LPSTREAM,LONG,BOOL,REFIID,LPVOID*);
59 static HRESULT (WINAPI *pOleLoadPictureEx)(LPSTREAM,LONG,BOOL,REFIID,DWORD,DWORD,DWORD,LPVOID*);
60
61 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
62
63 /* 1x1 pixel gif */
64 static const unsigned char gifimage[35] = {
65 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
66 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
67 0x01,0x00,0x3b
68 };
69
70 /* 1x1 pixel jpg */
71 static const unsigned char jpgimage[285] = {
72 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
73 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
74 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
75 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
76 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
77 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
78 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
79 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
80 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
81 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
82 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
83 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
84 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
85 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
86 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
87 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
88 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
89 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
90 };
91
92 /* 1x1 pixel png */
93 static const unsigned char pngimage[285] = {
94 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
95 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
96 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
97 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
98 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
99 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
100 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
101 };
102
103 /* 1bpp BI_RGB 1x1 pixel bmp */
104 static const unsigned char bmpimage[66] = {
105 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
106 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
107 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
108 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
109 0x00,0x00
110 };
111
112 /* 8bpp BI_RLE8 1x1 pixel bmp */
113 static const unsigned char bmpimage_rle8[] = {
114 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
115 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,
116 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
117 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x01,
118 0x00,0x00
119 };
120
121 /* 2x2 pixel gif */
122 static const unsigned char gif4pixel[42] = {
123 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
124 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
125 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
126 };
127
128 /* APM with an empty metafile with some padding zeros - looks like under Window the
129 * metafile data should be at least 20 bytes */
130 static const unsigned char apmdata[] = {
131 0xd7,0xcd,0xc6,0x9a, 0x00,0x00,0x00,0x00, 0x00,0x00,0xee,0x02, 0xb1,0x03,0xa0,0x05,
132 0x00,0x00,0x00,0x00, 0xee,0x53,0x01,0x00, 0x09,0x00,0x00,0x03, 0x13,0x00,0x00,0x00,
133 0x01,0x00,0x05,0x00, 0x00,0x00,0x00,0x00, 0x03,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
134 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
135 };
136
137 /* MF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
138 static const unsigned char metafile[] = {
139 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
140 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
141 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
142 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
143 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
144 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
145 0x00, 0x00
146 };
147
148 /* EMF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
149 static const unsigned char enhmetafile[] = {
150 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
155 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
156 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
157 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
160 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
163 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
164 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
165 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
167 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
168 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
169 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
170 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
173 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
174 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
175 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
176 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
177 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
178 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
179 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
180 0x14, 0x00, 0x00, 0x00
181 };
182
183 static HBITMAP stock_bm;
184
create_render_dc(void)185 static HDC create_render_dc( void )
186 {
187 HDC dc = CreateCompatibleDC( NULL );
188 BITMAPINFO info = {{sizeof(info.bmiHeader), 100, 100, 1, 32, BI_RGB }};
189 void *bits;
190 HBITMAP dib = CreateDIBSection( NULL, &info, DIB_RGB_COLORS, &bits, NULL, 0 );
191
192 stock_bm = SelectObject( dc, dib );
193 return dc;
194 }
195
delete_render_dc(HDC dc)196 static void delete_render_dc( HDC dc )
197 {
198 HBITMAP dib = SelectObject( dc, stock_bm );
199 DeleteObject( dib );
200 DeleteDC( dc );
201 }
202
203 typedef struct NoStatStreamImpl
204 {
205 IStream IStream_iface;
206 LONG ref;
207
208 HGLOBAL supportHandle;
209 ULARGE_INTEGER streamSize;
210 ULARGE_INTEGER currentPosition;
211 } NoStatStreamImpl;
212
213 static IStream* NoStatStream_Construct(HGLOBAL hGlobal);
214
215 static void
test_pic_with_stream(LPSTREAM stream,unsigned int imgsize)216 test_pic_with_stream(LPSTREAM stream, unsigned int imgsize)
217 {
218 IPicture* pic = NULL;
219 HRESULT hres;
220 LPVOID pvObj = NULL;
221 OLE_HANDLE handle, hPal;
222 OLE_XSIZE_HIMETRIC width;
223 OLE_YSIZE_HIMETRIC height;
224 short type;
225 DWORD attr;
226 ULONG res;
227
228 pvObj = NULL;
229 hres = pOleLoadPicture(stream, imgsize, TRUE, &IID_IPicture, &pvObj);
230 pic = pvObj;
231
232 ok(hres == S_OK,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres);
233 ok(pic != NULL,"OLP (NULL,..) returns NULL, instead of !NULL\n");
234 if (pic == NULL)
235 return;
236
237 pvObj = NULL;
238 hres = IPicture_QueryInterface (pic, &IID_IPicture, &pvObj);
239
240 ok(hres == S_OK,"IPicture_QI does not return S_OK, but 0x%08x\n", hres);
241 ok(pvObj != NULL,"IPicture_QI does return NULL, instead of a ptr\n");
242
243 IPicture_Release ((IPicture*)pvObj);
244
245 handle = 0;
246 hres = IPicture_get_Handle (pic, &handle);
247 ok(hres == S_OK,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres);
248 ok(handle != 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
249
250 if (handle)
251 {
252 BITMAP bmp;
253 GetObjectA(UlongToHandle(handle), sizeof(BITMAP), &bmp);
254 ok(bmp.bmBits != 0, "not a dib\n");
255 }
256
257 width = 0;
258 hres = IPicture_get_Width (pic, &width);
259 ok(hres == S_OK,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres);
260 ok(width != 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
261
262 height = 0;
263 hres = IPicture_get_Height (pic, &height);
264 ok(hres == S_OK,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres);
265 ok(height != 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
266
267 type = 0;
268 hres = IPicture_get_Type (pic, &type);
269 ok(hres == S_OK,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
270 ok(type == PICTYPE_BITMAP, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type, PICTYPE_BITMAP);
271
272 attr = 0;
273 hres = IPicture_get_Attributes (pic, &attr);
274 ok(hres == S_OK,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres);
275 ok(attr == 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr);
276
277 hPal = 0;
278 hres = IPicture_get_hPal (pic, &hPal);
279 ok(hres == S_OK,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres);
280 /* a single pixel b/w image has no palette */
281 ok(hPal == 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal);
282
283 res = IPicture_Release (pic);
284 ok (res == 0, "refcount after release is %d, but should be 0?\n", res);
285 }
286
287 static void
test_pic(const unsigned char * imgdata,unsigned int imgsize)288 test_pic(const unsigned char *imgdata, unsigned int imgsize)
289 {
290 LPSTREAM stream;
291 HGLOBAL hglob;
292 LPBYTE data;
293 HRESULT hres;
294 LARGE_INTEGER seekto;
295 ULARGE_INTEGER newpos1;
296 DWORD * header;
297 unsigned int i,j;
298
299 /* Let the fun begin */
300 hglob = GlobalAlloc (0, imgsize);
301 data = GlobalLock (hglob);
302 memcpy(data, imgdata, imgsize);
303 GlobalUnlock(hglob); data = NULL;
304
305 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
306 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
307
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);
312
313 IStream_Release(stream);
314
315 /* again with Non Statable and Non Seekable stream */
316 stream = NoStatStream_Construct(hglob);
317 hglob = 0; /* Non-statable impl always deletes on release */
318 test_pic_with_stream(stream, 0);
319
320 IStream_Release(stream);
321 for (i = 1; i <= 8; i++) {
322 /* more fun!!! */
323 hglob = GlobalAlloc (0, imgsize + i * (2 * sizeof(DWORD)));
324 data = GlobalLock (hglob);
325 header = (DWORD *)data;
326
327 /* multiple copies of header */
328 memcpy(data,"lt\0\0",4);
329 header[1] = imgsize;
330 for (j = 2; j <= i; j++) {
331 memcpy(&(header[2 * (j - 1)]), header, 2 * sizeof(DWORD));
332 }
333 memcpy(data + i * (2 * sizeof(DWORD)), imgdata, imgsize);
334 GlobalUnlock(hglob); data = NULL;
335
336 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
337 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
338
339 memset(&seekto,0,sizeof(seekto));
340 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
341 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
342 test_pic_with_stream(stream, imgsize);
343
344 IStream_Release(stream);
345
346 /* again with Non Statable and Non Seekable stream */
347 stream = NoStatStream_Construct(hglob);
348 hglob = 0; /* Non-statable impl always deletes on release */
349 test_pic_with_stream(stream, 0);
350
351 IStream_Release(stream);
352 }
353 }
354
test_empty_image(void)355 static void test_empty_image(void) {
356 LPBYTE data;
357 LPSTREAM stream;
358 IPicture* pic = NULL;
359 HRESULT hres;
360 LPVOID pvObj = NULL;
361 HGLOBAL hglob;
362 OLE_HANDLE handle;
363 ULARGE_INTEGER newpos1;
364 LARGE_INTEGER seekto;
365 short type;
366 DWORD attr;
367
368 /* Empty image. Happens occasionally in VB programs. */
369 hglob = GlobalAlloc (0, 8);
370 data = GlobalLock (hglob);
371 memcpy(data,"lt\0\0",4);
372 ((DWORD*)data)[1] = 0;
373 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
374 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
375
376 memset(&seekto,0,sizeof(seekto));
377 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
378 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
379
380 pvObj = NULL;
381 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
382 pic = pvObj;
383 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
384 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
385
386 hres = IPicture_get_Type (pic, &type);
387 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
388 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
389
390 attr = 0xdeadbeef;
391 hres = IPicture_get_Attributes (pic, &attr);
392 ok (hres == S_OK,"empty picture get attributes failed with hres 0x%08x\n", hres);
393 ok (attr == 0,"attr is %d, but should be 0\n", attr);
394
395 hres = IPicture_get_Handle (pic, &handle);
396 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
397 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
398 IPicture_Release (pic);
399 IStream_Release (stream);
400 }
401
test_empty_image_2(void)402 static void test_empty_image_2(void) {
403 LPBYTE data;
404 LPSTREAM stream;
405 IPicture* pic = NULL;
406 HRESULT hres;
407 LPVOID pvObj = NULL;
408 HGLOBAL hglob;
409 ULARGE_INTEGER newpos1;
410 LARGE_INTEGER seekto;
411 short type;
412
413 /* Empty image at random stream position. */
414 hglob = GlobalAlloc (0, 200);
415 data = GlobalLock (hglob);
416 data += 42;
417 memcpy(data,"lt\0\0",4);
418 ((DWORD*)data)[1] = 0;
419 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
420 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
421
422 memset(&seekto,0,sizeof(seekto));
423 seekto.u.LowPart = 42;
424 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
425 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
426
427 pvObj = NULL;
428 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
429 pic = pvObj;
430 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
431 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
432
433 hres = IPicture_get_Type (pic, &type);
434 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
435 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
436
437 IPicture_Release (pic);
438 IStream_Release (stream);
439 }
440
test_Invoke(void)441 static void test_Invoke(void)
442 {
443 IPictureDisp *picdisp;
444 HRESULT hr;
445 VARIANTARG vararg, args[10];
446 DISPPARAMS dispparams;
447 VARIANT varresult;
448 IStream *stream;
449 HGLOBAL hglob;
450 void *data;
451 HDC hdc;
452 int i;
453
454 hglob = GlobalAlloc (0, sizeof(gifimage));
455 data = GlobalLock(hglob);
456 memcpy(data, gifimage, sizeof(gifimage));
457 GlobalUnlock(hglob);
458
459 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
460 ok_ole_success(hr, "CreateStreamOnHGlobal");
461
462 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
463 IStream_Release(stream);
464 GlobalFree(hglob);
465 ok_ole_success(hr, "OleLoadPicture");
466
467 V_VT(&vararg) = VT_BOOL;
468 V_BOOL(&vararg) = VARIANT_FALSE;
469 dispparams.cNamedArgs = 0;
470 dispparams.rgdispidNamedArgs = NULL;
471 dispparams.cArgs = 1;
472 dispparams.rgvarg = &vararg;
473 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
474 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
475 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
476 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
477
478 dispparams.cArgs = 0;
479 dispparams.rgvarg = NULL;
480 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
481 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
482
483 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
484 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
485
486 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
487 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
488
489 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
490 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
491
492 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
493 ok_ole_success(hr, "IPictureDisp_Invoke");
494 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
495
496 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
497 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
498
499 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
500 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
501
502 dispparams.cArgs = 1;
503 dispparams.rgvarg = &vararg;
504 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
505 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
506
507 dispparams.cArgs = 1;
508 dispparams.rgvarg = &vararg;
509 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
510 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
511
512 /* DISPID_PICT_RENDER */
513 hdc = create_render_dc();
514
515 for (i = 0; i < ARRAY_SIZE(args); i++)
516 V_VT(&args[i]) = VT_I4;
517
518 V_I4(&args[0]) = 0;
519 V_I4(&args[1]) = 10;
520 V_I4(&args[2]) = 10;
521 V_I4(&args[3]) = 0;
522 V_I4(&args[4]) = 0;
523 V_I4(&args[5]) = 10;
524 V_I4(&args[6]) = 10;
525 V_I4(&args[7]) = 0;
526 V_I4(&args[8]) = 0;
527 V_I4(&args[9]) = HandleToLong(hdc);
528
529 dispparams.rgvarg = args;
530 dispparams.rgdispidNamedArgs = NULL;
531 dispparams.cArgs = 10;
532 dispparams.cNamedArgs = 0;
533
534 V_VT(&varresult) = VT_EMPTY;
535 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
536 ok(hr == S_OK, "got 0x%08x\n", hr);
537
538 /* Try with one argument set to VT_I2, it'd still work if coerced. */
539 V_VT(&args[3]) = VT_I2;
540 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
541 ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr);
542 V_VT(&args[3]) = VT_I4;
543
544 /* Wrong argument count */
545 dispparams.cArgs = 9;
546 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
547 ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
548
549 delete_render_dc(hdc);
550 IPictureDisp_Release(picdisp);
551 }
552
create_picture(short type,IPicture ** pict)553 static HRESULT create_picture(short type, IPicture **pict)
554 {
555 PICTDESC desc;
556
557 desc.cbSizeofstruct = sizeof(desc);
558 desc.picType = type;
559
560 switch (type)
561 {
562 case PICTYPE_UNINITIALIZED:
563 return OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)pict);
564
565 case PICTYPE_NONE:
566 break;
567
568 case PICTYPE_BITMAP:
569 desc.bmp.hbitmap = CreateBitmap(1, 1, 1, 1, NULL);
570 desc.bmp.hpal = (HPALETTE)0xbeefdead;
571 break;
572
573 case PICTYPE_ICON:
574 desc.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
575 break;
576
577 case PICTYPE_METAFILE:
578 {
579 HDC hdc = CreateMetaFileA(NULL);
580 desc.wmf.hmeta = CloseMetaFile(hdc);
581 desc.wmf.xExt = 1;
582 desc.wmf.yExt = 1;
583 break;
584 }
585
586 case PICTYPE_ENHMETAFILE:
587 {
588 HDC hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
589 desc.emf.hemf = CloseEnhMetaFile(hdc);
590 break;
591 }
592
593 default:
594 ok(0, "picture type %d is not supported\n", type);
595 return E_NOTIMPL;
596 }
597
598 return OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (void **)pict);
599 }
600
test_OleCreatePictureIndirect(void)601 static void test_OleCreatePictureIndirect(void)
602 {
603 PICTDESC desc;
604 OLE_HANDLE handle;
605 IPicture *pict;
606 HRESULT hr;
607 short type, i;
608
609 if (0)
610 {
611 /* crashes on native */
612 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, NULL);
613 }
614
615 desc.cbSizeofstruct = sizeof(desc);
616 desc.picType = PICTYPE_UNINITIALIZED;
617 pict = (void *)0xdeadbeef;
618 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (void **)&pict);
619 ok(hr == E_UNEXPECTED, "got %#x\n", hr);
620 ok(pict == NULL, "got %p\n", pict);
621
622 for (i = PICTYPE_UNINITIALIZED; i <= PICTYPE_ENHMETAFILE; i++)
623 {
624 hr = create_picture(i, &pict);
625 ok(hr == S_OK, "%d: got %#x\n", i, hr);
626
627 type = 0xdead;
628 hr = IPicture_get_Type(pict, &type);
629 ok(hr == S_OK, "%d: got %#x\n", i, hr);
630 ok(type == i, "%d: got %d\n", i, type);
631
632 handle = 0xdeadbeef;
633 hr = IPicture_get_Handle(pict, &handle);
634 ok(hr == S_OK, "%d: got %#x\n", i, hr);
635 if (type == PICTYPE_UNINITIALIZED || type == PICTYPE_NONE)
636 ok(handle == 0, "%d: got %#x\n", i, handle);
637 else
638 ok(handle != 0 && handle != 0xdeadbeef, "%d: got %#x\n", i, handle);
639
640 handle = 0xdeadbeef;
641 hr = IPicture_get_hPal(pict, &handle);
642 if (type == PICTYPE_BITMAP)
643 {
644 ok(hr == S_OK, "%d: got %#x\n", i, hr);
645 ok(handle == 0xbeefdead, "%d: got %#x\n", i, handle);
646 }
647 else
648 {
649 ok(hr == E_FAIL, "%d: got %#x\n", i, hr);
650 ok(handle == 0xdeadbeef || handle == 0 /* win64 */, "%d: got %#x\n", i, handle);
651 }
652
653 hr = IPicture_set_hPal(pict, HandleToUlong(GetStockObject(DEFAULT_PALETTE)));
654 if (type == PICTYPE_BITMAP)
655 ok(hr == S_OK, "%d: got %#x\n", i, hr);
656 else
657 ok(hr == E_FAIL, "%d: got %#x\n", i, hr);
658
659 IPicture_Release(pict);
660 }
661 }
662
test_apm(void)663 static void test_apm(void)
664 {
665 OLE_HANDLE handle;
666 LPSTREAM stream;
667 IPicture *pict;
668 HGLOBAL hglob;
669 LPBYTE *data;
670 LONG cxy;
671 BOOL keep;
672 short type;
673
674 hglob = GlobalAlloc (0, sizeof(apmdata));
675 data = GlobalLock(hglob);
676 memcpy(data, apmdata, sizeof(apmdata));
677
678 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
679 ole_check(pOleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict));
680
681 ole_check(IPicture_get_Handle(pict, &handle));
682 ok(handle != 0, "handle is null\n");
683
684 ole_check(IPicture_get_Type(pict, &type));
685 expect_eq(type, PICTYPE_METAFILE, short, "%d");
686
687 ole_check(IPicture_get_Height(pict, &cxy));
688 expect_eq(cxy, 1667, LONG, "%d");
689
690 ole_check(IPicture_get_Width(pict, &cxy));
691 expect_eq(cxy, 1323, LONG, "%d");
692
693 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
694 todo_wine expect_eq(keep, FALSE, LONG, "%d");
695
696 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL);
697 IPicture_Release(pict);
698 IStream_Release(stream);
699 }
700
test_metafile(void)701 static void test_metafile(void)
702 {
703 LPSTREAM stream;
704 IPicture *pict;
705 HGLOBAL hglob;
706 LPBYTE *data;
707
708 hglob = GlobalAlloc (0, sizeof(metafile));
709 data = GlobalLock(hglob);
710 memcpy(data, metafile, sizeof(metafile));
711
712 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
713 /* Windows does not load simple metafiles */
714 ole_expect(pOleLoadPictureEx(stream, sizeof(metafile), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict), E_FAIL);
715
716 IStream_Release(stream);
717 }
718
test_enhmetafile(void)719 static void test_enhmetafile(void)
720 {
721 OLE_HANDLE handle;
722 LPSTREAM stream;
723 IPicture *pict;
724 HGLOBAL hglob;
725 LPBYTE *data;
726 LONG cxy;
727 BOOL keep;
728 short type;
729
730 hglob = GlobalAlloc (0, sizeof(enhmetafile));
731 data = GlobalLock(hglob);
732 memcpy(data, enhmetafile, sizeof(enhmetafile));
733
734 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
735 ole_check(pOleLoadPictureEx(stream, sizeof(enhmetafile), TRUE, &IID_IPicture, 10, 10, 0, (LPVOID *)&pict));
736
737 ole_check(IPicture_get_Handle(pict, &handle));
738 ok(handle != 0, "handle is null\n");
739
740 ole_check(IPicture_get_Type(pict, &type));
741 expect_eq(type, PICTYPE_ENHMETAFILE, short, "%d");
742
743 ole_check(IPicture_get_Height(pict, &cxy));
744 expect_eq(cxy, -23, LONG, "%d");
745
746 ole_check(IPicture_get_Width(pict, &cxy));
747 expect_eq(cxy, -25, LONG, "%d");
748
749 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
750 todo_wine expect_eq(keep, FALSE, LONG, "%d");
751
752 IPicture_Release(pict);
753 IStream_Release(stream);
754 }
755
picture_render(IPicture * iface,HDC hdc,LONG x,LONG y,LONG cx,LONG cy,OLE_XPOS_HIMETRIC xSrc,OLE_YPOS_HIMETRIC ySrc,OLE_XSIZE_HIMETRIC cxSrc,OLE_YSIZE_HIMETRIC cySrc,const RECT * bounds)756 static HRESULT picture_render(IPicture *iface, HDC hdc, LONG x, LONG y, LONG cx, LONG cy,
757 OLE_XPOS_HIMETRIC xSrc,
758 OLE_YPOS_HIMETRIC ySrc,
759 OLE_XSIZE_HIMETRIC cxSrc,
760 OLE_YSIZE_HIMETRIC cySrc,
761 const RECT *bounds)
762 {
763 VARIANT ret, args[10];
764 HRESULT hr, hr_disp;
765 DISPPARAMS params;
766 IDispatch *disp;
767 int i;
768
769 hr = IPicture_Render(iface, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, bounds);
770
771 IPicture_QueryInterface(iface, &IID_IDispatch, (void**)&disp);
772
773 /* This is broken on 64 bits - accepted pointer argument type is still VT_I4 */
774 for (i = 0; i < ARRAY_SIZE(args); i++)
775 V_VT(&args[i]) = VT_I4;
776
777 /* pack arguments and call */
778 V_INT_PTR(&args[0]) = (INT_PTR)bounds;
779 V_I4(&args[1]) = cySrc;
780 V_I4(&args[2]) = cxSrc;
781 V_I4(&args[3]) = ySrc;
782 V_I4(&args[4]) = xSrc;
783 V_I4(&args[5]) = cy;
784 V_I4(&args[6]) = cx;
785 V_I4(&args[7]) = y;
786 V_I4(&args[8]) = x;
787 V_I4(&args[9]) = HandleToLong(hdc);
788
789 params.rgvarg = args;
790 params.rgdispidNamedArgs = NULL;
791 params.cArgs = 10;
792 params.cNamedArgs = 0;
793
794 V_VT(&ret) = VT_EMPTY;
795 hr_disp = IDispatch_Invoke(disp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD,
796 ¶ms, &ret, NULL, NULL);
797 ok(hr == hr_disp, "DISPID_PICT_RENDER returned wrong code, 0x%08x, expected 0x%08x\n",
798 hr_disp, hr);
799
800 IDispatch_Release(disp);
801
802 return hr;
803 }
804
test_Render(void)805 static void test_Render(void)
806 {
807 IPicture *pic;
808 HRESULT hres;
809 short type;
810 PICTDESC desc;
811 OLE_XSIZE_HIMETRIC pWidth;
812 OLE_YSIZE_HIMETRIC pHeight;
813 COLORREF result, expected;
814 HDC hdc = create_render_dc();
815
816 /* test IPicture::Render return code on uninitialized picture */
817 hres = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)&pic);
818 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres);
819 hres = IPicture_get_Type(pic, &type);
820 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
821 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
822 /* zero dimensions */
823 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
824 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
825 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
826 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
827 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
828 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
829 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
830 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
831 hres = picture_render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
832 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
833 hres = picture_render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
834 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
835 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
836 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
837 /* nonzero dimensions, PICTYPE_UNINITIALIZED */
838 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL);
839 ole_expect(hres, S_OK);
840 IPicture_Release(pic);
841
842 desc.cbSizeofstruct = sizeof(PICTDESC);
843 desc.picType = PICTYPE_ICON;
844 desc.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
845 if(!desc.icon.hicon){
846 win_skip("LoadIcon failed. Skipping...\n");
847 delete_render_dc(hdc);
848 return;
849 }
850
851 hres = OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (void **)&pic);
852 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres);
853 /* zero dimensions, PICTYPE_ICON */
854 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
855 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
856 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
857 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
858 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
859 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
860 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
861 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
862 hres = picture_render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
863 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
864 hres = picture_render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
865 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
866 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
867 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
868
869 /* Check if target size and position is respected */
870 IPicture_get_Width(pic, &pWidth);
871 IPicture_get_Height(pic, &pHeight);
872
873 SetPixelV(hdc, 0, 0, 0x00223344);
874 SetPixelV(hdc, 5, 5, 0x00223344);
875 SetPixelV(hdc, 10, 10, 0x00223344);
876 expected = GetPixel(hdc, 0, 0);
877
878 hres = picture_render(pic, hdc, 1, 1, 9, 9, 0, pHeight, pWidth, -pHeight, NULL);
879 ole_expect(hres, S_OK);
880
881 if(hres != S_OK) goto done;
882
883 /* Evaluate the rendered Icon */
884 result = GetPixel(hdc, 0, 0);
885 ok(result == expected,
886 "Color at 0,0 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
887 result = GetPixel(hdc, 5, 5);
888 ok(result != expected,
889 "Color at 5,5 should have changed, but still was 0x%06X\n", expected);
890 result = GetPixel(hdc, 10, 10);
891 ok(result == expected,
892 "Color at 10,10 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
893
894 done:
895 IPicture_Release(pic);
896 delete_render_dc(hdc);
897 }
898
test_get_Attributes(void)899 static void test_get_Attributes(void)
900 {
901 IPicture *pic;
902 HRESULT hres;
903 short type;
904 DWORD attr;
905
906 hres = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)&pic);
907 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres);
908 hres = IPicture_get_Type(pic, &type);
909 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
910 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
911
912 hres = IPicture_get_Attributes(pic, NULL);
913 ole_expect(hres, E_POINTER);
914
915 attr = 0xdeadbeef;
916 hres = IPicture_get_Attributes(pic, &attr);
917 ole_expect(hres, S_OK);
918 ok(attr == 0, "IPicture_get_Attributes does not reset attr to zero, got %d\n", attr);
919
920 IPicture_Release(pic);
921 }
922
test_get_Handle(void)923 static void test_get_Handle(void)
924 {
925 IPicture *pic;
926 HRESULT hres;
927
928 hres = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)&pic);
929 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres);
930 hres = IPicture_get_Handle(pic, NULL);
931 ole_expect(hres, E_POINTER);
932
933 IPicture_Release(pic);
934 }
935
test_get_Type(void)936 static void test_get_Type(void)
937 {
938 IPicture *pic;
939 HRESULT hres;
940
941 hres = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)&pic);
942 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres);
943
944 hres = IPicture_get_Type(pic, NULL);
945 ole_expect(hres, E_POINTER);
946
947 IPicture_Release(pic);
948 }
949
test_OleLoadPicturePath(void)950 static void test_OleLoadPicturePath(void)
951 {
952 static WCHAR emptyW[] = {0};
953
954 IPicture *pic;
955 HRESULT hres;
956 int i;
957 char temp_path[MAX_PATH];
958 char temp_file[MAX_PATH];
959 WCHAR temp_fileW[MAX_PATH + 5] = {'f','i','l','e',':','/','/','/'};
960 HANDLE file;
961 DWORD size;
962 WCHAR *ptr;
963 VARIANT var;
964
965 const struct
966 {
967 LPOLESTR szURLorPath;
968 REFIID riid;
969 IPicture **pic;
970 } invalid_parameters[] =
971 {
972 {NULL, NULL, NULL},
973 {NULL, NULL, &pic},
974 {NULL, &IID_IPicture, NULL},
975 {NULL, &IID_IPicture, &pic},
976 {emptyW, NULL, NULL},
977 {emptyW, &IID_IPicture, NULL},
978 };
979
980 for (i = 0; i < ARRAY_SIZE(invalid_parameters); i++)
981 {
982 pic = (IPicture *)0xdeadbeef;
983 hres = OleLoadPicturePath(invalid_parameters[i].szURLorPath, NULL, 0, 0,
984 invalid_parameters[i].riid,
985 (void **)invalid_parameters[i].pic);
986 ok(hres == E_INVALIDARG,
987 "[%d] Expected OleLoadPicturePath to return E_INVALIDARG, got 0x%08x\n", i, hres);
988 ok(pic == (IPicture *)0xdeadbeef,
989 "[%d] Expected output pointer to be 0xdeadbeef, got %p\n", i, pic);
990 }
991
992 pic = (IPicture *)0xdeadbeef;
993 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, NULL, (void **)&pic);
994 todo_wine
995 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
996 broken(hres == E_UNEXPECTED) || /* NT4 */
997 broken(hres == E_OUTOFMEMORY), /* Win2k/Win2k3 */
998 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
999 ok(pic == NULL,
1000 "Expected the output interface pointer to be NULL, got %p\n", pic);
1001
1002 pic = (IPicture *)0xdeadbeef;
1003 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
1004 todo_wine
1005 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
1006 broken(hres == E_UNEXPECTED) || /* NT4 */
1007 broken(hres == E_OUTOFMEMORY), /* Win2k/Win2k3 */
1008 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
1009 ok(pic == NULL,
1010 "Expected the output interface pointer to be NULL, got %p\n", pic);
1011
1012 /* Create a local temporary image file for testing. */
1013 GetTempPathA(sizeof(temp_path), temp_path);
1014 GetTempFileNameA(temp_path, "bmp", 0, temp_file);
1015 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1016 FILE_ATTRIBUTE_NORMAL, NULL);
1017 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
1018 CloseHandle(file);
1019
1020 MultiByteToWideChar(CP_ACP, 0, temp_file, -1, temp_fileW + 8, ARRAY_SIZE(temp_fileW) - 8);
1021
1022 /* Try a normal DOS path. */
1023 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
1024 ok(hres == S_OK ||
1025 broken(hres == E_UNEXPECTED), /* NT4 */
1026 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
1027 if (pic)
1028 IPicture_Release(pic);
1029
1030 VariantInit(&var);
1031 V_VT(&var) = VT_BSTR;
1032 V_BSTR(&var) = SysAllocString(temp_fileW + 8);
1033 hres = OleLoadPictureFile(var, (IDispatch **)&pic);
1034 ok(hres == S_OK, "OleLoadPictureFile error %#x\n", hres);
1035 IPicture_Release(pic);
1036 VariantClear(&var);
1037
1038 /* Try a DOS path with tacked on "file:". */
1039 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
1040 ok(hres == S_OK ||
1041 broken(hres == E_UNEXPECTED), /* NT4 */
1042 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
1043 if (pic)
1044 IPicture_Release(pic);
1045
1046 VariantInit(&var);
1047 V_VT(&var) = VT_BSTR;
1048 V_BSTR(&var) = SysAllocString(temp_fileW);
1049 hres = OleLoadPictureFile(var, (IDispatch **)&pic);
1050 ok(hres == CTL_E_PATHFILEACCESSERROR, "wrong error %#x\n", hres);
1051 VariantClear(&var);
1052
1053 DeleteFileA(temp_file);
1054
1055 /* Try with a nonexistent file. */
1056 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
1057 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
1058 broken(hres == E_UNEXPECTED) || /* NT4 */
1059 broken(hres == E_FAIL), /*Win2k */
1060 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
1061
1062 VariantInit(&var);
1063 V_VT(&var) = VT_BSTR;
1064 V_BSTR(&var) = SysAllocString(temp_fileW + 8);
1065 hres = OleLoadPictureFile(var, (IDispatch **)&pic);
1066 ok(hres == CTL_E_FILENOTFOUND, "wrong error %#x\n", hres);
1067 VariantClear(&var);
1068
1069 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
1070 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
1071 broken(hres == E_UNEXPECTED) || /* NT4 */
1072 broken(hres == E_FAIL), /* Win2k */
1073 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
1074
1075 VariantInit(&var);
1076 V_VT(&var) = VT_BSTR;
1077 V_BSTR(&var) = SysAllocString(temp_fileW);
1078 hres = OleLoadPictureFile(var, (IDispatch **)&pic);
1079 ok(hres == CTL_E_PATHFILEACCESSERROR, "wrong error %#x\n", hres);
1080 VariantClear(&var);
1081
1082 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1083 FILE_ATTRIBUTE_NORMAL, NULL);
1084 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
1085 CloseHandle(file);
1086
1087 /* Try a "file:" URL with slash separators. */
1088 ptr = temp_fileW + 8;
1089 while (*ptr)
1090 {
1091 if (*ptr == '\\')
1092 *ptr = '/';
1093 ptr++;
1094 }
1095
1096 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
1097 ok(hres == S_OK ||
1098 broken(hres == E_UNEXPECTED), /* NT4 */
1099 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
1100 if (pic)
1101 IPicture_Release(pic);
1102
1103 VariantInit(&var);
1104 V_VT(&var) = VT_BSTR;
1105 V_BSTR(&var) = SysAllocString(temp_fileW);
1106 hres = OleLoadPictureFile(var, (IDispatch **)&pic);
1107 ok(hres == CTL_E_PATHFILEACCESSERROR, "wrong error %#x\n", hres);
1108 VariantClear(&var);
1109
1110 DeleteFileA(temp_file);
1111
1112 /* Try with a nonexistent file. */
1113 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
1114 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
1115 broken(hres == E_UNEXPECTED) || /* NT4 */
1116 broken(hres == E_FAIL), /* Win2k */
1117 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
1118
1119 VariantInit(&var);
1120 V_VT(&var) = VT_BSTR;
1121 V_BSTR(&var) = SysAllocString(temp_fileW);
1122 hres = OleLoadPictureFile(var, (IDispatch **)&pic);
1123 ok(hres == CTL_E_PATHFILEACCESSERROR, "wrong error %#x\n", hres);
1124 VariantClear(&var);
1125
1126 VariantInit(&var);
1127 V_VT(&var) = VT_INT;
1128 V_INT(&var) = 762;
1129 hres = OleLoadPictureFile(var, (IDispatch **)&pic);
1130 ok(hres == CTL_E_FILENOTFOUND, "wrong error %#x\n", hres);
1131
1132 if (0) /* crashes under Windows */
1133 hres = OleLoadPictureFile(var, NULL);
1134 }
1135
test_himetric(void)1136 static void test_himetric(void)
1137 {
1138 static const BYTE bmp_bits[1024];
1139 OLE_XSIZE_HIMETRIC cx;
1140 OLE_YSIZE_HIMETRIC cy;
1141 IPicture *pic;
1142 PICTDESC desc;
1143 HBITMAP bmp;
1144 HRESULT hr;
1145 HICON icon;
1146 HDC hdc;
1147 INT d;
1148
1149 desc.cbSizeofstruct = sizeof(desc);
1150 desc.picType = PICTYPE_BITMAP;
1151 desc.bmp.hpal = NULL;
1152
1153 hdc = CreateCompatibleDC(0);
1154
1155 bmp = CreateBitmap(1.9 * GetDeviceCaps(hdc, LOGPIXELSX),
1156 1.9 * GetDeviceCaps(hdc, LOGPIXELSY), 1, 1, NULL);
1157
1158 desc.bmp.hbitmap = bmp;
1159
1160 /* size in himetric units reported rounded up to next integer value */
1161 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1162 ok(hr == S_OK, "got 0x%08x\n", hr);
1163
1164 cx = 0;
1165 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSX)), 2540, GetDeviceCaps(hdc, LOGPIXELSX));
1166 hr = IPicture_get_Width(pic, &cx);
1167 ok(hr == S_OK, "got 0x%08x\n", hr);
1168 ok(cx == d, "got %d, expected %d\n", cx, d);
1169
1170 cy = 0;
1171 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSY)), 2540, GetDeviceCaps(hdc, LOGPIXELSY));
1172 hr = IPicture_get_Height(pic, &cy);
1173 ok(hr == S_OK, "got 0x%08x\n", hr);
1174 ok(cy == d, "got %d, expected %d\n", cy, d);
1175
1176 DeleteObject(bmp);
1177 IPicture_Release(pic);
1178
1179 /* same thing with icon */
1180 icon = CreateIcon(NULL, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
1181 1, 1, bmp_bits, bmp_bits);
1182 ok(icon != NULL, "failed to create icon\n");
1183
1184 desc.picType = PICTYPE_ICON;
1185 desc.icon.hicon = icon;
1186
1187 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1188 ok(hr == S_OK, "got 0x%08x\n", hr);
1189
1190 cx = 0;
1191 d = MulDiv(GetSystemMetrics(SM_CXICON), 2540, GetDeviceCaps(hdc, LOGPIXELSX));
1192 hr = IPicture_get_Width(pic, &cx);
1193 ok(hr == S_OK, "got 0x%08x\n", hr);
1194 ok(cx == d, "got %d, expected %d\n", cx, d);
1195
1196 cy = 0;
1197 d = MulDiv(GetSystemMetrics(SM_CYICON), 2540, GetDeviceCaps(hdc, LOGPIXELSY));
1198 hr = IPicture_get_Height(pic, &cy);
1199 ok(hr == S_OK, "got 0x%08x\n", hr);
1200 ok(cy == d, "got %d, expected %d\n", cy, d);
1201
1202 IPicture_Release(pic);
1203 DestroyIcon(icon);
1204
1205 DeleteDC(hdc);
1206 }
1207
test_load_save_bmp(void)1208 static void test_load_save_bmp(void)
1209 {
1210 IPicture *pic;
1211 PICTDESC desc;
1212 short type;
1213 OLE_HANDLE handle;
1214 HGLOBAL hmem;
1215 DWORD *mem;
1216 IPersistStream *src_stream;
1217 IStream *dst_stream;
1218 LARGE_INTEGER offset;
1219 HRESULT hr;
1220 LONG size;
1221
1222 desc.cbSizeofstruct = sizeof(desc);
1223 desc.picType = PICTYPE_BITMAP;
1224 desc.bmp.hpal = 0;
1225 desc.bmp.hbitmap = CreateBitmap(1, 1, 1, 1, NULL);
1226 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1227 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1228
1229 type = -1;
1230 hr = IPicture_get_Type(pic, &type);
1231 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1232 ok(type == PICTYPE_BITMAP,"expected picture type PICTYPE_BITMAP, got %d\n", type);
1233
1234 hr = IPicture_get_Handle(pic, &handle);
1235 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1236 ok(IntToPtr(handle) == desc.bmp.hbitmap, "get_Handle returned wrong handle %#x\n", handle);
1237
1238 hmem = GlobalAlloc(GMEM_ZEROINIT, 4096);
1239 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1240 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr);
1241
1242 size = -1;
1243 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size);
1244 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1245 ok(size == 66, "expected 66, got %d\n", size);
1246 mem = GlobalLock(hmem);
1247 ok(!memcmp(&mem[0], "BM", 2), "got wrong bmp header %04x\n", mem[0]);
1248 GlobalUnlock(hmem);
1249
1250 size = -1;
1251 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size);
1252 ok(hr == E_FAIL, "expected E_FAIL, got %#x\n", hr);
1253 ok(size == -1, "expected -1, got %d\n", size);
1254
1255 offset.QuadPart = 0;
1256 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL);
1257 ok(hr == S_OK, "IStream_Seek %#x\n", hr);
1258
1259 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1260 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1261
1262 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1263 ok(hr == S_OK, "Save error %#x\n", hr);
1264
1265 IPersistStream_Release(src_stream);
1266 IStream_Release(dst_stream);
1267
1268 mem = GlobalLock(hmem);
1269 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1270 ok(mem[1] == 66, "expected stream size 66, got %u\n", mem[1]);
1271 ok(!memcmp(&mem[2], "BM", 2), "got wrong bmp header %04x\n", mem[2]);
1272
1273 GlobalUnlock(hmem);
1274 GlobalFree(hmem);
1275
1276 DeleteObject(desc.bmp.hbitmap);
1277 IPicture_Release(pic);
1278 }
1279
test_load_save_icon(void)1280 static void test_load_save_icon(void)
1281 {
1282 IPicture *pic;
1283 PICTDESC desc;
1284 short type;
1285 OLE_HANDLE handle;
1286 HGLOBAL hmem;
1287 DWORD *mem;
1288 IPersistStream *src_stream;
1289 IStream *dst_stream;
1290 LARGE_INTEGER offset;
1291 HRESULT hr;
1292 LONG size;
1293
1294 desc.cbSizeofstruct = sizeof(desc);
1295 desc.picType = PICTYPE_ICON;
1296 desc.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
1297 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1298 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1299
1300 type = -1;
1301 hr = IPicture_get_Type(pic, &type);
1302 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1303 ok(type == PICTYPE_ICON,"expected picture type PICTYPE_ICON, got %d\n", type);
1304
1305 hr = IPicture_get_Handle(pic, &handle);
1306 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1307 ok(IntToPtr(handle) == desc.icon.hicon, "get_Handle returned wrong handle %#x\n", handle);
1308
1309 hmem = GlobalAlloc(GMEM_ZEROINIT, 8192);
1310 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1311 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
1312
1313 size = -1;
1314 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size);
1315 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1316 todo_wine
1317 ok(size == 766, "expected 766, got %d\n", size);
1318 mem = GlobalLock(hmem);
1319 ok(mem[0] == 0x00010000, "got wrong icon header %04x\n", mem[0]);
1320 GlobalUnlock(hmem);
1321
1322 size = -1;
1323 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size);
1324 ok(hr == E_FAIL, "expected E_FAIL, got %#x\n", hr);
1325 ok(size == -1, "expected -1, got %d\n", size);
1326
1327 offset.QuadPart = 0;
1328 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL);
1329 ok(hr == S_OK, "IStream_Seek %#x\n", hr);
1330
1331 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1332 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1333
1334 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1335 ok(hr == S_OK, "Saveerror %#x\n", hr);
1336
1337 IPersistStream_Release(src_stream);
1338 IStream_Release(dst_stream);
1339
1340 mem = GlobalLock(hmem);
1341 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1342 todo_wine
1343 ok(mem[1] == 766, "expected stream size 766, got %u\n", mem[1]);
1344 ok(mem[2] == 0x00010000, "got wrong icon header %04x\n", mem[2]);
1345
1346 GlobalUnlock(hmem);
1347 GlobalFree(hmem);
1348
1349 DestroyIcon(desc.icon.hicon);
1350 IPicture_Release(pic);
1351 }
1352
test_load_save_empty_picture(void)1353 static void test_load_save_empty_picture(void)
1354 {
1355 IPicture *pic;
1356 PICTDESC desc;
1357 short type;
1358 OLE_HANDLE handle;
1359 HGLOBAL hmem;
1360 DWORD *mem;
1361 IPersistStream *src_stream;
1362 IStream *dst_stream, *stream;
1363 LARGE_INTEGER offset;
1364 HRESULT hr;
1365 LONG size;
1366
1367 memset(&pic, 0, sizeof(pic));
1368 desc.cbSizeofstruct = sizeof(desc);
1369 desc.picType = PICTYPE_NONE;
1370 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void **)&pic);
1371 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1372
1373 type = -1;
1374 hr = IPicture_get_Type(pic, &type);
1375 ok(hr == S_OK, "get_Type error %#x\n", hr);
1376 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
1377
1378 handle = (OLE_HANDLE)0xdeadbeef;
1379 hr = IPicture_get_Handle(pic, &handle);
1380 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1381 ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
1382
1383 hmem = GlobalAlloc(GMEM_ZEROINIT, 4096);
1384 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1385 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr);
1386
1387 size = -1;
1388 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size);
1389 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1390 ok(size == -1, "expected -1, got %d\n", size);
1391
1392 size = -1;
1393 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size);
1394 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1395 ok(size == -1, "expected -1, got %d\n", size);
1396
1397 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1398 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1399
1400 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1401 ok(hr == S_OK, "Save error %#x\n", hr);
1402
1403 mem = GlobalLock(hmem);
1404 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1405 ok(mem[1] == 0, "expected stream size 0, got %u\n", mem[1]);
1406 GlobalUnlock(hmem);
1407
1408 IPersistStream_Release(src_stream);
1409 IPicture_Release(pic);
1410
1411 /* first with statable and seekable stream */
1412 offset.QuadPart = 0;
1413 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL);
1414 ok(hr == S_OK, "IStream_Seek %#x\n", hr);
1415
1416 pic = NULL;
1417 hr = pOleLoadPicture(dst_stream, 0, FALSE, &IID_IPicture, (void **)&pic);
1418 ok(hr == S_OK, "OleLoadPicture error %#x\n", hr);
1419 ok(pic != NULL,"picture should not be not NULL\n");
1420 if (pic != NULL)
1421 {
1422 type = -1;
1423 hr = IPicture_get_Type(pic, &type);
1424 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1425 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
1426
1427 handle = (OLE_HANDLE)0xdeadbeef;
1428 hr = IPicture_get_Handle(pic, &handle);
1429 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1430 ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
1431
1432 IPicture_Release(pic);
1433 }
1434 IStream_Release(dst_stream);
1435
1436 /* again with non-statable and non-seekable stream */
1437 stream = NoStatStream_Construct(hmem);
1438 ok(stream != NULL, "failed to create empty image stream\n");
1439
1440 pic = NULL;
1441 hr = pOleLoadPicture(stream, 0, FALSE, &IID_IPicture, (void **)&pic);
1442 ok(hr == S_OK, "OleLoadPicture error %#x\n", hr);
1443 ok(pic != NULL,"picture should not be not NULL\n");
1444 if (pic != NULL)
1445 {
1446 type = -1;
1447 hr = IPicture_get_Type(pic, &type);
1448 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1449 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
1450
1451 handle = (OLE_HANDLE)0xdeadbeef;
1452 hr = IPicture_get_Handle(pic, &handle);
1453 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1454 ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
1455
1456 IPicture_Release(pic);
1457 }
1458 /* Non-statable impl always deletes on release */
1459 IStream_Release(stream);
1460 }
1461
test_load_save_emf(void)1462 static void test_load_save_emf(void)
1463 {
1464 HDC hdc;
1465 IPicture *pic;
1466 PICTDESC desc;
1467 short type;
1468 OLE_HANDLE handle;
1469 HGLOBAL hmem;
1470 DWORD *mem;
1471 ENHMETAHEADER *emh;
1472 IPersistStream *src_stream;
1473 IStream *dst_stream;
1474 LARGE_INTEGER offset;
1475 HRESULT hr;
1476 LONG size;
1477
1478 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
1479 ok(hdc != 0, "CreateEnhMetaFileA failed\n");
1480
1481 desc.cbSizeofstruct = sizeof(desc);
1482 desc.picType = PICTYPE_ENHMETAFILE;
1483 desc.emf.hemf = CloseEnhMetaFile(hdc);
1484 ok(desc.emf.hemf != 0, "CloseEnhMetaFile failed\n");
1485 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1486 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1487
1488 type = -1;
1489 hr = IPicture_get_Type(pic, &type);
1490 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1491 ok(type == PICTYPE_ENHMETAFILE,"expected PICTYPE_ENHMETAFILE, got %d\n", type);
1492
1493 hr = IPicture_get_Handle(pic, &handle);
1494 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1495 ok(IntToPtr(handle) == desc.emf.hemf, "get_Handle returned wrong handle %#x\n", handle);
1496
1497 hmem = GlobalAlloc(GMEM_MOVEABLE, 0);
1498 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1499 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr);
1500
1501 size = -1;
1502 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size);
1503 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1504 ok(size == 128, "expected 128, got %d\n", size);
1505 emh = GlobalLock(hmem);
1506 if (size)
1507 {
1508 ok(emh->iType == EMR_HEADER, "wrong iType %04x\n", emh->iType);
1509 ok(emh->dSignature == ENHMETA_SIGNATURE, "wrong dSignature %08x\n", emh->dSignature);
1510 }
1511 GlobalUnlock(hmem);
1512
1513 size = -1;
1514 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size);
1515 ok(hr == E_FAIL, "expected E_FAIL, got %#x\n", hr);
1516 ok(size == -1, "expected -1, got %d\n", size);
1517
1518 offset.QuadPart = 0;
1519 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL);
1520 ok(hr == S_OK, "IStream_Seek %#x\n", hr);
1521
1522 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1523 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1524
1525 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1526 ok(hr == S_OK, "Save error %#x\n", hr);
1527
1528 IPersistStream_Release(src_stream);
1529 IStream_Release(dst_stream);
1530
1531 mem = GlobalLock(hmem);
1532 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1533 ok(mem[1] == 128, "expected 128, got %u\n", mem[1]);
1534 emh = (ENHMETAHEADER *)(mem + 2);
1535 ok(emh->iType == EMR_HEADER, "wrong iType %04x\n", emh->iType);
1536 ok(emh->dSignature == ENHMETA_SIGNATURE, "wrong dSignature %08x\n", emh->dSignature);
1537
1538 GlobalUnlock(hmem);
1539 GlobalFree(hmem);
1540
1541 DeleteEnhMetaFile(desc.emf.hemf);
1542 IPicture_Release(pic);
1543 }
1544
START_TEST(olepicture)1545 START_TEST(olepicture)
1546 {
1547 hOleaut32 = GetModuleHandleA("oleaut32.dll");
1548 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
1549 pOleLoadPictureEx = (void*)GetProcAddress(hOleaut32, "OleLoadPictureEx");
1550 if (!pOleLoadPicture)
1551 {
1552 win_skip("OleLoadPicture is not available\n");
1553 return;
1554 }
1555
1556 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
1557 test_pic(gifimage, sizeof(gifimage));
1558 test_pic(jpgimage, sizeof(jpgimage));
1559 test_pic(bmpimage, sizeof(bmpimage));
1560 test_pic(bmpimage_rle8, sizeof(bmpimage_rle8));
1561 test_pic(gif4pixel, sizeof(gif4pixel));
1562 /* FIXME: No PNG support in Windows... */
1563 if (0) test_pic(pngimage, sizeof(pngimage));
1564 test_empty_image();
1565 test_empty_image_2();
1566 if (pOleLoadPictureEx)
1567 {
1568 test_apm();
1569 test_metafile();
1570 test_enhmetafile();
1571 }
1572 else
1573 win_skip("OleLoadPictureEx is not available\n");
1574 test_Invoke();
1575 test_OleCreatePictureIndirect();
1576 test_Render();
1577 test_get_Attributes();
1578 test_get_Handle();
1579 test_get_Type();
1580 test_OleLoadPicturePath();
1581 test_himetric();
1582 test_load_save_bmp();
1583 test_load_save_icon();
1584 test_load_save_empty_picture();
1585 test_load_save_emf();
1586 }
1587
1588
1589 /* Helper functions only ... */
1590
1591
impl_from_IStream(IStream * iface)1592 static inline NoStatStreamImpl *impl_from_IStream(IStream *iface)
1593 {
1594 return CONTAINING_RECORD(iface, NoStatStreamImpl, IStream_iface);
1595 }
1596
NoStatStreamImpl_Destroy(NoStatStreamImpl * This)1597 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
1598 {
1599 GlobalFree(This->supportHandle);
1600 This->supportHandle=0;
1601 HeapFree(GetProcessHeap(), 0, This);
1602 }
1603
NoStatStreamImpl_AddRef(IStream * iface)1604 static ULONG WINAPI NoStatStreamImpl_AddRef(
1605 IStream* iface)
1606 {
1607 NoStatStreamImpl* const This = impl_from_IStream(iface);
1608 return InterlockedIncrement(&This->ref);
1609 }
1610
NoStatStreamImpl_QueryInterface(IStream * iface,REFIID riid,void ** ppvObject)1611 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
1612 IStream* iface,
1613 REFIID riid, /* [in] */
1614 void** ppvObject) /* [iid_is][out] */
1615 {
1616 NoStatStreamImpl* const This = impl_from_IStream(iface);
1617 if (ppvObject==0) return E_INVALIDARG;
1618 *ppvObject = 0;
1619
1620 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IStream, riid))
1621 *ppvObject = &This->IStream_iface;
1622
1623 if ((*ppvObject)==0)
1624 return E_NOINTERFACE;
1625 NoStatStreamImpl_AddRef(iface);
1626 return S_OK;
1627 }
1628
NoStatStreamImpl_Release(IStream * iface)1629 static ULONG WINAPI NoStatStreamImpl_Release(
1630 IStream* iface)
1631 {
1632 NoStatStreamImpl* const This = impl_from_IStream(iface);
1633 ULONG newRef = InterlockedDecrement(&This->ref);
1634 if (newRef==0)
1635 NoStatStreamImpl_Destroy(This);
1636 return newRef;
1637 }
1638
NoStatStreamImpl_Read(IStream * iface,void * pv,ULONG cb,ULONG * pcbRead)1639 static HRESULT WINAPI NoStatStreamImpl_Read(
1640 IStream* iface,
1641 void* pv, /* [length_is][size_is][out] */
1642 ULONG cb, /* [in] */
1643 ULONG* pcbRead) /* [out] */
1644 {
1645 NoStatStreamImpl* const This = impl_from_IStream(iface);
1646 void* supportBuffer;
1647 ULONG bytesReadBuffer;
1648 ULONG bytesToReadFromBuffer;
1649
1650 if (pcbRead==0)
1651 pcbRead = &bytesReadBuffer;
1652 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
1653 supportBuffer = GlobalLock(This->supportHandle);
1654 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
1655 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
1656 *pcbRead = bytesToReadFromBuffer;
1657 GlobalUnlock(This->supportHandle);
1658 if(*pcbRead == cb)
1659 return S_OK;
1660 return S_FALSE;
1661 }
1662
NoStatStreamImpl_Write(IStream * iface,const void * pv,ULONG cb,ULONG * pcbWritten)1663 static HRESULT WINAPI NoStatStreamImpl_Write(
1664 IStream* iface,
1665 const void* pv, /* [size_is][in] */
1666 ULONG cb, /* [in] */
1667 ULONG* pcbWritten) /* [out] */
1668 {
1669 NoStatStreamImpl* const This = impl_from_IStream(iface);
1670 void* supportBuffer;
1671 ULARGE_INTEGER newSize;
1672 ULONG bytesWritten = 0;
1673
1674 if (pcbWritten == 0)
1675 pcbWritten = &bytesWritten;
1676 if (cb == 0)
1677 return S_OK;
1678 newSize.u.HighPart = 0;
1679 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
1680 if (newSize.u.LowPart > This->streamSize.u.LowPart)
1681 IStream_SetSize(iface, newSize);
1682
1683 supportBuffer = GlobalLock(This->supportHandle);
1684 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
1685 This->currentPosition.u.LowPart+=cb;
1686 *pcbWritten = cb;
1687 GlobalUnlock(This->supportHandle);
1688 return S_OK;
1689 }
1690
NoStatStreamImpl_Seek(IStream * iface,LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER * plibNewPosition)1691 static HRESULT WINAPI NoStatStreamImpl_Seek(
1692 IStream* iface,
1693 LARGE_INTEGER dlibMove, /* [in] */
1694 DWORD dwOrigin, /* [in] */
1695 ULARGE_INTEGER* plibNewPosition) /* [out] */
1696 {
1697 NoStatStreamImpl* const This = impl_from_IStream(iface);
1698 ULARGE_INTEGER newPosition;
1699 switch (dwOrigin)
1700 {
1701 case STREAM_SEEK_SET:
1702 newPosition.u.HighPart = 0;
1703 newPosition.u.LowPart = 0;
1704 break;
1705 case STREAM_SEEK_CUR:
1706 newPosition = This->currentPosition;
1707 break;
1708 case STREAM_SEEK_END:
1709 newPosition = This->streamSize;
1710 break;
1711 default:
1712 return STG_E_INVALIDFUNCTION;
1713 }
1714 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
1715 return STG_E_INVALIDFUNCTION;
1716 newPosition.QuadPart += dlibMove.QuadPart;
1717 if (plibNewPosition) *plibNewPosition = newPosition;
1718 This->currentPosition = newPosition;
1719 return S_OK;
1720 }
1721
NoStatStreamImpl_SetSize(IStream * iface,ULARGE_INTEGER libNewSize)1722 static HRESULT WINAPI NoStatStreamImpl_SetSize(
1723 IStream* iface,
1724 ULARGE_INTEGER libNewSize) /* [in] */
1725 {
1726 NoStatStreamImpl* const This = impl_from_IStream(iface);
1727 HGLOBAL supportHandle;
1728 if (libNewSize.u.HighPart != 0)
1729 return STG_E_INVALIDFUNCTION;
1730 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
1731 return S_OK;
1732 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
1733 if (supportHandle == 0)
1734 return STG_E_MEDIUMFULL;
1735 This->supportHandle = supportHandle;
1736 This->streamSize.u.LowPart = libNewSize.u.LowPart;
1737 return S_OK;
1738 }
1739
NoStatStreamImpl_CopyTo(IStream * iface,IStream * pstm,ULARGE_INTEGER cb,ULARGE_INTEGER * pcbRead,ULARGE_INTEGER * pcbWritten)1740 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
1741 IStream* iface,
1742 IStream* pstm, /* [unique][in] */
1743 ULARGE_INTEGER cb, /* [in] */
1744 ULARGE_INTEGER* pcbRead, /* [out] */
1745 ULARGE_INTEGER* pcbWritten) /* [out] */
1746 {
1747 HRESULT hr = S_OK;
1748 BYTE tmpBuffer[128];
1749 ULONG bytesRead, bytesWritten, copySize;
1750 ULARGE_INTEGER totalBytesRead;
1751 ULARGE_INTEGER totalBytesWritten;
1752
1753 if ( pstm == 0 )
1754 return STG_E_INVALIDPOINTER;
1755 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
1756 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
1757
1758 while ( cb.u.LowPart > 0 )
1759 {
1760 if ( cb.u.LowPart >= 128 )
1761 copySize = 128;
1762 else
1763 copySize = cb.u.LowPart;
1764 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
1765 totalBytesRead.u.LowPart += bytesRead;
1766 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
1767 totalBytesWritten.u.LowPart += bytesWritten;
1768 if (bytesRead != bytesWritten)
1769 {
1770 hr = STG_E_MEDIUMFULL;
1771 break;
1772 }
1773 if (bytesRead!=copySize)
1774 cb.u.LowPart = 0;
1775 else
1776 cb.u.LowPart -= bytesRead;
1777 }
1778 if (pcbRead)
1779 {
1780 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
1781 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
1782 }
1783
1784 if (pcbWritten)
1785 {
1786 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
1787 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
1788 }
1789 return hr;
1790 }
1791
NoStatStreamImpl_Commit(IStream * iface,DWORD grfCommitFlags)1792 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
1793 {
1794 return S_OK;
1795 }
NoStatStreamImpl_Revert(IStream * iface)1796 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
1797
NoStatStreamImpl_LockRegion(IStream * iface,ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType)1798 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
1799 IStream* iface,
1800 ULARGE_INTEGER libOffset, /* [in] */
1801 ULARGE_INTEGER cb, /* [in] */
1802 DWORD dwLockType) /* [in] */
1803 {
1804 return S_OK;
1805 }
1806
NoStatStreamImpl_UnlockRegion(IStream * iface,ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType)1807 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
1808 IStream* iface,
1809 ULARGE_INTEGER libOffset, /* [in] */
1810 ULARGE_INTEGER cb, /* [in] */
1811 DWORD dwLockType) /* [in] */
1812 {
1813 return S_OK;
1814 }
1815
NoStatStreamImpl_Stat(IStream * iface,STATSTG * pstatstg,DWORD grfStatFlag)1816 static HRESULT WINAPI NoStatStreamImpl_Stat(
1817 IStream* iface,
1818 STATSTG* pstatstg, /* [out] */
1819 DWORD grfStatFlag) /* [in] */
1820 {
1821 return E_NOTIMPL;
1822 }
1823
NoStatStreamImpl_Clone(IStream * iface,IStream ** ppstm)1824 static HRESULT WINAPI NoStatStreamImpl_Clone(
1825 IStream* iface,
1826 IStream** ppstm) /* [out] */
1827 {
1828 return E_NOTIMPL;
1829 }
1830 static const IStreamVtbl NoStatStreamImpl_Vtbl;
1831
1832 /*
1833 Build an object that implements IStream, without IStream_Stat capabilities.
1834 Receives a memory handle with data buffer. If memory handle is non-null,
1835 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
1836 In any case the object takes ownership of memory handle and will free it on
1837 object release.
1838 */
NoStatStream_Construct(HGLOBAL hGlobal)1839 static IStream* NoStatStream_Construct(HGLOBAL hGlobal)
1840 {
1841 NoStatStreamImpl* newStream;
1842
1843 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
1844 if (newStream!=0)
1845 {
1846 newStream->IStream_iface.lpVtbl = &NoStatStreamImpl_Vtbl;
1847 newStream->ref = 1;
1848 newStream->supportHandle = hGlobal;
1849
1850 if (!newStream->supportHandle)
1851 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
1852 GMEM_SHARE, 0);
1853 newStream->currentPosition.u.HighPart = 0;
1854 newStream->currentPosition.u.LowPart = 0;
1855 newStream->streamSize.u.HighPart = 0;
1856 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
1857 }
1858 return &newStream->IStream_iface;
1859 }
1860
1861
1862 static const IStreamVtbl NoStatStreamImpl_Vtbl =
1863 {
1864 NoStatStreamImpl_QueryInterface,
1865 NoStatStreamImpl_AddRef,
1866 NoStatStreamImpl_Release,
1867 NoStatStreamImpl_Read,
1868 NoStatStreamImpl_Write,
1869 NoStatStreamImpl_Seek,
1870 NoStatStreamImpl_SetSize,
1871 NoStatStreamImpl_CopyTo,
1872 NoStatStreamImpl_Commit,
1873 NoStatStreamImpl_Revert,
1874 NoStatStreamImpl_LockRegion,
1875 NoStatStreamImpl_UnlockRegion,
1876 NoStatStreamImpl_Stat,
1877 NoStatStreamImpl_Clone
1878 };
1879