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