f00055ef036a48f4e48b23e34cd3fb9ae0fbd60d
[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 if (handle)
220 {
221 BITMAP bmp;
222 GetObject((HGDIOBJ)handle, sizeof(BITMAP), &bmp);
223 todo_wine ok(bmp.bmBits != 0, "not a dib\n");
224 }
225
226 width = 0;
227 hres = IPicture_get_Width (pic, &width);
228 ok(hres == S_OK,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres);
229 ok(width != 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
230
231 height = 0;
232 hres = IPicture_get_Height (pic, &height);
233 ok(hres == S_OK,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres);
234 ok(height != 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
235
236 type = 0;
237 hres = IPicture_get_Type (pic, &type);
238 ok(hres == S_OK,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
239 ok(type == PICTYPE_BITMAP, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type, PICTYPE_BITMAP);
240
241 attr = 0;
242 hres = IPicture_get_Attributes (pic, &attr);
243 ok(hres == S_OK,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres);
244 ok(attr == 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr);
245
246 hPal = 0;
247 hres = IPicture_get_hPal (pic, &hPal);
248 ok(hres == S_OK,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres);
249 /* a single pixel b/w image has no palette */
250 ok(hPal == 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal);
251
252 res = IPicture_Release (pic);
253 ok (res == 0, "refcount after release is %d, but should be 0?\n", res);
254 }
255
256 static void
257 test_pic(const unsigned char *imgdata, unsigned int imgsize)
258 {
259 LPSTREAM stream;
260 HGLOBAL hglob;
261 LPBYTE data;
262 HRESULT hres;
263 LARGE_INTEGER seekto;
264 ULARGE_INTEGER newpos1;
265 DWORD * header;
266 unsigned int i,j;
267
268 /* Let the fun begin */
269 hglob = GlobalAlloc (0, imgsize);
270 data = GlobalLock (hglob);
271 memcpy(data, imgdata, imgsize);
272 GlobalUnlock(hglob); data = NULL;
273
274 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
275 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
276
277 memset(&seekto,0,sizeof(seekto));
278 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
279 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
280 test_pic_with_stream(stream, imgsize);
281
282 IStream_Release(stream);
283
284 /* again with Non Statable and Non Seekable stream */
285 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
286 hglob = 0; /* Non-statable impl always deletes on release */
287 test_pic_with_stream(stream, 0);
288
289 IStream_Release(stream);
290 for (i = 1; i <= 8; i++) {
291 /* more fun!!! */
292 hglob = GlobalAlloc (0, imgsize + i * (2 * sizeof(DWORD)));
293 data = GlobalLock (hglob);
294 header = (DWORD *)data;
295
296 /* multiple copies of header */
297 memcpy(data,"lt\0\0",4);
298 header[1] = imgsize;
299 for (j = 2; j <= i; j++) {
300 memcpy(&(header[2 * (j - 1)]), header, 2 * sizeof(DWORD));
301 }
302 memcpy(data + i * (2 * sizeof(DWORD)), imgdata, imgsize);
303 GlobalUnlock(hglob); data = NULL;
304
305 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
306 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
307
308 memset(&seekto,0,sizeof(seekto));
309 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
310 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
311 test_pic_with_stream(stream, imgsize);
312
313 IStream_Release(stream);
314
315 /* again with Non Statable and Non Seekable stream */
316 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
317 hglob = 0; /* Non-statable impl always deletes on release */
318 test_pic_with_stream(stream, 0);
319
320 IStream_Release(stream);
321 }
322 }
323
324 static void test_empty_image(void) {
325 LPBYTE data;
326 LPSTREAM stream;
327 IPicture* pic = NULL;
328 HRESULT hres;
329 LPVOID pvObj = NULL;
330 HGLOBAL hglob;
331 OLE_HANDLE handle;
332 ULARGE_INTEGER newpos1;
333 LARGE_INTEGER seekto;
334 short type;
335 DWORD attr;
336
337 /* Empty image. Happens occasionally in VB programs. */
338 hglob = GlobalAlloc (0, 8);
339 data = GlobalLock (hglob);
340 memcpy(data,"lt\0\0",4);
341 ((DWORD*)data)[1] = 0;
342 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
343 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
344
345 memset(&seekto,0,sizeof(seekto));
346 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
347 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
348
349 pvObj = NULL;
350 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
351 pic = pvObj;
352 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
353 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
354
355 hres = IPicture_get_Type (pic, &type);
356 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
357 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
358
359 attr = 0xdeadbeef;
360 hres = IPicture_get_Attributes (pic, &attr);
361 ok (hres == S_OK,"empty picture get attributes failed with hres 0x%08x\n", hres);
362 ok (attr == 0,"attr is %d, but should be 0\n", attr);
363
364 hres = IPicture_get_Handle (pic, &handle);
365 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
366 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
367 IPicture_Release (pic);
368 IStream_Release (stream);
369 }
370
371 static void test_empty_image_2(void) {
372 LPBYTE data;
373 LPSTREAM stream;
374 IPicture* pic = NULL;
375 HRESULT hres;
376 LPVOID pvObj = NULL;
377 HGLOBAL hglob;
378 ULARGE_INTEGER newpos1;
379 LARGE_INTEGER seekto;
380 short type;
381
382 /* Empty image at random stream position. */
383 hglob = GlobalAlloc (0, 200);
384 data = GlobalLock (hglob);
385 data += 42;
386 memcpy(data,"lt\0\0",4);
387 ((DWORD*)data)[1] = 0;
388 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
389 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
390
391 memset(&seekto,0,sizeof(seekto));
392 seekto.u.LowPart = 42;
393 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
394 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
395
396 pvObj = NULL;
397 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
398 pic = pvObj;
399 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
400 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
401
402 hres = IPicture_get_Type (pic, &type);
403 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
404 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
405
406 IPicture_Release (pic);
407 IStream_Release (stream);
408 }
409
410 static void test_Invoke(void)
411 {
412 IPictureDisp *picdisp;
413 HRESULT hr;
414 VARIANTARG vararg;
415 DISPPARAMS dispparams;
416 VARIANT varresult;
417 IStream *stream;
418 HGLOBAL hglob;
419 void *data;
420
421 hglob = GlobalAlloc (0, sizeof(gifimage));
422 data = GlobalLock(hglob);
423 memcpy(data, gifimage, sizeof(gifimage));
424 GlobalUnlock(hglob);
425
426 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
427 ok_ole_success(hr, "CreateStreamOnHGlobal");
428
429 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
430 IStream_Release(stream);
431 GlobalFree(hglob);
432 ok_ole_success(hr, "OleLoadPicture");
433
434 V_VT(&vararg) = VT_BOOL;
435 V_BOOL(&vararg) = VARIANT_FALSE;
436 dispparams.cNamedArgs = 0;
437 dispparams.rgdispidNamedArgs = NULL;
438 dispparams.cArgs = 1;
439 dispparams.rgvarg = &vararg;
440 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
441 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
442 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
443 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
444
445 dispparams.cArgs = 0;
446 dispparams.rgvarg = NULL;
447 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
448 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
449
450 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
451 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
452
453 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
454 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
455
456 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
457 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
458
459 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
460 ok_ole_success(hr, "IPictureDisp_Invoke");
461 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
462
463 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
464 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
465
466 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
467 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
468
469 dispparams.cArgs = 1;
470 dispparams.rgvarg = &vararg;
471 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
472 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
473
474 dispparams.cArgs = 1;
475 dispparams.rgvarg = &vararg;
476 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
477 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
478
479 IPictureDisp_Release(picdisp);
480 }
481
482 static void test_OleCreatePictureIndirect(void)
483 {
484 IPicture *pict;
485 HRESULT hr;
486 short type;
487 OLE_HANDLE handle;
488
489 if(!pOleCreatePictureIndirect)
490 {
491 win_skip("Skipping OleCreatePictureIndirect tests\n");
492 return;
493 }
494
495 hr = pOleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict);
496 ok(hr == S_OK, "hr %08x\n", hr);
497
498 hr = IPicture_get_Type(pict, &type);
499 ok(hr == S_OK, "hr %08x\n", hr);
500 ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type);
501
502 hr = IPicture_get_Handle(pict, &handle);
503 ok(hr == S_OK, "hr %08x\n", hr);
504 ok(handle == 0, "handle %08x\n", handle);
505
506 IPicture_Release(pict);
507 }
508
509 static void test_apm(void)
510 {
511 OLE_HANDLE handle;
512 LPSTREAM stream;
513 IPicture *pict;
514 HGLOBAL hglob;
515 LPBYTE *data;
516 LONG cxy;
517 BOOL keep;
518 short type;
519
520 hglob = GlobalAlloc (0, sizeof(apmdata));
521 data = GlobalLock(hglob);
522 memcpy(data, apmdata, sizeof(apmdata));
523
524 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
525 ole_check(OleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict));
526
527 ole_check(IPicture_get_Handle(pict, &handle));
528 ok(handle != 0, "handle is null\n");
529
530 ole_check(IPicture_get_Type(pict, &type));
531 expect_eq(type, PICTYPE_METAFILE, short, "%d");
532
533 ole_check(IPicture_get_Height(pict, &cxy));
534 expect_eq(cxy, 1667, LONG, "%d");
535
536 ole_check(IPicture_get_Width(pict, &cxy));
537 expect_eq(cxy, 1323, LONG, "%d");
538
539 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
540 todo_wine expect_eq(keep, FALSE, LONG, "%d");
541
542 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL);
543 IPicture_Release(pict);
544 IStream_Release(stream);
545 }
546
547 static void test_metafile(void)
548 {
549 LPSTREAM stream;
550 IPicture *pict;
551 HGLOBAL hglob;
552 LPBYTE *data;
553
554 hglob = GlobalAlloc (0, sizeof(metafile));
555 data = GlobalLock(hglob);
556 memcpy(data, metafile, sizeof(metafile));
557
558 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
559 /* Windows does not load simple metafiles */
560 ole_expect(OleLoadPictureEx(stream, sizeof(metafile), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict), E_FAIL);
561
562 IStream_Release(stream);
563 }
564
565 static void test_enhmetafile(void)
566 {
567 OLE_HANDLE handle;
568 LPSTREAM stream;
569 IPicture *pict;
570 HGLOBAL hglob;
571 LPBYTE *data;
572 LONG cxy;
573 BOOL keep;
574 short type;
575
576 hglob = GlobalAlloc (0, sizeof(enhmetafile));
577 data = GlobalLock(hglob);
578 memcpy(data, enhmetafile, sizeof(enhmetafile));
579
580 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
581 ole_check(OleLoadPictureEx(stream, sizeof(enhmetafile), TRUE, &IID_IPicture, 10, 10, 0, (LPVOID *)&pict));
582
583 ole_check(IPicture_get_Handle(pict, &handle));
584 ok(handle != 0, "handle is null\n");
585
586 ole_check(IPicture_get_Type(pict, &type));
587 expect_eq(type, PICTYPE_ENHMETAFILE, short, "%d");
588
589 ole_check(IPicture_get_Height(pict, &cxy));
590 expect_eq(cxy, -23, LONG, "%d");
591
592 ole_check(IPicture_get_Width(pict, &cxy));
593 expect_eq(cxy, -25, LONG, "%d");
594
595 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
596 todo_wine expect_eq(keep, FALSE, LONG, "%d");
597
598 IPicture_Release(pict);
599 IStream_Release(stream);
600 }
601
602 static void test_Render(void)
603 {
604 IPicture *pic;
605 HRESULT hres;
606 short type;
607 PICTDESC desc;
608 OLE_XSIZE_HIMETRIC pWidth;
609 OLE_YSIZE_HIMETRIC pHeight;
610 COLORREF result, expected;
611 HDC hdc = GetDC(0);
612
613 /* test IPicture::Render return code on uninitialized picture */
614 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
615 hres = IPicture_get_Type(pic, &type);
616 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
617 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
618 /* zero dimensions */
619 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
620 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
621 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
622 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
623 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
624 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
625 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
626 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
627 hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
628 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
629 hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
630 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
631 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
632 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
633 /* nonzero dimensions, PICTYPE_UNINITIALIZED */
634 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL);
635 ole_expect(hres, S_OK);
636 IPicture_Release(pic);
637
638 desc.cbSizeofstruct = sizeof(PICTDESC);
639 desc.picType = PICTYPE_ICON;
640 desc.u.icon.hicon = LoadIcon(NULL, IDI_APPLICATION);
641 if(!desc.u.icon.hicon){
642 win_skip("LoadIcon failed. Skipping...\n");
643 ReleaseDC(NULL, hdc);
644 return;
645 }
646
647 OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (VOID**)&pic);
648 /* zero dimensions, PICTYPE_ICON */
649 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
650 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
651 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
652 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
653 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
654 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
655 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
656 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
657 hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
658 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
659 hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
660 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
661 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
662 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
663
664 /* Check if target size and position is respected */
665 IPicture_get_Width(pic, &pWidth);
666 IPicture_get_Height(pic, &pHeight);
667
668 SetPixelV(hdc, 0, 0, 0x00F0F0F0);
669 SetPixelV(hdc, 5, 5, 0x00F0F0F0);
670 SetPixelV(hdc, 10, 10, 0x00F0F0F0);
671 expected = GetPixel(hdc, 0, 0);
672
673 hres = IPicture_Render(pic, hdc, 1, 1, 9, 9, 0, 0, pWidth, -pHeight, NULL);
674 ole_expect(hres, S_OK);
675
676 if(hres != S_OK) {
677 IPicture_Release(pic);
678 ReleaseDC(NULL, hdc);
679 return;
680 }
681
682 /* Evaluate the rendered Icon */
683 result = GetPixel(hdc, 0, 0);
684 ok(result == expected,
685 "Color at 0,0 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
686 result = GetPixel(hdc, 5, 5);
687 ok(result != expected ||
688 broken(result == expected), /* WinNT 4.0 and older may claim they drew */
689 /* the icon, even if they didn't. */
690 "Color at 5,5 should have changed, but still was 0x%06X\n", expected);
691 result = GetPixel(hdc, 10, 10);
692 ok(result == expected,
693 "Color at 10,10 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
694
695 IPicture_Release(pic);
696 ReleaseDC(NULL, hdc);
697 }
698
699 static void test_get_Attributes(void)
700 {
701 IPicture *pic;
702 HRESULT hres;
703 short type;
704 DWORD attr;
705
706 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
707 hres = IPicture_get_Type(pic, &type);
708 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
709 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
710
711 hres = IPicture_get_Attributes(pic, NULL);
712 ole_expect(hres, E_POINTER);
713
714 attr = 0xdeadbeef;
715 hres = IPicture_get_Attributes(pic, &attr);
716 ole_expect(hres, S_OK);
717 ok(attr == 0, "IPicture_get_Attributes does not reset attr to zero, got %d\n", attr);
718
719 IPicture_Release(pic);
720 }
721
722 static void test_get_Handle(void)
723 {
724 IPicture *pic;
725 HRESULT hres;
726
727 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
728
729 hres = IPicture_get_Handle(pic, NULL);
730 ole_expect(hres, E_POINTER);
731
732 IPicture_Release(pic);
733 }
734
735 static void test_get_Type(void)
736 {
737 IPicture *pic;
738 HRESULT hres;
739
740 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
741
742 hres = IPicture_get_Type(pic, NULL);
743 ole_expect(hres, E_POINTER);
744
745 IPicture_Release(pic);
746 }
747
748 static void test_OleLoadPicturePath(void)
749 {
750 static WCHAR emptyW[] = {0};
751
752 IPicture *pic;
753 HRESULT hres;
754 int i;
755 char temp_path[MAX_PATH];
756 char temp_file[MAX_PATH];
757 WCHAR temp_fileW[MAX_PATH + 5] = {'f','i','l','e',':','/','/','/'};
758 HANDLE file;
759 DWORD size;
760 WCHAR *ptr;
761
762 const struct
763 {
764 LPOLESTR szURLorPath;
765 REFIID riid;
766 IPicture **pic;
767 } invalid_parameters[] =
768 {
769 {NULL, NULL, NULL},
770 {NULL, NULL, &pic},
771 {NULL, &IID_IPicture, NULL},
772 {NULL, &IID_IPicture, &pic},
773 {emptyW, NULL, NULL},
774 {emptyW, &IID_IPicture, NULL},
775 };
776
777 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
778 {
779 pic = (IPicture *)0xdeadbeef;
780 hres = OleLoadPicturePath(invalid_parameters[i].szURLorPath, NULL, 0, 0,
781 invalid_parameters[i].riid,
782 (void **)invalid_parameters[i].pic);
783 ok(hres == E_INVALIDARG,
784 "[%d] Expected OleLoadPicturePath to return E_INVALIDARG, got 0x%08x\n", i, hres);
785 ok(pic == (IPicture *)0xdeadbeef,
786 "[%d] Expected output pointer to be 0xdeadbeef, got %p\n", i, pic);
787 }
788
789 pic = (IPicture *)0xdeadbeef;
790 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, NULL, (void **)&pic);
791 todo_wine
792 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
793 hres == E_UNEXPECTED || /* NT4/Win95 */
794 hres == E_FAIL || /* Win95 OSR2 */
795 hres == E_OUTOFMEMORY, /* Win98/Win2k/Win2k3 */
796 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
797 ok(pic == NULL,
798 "Expected the output interface pointer to be NULL, got %p\n", pic);
799
800 pic = (IPicture *)0xdeadbeef;
801 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
802 todo_wine
803 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
804 hres == E_UNEXPECTED || /* NT4/Win95 */
805 hres == E_FAIL || /* Win95 OSR2 */
806 hres == E_OUTOFMEMORY, /* Win98/Win2k/Win2k3 */
807 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
808 ok(pic == NULL,
809 "Expected the output interface pointer to be NULL, got %p\n", pic);
810
811 /* Create a local temporary image file for testing. */
812 GetTempPathA(sizeof(temp_path), temp_path);
813 GetTempFileNameA(temp_path, "bmp", 0, temp_file);
814 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
815 FILE_ATTRIBUTE_NORMAL, NULL);
816 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
817 CloseHandle(file);
818
819 MultiByteToWideChar(CP_ACP, 0, temp_file, -1, temp_fileW + 8, sizeof(temp_fileW)/sizeof(WCHAR) - 8);
820
821 /* Try a normal DOS path. */
822 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
823 ok(hres == S_OK ||
824 broken(hres == E_UNEXPECTED), /* NT4/Win95 */
825 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
826 if (pic)
827 IPicture_Release(pic);
828
829 /* Try a DOS path with tacked on "file:". */
830 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
831 ok(hres == S_OK ||
832 broken(hres == E_UNEXPECTED), /* NT4/Win95 */
833 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
834 if (pic)
835 IPicture_Release(pic);
836
837 DeleteFileA(temp_file);
838
839 /* Try with a nonexistent file. */
840 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
841 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
842 hres == E_UNEXPECTED || /* NT4/Win95 */
843 hres == E_FAIL, /* Win9x/Win2k */
844 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
845
846 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
847 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
848 hres == E_UNEXPECTED || /* NT4/Win95 */
849 hres == E_FAIL, /* Win9x/Win2k */
850 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
851
852 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
853 FILE_ATTRIBUTE_NORMAL, NULL);
854 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
855 CloseHandle(file);
856
857 /* Try a "file:" URL with slash separators. */
858 ptr = temp_fileW + 8;
859 while (*ptr)
860 {
861 if (*ptr == '\\')
862 *ptr = '/';
863 ptr++;
864 }
865
866 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
867 ok(hres == S_OK ||
868 broken(hres == E_UNEXPECTED), /* NT4/Win95 */
869 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
870 if (pic)
871 IPicture_Release(pic);
872
873 DeleteFileA(temp_file);
874
875 /* Try with a nonexistent file. */
876 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
877 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
878 hres == E_UNEXPECTED || /* NT4/Win95 */
879 hres == E_FAIL, /* Win9x/Win2k */
880 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
881 }
882
883 START_TEST(olepicture)
884 {
885 hOleaut32 = GetModuleHandleA("oleaut32.dll");
886 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
887 pOleCreatePictureIndirect = (void*)GetProcAddress(hOleaut32, "OleCreatePictureIndirect");
888 if (!pOleLoadPicture)
889 {
890 win_skip("OleLoadPicture is not available\n");
891 return;
892 }
893
894 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
895 test_pic(gifimage, sizeof(gifimage));
896 test_pic(jpgimage, sizeof(jpgimage));
897 test_pic(bmpimage, sizeof(bmpimage));
898 test_pic(gif4pixel, sizeof(gif4pixel));
899 /* FIXME: No PNG support in Windows... */
900 if (0) test_pic(pngimage, sizeof(pngimage));
901 test_empty_image();
902 test_empty_image_2();
903 test_apm();
904 test_metafile();
905 test_enhmetafile();
906
907 test_Invoke();
908 test_OleCreatePictureIndirect();
909 test_Render();
910 test_get_Attributes();
911 test_get_Handle();
912 test_get_Type();
913 test_OleLoadPicturePath();
914 }
915
916
917 /* Helper functions only ... */
918
919
920 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
921 {
922 GlobalFree(This->supportHandle);
923 This->supportHandle=0;
924 HeapFree(GetProcessHeap(), 0, This);
925 }
926
927 static ULONG WINAPI NoStatStreamImpl_AddRef(
928 IStream* iface)
929 {
930 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
931 return InterlockedIncrement(&This->ref);
932 }
933
934 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
935 IStream* iface,
936 REFIID riid, /* [in] */
937 void** ppvObject) /* [iid_is][out] */
938 {
939 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
940 if (ppvObject==0) return E_INVALIDARG;
941 *ppvObject = 0;
942 if (IsEqualIID(&IID_IUnknown, riid))
943 {
944 *ppvObject = This;
945 }
946 else if (IsEqualIID(&IID_IStream, riid))
947 {
948 *ppvObject = This;
949 }
950
951 if ((*ppvObject)==0)
952 return E_NOINTERFACE;
953 NoStatStreamImpl_AddRef(iface);
954 return S_OK;
955 }
956
957 static ULONG WINAPI NoStatStreamImpl_Release(
958 IStream* iface)
959 {
960 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
961 ULONG newRef = InterlockedDecrement(&This->ref);
962 if (newRef==0)
963 NoStatStreamImpl_Destroy(This);
964 return newRef;
965 }
966
967 static HRESULT WINAPI NoStatStreamImpl_Read(
968 IStream* iface,
969 void* pv, /* [length_is][size_is][out] */
970 ULONG cb, /* [in] */
971 ULONG* pcbRead) /* [out] */
972 {
973 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
974 void* supportBuffer;
975 ULONG bytesReadBuffer;
976 ULONG bytesToReadFromBuffer;
977
978 if (pcbRead==0)
979 pcbRead = &bytesReadBuffer;
980 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
981 supportBuffer = GlobalLock(This->supportHandle);
982 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
983 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
984 *pcbRead = bytesToReadFromBuffer;
985 GlobalUnlock(This->supportHandle);
986 if(*pcbRead == cb)
987 return S_OK;
988 return S_FALSE;
989 }
990
991 static HRESULT WINAPI NoStatStreamImpl_Write(
992 IStream* iface,
993 const void* pv, /* [size_is][in] */
994 ULONG cb, /* [in] */
995 ULONG* pcbWritten) /* [out] */
996 {
997 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
998 void* supportBuffer;
999 ULARGE_INTEGER newSize;
1000 ULONG bytesWritten = 0;
1001
1002 if (pcbWritten == 0)
1003 pcbWritten = &bytesWritten;
1004 if (cb == 0)
1005 return S_OK;
1006 newSize.u.HighPart = 0;
1007 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
1008 if (newSize.u.LowPart > This->streamSize.u.LowPart)
1009 IStream_SetSize(iface, newSize);
1010
1011 supportBuffer = GlobalLock(This->supportHandle);
1012 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
1013 This->currentPosition.u.LowPart+=cb;
1014 *pcbWritten = cb;
1015 GlobalUnlock(This->supportHandle);
1016 return S_OK;
1017 }
1018
1019 static HRESULT WINAPI NoStatStreamImpl_Seek(
1020 IStream* iface,
1021 LARGE_INTEGER dlibMove, /* [in] */
1022 DWORD dwOrigin, /* [in] */
1023 ULARGE_INTEGER* plibNewPosition) /* [out] */
1024 {
1025 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
1026 ULARGE_INTEGER newPosition;
1027 switch (dwOrigin)
1028 {
1029 case STREAM_SEEK_SET:
1030 newPosition.u.HighPart = 0;
1031 newPosition.u.LowPart = 0;
1032 break;
1033 case STREAM_SEEK_CUR:
1034 newPosition = This->currentPosition;
1035 break;
1036 case STREAM_SEEK_END:
1037 newPosition = This->streamSize;
1038 break;
1039 default:
1040 return STG_E_INVALIDFUNCTION;
1041 }
1042 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
1043 return STG_E_INVALIDFUNCTION;
1044 newPosition.QuadPart += dlibMove.QuadPart;
1045 if (plibNewPosition) *plibNewPosition = newPosition;
1046 This->currentPosition = newPosition;
1047 return S_OK;
1048 }
1049
1050 static HRESULT WINAPI NoStatStreamImpl_SetSize(
1051 IStream* iface,
1052 ULARGE_INTEGER libNewSize) /* [in] */
1053 {
1054 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
1055 HGLOBAL supportHandle;
1056 if (libNewSize.u.HighPart != 0)
1057 return STG_E_INVALIDFUNCTION;
1058 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
1059 return S_OK;
1060 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
1061 if (supportHandle == 0)
1062 return STG_E_MEDIUMFULL;
1063 This->supportHandle = supportHandle;
1064 This->streamSize.u.LowPart = libNewSize.u.LowPart;
1065 return S_OK;
1066 }
1067
1068 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
1069 IStream* iface,
1070 IStream* pstm, /* [unique][in] */
1071 ULARGE_INTEGER cb, /* [in] */
1072 ULARGE_INTEGER* pcbRead, /* [out] */
1073 ULARGE_INTEGER* pcbWritten) /* [out] */
1074 {
1075 HRESULT hr = S_OK;
1076 BYTE tmpBuffer[128];
1077 ULONG bytesRead, bytesWritten, copySize;
1078 ULARGE_INTEGER totalBytesRead;
1079 ULARGE_INTEGER totalBytesWritten;
1080
1081 if ( pstm == 0 )
1082 return STG_E_INVALIDPOINTER;
1083 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
1084 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
1085
1086 while ( cb.u.LowPart > 0 )
1087 {
1088 if ( cb.u.LowPart >= 128 )
1089 copySize = 128;
1090 else
1091 copySize = cb.u.LowPart;
1092 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
1093 totalBytesRead.u.LowPart += bytesRead;
1094 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
1095 totalBytesWritten.u.LowPart += bytesWritten;
1096 if (bytesRead != bytesWritten)
1097 {
1098 hr = STG_E_MEDIUMFULL;
1099 break;
1100 }
1101 if (bytesRead!=copySize)
1102 cb.u.LowPart = 0;
1103 else
1104 cb.u.LowPart -= bytesRead;
1105 }
1106 if (pcbRead)
1107 {
1108 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
1109 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
1110 }
1111
1112 if (pcbWritten)
1113 {
1114 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
1115 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
1116 }
1117 return hr;
1118 }
1119
1120 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
1121 {
1122 return S_OK;
1123 }
1124 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
1125
1126 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
1127 IStream* iface,
1128 ULARGE_INTEGER libOffset, /* [in] */
1129 ULARGE_INTEGER cb, /* [in] */
1130 DWORD dwLockType) /* [in] */
1131 {
1132 return S_OK;
1133 }
1134
1135 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
1136 IStream* iface,
1137 ULARGE_INTEGER libOffset, /* [in] */
1138 ULARGE_INTEGER cb, /* [in] */
1139 DWORD dwLockType) /* [in] */
1140 {
1141 return S_OK;
1142 }
1143
1144 static HRESULT WINAPI NoStatStreamImpl_Stat(
1145 IStream* iface,
1146 STATSTG* pstatstg, /* [out] */
1147 DWORD grfStatFlag) /* [in] */
1148 {
1149 return E_NOTIMPL;
1150 }
1151
1152 static HRESULT WINAPI NoStatStreamImpl_Clone(
1153 IStream* iface,
1154 IStream** ppstm) /* [out] */
1155 {
1156 return E_NOTIMPL;
1157 }
1158 static const IStreamVtbl NoStatStreamImpl_Vtbl;
1159
1160 /*
1161 Build an object that implements IStream, without IStream_Stat capabilities.
1162 Receives a memory handle with data buffer. If memory handle is non-null,
1163 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
1164 In any case the object takes ownership of memory handle and will free it on
1165 object release.
1166 */
1167 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal)
1168 {
1169 NoStatStreamImpl* newStream;
1170
1171 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
1172 if (newStream!=0)
1173 {
1174 newStream->lpVtbl = &NoStatStreamImpl_Vtbl;
1175 newStream->ref = 1;
1176 newStream->supportHandle = hGlobal;
1177
1178 if (!newStream->supportHandle)
1179 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
1180 GMEM_SHARE, 0);
1181 newStream->currentPosition.u.HighPart = 0;
1182 newStream->currentPosition.u.LowPart = 0;
1183 newStream->streamSize.u.HighPart = 0;
1184 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
1185 }
1186 return newStream;
1187 }
1188
1189
1190 static const IStreamVtbl NoStatStreamImpl_Vtbl =
1191 {
1192 NoStatStreamImpl_QueryInterface,
1193 NoStatStreamImpl_AddRef,
1194 NoStatStreamImpl_Release,
1195 NoStatStreamImpl_Read,
1196 NoStatStreamImpl_Write,
1197 NoStatStreamImpl_Seek,
1198 NoStatStreamImpl_SetSize,
1199 NoStatStreamImpl_CopyTo,
1200 NoStatStreamImpl_Commit,
1201 NoStatStreamImpl_Revert,
1202 NoStatStreamImpl_LockRegion,
1203 NoStatStreamImpl_UnlockRegion,
1204 NoStatStreamImpl_Stat,
1205 NoStatStreamImpl_Clone
1206 };