Sync advapi32, gdi32, gdiplus, inetmib1, kernel32, mlang, msi, msvcrt, ntdll, oleaut3...
[reactos.git] / rostests / winetests / oleaut32 / olepicture.c
1 /*
2 * OLEPICTURE test program
3 *
4 * Copyright 2005 Marcus Meissner
5 *
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <math.h>
25 #include <float.h>
26
27 #define COBJMACROS
28 #define NONAMELESSUNION
29
30 #include "wine/test.h"
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winuser.h>
34 #include <wingdi.h>
35 #include <winnls.h>
36 #include <winerror.h>
37 #include <winnt.h>
38
39 #include <urlmon.h>
40 #include <wtypes.h>
41 #include <olectl.h>
42 #include <objidl.h>
43
44 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
45
46 #define ole_expect(expr, expect) { \
47 HRESULT r = expr; \
48 ok(r == (expect), #expr " returned %x, expected %s (%x)\n", r, #expect, expect); \
49 }
50
51 #define ole_check(expr) ole_expect(expr, S_OK);
52
53 static HMODULE hOleaut32;
54
55 static HRESULT (WINAPI *pOleLoadPicture)(LPSTREAM,LONG,BOOL,REFIID,LPVOID*);
56 static HRESULT (WINAPI *pOleCreatePictureIndirect)(PICTDESC*,REFIID,BOOL,LPVOID*);
57
58 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
59
60 /* 1x1 pixel gif */
61 static const unsigned char gifimage[35] = {
62 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
63 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
64 0x01,0x00,0x3b
65 };
66
67 /* 1x1 pixel jpg */
68 static const unsigned char jpgimage[285] = {
69 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
70 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
71 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
72 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
73 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
74 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
75 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
76 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
77 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
78 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
79 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
80 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
81 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
82 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
83 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
84 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
85 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
86 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
87 };
88
89 /* 1x1 pixel png */
90 static const unsigned char pngimage[285] = {
91 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
92 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
93 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
94 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
95 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
96 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
97 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
98 };
99
100 /* 1x1 pixel bmp */
101 static const unsigned char bmpimage[66] = {
102 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
103 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
104 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
105 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
106 0x00,0x00
107 };
108
109 /* 2x2 pixel gif */
110 static const unsigned char gif4pixel[42] = {
111 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
112 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
113 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
114 };
115
116 /* APM with an empty metafile with some padding zeros - looks like under Window the
117 * metafile data should be at least 20 bytes */
118 static const unsigned char apmdata[] = {
119 0xd7,0xcd,0xc6,0x9a, 0x00,0x00,0x00,0x00, 0x00,0x00,0xee,0x02, 0xb1,0x03,0xa0,0x05,
120 0x00,0x00,0x00,0x00, 0xee,0x53,0x01,0x00, 0x09,0x00,0x00,0x03, 0x13,0x00,0x00,0x00,
121 0x01,0x00,0x05,0x00, 0x00,0x00,0x00,0x00, 0x03,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
122 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
123 };
124
125 /* MF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
126 static const unsigned char metafile[] = {
127 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
128 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
129 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
130 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
131 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
132 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
133 0x00, 0x00
134 };
135
136 /* EMF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
137 static const unsigned char enhmetafile[] = {
138 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
143 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
144 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
145 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
148 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
151 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
152 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
153 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
155 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
156 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
157 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
158 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
161 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
162 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
163 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
164 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
165 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
166 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
167 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
168 0x14, 0x00, 0x00, 0x00
169 };
170
171
172 struct NoStatStreamImpl
173 {
174 const IStreamVtbl *lpVtbl;
175 LONG ref;
176
177 HGLOBAL supportHandle;
178 ULARGE_INTEGER streamSize;
179 ULARGE_INTEGER currentPosition;
180 };
181 typedef struct NoStatStreamImpl NoStatStreamImpl;
182 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal);
183
184 static void
185 test_pic_with_stream(LPSTREAM stream, unsigned int imgsize)
186 {
187 IPicture* pic = NULL;
188 HRESULT hres;
189 LPVOID pvObj = NULL;
190 OLE_HANDLE handle, hPal;
191 OLE_XSIZE_HIMETRIC width;
192 OLE_YSIZE_HIMETRIC height;
193 short type;
194 DWORD attr;
195 ULONG res;
196
197 pvObj = NULL;
198 hres = pOleLoadPicture(stream, imgsize, TRUE, &IID_IPicture, &pvObj);
199 pic = pvObj;
200
201 ok(hres == S_OK,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres);
202 ok(pic != NULL,"OLP (NULL,..) returns NULL, instead of !NULL\n");
203 if (pic == NULL)
204 return;
205
206 pvObj = NULL;
207 hres = IPicture_QueryInterface (pic, &IID_IPicture, &pvObj);
208
209 ok(hres == S_OK,"IPicture_QI does not return S_OK, but 0x%08x\n", hres);
210 ok(pvObj != NULL,"IPicture_QI does return NULL, instead of a ptr\n");
211
212 IPicture_Release ((IPicture*)pvObj);
213
214 handle = 0;
215 hres = IPicture_get_Handle (pic, &handle);
216 ok(hres == S_OK,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres);
217 ok(handle != 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
218
219 width = 0;
220 hres = IPicture_get_Width (pic, &width);
221 ok(hres == S_OK,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres);
222 ok(width != 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
223
224 height = 0;
225 hres = IPicture_get_Height (pic, &height);
226 ok(hres == S_OK,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres);
227 ok(height != 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
228
229 type = 0;
230 hres = IPicture_get_Type (pic, &type);
231 ok(hres == S_OK,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
232 ok(type == PICTYPE_BITMAP, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type, PICTYPE_BITMAP);
233
234 attr = 0;
235 hres = IPicture_get_Attributes (pic, &attr);
236 ok(hres == S_OK,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres);
237 ok(attr == 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr);
238
239 hPal = 0;
240 hres = IPicture_get_hPal (pic, &hPal);
241 ok(hres == S_OK,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres);
242 /* a single pixel b/w image has no palette */
243 ok(hPal == 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal);
244
245 res = IPicture_Release (pic);
246 ok (res == 0, "refcount after release is %d, but should be 0?\n", res);
247 }
248
249 static void
250 test_pic(const unsigned char *imgdata, unsigned int imgsize)
251 {
252 LPSTREAM stream;
253 HGLOBAL hglob;
254 LPBYTE data;
255 HRESULT hres;
256 LARGE_INTEGER seekto;
257 ULARGE_INTEGER newpos1;
258 DWORD * header;
259 unsigned int i,j;
260
261 /* Let the fun begin */
262 hglob = GlobalAlloc (0, imgsize);
263 data = GlobalLock (hglob);
264 memcpy(data, imgdata, imgsize);
265 GlobalUnlock(hglob); data = NULL;
266
267 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
268 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
269
270 memset(&seekto,0,sizeof(seekto));
271 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
272 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
273 test_pic_with_stream(stream, imgsize);
274
275 IStream_Release(stream);
276
277 /* again with Non Statable and Non Seekable stream */
278 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
279 hglob = 0; /* Non-statable impl always deletes on release */
280 test_pic_with_stream(stream, 0);
281
282 IStream_Release(stream);
283 for (i = 1; i <= 8; i++) {
284 /* more fun!!! */
285 hglob = GlobalAlloc (0, imgsize + i * (2 * sizeof(DWORD)));
286 data = GlobalLock (hglob);
287 header = (DWORD *)data;
288
289 /* multiple copies of header */
290 memcpy(data,"lt\0\0",4);
291 header[1] = imgsize;
292 for (j = 2; j <= i; j++) {
293 memcpy(&(header[2 * (j - 1)]), header, 2 * sizeof(DWORD));
294 }
295 memcpy(data + i * (2 * sizeof(DWORD)), 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 = (LPSTREAM)NoStatStreamImpl_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 }
315 }
316
317 static void test_empty_image(void) {
318 LPBYTE data;
319 LPSTREAM stream;
320 IPicture* pic = NULL;
321 HRESULT hres;
322 LPVOID pvObj = NULL;
323 HGLOBAL hglob;
324 OLE_HANDLE handle;
325 ULARGE_INTEGER newpos1;
326 LARGE_INTEGER seekto;
327 short type;
328 DWORD attr;
329
330 /* Empty image. Happens occasionally in VB programs. */
331 hglob = GlobalAlloc (0, 8);
332 data = GlobalLock (hglob);
333 memcpy(data,"lt\0\0",4);
334 ((DWORD*)data)[1] = 0;
335 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
336 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
337
338 memset(&seekto,0,sizeof(seekto));
339 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
340 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
341
342 pvObj = NULL;
343 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
344 pic = pvObj;
345 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
346 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
347
348 hres = IPicture_get_Type (pic, &type);
349 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
350 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
351
352 attr = 0xdeadbeef;
353 hres = IPicture_get_Attributes (pic, &attr);
354 ok (hres == S_OK,"empty picture get attributes failed with hres 0x%08x\n", hres);
355 ok (attr == 0,"attr is %d, but should be 0\n", attr);
356
357 hres = IPicture_get_Handle (pic, &handle);
358 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
359 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
360 IPicture_Release (pic);
361 IStream_Release (stream);
362 }
363
364 static void test_empty_image_2(void) {
365 LPBYTE data;
366 LPSTREAM stream;
367 IPicture* pic = NULL;
368 HRESULT hres;
369 LPVOID pvObj = NULL;
370 HGLOBAL hglob;
371 ULARGE_INTEGER newpos1;
372 LARGE_INTEGER seekto;
373 short type;
374
375 /* Empty image at random stream position. */
376 hglob = GlobalAlloc (0, 200);
377 data = GlobalLock (hglob);
378 data += 42;
379 memcpy(data,"lt\0\0",4);
380 ((DWORD*)data)[1] = 0;
381 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
382 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
383
384 memset(&seekto,0,sizeof(seekto));
385 seekto.u.LowPart = 42;
386 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
387 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
388
389 pvObj = NULL;
390 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
391 pic = pvObj;
392 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
393 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
394
395 hres = IPicture_get_Type (pic, &type);
396 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
397 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
398
399 IPicture_Release (pic);
400 IStream_Release (stream);
401 }
402
403 static void test_Invoke(void)
404 {
405 IPictureDisp *picdisp;
406 HRESULT hr;
407 VARIANTARG vararg;
408 DISPPARAMS dispparams;
409 VARIANT varresult;
410 IStream *stream;
411 HGLOBAL hglob;
412 void *data;
413
414 hglob = GlobalAlloc (0, sizeof(gifimage));
415 data = GlobalLock(hglob);
416 memcpy(data, gifimage, sizeof(gifimage));
417 GlobalUnlock(hglob);
418
419 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
420 ok_ole_success(hr, "CreateStreamOnHGlobal");
421
422 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
423 IStream_Release(stream);
424 GlobalFree(hglob);
425 ok_ole_success(hr, "OleLoadPicture");
426
427 V_VT(&vararg) = VT_BOOL;
428 V_BOOL(&vararg) = VARIANT_FALSE;
429 dispparams.cNamedArgs = 0;
430 dispparams.rgdispidNamedArgs = NULL;
431 dispparams.cArgs = 1;
432 dispparams.rgvarg = &vararg;
433 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
434 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
435 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
436 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
437
438 dispparams.cArgs = 0;
439 dispparams.rgvarg = NULL;
440 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
441 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
442
443 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
444 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
445
446 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
447 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
448
449 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
450 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
451
452 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
453 ok_ole_success(hr, "IPictureDisp_Invoke");
454 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
455
456 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
457 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
458
459 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
460 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
461
462 dispparams.cArgs = 1;
463 dispparams.rgvarg = &vararg;
464 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
465 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
466
467 dispparams.cArgs = 1;
468 dispparams.rgvarg = &vararg;
469 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
470 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
471
472 IPictureDisp_Release(picdisp);
473 }
474
475 static void test_OleCreatePictureIndirect(void)
476 {
477 IPicture *pict;
478 HRESULT hr;
479 short type;
480 OLE_HANDLE handle;
481
482 if(!pOleCreatePictureIndirect)
483 {
484 win_skip("Skipping OleCreatePictureIndirect tests\n");
485 return;
486 }
487
488 hr = pOleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict);
489 ok(hr == S_OK, "hr %08x\n", hr);
490
491 hr = IPicture_get_Type(pict, &type);
492 ok(hr == S_OK, "hr %08x\n", hr);
493 ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type);
494
495 hr = IPicture_get_Handle(pict, &handle);
496 ok(hr == S_OK, "hr %08x\n", hr);
497 ok(handle == 0, "handle %08x\n", handle);
498
499 IPicture_Release(pict);
500 }
501
502 static void test_apm(void)
503 {
504 OLE_HANDLE handle;
505 LPSTREAM stream;
506 IPicture *pict;
507 HGLOBAL hglob;
508 LPBYTE *data;
509 LONG cxy;
510 BOOL keep;
511 short type;
512
513 hglob = GlobalAlloc (0, sizeof(apmdata));
514 data = GlobalLock(hglob);
515 memcpy(data, apmdata, sizeof(apmdata));
516
517 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
518 ole_check(OleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict));
519
520 ole_check(IPicture_get_Handle(pict, &handle));
521 ok(handle != 0, "handle is null\n");
522
523 ole_check(IPicture_get_Type(pict, &type));
524 expect_eq(type, PICTYPE_METAFILE, short, "%d");
525
526 ole_check(IPicture_get_Height(pict, &cxy));
527 expect_eq(cxy, 1667, LONG, "%d");
528
529 ole_check(IPicture_get_Width(pict, &cxy));
530 expect_eq(cxy, 1323, LONG, "%d");
531
532 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
533 todo_wine expect_eq(keep, FALSE, LONG, "%d");
534
535 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL);
536 IPicture_Release(pict);
537 IStream_Release(stream);
538 }
539
540 static void test_metafile(void)
541 {
542 LPSTREAM stream;
543 IPicture *pict;
544 HGLOBAL hglob;
545 LPBYTE *data;
546
547 hglob = GlobalAlloc (0, sizeof(metafile));
548 data = GlobalLock(hglob);
549 memcpy(data, metafile, sizeof(metafile));
550
551 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
552 /* Windows does not load simple metafiles */
553 ole_expect(OleLoadPictureEx(stream, sizeof(metafile), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict), E_FAIL);
554
555 IStream_Release(stream);
556 }
557
558 static void test_enhmetafile(void)
559 {
560 OLE_HANDLE handle;
561 LPSTREAM stream;
562 IPicture *pict;
563 HGLOBAL hglob;
564 LPBYTE *data;
565 LONG cxy;
566 BOOL keep;
567 short type;
568
569 hglob = GlobalAlloc (0, sizeof(enhmetafile));
570 data = GlobalLock(hglob);
571 memcpy(data, enhmetafile, sizeof(enhmetafile));
572
573 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
574 ole_check(OleLoadPictureEx(stream, sizeof(enhmetafile), TRUE, &IID_IPicture, 10, 10, 0, (LPVOID *)&pict));
575
576 ole_check(IPicture_get_Handle(pict, &handle));
577 ok(handle != 0, "handle is null\n");
578
579 ole_check(IPicture_get_Type(pict, &type));
580 expect_eq(type, PICTYPE_ENHMETAFILE, short, "%d");
581
582 ole_check(IPicture_get_Height(pict, &cxy));
583 expect_eq(cxy, -23, LONG, "%d");
584
585 ole_check(IPicture_get_Width(pict, &cxy));
586 expect_eq(cxy, -25, LONG, "%d");
587
588 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
589 todo_wine expect_eq(keep, FALSE, LONG, "%d");
590
591 IPicture_Release(pict);
592 IStream_Release(stream);
593 }
594
595 static void test_Render(void)
596 {
597 IPicture *pic;
598 HRESULT hres;
599 short type;
600 PICTDESC desc;
601 OLE_XSIZE_HIMETRIC pWidth;
602 OLE_YSIZE_HIMETRIC pHeight;
603 COLORREF result, expected;
604 HDC hdc = GetDC(0);
605
606 /* test IPicture::Render return code on uninitialized picture */
607 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
608 hres = IPicture_get_Type(pic, &type);
609 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
610 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
611 /* zero dimensions */
612 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
613 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
614 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
615 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
616 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
617 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
618 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
619 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
620 hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
621 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
622 hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
623 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
624 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
625 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
626 /* nonzero dimensions, PICTYPE_UNINITIALIZED */
627 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL);
628 ole_expect(hres, S_OK);
629 IPicture_Release(pic);
630
631 desc.cbSizeofstruct = sizeof(PICTDESC);
632 desc.picType = PICTYPE_ICON;
633 desc.u.icon.hicon = LoadIcon(NULL, IDI_APPLICATION);
634 if(!desc.u.icon.hicon){
635 win_skip("LoadIcon failed. Skipping...\n");
636 ReleaseDC(NULL, hdc);
637 return;
638 }
639
640 OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (VOID**)&pic);
641 /* zero dimensions, PICTYPE_ICON */
642 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
643 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
644 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
645 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
646 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
647 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
648 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
649 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
650 hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
651 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
652 hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
653 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
654 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
655 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
656
657 /* Check if target size and position is respected */
658 IPicture_get_Width(pic, &pWidth);
659 IPicture_get_Height(pic, &pHeight);
660
661 SetPixelV(hdc, 0, 0, 0x00F0F0F0);
662 SetPixelV(hdc, 5, 5, 0x00F0F0F0);
663 SetPixelV(hdc, 10, 10, 0x00F0F0F0);
664 expected = GetPixel(hdc, 0, 0);
665
666 hres = IPicture_Render(pic, hdc, 1, 1, 9, 9, 0, 0, pWidth, -pHeight, NULL);
667 ole_expect(hres, S_OK);
668
669 if(hres != S_OK) {
670 IPicture_Release(pic);
671 ReleaseDC(NULL, hdc);
672 return;
673 }
674
675 /* Evaluate the rendered Icon */
676 result = GetPixel(hdc, 0, 0);
677 ok(result == expected,
678 "Color at 0,0 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
679 result = GetPixel(hdc, 5, 5);
680 ok(result != expected ||
681 broken(result == expected), /* WinNT 4.0 and older may claim they drew */
682 /* the icon, even if they didn't. */
683 "Color at 5,5 should have changed, but still was 0x%06X\n", expected);
684 result = GetPixel(hdc, 10, 10);
685 ok(result == expected,
686 "Color at 10,10 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
687
688 IPicture_Release(pic);
689 ReleaseDC(NULL, hdc);
690 }
691
692 static void test_get_Attributes(void)
693 {
694 IPicture *pic;
695 HRESULT hres;
696 short type;
697 DWORD attr;
698
699 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
700 hres = IPicture_get_Type(pic, &type);
701 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
702 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
703
704 hres = IPicture_get_Attributes(pic, NULL);
705 ole_expect(hres, E_POINTER);
706
707 attr = 0xdeadbeef;
708 hres = IPicture_get_Attributes(pic, &attr);
709 ole_expect(hres, S_OK);
710 ok(attr == 0, "IPicture_get_Attributes does not reset attr to zero, got %d\n", attr);
711
712 IPicture_Release(pic);
713 }
714
715 static void test_get_Handle(void)
716 {
717 IPicture *pic;
718 HRESULT hres;
719
720 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
721
722 hres = IPicture_get_Handle(pic, NULL);
723 ole_expect(hres, E_POINTER);
724
725 IPicture_Release(pic);
726 }
727
728 static void test_get_Type(void)
729 {
730 IPicture *pic;
731 HRESULT hres;
732
733 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
734
735 hres = IPicture_get_Type(pic, NULL);
736 ole_expect(hres, E_POINTER);
737
738 IPicture_Release(pic);
739 }
740
741 static void test_OleLoadPicturePath(void)
742 {
743 static WCHAR emptyW[] = {0};
744
745 IPicture *pic;
746 HRESULT hres;
747 int i;
748 char temp_path[MAX_PATH];
749 char temp_file[MAX_PATH];
750 WCHAR temp_fileW[MAX_PATH + 5] = {'f','i','l','e',':','/','/','/'};
751 HANDLE file;
752 DWORD size;
753 WCHAR *ptr;
754
755 const struct
756 {
757 LPOLESTR szURLorPath;
758 REFIID riid;
759 IPicture **pic;
760 } invalid_parameters[] =
761 {
762 {NULL, NULL, NULL},
763 {NULL, NULL, &pic},
764 {NULL, &IID_IPicture, NULL},
765 {NULL, &IID_IPicture, &pic},
766 {emptyW, NULL, NULL},
767 {emptyW, &IID_IPicture, NULL},
768 };
769
770 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
771 {
772 pic = (IPicture *)0xdeadbeef;
773 hres = OleLoadPicturePath(invalid_parameters[i].szURLorPath, NULL, 0, 0,
774 invalid_parameters[i].riid,
775 (void **)invalid_parameters[i].pic);
776 ok(hres == E_INVALIDARG,
777 "[%d] Expected OleLoadPicturePath to return E_INVALIDARG, got 0x%08x\n", i, hres);
778 ok(pic == (IPicture *)0xdeadbeef,
779 "[%d] Expected output pointer to be 0xdeadbeef, got %p\n", i, pic);
780 }
781
782 pic = (IPicture *)0xdeadbeef;
783 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, NULL, (void **)&pic);
784 todo_wine
785 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
786 hres == E_UNEXPECTED || /* NT4/Win95 */
787 hres == E_FAIL || /* Win95 OSR2 */
788 hres == E_OUTOFMEMORY, /* Win98/Win2k/Win2k3 */
789 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
790 ok(pic == NULL,
791 "Expected the output interface pointer to be NULL, got %p\n", pic);
792
793 pic = (IPicture *)0xdeadbeef;
794 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
795 todo_wine
796 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
797 hres == E_UNEXPECTED || /* NT4/Win95 */
798 hres == E_FAIL || /* Win95 OSR2 */
799 hres == E_OUTOFMEMORY, /* Win98/Win2k/Win2k3 */
800 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
801 ok(pic == NULL,
802 "Expected the output interface pointer to be NULL, got %p\n", pic);
803
804 /* Create a local temporary image file for testing. */
805 GetTempPathA(sizeof(temp_path), temp_path);
806 GetTempFileNameA(temp_path, "bmp", 0, temp_file);
807 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
808 FILE_ATTRIBUTE_NORMAL, NULL);
809 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
810 CloseHandle(file);
811
812 MultiByteToWideChar(CP_ACP, 0, temp_file, -1, temp_fileW + 8, sizeof(temp_fileW)/sizeof(WCHAR) - 8);
813
814 /* Try a normal DOS path. */
815 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
816 ok(hres == S_OK ||
817 broken(hres == E_UNEXPECTED), /* NT4/Win95 */
818 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
819 if (pic)
820 IPicture_Release(pic);
821
822 /* Try a DOS path with tacked on "file:". */
823 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
824 ok(hres == S_OK ||
825 broken(hres == E_UNEXPECTED), /* NT4/Win95 */
826 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
827 if (pic)
828 IPicture_Release(pic);
829
830 DeleteFileA(temp_file);
831
832 /* Try with a nonexistent file. */
833 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
834 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
835 hres == E_UNEXPECTED || /* NT4/Win95 */
836 hres == E_FAIL, /* Win9x/Win2k */
837 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
838
839 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
840 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
841 hres == E_UNEXPECTED || /* NT4/Win95 */
842 hres == E_FAIL, /* Win9x/Win2k */
843 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
844
845 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
846 FILE_ATTRIBUTE_NORMAL, NULL);
847 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
848 CloseHandle(file);
849
850 /* Try a "file:" URL with slash separators. */
851 ptr = temp_fileW + 8;
852 while (*ptr)
853 {
854 if (*ptr == '\\')
855 *ptr = '/';
856 ptr++;
857 }
858
859 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
860 ok(hres == S_OK ||
861 broken(hres == E_UNEXPECTED), /* NT4/Win95 */
862 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
863 if (pic)
864 IPicture_Release(pic);
865
866 DeleteFileA(temp_file);
867
868 /* Try with a nonexistent file. */
869 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
870 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
871 hres == E_UNEXPECTED || /* NT4/Win95 */
872 hres == E_FAIL, /* Win9x/Win2k */
873 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
874 }
875
876 START_TEST(olepicture)
877 {
878 hOleaut32 = GetModuleHandleA("oleaut32.dll");
879 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
880 pOleCreatePictureIndirect = (void*)GetProcAddress(hOleaut32, "OleCreatePictureIndirect");
881 if (!pOleLoadPicture)
882 {
883 win_skip("OleLoadPicture is not available\n");
884 return;
885 }
886
887 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
888 test_pic(gifimage, sizeof(gifimage));
889 test_pic(jpgimage, sizeof(jpgimage));
890 test_pic(bmpimage, sizeof(bmpimage));
891 test_pic(gif4pixel, sizeof(gif4pixel));
892 /* FIXME: No PNG support in Windows... */
893 if (0) test_pic(pngimage, sizeof(pngimage));
894 test_empty_image();
895 test_empty_image_2();
896 test_apm();
897 test_metafile();
898 test_enhmetafile();
899
900 test_Invoke();
901 test_OleCreatePictureIndirect();
902 test_Render();
903 test_get_Attributes();
904 test_get_Handle();
905 test_get_Type();
906 test_OleLoadPicturePath();
907 }
908
909
910 /* Helper functions only ... */
911
912
913 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
914 {
915 GlobalFree(This->supportHandle);
916 This->supportHandle=0;
917 HeapFree(GetProcessHeap(), 0, This);
918 }
919
920 static ULONG WINAPI NoStatStreamImpl_AddRef(
921 IStream* iface)
922 {
923 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
924 return InterlockedIncrement(&This->ref);
925 }
926
927 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
928 IStream* iface,
929 REFIID riid, /* [in] */
930 void** ppvObject) /* [iid_is][out] */
931 {
932 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
933 if (ppvObject==0) return E_INVALIDARG;
934 *ppvObject = 0;
935 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
936 {
937 *ppvObject = This;
938 }
939 else if (memcmp(&IID_IStream, riid, sizeof(IID_IStream)) == 0)
940 {
941 *ppvObject = This;
942 }
943
944 if ((*ppvObject)==0)
945 return E_NOINTERFACE;
946 NoStatStreamImpl_AddRef(iface);
947 return S_OK;
948 }
949
950 static ULONG WINAPI NoStatStreamImpl_Release(
951 IStream* iface)
952 {
953 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
954 ULONG newRef = InterlockedDecrement(&This->ref);
955 if (newRef==0)
956 NoStatStreamImpl_Destroy(This);
957 return newRef;
958 }
959
960 static HRESULT WINAPI NoStatStreamImpl_Read(
961 IStream* iface,
962 void* pv, /* [length_is][size_is][out] */
963 ULONG cb, /* [in] */
964 ULONG* pcbRead) /* [out] */
965 {
966 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
967 void* supportBuffer;
968 ULONG bytesReadBuffer;
969 ULONG bytesToReadFromBuffer;
970
971 if (pcbRead==0)
972 pcbRead = &bytesReadBuffer;
973 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
974 supportBuffer = GlobalLock(This->supportHandle);
975 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
976 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
977 *pcbRead = bytesToReadFromBuffer;
978 GlobalUnlock(This->supportHandle);
979 if(*pcbRead == cb)
980 return S_OK;
981 return S_FALSE;
982 }
983
984 static HRESULT WINAPI NoStatStreamImpl_Write(
985 IStream* iface,
986 const void* pv, /* [size_is][in] */
987 ULONG cb, /* [in] */
988 ULONG* pcbWritten) /* [out] */
989 {
990 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
991 void* supportBuffer;
992 ULARGE_INTEGER newSize;
993 ULONG bytesWritten = 0;
994
995 if (pcbWritten == 0)
996 pcbWritten = &bytesWritten;
997 if (cb == 0)
998 return S_OK;
999 newSize.u.HighPart = 0;
1000 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
1001 if (newSize.u.LowPart > This->streamSize.u.LowPart)
1002 IStream_SetSize(iface, newSize);
1003
1004 supportBuffer = GlobalLock(This->supportHandle);
1005 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
1006 This->currentPosition.u.LowPart+=cb;
1007 *pcbWritten = cb;
1008 GlobalUnlock(This->supportHandle);
1009 return S_OK;
1010 }
1011
1012 static HRESULT WINAPI NoStatStreamImpl_Seek(
1013 IStream* iface,
1014 LARGE_INTEGER dlibMove, /* [in] */
1015 DWORD dwOrigin, /* [in] */
1016 ULARGE_INTEGER* plibNewPosition) /* [out] */
1017 {
1018 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
1019 ULARGE_INTEGER newPosition;
1020 switch (dwOrigin)
1021 {
1022 case STREAM_SEEK_SET:
1023 newPosition.u.HighPart = 0;
1024 newPosition.u.LowPart = 0;
1025 break;
1026 case STREAM_SEEK_CUR:
1027 newPosition = This->currentPosition;
1028 break;
1029 case STREAM_SEEK_END:
1030 newPosition = This->streamSize;
1031 break;
1032 default:
1033 return STG_E_INVALIDFUNCTION;
1034 }
1035 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
1036 return STG_E_INVALIDFUNCTION;
1037 newPosition.QuadPart += dlibMove.QuadPart;
1038 if (plibNewPosition) *plibNewPosition = newPosition;
1039 This->currentPosition = newPosition;
1040 return S_OK;
1041 }
1042
1043 static HRESULT WINAPI NoStatStreamImpl_SetSize(
1044 IStream* iface,
1045 ULARGE_INTEGER libNewSize) /* [in] */
1046 {
1047 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
1048 HGLOBAL supportHandle;
1049 if (libNewSize.u.HighPart != 0)
1050 return STG_E_INVALIDFUNCTION;
1051 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
1052 return S_OK;
1053 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
1054 if (supportHandle == 0)
1055 return STG_E_MEDIUMFULL;
1056 This->supportHandle = supportHandle;
1057 This->streamSize.u.LowPart = libNewSize.u.LowPart;
1058 return S_OK;
1059 }
1060
1061 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
1062 IStream* iface,
1063 IStream* pstm, /* [unique][in] */
1064 ULARGE_INTEGER cb, /* [in] */
1065 ULARGE_INTEGER* pcbRead, /* [out] */
1066 ULARGE_INTEGER* pcbWritten) /* [out] */
1067 {
1068 HRESULT hr = S_OK;
1069 BYTE tmpBuffer[128];
1070 ULONG bytesRead, bytesWritten, copySize;
1071 ULARGE_INTEGER totalBytesRead;
1072 ULARGE_INTEGER totalBytesWritten;
1073
1074 if ( pstm == 0 )
1075 return STG_E_INVALIDPOINTER;
1076 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
1077 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
1078
1079 while ( cb.u.LowPart > 0 )
1080 {
1081 if ( cb.u.LowPart >= 128 )
1082 copySize = 128;
1083 else
1084 copySize = cb.u.LowPart;
1085 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
1086 totalBytesRead.u.LowPart += bytesRead;
1087 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
1088 totalBytesWritten.u.LowPart += bytesWritten;
1089 if (bytesRead != bytesWritten)
1090 {
1091 hr = STG_E_MEDIUMFULL;
1092 break;
1093 }
1094 if (bytesRead!=copySize)
1095 cb.u.LowPart = 0;
1096 else
1097 cb.u.LowPart -= bytesRead;
1098 }
1099 if (pcbRead)
1100 {
1101 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
1102 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
1103 }
1104
1105 if (pcbWritten)
1106 {
1107 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
1108 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
1109 }
1110 return hr;
1111 }
1112
1113 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
1114 {
1115 return S_OK;
1116 }
1117 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
1118
1119 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
1120 IStream* iface,
1121 ULARGE_INTEGER libOffset, /* [in] */
1122 ULARGE_INTEGER cb, /* [in] */
1123 DWORD dwLockType) /* [in] */
1124 {
1125 return S_OK;
1126 }
1127
1128 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
1129 IStream* iface,
1130 ULARGE_INTEGER libOffset, /* [in] */
1131 ULARGE_INTEGER cb, /* [in] */
1132 DWORD dwLockType) /* [in] */
1133 {
1134 return S_OK;
1135 }
1136
1137 static HRESULT WINAPI NoStatStreamImpl_Stat(
1138 IStream* iface,
1139 STATSTG* pstatstg, /* [out] */
1140 DWORD grfStatFlag) /* [in] */
1141 {
1142 return E_NOTIMPL;
1143 }
1144
1145 static HRESULT WINAPI NoStatStreamImpl_Clone(
1146 IStream* iface,
1147 IStream** ppstm) /* [out] */
1148 {
1149 return E_NOTIMPL;
1150 }
1151 static const IStreamVtbl NoStatStreamImpl_Vtbl;
1152
1153 /*
1154 Build an object that implements IStream, without IStream_Stat capabilities.
1155 Receives a memory handle with data buffer. If memory handle is non-null,
1156 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
1157 In any case the object takes ownership of memory handle and will free it on
1158 object release.
1159 */
1160 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal)
1161 {
1162 NoStatStreamImpl* newStream;
1163
1164 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
1165 if (newStream!=0)
1166 {
1167 newStream->lpVtbl = &NoStatStreamImpl_Vtbl;
1168 newStream->ref = 1;
1169 newStream->supportHandle = hGlobal;
1170
1171 if (!newStream->supportHandle)
1172 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
1173 GMEM_SHARE, 0);
1174 newStream->currentPosition.u.HighPart = 0;
1175 newStream->currentPosition.u.LowPart = 0;
1176 newStream->streamSize.u.HighPart = 0;
1177 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
1178 }
1179 return newStream;
1180 }
1181
1182
1183 static const IStreamVtbl NoStatStreamImpl_Vtbl =
1184 {
1185 NoStatStreamImpl_QueryInterface,
1186 NoStatStreamImpl_AddRef,
1187 NoStatStreamImpl_Release,
1188 NoStatStreamImpl_Read,
1189 NoStatStreamImpl_Write,
1190 NoStatStreamImpl_Seek,
1191 NoStatStreamImpl_SetSize,
1192 NoStatStreamImpl_CopyTo,
1193 NoStatStreamImpl_Commit,
1194 NoStatStreamImpl_Revert,
1195 NoStatStreamImpl_LockRegion,
1196 NoStatStreamImpl_UnlockRegion,
1197 NoStatStreamImpl_Stat,
1198 NoStatStreamImpl_Clone
1199 };