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