2 * OLEPICTURE test program
4 * Copyright 2005 Marcus Meissner
5 * Copyright 2012 Dmitry Timoshkov
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.
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.
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
22 #define WIN32_NO_STATUS
24 #define COM_NO_WINDOWS_H
33 #define NONAMELESSUNION
35 #include <wine/test.h>
37 //#include <winbase.h>
38 //#include <winuser.h>
41 //#include <winerror.h>
49 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
51 #define ole_expect(expr, expect) { \
53 ok(r == (expect), #expr " returned %x, expected %s (%x)\n", r, #expect, expect); \
56 #define ole_check(expr) ole_expect(expr, S_OK);
58 static HMODULE hOleaut32
;
60 static HRESULT (WINAPI
*pOleLoadPicture
)(LPSTREAM
,LONG
,BOOL
,REFIID
,LPVOID
*);
61 static HRESULT (WINAPI
*pOleLoadPictureEx
)(LPSTREAM
,LONG
,BOOL
,REFIID
,DWORD
,DWORD
,DWORD
,LPVOID
*);
63 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
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,
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
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
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,
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
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
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,
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
177 typedef struct NoStatStreamImpl
179 IStream IStream_iface
;
182 HGLOBAL supportHandle
;
183 ULARGE_INTEGER streamSize
;
184 ULARGE_INTEGER currentPosition
;
187 static IStream
* NoStatStream_Construct(HGLOBAL hGlobal
);
190 test_pic_with_stream(LPSTREAM stream
, unsigned int imgsize
)
192 IPicture
* pic
= NULL
;
195 OLE_HANDLE handle
, hPal
;
196 OLE_XSIZE_HIMETRIC width
;
197 OLE_YSIZE_HIMETRIC height
;
203 hres
= pOleLoadPicture(stream
, imgsize
, TRUE
, &IID_IPicture
, &pvObj
);
206 ok(hres
== S_OK
,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres
);
207 ok(pic
!= NULL
,"OLP (NULL,..) returns NULL, instead of !NULL\n");
212 hres
= IPicture_QueryInterface (pic
, &IID_IPicture
, &pvObj
);
214 ok(hres
== S_OK
,"IPicture_QI does not return S_OK, but 0x%08x\n", hres
);
215 ok(pvObj
!= NULL
,"IPicture_QI does return NULL, instead of a ptr\n");
217 IPicture_Release ((IPicture
*)pvObj
);
220 hres
= IPicture_get_Handle (pic
, &handle
);
221 ok(hres
== S_OK
,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres
);
222 ok(handle
!= 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
227 GetObject(UlongToHandle(handle
), sizeof(BITMAP
), &bmp
);
228 todo_wine
ok(bmp
.bmBits
!= 0, "not a dib\n");
232 hres
= IPicture_get_Width (pic
, &width
);
233 ok(hres
== S_OK
,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres
);
234 ok(width
!= 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
237 hres
= IPicture_get_Height (pic
, &height
);
238 ok(hres
== S_OK
,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres
);
239 ok(height
!= 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
242 hres
= IPicture_get_Type (pic
, &type
);
243 ok(hres
== S_OK
,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres
);
244 ok(type
== PICTYPE_BITMAP
, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type
, PICTYPE_BITMAP
);
247 hres
= IPicture_get_Attributes (pic
, &attr
);
248 ok(hres
== S_OK
,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres
);
249 ok(attr
== 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr
);
252 hres
= IPicture_get_hPal (pic
, &hPal
);
253 ok(hres
== S_OK
,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres
);
254 /* a single pixel b/w image has no palette */
255 ok(hPal
== 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal
);
257 res
= IPicture_Release (pic
);
258 ok (res
== 0, "refcount after release is %d, but should be 0?\n", res
);
262 test_pic(const unsigned char *imgdata
, unsigned int imgsize
)
268 LARGE_INTEGER seekto
;
269 ULARGE_INTEGER newpos1
;
273 /* Let the fun begin */
274 hglob
= GlobalAlloc (0, imgsize
);
275 data
= GlobalLock (hglob
);
276 memcpy(data
, imgdata
, imgsize
);
277 GlobalUnlock(hglob
); data
= NULL
;
279 hres
= CreateStreamOnHGlobal (hglob
, FALSE
, &stream
);
280 ok (hres
== S_OK
, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres
);
282 memset(&seekto
,0,sizeof(seekto
));
283 hres
= IStream_Seek(stream
,seekto
,SEEK_CUR
,&newpos1
);
284 ok (hres
== S_OK
, "istream seek failed? doubt it... hres 0x%08x\n", hres
);
285 test_pic_with_stream(stream
, imgsize
);
287 IStream_Release(stream
);
289 /* again with Non Statable and Non Seekable stream */
290 stream
= NoStatStream_Construct(hglob
);
291 hglob
= 0; /* Non-statable impl always deletes on release */
292 test_pic_with_stream(stream
, 0);
294 IStream_Release(stream
);
295 for (i
= 1; i
<= 8; i
++) {
297 hglob
= GlobalAlloc (0, imgsize
+ i
* (2 * sizeof(DWORD
)));
298 data
= GlobalLock (hglob
);
299 header
= (DWORD
*)data
;
301 /* multiple copies of header */
302 memcpy(data
,"lt\0\0",4);
304 for (j
= 2; j
<= i
; j
++) {
305 memcpy(&(header
[2 * (j
- 1)]), header
, 2 * sizeof(DWORD
));
307 memcpy(data
+ i
* (2 * sizeof(DWORD
)), imgdata
, imgsize
);
308 GlobalUnlock(hglob
); data
= NULL
;
310 hres
= CreateStreamOnHGlobal (hglob
, FALSE
, &stream
);
311 ok (hres
== S_OK
, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres
);
313 memset(&seekto
,0,sizeof(seekto
));
314 hres
= IStream_Seek(stream
,seekto
,SEEK_CUR
,&newpos1
);
315 ok (hres
== S_OK
, "istream seek failed? doubt it... hres 0x%08x\n", hres
);
316 test_pic_with_stream(stream
, imgsize
);
318 IStream_Release(stream
);
320 /* again with Non Statable and Non Seekable stream */
321 stream
= NoStatStream_Construct(hglob
);
322 hglob
= 0; /* Non-statable impl always deletes on release */
323 test_pic_with_stream(stream
, 0);
325 IStream_Release(stream
);
329 static void test_empty_image(void) {
332 IPicture
* pic
= NULL
;
337 ULARGE_INTEGER newpos1
;
338 LARGE_INTEGER seekto
;
342 /* Empty image. Happens occasionally in VB programs. */
343 hglob
= GlobalAlloc (0, 8);
344 data
= GlobalLock (hglob
);
345 memcpy(data
,"lt\0\0",4);
346 ((DWORD
*)data
)[1] = 0;
347 hres
= CreateStreamOnHGlobal (hglob
, TRUE
, &stream
);
348 ok (hres
== S_OK
, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres
);
350 memset(&seekto
,0,sizeof(seekto
));
351 hres
= IStream_Seek(stream
,seekto
,SEEK_CUR
,&newpos1
);
352 ok (hres
== S_OK
, "istream seek failed? doubt it... hres 0x%08x\n", hres
);
355 hres
= pOleLoadPicture(stream
, 8, TRUE
, &IID_IPicture
, &pvObj
);
357 ok(hres
== S_OK
,"empty picture not loaded, hres 0x%08x\n", hres
);
358 ok(pic
!= NULL
,"empty picture not loaded, pic is NULL\n");
360 hres
= IPicture_get_Type (pic
, &type
);
361 ok (hres
== S_OK
,"empty picture get type failed with hres 0x%08x\n", hres
);
362 ok (type
== PICTYPE_NONE
,"type is %d, but should be PICTYPE_NONE(0)\n", type
);
365 hres
= IPicture_get_Attributes (pic
, &attr
);
366 ok (hres
== S_OK
,"empty picture get attributes failed with hres 0x%08x\n", hres
);
367 ok (attr
== 0,"attr is %d, but should be 0\n", attr
);
369 hres
= IPicture_get_Handle (pic
, &handle
);
370 ok (hres
== S_OK
,"empty picture get handle failed with hres 0x%08x\n", hres
);
371 ok (handle
== 0, "empty picture get handle did not return 0, but 0x%08x\n", handle
);
372 IPicture_Release (pic
);
373 IStream_Release (stream
);
376 static void test_empty_image_2(void) {
379 IPicture
* pic
= NULL
;
383 ULARGE_INTEGER newpos1
;
384 LARGE_INTEGER seekto
;
387 /* Empty image at random stream position. */
388 hglob
= GlobalAlloc (0, 200);
389 data
= GlobalLock (hglob
);
391 memcpy(data
,"lt\0\0",4);
392 ((DWORD
*)data
)[1] = 0;
393 hres
= CreateStreamOnHGlobal (hglob
, TRUE
, &stream
);
394 ok (hres
== S_OK
, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres
);
396 memset(&seekto
,0,sizeof(seekto
));
397 seekto
.u
.LowPart
= 42;
398 hres
= IStream_Seek(stream
,seekto
,SEEK_CUR
,&newpos1
);
399 ok (hres
== S_OK
, "istream seek failed? doubt it... hres 0x%08x\n", hres
);
402 hres
= pOleLoadPicture(stream
, 8, TRUE
, &IID_IPicture
, &pvObj
);
404 ok(hres
== S_OK
,"empty picture not loaded, hres 0x%08x\n", hres
);
405 ok(pic
!= NULL
,"empty picture not loaded, pic is NULL\n");
407 hres
= IPicture_get_Type (pic
, &type
);
408 ok (hres
== S_OK
,"empty picture get type failed with hres 0x%08x\n", hres
);
409 ok (type
== PICTYPE_NONE
,"type is %d, but should be PICTYPE_NONE(0)\n", type
);
411 IPicture_Release (pic
);
412 IStream_Release (stream
);
415 static void test_Invoke(void)
417 IPictureDisp
*picdisp
;
420 DISPPARAMS dispparams
;
426 hglob
= GlobalAlloc (0, sizeof(gifimage
));
427 data
= GlobalLock(hglob
);
428 memcpy(data
, gifimage
, sizeof(gifimage
));
431 hr
= CreateStreamOnHGlobal (hglob
, FALSE
, &stream
);
432 ok_ole_success(hr
, "CreateStreamOnHGlobal");
434 hr
= pOleLoadPicture(stream
, sizeof(gifimage
), TRUE
, &IID_IPictureDisp
, (void **)&picdisp
);
435 IStream_Release(stream
);
437 ok_ole_success(hr
, "OleLoadPicture");
439 V_VT(&vararg
) = VT_BOOL
;
440 V_BOOL(&vararg
) = VARIANT_FALSE
;
441 dispparams
.cNamedArgs
= 0;
442 dispparams
.rgdispidNamedArgs
= NULL
;
443 dispparams
.cArgs
= 1;
444 dispparams
.rgvarg
= &vararg
;
445 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_IPictureDisp
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
446 ok(hr
== DISP_E_UNKNOWNNAME
, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr
);
447 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_IUnknown
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
448 ok(hr
== DISP_E_UNKNOWNNAME
, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr
);
450 dispparams
.cArgs
= 0;
451 dispparams
.rgvarg
= NULL
;
452 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
453 ok(hr
== DISP_E_BADPARAMCOUNT
, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr
);
455 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYPUT
, NULL
, NULL
, NULL
, NULL
);
456 ok(hr
== DISP_E_PARAMNOTOPTIONAL
, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr
);
458 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, NULL
, NULL
, NULL
, NULL
);
459 ok(hr
== DISP_E_PARAMNOTOPTIONAL
, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr
);
461 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, NULL
, &varresult
, NULL
, NULL
);
462 ok(hr
== DISP_E_PARAMNOTOPTIONAL
, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr
);
464 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
465 ok_ole_success(hr
, "IPictureDisp_Invoke");
466 ok(V_VT(&varresult
) == VT_I4
, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult
));
468 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_METHOD
, &dispparams
, &varresult
, NULL
, NULL
);
469 ok(hr
== DISP_E_MEMBERNOTFOUND
, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr
);
471 hr
= IPictureDisp_Invoke(picdisp
, 0xdeadbeef, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
472 ok(hr
== DISP_E_MEMBERNOTFOUND
, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr
);
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
);
479 dispparams
.cArgs
= 1;
480 dispparams
.rgvarg
= &vararg
;
481 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
482 ok(hr
== DISP_E_BADPARAMCOUNT
, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr
);
484 IPictureDisp_Release(picdisp
);
487 static void test_OleCreatePictureIndirect(void)
496 /* crashes on native */
497 OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, NULL
);
500 hr
= OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (void**)&pict
);
501 ok(hr
== S_OK
, "hr %08x\n", hr
);
504 hr
= IPicture_get_Type(pict
, &type
);
505 ok(hr
== S_OK
, "hr %08x\n", hr
);
506 ok(type
== PICTYPE_UNINITIALIZED
, "type %d\n", type
);
509 hr
= IPicture_get_Handle(pict
, &handle
);
510 ok(hr
== S_OK
, "hr %08x\n", hr
);
511 ok(handle
== 0, "handle %08x\n", handle
);
513 IPicture_Release(pict
);
516 static void test_apm(void)
527 if(!winetest_interactive
) {
528 skip("ROSTESTS-2: oleaut_winetest:olepicture crashes with Page Fault.\n");
532 hglob
= GlobalAlloc (0, sizeof(apmdata
));
533 data
= GlobalLock(hglob
);
534 memcpy(data
, apmdata
, sizeof(apmdata
));
536 ole_check(CreateStreamOnHGlobal(hglob
, TRUE
, &stream
));
537 ole_check(pOleLoadPictureEx(stream
, sizeof(apmdata
), TRUE
, &IID_IPicture
, 100, 100, 0, (LPVOID
*)&pict
));
539 ole_check(IPicture_get_Handle(pict
, &handle
));
540 ok(handle
!= 0, "handle is null\n");
542 ole_check(IPicture_get_Type(pict
, &type
));
543 expect_eq(type
, PICTYPE_METAFILE
, short, "%d");
545 ole_check(IPicture_get_Height(pict
, &cxy
));
546 expect_eq(cxy
, 1667, LONG
, "%d");
548 ole_check(IPicture_get_Width(pict
, &cxy
));
549 expect_eq(cxy
, 1323, LONG
, "%d");
551 ole_check(IPicture_get_KeepOriginalFormat(pict
, &keep
));
552 todo_wine
expect_eq(keep
, FALSE
, LONG
, "%d");
554 ole_expect(IPicture_get_hPal(pict
, &handle
), E_FAIL
);
555 IPicture_Release(pict
);
556 IStream_Release(stream
);
559 static void test_metafile(void)
566 hglob
= GlobalAlloc (0, sizeof(metafile
));
567 data
= GlobalLock(hglob
);
568 memcpy(data
, metafile
, sizeof(metafile
));
570 ole_check(CreateStreamOnHGlobal(hglob
, TRUE
, &stream
));
571 /* Windows does not load simple metafiles */
572 ole_expect(pOleLoadPictureEx(stream
, sizeof(metafile
), TRUE
, &IID_IPicture
, 100, 100, 0, (LPVOID
*)&pict
), E_FAIL
);
574 IStream_Release(stream
);
577 static void test_enhmetafile(void)
588 if(!winetest_interactive
) {
589 skip("ROSTESTS-2: oleaut_winetest:olepicture crashes with Page Fault.\n");
593 hglob
= GlobalAlloc (0, sizeof(enhmetafile
));
594 data
= GlobalLock(hglob
);
595 memcpy(data
, enhmetafile
, sizeof(enhmetafile
));
597 ole_check(CreateStreamOnHGlobal(hglob
, TRUE
, &stream
));
598 ole_check(pOleLoadPictureEx(stream
, sizeof(enhmetafile
), TRUE
, &IID_IPicture
, 10, 10, 0, (LPVOID
*)&pict
));
600 ole_check(IPicture_get_Handle(pict
, &handle
));
601 ok(handle
!= 0, "handle is null\n");
603 ole_check(IPicture_get_Type(pict
, &type
));
604 expect_eq(type
, PICTYPE_ENHMETAFILE
, short, "%d");
606 ole_check(IPicture_get_Height(pict
, &cxy
));
607 expect_eq(cxy
, -23, LONG
, "%d");
609 ole_check(IPicture_get_Width(pict
, &cxy
));
610 expect_eq(cxy
, -25, LONG
, "%d");
612 ole_check(IPicture_get_KeepOriginalFormat(pict
, &keep
));
613 todo_wine
expect_eq(keep
, FALSE
, LONG
, "%d");
615 IPicture_Release(pict
);
616 IStream_Release(stream
);
619 static void test_Render(void)
625 OLE_XSIZE_HIMETRIC pWidth
;
626 OLE_YSIZE_HIMETRIC pHeight
;
627 COLORREF result
, expected
;
630 /* test IPicture::Render return code on uninitialized picture */
631 OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (VOID
**)&pic
);
632 hres
= IPicture_get_Type(pic
, &type
);
633 ok(hres
== S_OK
, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres
);
634 ok(type
== PICTYPE_UNINITIALIZED
, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type
);
635 /* zero dimensions */
636 hres
= IPicture_Render(pic
, hdc
, 0, 0, 0, 0, 0, 0, 0, 0, NULL
);
637 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
638 hres
= IPicture_Render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 10, 0, NULL
);
639 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
640 hres
= IPicture_Render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 0, 10, NULL
);
641 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
642 hres
= IPicture_Render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 0, 0, NULL
);
643 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
644 hres
= IPicture_Render(pic
, hdc
, 0, 0, 0, 10, 0, 0, 10, 10, NULL
);
645 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
646 hres
= IPicture_Render(pic
, hdc
, 0, 0, 10, 0, 0, 0, 10, 10, NULL
);
647 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
648 hres
= IPicture_Render(pic
, hdc
, 0, 0, 0, 0, 0, 0, 10, 10, NULL
);
649 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
650 /* nonzero dimensions, PICTYPE_UNINITIALIZED */
651 hres
= IPicture_Render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 10, 10, NULL
);
652 ole_expect(hres
, S_OK
);
653 IPicture_Release(pic
);
655 desc
.cbSizeofstruct
= sizeof(PICTDESC
);
656 desc
.picType
= PICTYPE_ICON
;
657 desc
.u
.icon
.hicon
= LoadIcon(NULL
, IDI_APPLICATION
);
658 if(!desc
.u
.icon
.hicon
){
659 win_skip("LoadIcon failed. Skipping...\n");
660 ReleaseDC(NULL
, hdc
);
664 OleCreatePictureIndirect(&desc
, &IID_IPicture
, TRUE
, (VOID
**)&pic
);
665 /* zero dimensions, PICTYPE_ICON */
666 hres
= IPicture_Render(pic
, hdc
, 0, 0, 0, 0, 0, 0, 0, 0, NULL
);
667 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
668 hres
= IPicture_Render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 10, 0, NULL
);
669 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
670 hres
= IPicture_Render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 0, 10, NULL
);
671 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
672 hres
= IPicture_Render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 0, 0, NULL
);
673 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
674 hres
= IPicture_Render(pic
, hdc
, 0, 0, 0, 10, 0, 0, 10, 10, NULL
);
675 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
676 hres
= IPicture_Render(pic
, hdc
, 0, 0, 10, 0, 0, 0, 10, 10, NULL
);
677 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
678 hres
= IPicture_Render(pic
, hdc
, 0, 0, 0, 0, 0, 0, 10, 10, NULL
);
679 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
681 /* Check if target size and position is respected */
682 IPicture_get_Width(pic
, &pWidth
);
683 IPicture_get_Height(pic
, &pHeight
);
685 SetPixelV(hdc
, 0, 0, 0x00223344);
686 SetPixelV(hdc
, 5, 5, 0x00223344);
687 SetPixelV(hdc
, 10, 10, 0x00223344);
688 expected
= GetPixel(hdc
, 0, 0);
690 hres
= IPicture_Render(pic
, hdc
, 1, 1, 9, 9, 0, 0, pWidth
, -pHeight
, NULL
);
691 ole_expect(hres
, S_OK
);
694 IPicture_Release(pic
);
695 ReleaseDC(NULL
, hdc
);
699 /* Evaluate the rendered Icon */
700 result
= GetPixel(hdc
, 0, 0);
701 ok(result
== expected
,
702 "Color at 0,0 should be unchanged 0x%06X, but was 0x%06X\n", expected
, result
);
703 result
= GetPixel(hdc
, 5, 5);
704 ok(result
!= expected
||
705 broken(result
== expected
), /* WinNT 4.0 and older may claim they drew */
706 /* the icon, even if they didn't. */
707 "Color at 5,5 should have changed, but still was 0x%06X\n", expected
);
708 result
= GetPixel(hdc
, 10, 10);
709 ok(result
== expected
,
710 "Color at 10,10 should be unchanged 0x%06X, but was 0x%06X\n", expected
, result
);
712 IPicture_Release(pic
);
713 ReleaseDC(NULL
, hdc
);
716 static void test_get_Attributes(void)
723 OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (VOID
**)&pic
);
724 hres
= IPicture_get_Type(pic
, &type
);
725 ok(hres
== S_OK
, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres
);
726 ok(type
== PICTYPE_UNINITIALIZED
, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type
);
728 hres
= IPicture_get_Attributes(pic
, NULL
);
729 ole_expect(hres
, E_POINTER
);
732 hres
= IPicture_get_Attributes(pic
, &attr
);
733 ole_expect(hres
, S_OK
);
734 ok(attr
== 0, "IPicture_get_Attributes does not reset attr to zero, got %d\n", attr
);
736 IPicture_Release(pic
);
739 static void test_get_Handle(void)
744 OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (VOID
**)&pic
);
746 hres
= IPicture_get_Handle(pic
, NULL
);
747 ole_expect(hres
, E_POINTER
);
749 IPicture_Release(pic
);
752 static void test_get_Type(void)
757 OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (VOID
**)&pic
);
759 hres
= IPicture_get_Type(pic
, NULL
);
760 ole_expect(hres
, E_POINTER
);
762 IPicture_Release(pic
);
765 static void test_OleLoadPicturePath(void)
767 static WCHAR emptyW
[] = {0};
772 char temp_path
[MAX_PATH
];
773 char temp_file
[MAX_PATH
];
774 WCHAR temp_fileW
[MAX_PATH
+ 5] = {'f','i','l','e',':','/','/','/'};
781 LPOLESTR szURLorPath
;
784 } invalid_parameters
[] =
788 {NULL
, &IID_IPicture
, NULL
},
789 {NULL
, &IID_IPicture
, &pic
},
790 {emptyW
, NULL
, NULL
},
791 {emptyW
, &IID_IPicture
, NULL
},
794 for (i
= 0; i
< sizeof(invalid_parameters
)/sizeof(invalid_parameters
[0]); i
++)
796 pic
= (IPicture
*)0xdeadbeef;
797 hres
= OleLoadPicturePath(invalid_parameters
[i
].szURLorPath
, NULL
, 0, 0,
798 invalid_parameters
[i
].riid
,
799 (void **)invalid_parameters
[i
].pic
);
800 ok(hres
== E_INVALIDARG
,
801 "[%d] Expected OleLoadPicturePath to return E_INVALIDARG, got 0x%08x\n", i
, hres
);
802 ok(pic
== (IPicture
*)0xdeadbeef,
803 "[%d] Expected output pointer to be 0xdeadbeef, got %p\n", i
, pic
);
806 pic
= (IPicture
*)0xdeadbeef;
807 hres
= OleLoadPicturePath(emptyW
, NULL
, 0, 0, NULL
, (void **)&pic
);
809 ok(hres
== INET_E_UNKNOWN_PROTOCOL
|| /* XP/Vista+ */
810 broken(hres
== E_UNEXPECTED
) || /* NT4 */
811 broken(hres
== E_OUTOFMEMORY
), /* Win2k/Win2k3 */
812 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres
);
814 "Expected the output interface pointer to be NULL, got %p\n", pic
);
816 pic
= (IPicture
*)0xdeadbeef;
817 hres
= OleLoadPicturePath(emptyW
, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
819 ok(hres
== INET_E_UNKNOWN_PROTOCOL
|| /* XP/Vista+ */
820 broken(hres
== E_UNEXPECTED
) || /* NT4 */
821 broken(hres
== E_OUTOFMEMORY
), /* Win2k/Win2k3 */
822 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres
);
824 "Expected the output interface pointer to be NULL, got %p\n", pic
);
826 /* Create a local temporary image file for testing. */
827 GetTempPathA(sizeof(temp_path
), temp_path
);
828 GetTempFileNameA(temp_path
, "bmp", 0, temp_file
);
829 file
= CreateFileA(temp_file
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
830 FILE_ATTRIBUTE_NORMAL
, NULL
);
831 WriteFile(file
, bmpimage
, sizeof(bmpimage
), &size
, NULL
);
834 MultiByteToWideChar(CP_ACP
, 0, temp_file
, -1, temp_fileW
+ 8, sizeof(temp_fileW
)/sizeof(WCHAR
) - 8);
836 /* Try a normal DOS path. */
837 hres
= OleLoadPicturePath(temp_fileW
+ 8, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
839 broken(hres
== E_UNEXPECTED
), /* NT4 */
840 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres
);
842 IPicture_Release(pic
);
844 /* Try a DOS path with tacked on "file:". */
845 hres
= OleLoadPicturePath(temp_fileW
, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
847 broken(hres
== E_UNEXPECTED
), /* NT4 */
848 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres
);
850 IPicture_Release(pic
);
852 DeleteFileA(temp_file
);
854 /* Try with a nonexistent file. */
855 hres
= OleLoadPicturePath(temp_fileW
+ 8, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
856 ok(hres
== INET_E_RESOURCE_NOT_FOUND
|| /* XP+ */
857 broken(hres
== E_UNEXPECTED
) || /* NT4 */
858 broken(hres
== E_FAIL
), /*Win2k */
859 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres
);
861 hres
= OleLoadPicturePath(temp_fileW
, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
862 ok(hres
== INET_E_RESOURCE_NOT_FOUND
|| /* XP+ */
863 broken(hres
== E_UNEXPECTED
) || /* NT4 */
864 broken(hres
== E_FAIL
), /* Win2k */
865 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres
);
867 file
= CreateFileA(temp_file
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
868 FILE_ATTRIBUTE_NORMAL
, NULL
);
869 WriteFile(file
, bmpimage
, sizeof(bmpimage
), &size
, NULL
);
872 /* Try a "file:" URL with slash separators. */
873 ptr
= temp_fileW
+ 8;
881 hres
= OleLoadPicturePath(temp_fileW
, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
883 broken(hres
== E_UNEXPECTED
), /* NT4 */
884 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres
);
886 IPicture_Release(pic
);
888 DeleteFileA(temp_file
);
890 /* Try with a nonexistent file. */
891 hres
= OleLoadPicturePath(temp_fileW
, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
892 ok(hres
== INET_E_RESOURCE_NOT_FOUND
|| /* XP+ */
893 broken(hres
== E_UNEXPECTED
) || /* NT4 */
894 broken(hres
== E_FAIL
), /* Win2k */
895 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres
);
898 static void test_himetric(void)
900 static const BYTE bmp_bits
[1024];
901 OLE_XSIZE_HIMETRIC cx
;
902 OLE_YSIZE_HIMETRIC cy
;
911 desc
.cbSizeofstruct
= sizeof(desc
);
912 desc
.picType
= PICTYPE_BITMAP
;
913 desc
.u
.bmp
.hpal
= NULL
;
915 hdc
= CreateCompatibleDC(0);
917 bmp
= CreateBitmap(1.9 * GetDeviceCaps(hdc
, LOGPIXELSX
),
918 1.9 * GetDeviceCaps(hdc
, LOGPIXELSY
), 1, 1, NULL
);
920 desc
.u
.bmp
.hbitmap
= bmp
;
922 /* size in himetric units reported rounded up to next integer value */
923 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void**)&pic
);
924 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
927 d
= MulDiv((INT
)(1.9 * GetDeviceCaps(hdc
, LOGPIXELSX
)), 2540, GetDeviceCaps(hdc
, LOGPIXELSX
));
928 hr
= IPicture_get_Width(pic
, &cx
);
929 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
930 ok(cx
== d
, "got %d, expected %d\n", cx
, d
);
933 d
= MulDiv((INT
)(1.9 * GetDeviceCaps(hdc
, LOGPIXELSY
)), 2540, GetDeviceCaps(hdc
, LOGPIXELSY
));
934 hr
= IPicture_get_Height(pic
, &cy
);
935 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
936 ok(cy
== d
, "got %d, expected %d\n", cy
, d
);
939 IPicture_Release(pic
);
941 /* same thing with icon */
942 icon
= CreateIcon(NULL
, GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
),
943 1, 1, bmp_bits
, bmp_bits
);
944 ok(icon
!= NULL
, "failed to create icon\n");
946 desc
.picType
= PICTYPE_ICON
;
947 desc
.u
.icon
.hicon
= icon
;
949 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void**)&pic
);
950 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
953 d
= MulDiv(GetSystemMetrics(SM_CXICON
), 2540, GetDeviceCaps(hdc
, LOGPIXELSX
));
954 hr
= IPicture_get_Width(pic
, &cx
);
955 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
956 ok(cx
== d
, "got %d, expected %d\n", cx
, d
);
959 d
= MulDiv(GetSystemMetrics(SM_CYICON
), 2540, GetDeviceCaps(hdc
, LOGPIXELSY
));
960 hr
= IPicture_get_Height(pic
, &cy
);
961 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
962 ok(cy
== d
, "got %d, expected %d\n", cy
, d
);
964 IPicture_Release(pic
);
970 static void test_load_save_bmp(void)
978 IPersistStream
*src_stream
;
982 desc
.cbSizeofstruct
= sizeof(desc
);
983 desc
.picType
= PICTYPE_BITMAP
;
985 desc
.u
.bmp
.hbitmap
= CreateBitmap(1, 1, 1, 1, NULL
);
986 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void**)&pic
);
987 ok(hr
== S_OK
, "OleCreatePictureIndirect error %#x\n", hr
);
990 hr
= IPicture_get_Type(pic
, &type
);
991 ok(hr
== S_OK
,"get_Type error %#8x\n", hr
);
992 ok(type
== PICTYPE_BITMAP
,"expected picture type PICTYPE_BITMAP, got %d\n", type
);
994 hr
= IPicture_get_Handle(pic
, &handle
);
995 ok(hr
== S_OK
,"get_Handle error %#8x\n", hr
);
996 ok(IntToPtr(handle
) == desc
.u
.bmp
.hbitmap
, "get_Handle returned wrong handle %#x\n", handle
);
998 hmem
= GlobalAlloc(GMEM_ZEROINIT
, 4096);
999 hr
= CreateStreamOnHGlobal(hmem
, FALSE
, &dst_stream
);
1000 ok(hr
== S_OK
, "createstreamonhglobal error %#x\n", hr
);
1002 hr
= IPicture_QueryInterface(pic
, &IID_IPersistStream
, (void **)&src_stream
);
1003 ok(hr
== S_OK
, "QueryInterface error %#x\n", hr
);
1005 hr
= IPersistStream_Save(src_stream
, dst_stream
, TRUE
);
1006 ok(hr
== S_OK
, "Save error %#x\n", hr
);
1008 IPersistStream_Release(src_stream
);
1009 IStream_Release(dst_stream
);
1011 mem
= GlobalLock(hmem
);
1012 ok(!memcmp(mem
, "lt\0\0", 4), "got wrong stream header %04x\n", mem
[0]);
1013 ok(mem
[1] == 66, "expected stream size 66, got %u\n", mem
[1]);
1014 ok(!memcmp(&mem
[2], "BM", 2), "got wrong bmp header %04x\n", mem
[2]);
1019 DeleteObject(desc
.u
.bmp
.hbitmap
);
1020 IPicture_Release(pic
);
1023 static void test_load_save_icon(void)
1031 IPersistStream
*src_stream
;
1032 IStream
*dst_stream
;
1035 desc
.cbSizeofstruct
= sizeof(desc
);
1036 desc
.picType
= PICTYPE_ICON
;
1037 desc
.u
.icon
.hicon
= LoadIcon(0, IDI_APPLICATION
);
1038 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void**)&pic
);
1039 ok(hr
== S_OK
, "OleCreatePictureIndirect error %#x\n", hr
);
1042 hr
= IPicture_get_Type(pic
, &type
);
1043 ok(hr
== S_OK
,"get_Type error %#8x\n", hr
);
1044 ok(type
== PICTYPE_ICON
,"expected picture type PICTYPE_ICON, got %d\n", type
);
1046 hr
= IPicture_get_Handle(pic
, &handle
);
1047 ok(hr
== S_OK
,"get_Handle error %#8x\n", hr
);
1048 ok(IntToPtr(handle
) == desc
.u
.icon
.hicon
, "get_Handle returned wrong handle %#x\n", handle
);
1050 hmem
= GlobalAlloc(GMEM_ZEROINIT
, 8192);
1051 hr
= CreateStreamOnHGlobal(hmem
, FALSE
, &dst_stream
);
1052 ok(hr
== S_OK
, "CreateStreamOnHGlobal error %#x\n", hr
);
1054 hr
= IPicture_QueryInterface(pic
, &IID_IPersistStream
, (void **)&src_stream
);
1055 ok(hr
== S_OK
, "QueryInterface error %#x\n", hr
);
1057 hr
= IPersistStream_Save(src_stream
, dst_stream
, TRUE
);
1058 ok(hr
== S_OK
, "Saveerror %#x\n", hr
);
1060 IPersistStream_Release(src_stream
);
1061 IStream_Release(dst_stream
);
1063 mem
= GlobalLock(hmem
);
1064 ok(!memcmp(mem
, "lt\0\0", 4), "got wrong stream header %04x\n", mem
[0]);
1066 ok(mem
[1] == 766, "expected stream size 766, got %u\n", mem
[1]);
1067 ok(mem
[2] == 0x00010000, "got wrong icon header %04x\n", mem
[2]);
1072 DestroyIcon(desc
.u
.icon
.hicon
);
1073 IPicture_Release(pic
);
1076 static void test_load_save_empty_picture(void)
1084 IPersistStream
*src_stream
;
1085 IStream
*dst_stream
;
1088 memset(&pic
, 0, sizeof(pic
));
1089 desc
.cbSizeofstruct
= sizeof(desc
);
1090 desc
.picType
= PICTYPE_NONE
;
1091 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void **)&pic
);
1092 ok(hr
== S_OK
, "OleCreatePictureIndirect error %#x\n", hr
);
1095 hr
= IPicture_get_Type(pic
, &type
);
1096 ok(hr
== S_OK
,"get_Type error %#8x\n", hr
);
1097 ok(type
== PICTYPE_NONE
,"expected picture type PICTYPE_NONE, got %d\n", type
);
1099 handle
= (OLE_HANDLE
)0xdeadbeef;
1100 hr
= IPicture_get_Handle(pic
, &handle
);
1101 ok(hr
== S_OK
,"get_Handle error %#8x\n", hr
);
1102 ok(!handle
, "get_Handle returned wrong handle %#x\n", handle
);
1104 hmem
= GlobalAlloc(GMEM_ZEROINIT
, 4096);
1105 hr
= CreateStreamOnHGlobal(hmem
, FALSE
, &dst_stream
);
1106 ok(hr
== S_OK
, "createstreamonhglobal error %#x\n", hr
);
1108 hr
= IPicture_QueryInterface(pic
, &IID_IPersistStream
, (void **)&src_stream
);
1109 ok(hr
== S_OK
, "QueryInterface error %#x\n", hr
);
1111 hr
= IPersistStream_Save(src_stream
, dst_stream
, TRUE
);
1112 ok(hr
== S_OK
, "Save error %#x\n", hr
);
1114 mem
= GlobalLock(hmem
);
1115 ok(!memcmp(mem
, "lt\0\0", 4), "got wrong stream header %04x\n", mem
[0]);
1116 ok(mem
[1] == 0, "expected stream size 0, got %u\n", mem
[1]);
1119 IPersistStream_Release(src_stream
);
1120 IStream_Release(dst_stream
);
1123 IPicture_Release(pic
);
1126 START_TEST(olepicture
)
1128 hOleaut32
= GetModuleHandleA("oleaut32.dll");
1129 pOleLoadPicture
= (void*)GetProcAddress(hOleaut32
, "OleLoadPicture");
1130 pOleLoadPictureEx
= (void*)GetProcAddress(hOleaut32
, "OleLoadPictureEx");
1131 if (!pOleLoadPicture
)
1133 win_skip("OleLoadPicture is not available\n");
1137 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
1138 test_pic(gifimage
, sizeof(gifimage
));
1139 test_pic(jpgimage
, sizeof(jpgimage
));
1140 test_pic(bmpimage
, sizeof(bmpimage
));
1141 test_pic(gif4pixel
, sizeof(gif4pixel
));
1142 /* FIXME: No PNG support in Windows... */
1143 if (0) test_pic(pngimage
, sizeof(pngimage
));
1145 test_empty_image_2();
1146 if (pOleLoadPictureEx
)
1153 win_skip("OleLoadPictureEx is not available\n");
1155 test_OleCreatePictureIndirect();
1157 test_get_Attributes();
1160 test_OleLoadPicturePath();
1162 test_load_save_bmp();
1163 test_load_save_icon();
1164 test_load_save_empty_picture();
1168 /* Helper functions only ... */
1171 static inline NoStatStreamImpl
*impl_from_IStream(IStream
*iface
)
1173 return CONTAINING_RECORD(iface
, NoStatStreamImpl
, IStream_iface
);
1176 static void NoStatStreamImpl_Destroy(NoStatStreamImpl
* This
)
1178 GlobalFree(This
->supportHandle
);
1179 This
->supportHandle
=0;
1180 HeapFree(GetProcessHeap(), 0, This
);
1183 static ULONG WINAPI
NoStatStreamImpl_AddRef(
1186 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1187 return InterlockedIncrement(&This
->ref
);
1190 static HRESULT WINAPI
NoStatStreamImpl_QueryInterface(
1192 REFIID riid
, /* [in] */
1193 void** ppvObject
) /* [iid_is][out] */
1195 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1196 if (ppvObject
==0) return E_INVALIDARG
;
1198 if (IsEqualIID(&IID_IUnknown
, riid
))
1202 else if (IsEqualIID(&IID_IStream
, riid
))
1207 if ((*ppvObject
)==0)
1208 return E_NOINTERFACE
;
1209 NoStatStreamImpl_AddRef(iface
);
1213 static ULONG WINAPI
NoStatStreamImpl_Release(
1216 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1217 ULONG newRef
= InterlockedDecrement(&This
->ref
);
1219 NoStatStreamImpl_Destroy(This
);
1223 static HRESULT WINAPI
NoStatStreamImpl_Read(
1225 void* pv
, /* [length_is][size_is][out] */
1226 ULONG cb
, /* [in] */
1227 ULONG
* pcbRead
) /* [out] */
1229 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1230 void* supportBuffer
;
1231 ULONG bytesReadBuffer
;
1232 ULONG bytesToReadFromBuffer
;
1235 pcbRead
= &bytesReadBuffer
;
1236 bytesToReadFromBuffer
= min( This
->streamSize
.u
.LowPart
- This
->currentPosition
.u
.LowPart
, cb
);
1237 supportBuffer
= GlobalLock(This
->supportHandle
);
1238 memcpy(pv
, (char *) supportBuffer
+This
->currentPosition
.u
.LowPart
, bytesToReadFromBuffer
);
1239 This
->currentPosition
.u
.LowPart
+=bytesToReadFromBuffer
;
1240 *pcbRead
= bytesToReadFromBuffer
;
1241 GlobalUnlock(This
->supportHandle
);
1247 static HRESULT WINAPI
NoStatStreamImpl_Write(
1249 const void* pv
, /* [size_is][in] */
1250 ULONG cb
, /* [in] */
1251 ULONG
* pcbWritten
) /* [out] */
1253 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1254 void* supportBuffer
;
1255 ULARGE_INTEGER newSize
;
1256 ULONG bytesWritten
= 0;
1258 if (pcbWritten
== 0)
1259 pcbWritten
= &bytesWritten
;
1262 newSize
.u
.HighPart
= 0;
1263 newSize
.u
.LowPart
= This
->currentPosition
.u
.LowPart
+ cb
;
1264 if (newSize
.u
.LowPart
> This
->streamSize
.u
.LowPart
)
1265 IStream_SetSize(iface
, newSize
);
1267 supportBuffer
= GlobalLock(This
->supportHandle
);
1268 memcpy((char *) supportBuffer
+This
->currentPosition
.u
.LowPart
, pv
, cb
);
1269 This
->currentPosition
.u
.LowPart
+=cb
;
1271 GlobalUnlock(This
->supportHandle
);
1275 static HRESULT WINAPI
NoStatStreamImpl_Seek(
1277 LARGE_INTEGER dlibMove
, /* [in] */
1278 DWORD dwOrigin
, /* [in] */
1279 ULARGE_INTEGER
* plibNewPosition
) /* [out] */
1281 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1282 ULARGE_INTEGER newPosition
;
1285 case STREAM_SEEK_SET
:
1286 newPosition
.u
.HighPart
= 0;
1287 newPosition
.u
.LowPart
= 0;
1289 case STREAM_SEEK_CUR
:
1290 newPosition
= This
->currentPosition
;
1292 case STREAM_SEEK_END
:
1293 newPosition
= This
->streamSize
;
1296 return STG_E_INVALIDFUNCTION
;
1298 if (dlibMove
.QuadPart
< 0 && newPosition
.QuadPart
< -dlibMove
.QuadPart
)
1299 return STG_E_INVALIDFUNCTION
;
1300 newPosition
.QuadPart
+= dlibMove
.QuadPart
;
1301 if (plibNewPosition
) *plibNewPosition
= newPosition
;
1302 This
->currentPosition
= newPosition
;
1306 static HRESULT WINAPI
NoStatStreamImpl_SetSize(
1308 ULARGE_INTEGER libNewSize
) /* [in] */
1310 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1311 HGLOBAL supportHandle
;
1312 if (libNewSize
.u
.HighPart
!= 0)
1313 return STG_E_INVALIDFUNCTION
;
1314 if (This
->streamSize
.u
.LowPart
== libNewSize
.u
.LowPart
)
1316 supportHandle
= GlobalReAlloc(This
->supportHandle
, libNewSize
.u
.LowPart
, 0);
1317 if (supportHandle
== 0)
1318 return STG_E_MEDIUMFULL
;
1319 This
->supportHandle
= supportHandle
;
1320 This
->streamSize
.u
.LowPart
= libNewSize
.u
.LowPart
;
1324 static HRESULT WINAPI
NoStatStreamImpl_CopyTo(
1326 IStream
* pstm
, /* [unique][in] */
1327 ULARGE_INTEGER cb
, /* [in] */
1328 ULARGE_INTEGER
* pcbRead
, /* [out] */
1329 ULARGE_INTEGER
* pcbWritten
) /* [out] */
1332 BYTE tmpBuffer
[128];
1333 ULONG bytesRead
, bytesWritten
, copySize
;
1334 ULARGE_INTEGER totalBytesRead
;
1335 ULARGE_INTEGER totalBytesWritten
;
1338 return STG_E_INVALIDPOINTER
;
1339 totalBytesRead
.u
.LowPart
= totalBytesRead
.u
.HighPart
= 0;
1340 totalBytesWritten
.u
.LowPart
= totalBytesWritten
.u
.HighPart
= 0;
1342 while ( cb
.u
.LowPart
> 0 )
1344 if ( cb
.u
.LowPart
>= 128 )
1347 copySize
= cb
.u
.LowPart
;
1348 IStream_Read(iface
, tmpBuffer
, copySize
, &bytesRead
);
1349 totalBytesRead
.u
.LowPart
+= bytesRead
;
1350 IStream_Write(pstm
, tmpBuffer
, bytesRead
, &bytesWritten
);
1351 totalBytesWritten
.u
.LowPart
+= bytesWritten
;
1352 if (bytesRead
!= bytesWritten
)
1354 hr
= STG_E_MEDIUMFULL
;
1357 if (bytesRead
!=copySize
)
1360 cb
.u
.LowPart
-= bytesRead
;
1364 pcbRead
->u
.LowPart
= totalBytesRead
.u
.LowPart
;
1365 pcbRead
->u
.HighPart
= totalBytesRead
.u
.HighPart
;
1370 pcbWritten
->u
.LowPart
= totalBytesWritten
.u
.LowPart
;
1371 pcbWritten
->u
.HighPart
= totalBytesWritten
.u
.HighPart
;
1376 static HRESULT WINAPI
NoStatStreamImpl_Commit(IStream
* iface
,DWORD grfCommitFlags
)
1380 static HRESULT WINAPI
NoStatStreamImpl_Revert(IStream
* iface
) { return S_OK
; }
1382 static HRESULT WINAPI
NoStatStreamImpl_LockRegion(
1384 ULARGE_INTEGER libOffset
, /* [in] */
1385 ULARGE_INTEGER cb
, /* [in] */
1386 DWORD dwLockType
) /* [in] */
1391 static HRESULT WINAPI
NoStatStreamImpl_UnlockRegion(
1393 ULARGE_INTEGER libOffset
, /* [in] */
1394 ULARGE_INTEGER cb
, /* [in] */
1395 DWORD dwLockType
) /* [in] */
1400 static HRESULT WINAPI
NoStatStreamImpl_Stat(
1402 STATSTG
* pstatstg
, /* [out] */
1403 DWORD grfStatFlag
) /* [in] */
1408 static HRESULT WINAPI
NoStatStreamImpl_Clone(
1410 IStream
** ppstm
) /* [out] */
1414 static const IStreamVtbl NoStatStreamImpl_Vtbl
;
1417 Build an object that implements IStream, without IStream_Stat capabilities.
1418 Receives a memory handle with data buffer. If memory handle is non-null,
1419 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
1420 In any case the object takes ownership of memory handle and will free it on
1423 static IStream
* NoStatStream_Construct(HGLOBAL hGlobal
)
1425 NoStatStreamImpl
* newStream
;
1427 newStream
= HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl
));
1430 newStream
->IStream_iface
.lpVtbl
= &NoStatStreamImpl_Vtbl
;
1432 newStream
->supportHandle
= hGlobal
;
1434 if (!newStream
->supportHandle
)
1435 newStream
->supportHandle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_NODISCARD
|
1437 newStream
->currentPosition
.u
.HighPart
= 0;
1438 newStream
->currentPosition
.u
.LowPart
= 0;
1439 newStream
->streamSize
.u
.HighPart
= 0;
1440 newStream
->streamSize
.u
.LowPart
= GlobalSize(newStream
->supportHandle
);
1442 return &newStream
->IStream_iface
;
1446 static const IStreamVtbl NoStatStreamImpl_Vtbl
=
1448 NoStatStreamImpl_QueryInterface
,
1449 NoStatStreamImpl_AddRef
,
1450 NoStatStreamImpl_Release
,
1451 NoStatStreamImpl_Read
,
1452 NoStatStreamImpl_Write
,
1453 NoStatStreamImpl_Seek
,
1454 NoStatStreamImpl_SetSize
,
1455 NoStatStreamImpl_CopyTo
,
1456 NoStatStreamImpl_Commit
,
1457 NoStatStreamImpl_Revert
,
1458 NoStatStreamImpl_LockRegion
,
1459 NoStatStreamImpl_UnlockRegion
,
1460 NoStatStreamImpl_Stat
,
1461 NoStatStreamImpl_Clone