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
105 /* 1bpp BI_RGB 1x1 pixel bmp */
106 static const unsigned char bmpimage
[66] = {
107 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
108 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
109 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
110 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
114 /* 8bpp BI_RLE8 1x1 pixel bmp */
115 static const unsigned char bmpimage_rle8
[] = {
116 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
117 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,
118 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
119 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x01,
124 static const unsigned char gif4pixel
[42] = {
125 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
126 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
127 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
130 /* APM with an empty metafile with some padding zeros - looks like under Window the
131 * metafile data should be at least 20 bytes */
132 static const unsigned char apmdata
[] = {
133 0xd7,0xcd,0xc6,0x9a, 0x00,0x00,0x00,0x00, 0x00,0x00,0xee,0x02, 0xb1,0x03,0xa0,0x05,
134 0x00,0x00,0x00,0x00, 0xee,0x53,0x01,0x00, 0x09,0x00,0x00,0x03, 0x13,0x00,0x00,0x00,
135 0x01,0x00,0x05,0x00, 0x00,0x00,0x00,0x00, 0x03,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
136 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
139 /* MF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
140 static const unsigned char metafile
[] = {
141 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
142 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
143 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
144 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
145 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
146 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
150 /* EMF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
151 static const unsigned char enhmetafile
[] = {
152 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
157 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
158 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
159 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
162 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
165 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
166 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
167 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
169 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
170 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
171 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
172 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
175 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
176 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
177 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
178 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
179 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
180 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
181 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
182 0x14, 0x00, 0x00, 0x00
185 static HBITMAP stock_bm
;
187 static HDC
create_render_dc( void )
189 HDC dc
= CreateCompatibleDC( NULL
);
190 BITMAPINFO info
= {{sizeof(info
.bmiHeader
), 100, 100, 1, 32, BI_RGB
}};
192 HBITMAP dib
= CreateDIBSection( NULL
, &info
, DIB_RGB_COLORS
, &bits
, NULL
, 0 );
194 stock_bm
= SelectObject( dc
, dib
);
198 static void delete_render_dc( HDC dc
)
200 HBITMAP dib
= SelectObject( dc
, stock_bm
);
205 typedef struct NoStatStreamImpl
207 IStream IStream_iface
;
210 HGLOBAL supportHandle
;
211 ULARGE_INTEGER streamSize
;
212 ULARGE_INTEGER currentPosition
;
215 static IStream
* NoStatStream_Construct(HGLOBAL hGlobal
);
218 test_pic_with_stream(LPSTREAM stream
, unsigned int imgsize
)
220 IPicture
* pic
= NULL
;
223 OLE_HANDLE handle
, hPal
;
224 OLE_XSIZE_HIMETRIC width
;
225 OLE_YSIZE_HIMETRIC height
;
231 hres
= pOleLoadPicture(stream
, imgsize
, TRUE
, &IID_IPicture
, &pvObj
);
234 ok(hres
== S_OK
,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres
);
235 ok(pic
!= NULL
,"OLP (NULL,..) returns NULL, instead of !NULL\n");
240 hres
= IPicture_QueryInterface (pic
, &IID_IPicture
, &pvObj
);
242 ok(hres
== S_OK
,"IPicture_QI does not return S_OK, but 0x%08x\n", hres
);
243 ok(pvObj
!= NULL
,"IPicture_QI does return NULL, instead of a ptr\n");
245 IPicture_Release ((IPicture
*)pvObj
);
248 hres
= IPicture_get_Handle (pic
, &handle
);
249 ok(hres
== S_OK
,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres
);
250 ok(handle
!= 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
255 GetObjectA(UlongToHandle(handle
), sizeof(BITMAP
), &bmp
);
256 ok(bmp
.bmBits
!= 0, "not a dib\n");
260 hres
= IPicture_get_Width (pic
, &width
);
261 ok(hres
== S_OK
,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres
);
262 ok(width
!= 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
265 hres
= IPicture_get_Height (pic
, &height
);
266 ok(hres
== S_OK
,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres
);
267 ok(height
!= 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
270 hres
= IPicture_get_Type (pic
, &type
);
271 ok(hres
== S_OK
,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres
);
272 ok(type
== PICTYPE_BITMAP
, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type
, PICTYPE_BITMAP
);
275 hres
= IPicture_get_Attributes (pic
, &attr
);
276 ok(hres
== S_OK
,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres
);
277 ok(attr
== 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr
);
280 hres
= IPicture_get_hPal (pic
, &hPal
);
281 ok(hres
== S_OK
,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres
);
282 /* a single pixel b/w image has no palette */
283 ok(hPal
== 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal
);
285 res
= IPicture_Release (pic
);
286 ok (res
== 0, "refcount after release is %d, but should be 0?\n", res
);
290 test_pic(const unsigned char *imgdata
, unsigned int imgsize
)
296 LARGE_INTEGER seekto
;
297 ULARGE_INTEGER newpos1
;
301 /* Let the fun begin */
302 hglob
= GlobalAlloc (0, imgsize
);
303 data
= GlobalLock (hglob
);
304 memcpy(data
, imgdata
, imgsize
);
305 GlobalUnlock(hglob
); data
= NULL
;
307 hres
= CreateStreamOnHGlobal (hglob
, FALSE
, &stream
);
308 ok (hres
== S_OK
, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres
);
310 memset(&seekto
,0,sizeof(seekto
));
311 hres
= IStream_Seek(stream
,seekto
,SEEK_CUR
,&newpos1
);
312 ok (hres
== S_OK
, "istream seek failed? doubt it... hres 0x%08x\n", hres
);
313 test_pic_with_stream(stream
, imgsize
);
315 IStream_Release(stream
);
317 /* again with Non Statable and Non Seekable stream */
318 stream
= NoStatStream_Construct(hglob
);
319 hglob
= 0; /* Non-statable impl always deletes on release */
320 test_pic_with_stream(stream
, 0);
322 IStream_Release(stream
);
323 for (i
= 1; i
<= 8; i
++) {
325 hglob
= GlobalAlloc (0, imgsize
+ i
* (2 * sizeof(DWORD
)));
326 data
= GlobalLock (hglob
);
327 header
= (DWORD
*)data
;
329 /* multiple copies of header */
330 memcpy(data
,"lt\0\0",4);
332 for (j
= 2; j
<= i
; j
++) {
333 memcpy(&(header
[2 * (j
- 1)]), header
, 2 * sizeof(DWORD
));
335 memcpy(data
+ i
* (2 * sizeof(DWORD
)), imgdata
, imgsize
);
336 GlobalUnlock(hglob
); data
= NULL
;
338 hres
= CreateStreamOnHGlobal (hglob
, FALSE
, &stream
);
339 ok (hres
== S_OK
, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres
);
341 memset(&seekto
,0,sizeof(seekto
));
342 hres
= IStream_Seek(stream
,seekto
,SEEK_CUR
,&newpos1
);
343 ok (hres
== S_OK
, "istream seek failed? doubt it... hres 0x%08x\n", hres
);
344 test_pic_with_stream(stream
, imgsize
);
346 IStream_Release(stream
);
348 /* again with Non Statable and Non Seekable stream */
349 stream
= NoStatStream_Construct(hglob
);
350 hglob
= 0; /* Non-statable impl always deletes on release */
351 test_pic_with_stream(stream
, 0);
353 IStream_Release(stream
);
357 static void test_empty_image(void) {
360 IPicture
* pic
= NULL
;
365 ULARGE_INTEGER newpos1
;
366 LARGE_INTEGER seekto
;
370 /* Empty image. Happens occasionally in VB programs. */
371 hglob
= GlobalAlloc (0, 8);
372 data
= GlobalLock (hglob
);
373 memcpy(data
,"lt\0\0",4);
374 ((DWORD
*)data
)[1] = 0;
375 hres
= CreateStreamOnHGlobal (hglob
, TRUE
, &stream
);
376 ok (hres
== S_OK
, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres
);
378 memset(&seekto
,0,sizeof(seekto
));
379 hres
= IStream_Seek(stream
,seekto
,SEEK_CUR
,&newpos1
);
380 ok (hres
== S_OK
, "istream seek failed? doubt it... hres 0x%08x\n", hres
);
383 hres
= pOleLoadPicture(stream
, 8, TRUE
, &IID_IPicture
, &pvObj
);
385 ok(hres
== S_OK
,"empty picture not loaded, hres 0x%08x\n", hres
);
386 ok(pic
!= NULL
,"empty picture not loaded, pic is NULL\n");
388 hres
= IPicture_get_Type (pic
, &type
);
389 ok (hres
== S_OK
,"empty picture get type failed with hres 0x%08x\n", hres
);
390 ok (type
== PICTYPE_NONE
,"type is %d, but should be PICTYPE_NONE(0)\n", type
);
393 hres
= IPicture_get_Attributes (pic
, &attr
);
394 ok (hres
== S_OK
,"empty picture get attributes failed with hres 0x%08x\n", hres
);
395 ok (attr
== 0,"attr is %d, but should be 0\n", attr
);
397 hres
= IPicture_get_Handle (pic
, &handle
);
398 ok (hres
== S_OK
,"empty picture get handle failed with hres 0x%08x\n", hres
);
399 ok (handle
== 0, "empty picture get handle did not return 0, but 0x%08x\n", handle
);
400 IPicture_Release (pic
);
401 IStream_Release (stream
);
404 static void test_empty_image_2(void) {
407 IPicture
* pic
= NULL
;
411 ULARGE_INTEGER newpos1
;
412 LARGE_INTEGER seekto
;
415 /* Empty image at random stream position. */
416 hglob
= GlobalAlloc (0, 200);
417 data
= GlobalLock (hglob
);
419 memcpy(data
,"lt\0\0",4);
420 ((DWORD
*)data
)[1] = 0;
421 hres
= CreateStreamOnHGlobal (hglob
, TRUE
, &stream
);
422 ok (hres
== S_OK
, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres
);
424 memset(&seekto
,0,sizeof(seekto
));
425 seekto
.u
.LowPart
= 42;
426 hres
= IStream_Seek(stream
,seekto
,SEEK_CUR
,&newpos1
);
427 ok (hres
== S_OK
, "istream seek failed? doubt it... hres 0x%08x\n", hres
);
430 hres
= pOleLoadPicture(stream
, 8, TRUE
, &IID_IPicture
, &pvObj
);
432 ok(hres
== S_OK
,"empty picture not loaded, hres 0x%08x\n", hres
);
433 ok(pic
!= NULL
,"empty picture not loaded, pic is NULL\n");
435 hres
= IPicture_get_Type (pic
, &type
);
436 ok (hres
== S_OK
,"empty picture get type failed with hres 0x%08x\n", hres
);
437 ok (type
== PICTYPE_NONE
,"type is %d, but should be PICTYPE_NONE(0)\n", type
);
439 IPicture_Release (pic
);
440 IStream_Release (stream
);
443 static void test_Invoke(void)
445 IPictureDisp
*picdisp
;
447 VARIANTARG vararg
, args
[10];
448 DISPPARAMS dispparams
;
456 hglob
= GlobalAlloc (0, sizeof(gifimage
));
457 data
= GlobalLock(hglob
);
458 memcpy(data
, gifimage
, sizeof(gifimage
));
461 hr
= CreateStreamOnHGlobal (hglob
, FALSE
, &stream
);
462 ok_ole_success(hr
, "CreateStreamOnHGlobal");
464 hr
= pOleLoadPicture(stream
, sizeof(gifimage
), TRUE
, &IID_IPictureDisp
, (void **)&picdisp
);
465 IStream_Release(stream
);
467 ok_ole_success(hr
, "OleLoadPicture");
469 V_VT(&vararg
) = VT_BOOL
;
470 V_BOOL(&vararg
) = VARIANT_FALSE
;
471 dispparams
.cNamedArgs
= 0;
472 dispparams
.rgdispidNamedArgs
= NULL
;
473 dispparams
.cArgs
= 1;
474 dispparams
.rgvarg
= &vararg
;
475 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_IPictureDisp
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
476 ok(hr
== DISP_E_UNKNOWNNAME
, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr
);
477 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_IUnknown
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
478 ok(hr
== DISP_E_UNKNOWNNAME
, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr
);
480 dispparams
.cArgs
= 0;
481 dispparams
.rgvarg
= NULL
;
482 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
483 ok(hr
== DISP_E_BADPARAMCOUNT
, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr
);
485 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYPUT
, NULL
, NULL
, NULL
, NULL
);
486 ok(hr
== DISP_E_PARAMNOTOPTIONAL
, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr
);
488 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, NULL
, NULL
, NULL
, NULL
);
489 ok(hr
== DISP_E_PARAMNOTOPTIONAL
, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr
);
491 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, NULL
, &varresult
, NULL
, NULL
);
492 ok(hr
== DISP_E_PARAMNOTOPTIONAL
, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr
);
494 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
495 ok_ole_success(hr
, "IPictureDisp_Invoke");
496 ok(V_VT(&varresult
) == VT_I4
, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult
));
498 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_METHOD
, &dispparams
, &varresult
, NULL
, NULL
);
499 ok(hr
== DISP_E_MEMBERNOTFOUND
, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr
);
501 hr
= IPictureDisp_Invoke(picdisp
, 0xdeadbeef, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
502 ok(hr
== DISP_E_MEMBERNOTFOUND
, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr
);
504 dispparams
.cArgs
= 1;
505 dispparams
.rgvarg
= &vararg
;
506 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
507 ok(hr
== DISP_E_BADPARAMCOUNT
, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr
);
509 dispparams
.cArgs
= 1;
510 dispparams
.rgvarg
= &vararg
;
511 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
512 ok(hr
== DISP_E_BADPARAMCOUNT
, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr
);
514 /* DISPID_PICT_RENDER */
515 hdc
= create_render_dc();
517 for (i
= 0; i
< sizeof(args
)/sizeof(args
[0]); i
++)
518 V_VT(&args
[i
]) = VT_I4
;
529 V_I4(&args
[9]) = HandleToLong(hdc
);
531 dispparams
.rgvarg
= args
;
532 dispparams
.rgdispidNamedArgs
= NULL
;
533 dispparams
.cArgs
= 10;
534 dispparams
.cNamedArgs
= 0;
536 V_VT(&varresult
) = VT_EMPTY
;
537 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_RENDER
, &GUID_NULL
, 0, DISPATCH_METHOD
, &dispparams
, &varresult
, NULL
, NULL
);
538 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
540 /* Try with one argument set to VT_I2, it'd still work if coerced. */
541 V_VT(&args
[3]) = VT_I2
;
542 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_RENDER
, &GUID_NULL
, 0, DISPATCH_METHOD
, &dispparams
, &varresult
, NULL
, NULL
);
543 ok(hr
== DISP_E_TYPEMISMATCH
, "got 0x%08x\n", hr
);
544 V_VT(&args
[3]) = VT_I4
;
546 /* Wrong argument count */
547 dispparams
.cArgs
= 9;
548 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_RENDER
, &GUID_NULL
, 0, DISPATCH_METHOD
, &dispparams
, &varresult
, NULL
, NULL
);
549 ok(hr
== DISP_E_BADPARAMCOUNT
, "got 0x%08x\n", hr
);
551 delete_render_dc(hdc
);
552 IPictureDisp_Release(picdisp
);
555 static void test_OleCreatePictureIndirect(void)
564 /* crashes on native */
565 OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, NULL
);
568 hr
= OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (void**)&pict
);
569 ok(hr
== S_OK
, "hr %08x\n", hr
);
572 hr
= IPicture_get_Type(pict
, &type
);
573 ok(hr
== S_OK
, "hr %08x\n", hr
);
574 ok(type
== PICTYPE_UNINITIALIZED
, "type %d\n", type
);
577 hr
= IPicture_get_Handle(pict
, &handle
);
578 ok(hr
== S_OK
, "hr %08x\n", hr
);
579 ok(handle
== 0, "handle %08x\n", handle
);
581 IPicture_Release(pict
);
584 static void test_apm(void)
595 hglob
= GlobalAlloc (0, sizeof(apmdata
));
596 data
= GlobalLock(hglob
);
597 memcpy(data
, apmdata
, sizeof(apmdata
));
599 ole_check(CreateStreamOnHGlobal(hglob
, TRUE
, &stream
));
600 ole_check(pOleLoadPictureEx(stream
, sizeof(apmdata
), TRUE
, &IID_IPicture
, 100, 100, 0, (LPVOID
*)&pict
));
602 ole_check(IPicture_get_Handle(pict
, &handle
));
603 ok(handle
!= 0, "handle is null\n");
605 ole_check(IPicture_get_Type(pict
, &type
));
606 expect_eq(type
, PICTYPE_METAFILE
, short, "%d");
608 ole_check(IPicture_get_Height(pict
, &cxy
));
609 expect_eq(cxy
, 1667, LONG
, "%d");
611 ole_check(IPicture_get_Width(pict
, &cxy
));
612 expect_eq(cxy
, 1323, LONG
, "%d");
614 ole_check(IPicture_get_KeepOriginalFormat(pict
, &keep
));
615 todo_wine
expect_eq(keep
, FALSE
, LONG
, "%d");
617 ole_expect(IPicture_get_hPal(pict
, &handle
), E_FAIL
);
618 IPicture_Release(pict
);
619 IStream_Release(stream
);
622 static void test_metafile(void)
629 hglob
= GlobalAlloc (0, sizeof(metafile
));
630 data
= GlobalLock(hglob
);
631 memcpy(data
, metafile
, sizeof(metafile
));
633 ole_check(CreateStreamOnHGlobal(hglob
, TRUE
, &stream
));
634 /* Windows does not load simple metafiles */
635 ole_expect(pOleLoadPictureEx(stream
, sizeof(metafile
), TRUE
, &IID_IPicture
, 100, 100, 0, (LPVOID
*)&pict
), E_FAIL
);
637 IStream_Release(stream
);
640 static void test_enhmetafile(void)
651 hglob
= GlobalAlloc (0, sizeof(enhmetafile
));
652 data
= GlobalLock(hglob
);
653 memcpy(data
, enhmetafile
, sizeof(enhmetafile
));
655 ole_check(CreateStreamOnHGlobal(hglob
, TRUE
, &stream
));
656 ole_check(pOleLoadPictureEx(stream
, sizeof(enhmetafile
), TRUE
, &IID_IPicture
, 10, 10, 0, (LPVOID
*)&pict
));
658 ole_check(IPicture_get_Handle(pict
, &handle
));
659 ok(handle
!= 0, "handle is null\n");
661 ole_check(IPicture_get_Type(pict
, &type
));
662 expect_eq(type
, PICTYPE_ENHMETAFILE
, short, "%d");
664 ole_check(IPicture_get_Height(pict
, &cxy
));
665 expect_eq(cxy
, -23, LONG
, "%d");
667 ole_check(IPicture_get_Width(pict
, &cxy
));
668 expect_eq(cxy
, -25, LONG
, "%d");
670 ole_check(IPicture_get_KeepOriginalFormat(pict
, &keep
));
671 todo_wine
expect_eq(keep
, FALSE
, LONG
, "%d");
673 IPicture_Release(pict
);
674 IStream_Release(stream
);
677 static HRESULT
picture_render(IPicture
*iface
, HDC hdc
, LONG x
, LONG y
, LONG cx
, LONG cy
,
678 OLE_XPOS_HIMETRIC xSrc
,
679 OLE_YPOS_HIMETRIC ySrc
,
680 OLE_XSIZE_HIMETRIC cxSrc
,
681 OLE_YSIZE_HIMETRIC cySrc
,
684 VARIANT ret
, args
[10];
690 hr
= IPicture_Render(iface
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, bounds
);
692 IPicture_QueryInterface(iface
, &IID_IDispatch
, (void**)&disp
);
694 /* This is broken on 64 bits - accepted pointer argument type is still VT_I4 */
695 for (i
= 0; i
< sizeof(args
)/sizeof(args
[0]); i
++)
696 V_VT(&args
[i
]) = VT_I4
;
698 /* pack arguments and call */
699 V_INT_PTR(&args
[0]) = (INT_PTR
)bounds
;
700 V_I4(&args
[1]) = cySrc
;
701 V_I4(&args
[2]) = cxSrc
;
702 V_I4(&args
[3]) = ySrc
;
703 V_I4(&args
[4]) = xSrc
;
708 V_I4(&args
[9]) = HandleToLong(hdc
);
710 params
.rgvarg
= args
;
711 params
.rgdispidNamedArgs
= NULL
;
713 params
.cNamedArgs
= 0;
715 V_VT(&ret
) = VT_EMPTY
;
716 hr_disp
= IDispatch_Invoke(disp
, DISPID_PICT_RENDER
, &GUID_NULL
, 0, DISPATCH_METHOD
,
717 ¶ms
, &ret
, NULL
, NULL
);
718 ok(hr
== hr_disp
, "DISPID_PICT_RENDER returned wrong code, 0x%08x, expected 0x%08x\n",
721 IDispatch_Release(disp
);
726 static void test_Render(void)
732 OLE_XSIZE_HIMETRIC pWidth
;
733 OLE_YSIZE_HIMETRIC pHeight
;
734 COLORREF result
, expected
;
735 HDC hdc
= create_render_dc();
737 /* test IPicture::Render return code on uninitialized picture */
738 OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (VOID
**)&pic
);
739 hres
= IPicture_get_Type(pic
, &type
);
740 ok(hres
== S_OK
, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres
);
741 ok(type
== PICTYPE_UNINITIALIZED
, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type
);
742 /* zero dimensions */
743 hres
= picture_render(pic
, hdc
, 0, 0, 0, 0, 0, 0, 0, 0, NULL
);
744 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
745 hres
= picture_render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 10, 0, NULL
);
746 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
747 hres
= picture_render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 0, 10, NULL
);
748 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
749 hres
= picture_render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 0, 0, NULL
);
750 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
751 hres
= picture_render(pic
, hdc
, 0, 0, 0, 10, 0, 0, 10, 10, NULL
);
752 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
753 hres
= picture_render(pic
, hdc
, 0, 0, 10, 0, 0, 0, 10, 10, NULL
);
754 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
755 hres
= picture_render(pic
, hdc
, 0, 0, 0, 0, 0, 0, 10, 10, NULL
);
756 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
757 /* nonzero dimensions, PICTYPE_UNINITIALIZED */
758 hres
= picture_render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 10, 10, NULL
);
759 ole_expect(hres
, S_OK
);
760 IPicture_Release(pic
);
762 desc
.cbSizeofstruct
= sizeof(PICTDESC
);
763 desc
.picType
= PICTYPE_ICON
;
764 desc
.u
.icon
.hicon
= LoadIconA(NULL
, (LPCSTR
)IDI_APPLICATION
);
765 if(!desc
.u
.icon
.hicon
){
766 win_skip("LoadIcon failed. Skipping...\n");
767 delete_render_dc(hdc
);
771 OleCreatePictureIndirect(&desc
, &IID_IPicture
, TRUE
, (VOID
**)&pic
);
772 /* zero dimensions, PICTYPE_ICON */
773 hres
= picture_render(pic
, hdc
, 0, 0, 0, 0, 0, 0, 0, 0, NULL
);
774 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
775 hres
= picture_render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 10, 0, NULL
);
776 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
777 hres
= picture_render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 0, 10, NULL
);
778 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
779 hres
= picture_render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 0, 0, NULL
);
780 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
781 hres
= picture_render(pic
, hdc
, 0, 0, 0, 10, 0, 0, 10, 10, NULL
);
782 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
783 hres
= picture_render(pic
, hdc
, 0, 0, 10, 0, 0, 0, 10, 10, NULL
);
784 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
785 hres
= picture_render(pic
, hdc
, 0, 0, 0, 0, 0, 0, 10, 10, NULL
);
786 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
788 /* Check if target size and position is respected */
789 IPicture_get_Width(pic
, &pWidth
);
790 IPicture_get_Height(pic
, &pHeight
);
792 SetPixelV(hdc
, 0, 0, 0x00223344);
793 SetPixelV(hdc
, 5, 5, 0x00223344);
794 SetPixelV(hdc
, 10, 10, 0x00223344);
795 expected
= GetPixel(hdc
, 0, 0);
797 hres
= picture_render(pic
, hdc
, 1, 1, 9, 9, 0, 0, pWidth
, -pHeight
, NULL
);
798 ole_expect(hres
, S_OK
);
800 if(hres
!= S_OK
) goto done
;
802 /* Evaluate the rendered Icon */
803 result
= GetPixel(hdc
, 0, 0);
804 ok(result
== expected
,
805 "Color at 0,0 should be unchanged 0x%06X, but was 0x%06X\n", expected
, result
);
806 result
= GetPixel(hdc
, 5, 5);
807 ok(result
!= expected
,
808 "Color at 5,5 should have changed, but still was 0x%06X\n", expected
);
809 result
= GetPixel(hdc
, 10, 10);
810 ok(result
== expected
,
811 "Color at 10,10 should be unchanged 0x%06X, but was 0x%06X\n", expected
, result
);
814 IPicture_Release(pic
);
815 delete_render_dc(hdc
);
818 static void test_get_Attributes(void)
825 OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (VOID
**)&pic
);
826 hres
= IPicture_get_Type(pic
, &type
);
827 ok(hres
== S_OK
, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres
);
828 ok(type
== PICTYPE_UNINITIALIZED
, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type
);
830 hres
= IPicture_get_Attributes(pic
, NULL
);
831 ole_expect(hres
, E_POINTER
);
834 hres
= IPicture_get_Attributes(pic
, &attr
);
835 ole_expect(hres
, S_OK
);
836 ok(attr
== 0, "IPicture_get_Attributes does not reset attr to zero, got %d\n", attr
);
838 IPicture_Release(pic
);
841 static void test_get_Handle(void)
846 OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (VOID
**)&pic
);
848 hres
= IPicture_get_Handle(pic
, NULL
);
849 ole_expect(hres
, E_POINTER
);
851 IPicture_Release(pic
);
854 static void test_get_Type(void)
859 OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (VOID
**)&pic
);
861 hres
= IPicture_get_Type(pic
, NULL
);
862 ole_expect(hres
, E_POINTER
);
864 IPicture_Release(pic
);
867 static void test_OleLoadPicturePath(void)
869 static WCHAR emptyW
[] = {0};
874 char temp_path
[MAX_PATH
];
875 char temp_file
[MAX_PATH
];
876 WCHAR temp_fileW
[MAX_PATH
+ 5] = {'f','i','l','e',':','/','/','/'};
884 LPOLESTR szURLorPath
;
887 } invalid_parameters
[] =
891 {NULL
, &IID_IPicture
, NULL
},
892 {NULL
, &IID_IPicture
, &pic
},
893 {emptyW
, NULL
, NULL
},
894 {emptyW
, &IID_IPicture
, NULL
},
897 for (i
= 0; i
< sizeof(invalid_parameters
)/sizeof(invalid_parameters
[0]); i
++)
899 pic
= (IPicture
*)0xdeadbeef;
900 hres
= OleLoadPicturePath(invalid_parameters
[i
].szURLorPath
, NULL
, 0, 0,
901 invalid_parameters
[i
].riid
,
902 (void **)invalid_parameters
[i
].pic
);
903 ok(hres
== E_INVALIDARG
,
904 "[%d] Expected OleLoadPicturePath to return E_INVALIDARG, got 0x%08x\n", i
, hres
);
905 ok(pic
== (IPicture
*)0xdeadbeef,
906 "[%d] Expected output pointer to be 0xdeadbeef, got %p\n", i
, pic
);
909 pic
= (IPicture
*)0xdeadbeef;
910 hres
= OleLoadPicturePath(emptyW
, NULL
, 0, 0, NULL
, (void **)&pic
);
912 ok(hres
== INET_E_UNKNOWN_PROTOCOL
|| /* XP/Vista+ */
913 broken(hres
== E_UNEXPECTED
) || /* NT4 */
914 broken(hres
== E_OUTOFMEMORY
), /* Win2k/Win2k3 */
915 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres
);
917 "Expected the output interface pointer to be NULL, got %p\n", pic
);
919 pic
= (IPicture
*)0xdeadbeef;
920 hres
= OleLoadPicturePath(emptyW
, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
922 ok(hres
== INET_E_UNKNOWN_PROTOCOL
|| /* XP/Vista+ */
923 broken(hres
== E_UNEXPECTED
) || /* NT4 */
924 broken(hres
== E_OUTOFMEMORY
), /* Win2k/Win2k3 */
925 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres
);
927 "Expected the output interface pointer to be NULL, got %p\n", pic
);
929 /* Create a local temporary image file for testing. */
930 GetTempPathA(sizeof(temp_path
), temp_path
);
931 GetTempFileNameA(temp_path
, "bmp", 0, temp_file
);
932 file
= CreateFileA(temp_file
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
933 FILE_ATTRIBUTE_NORMAL
, NULL
);
934 WriteFile(file
, bmpimage
, sizeof(bmpimage
), &size
, NULL
);
937 MultiByteToWideChar(CP_ACP
, 0, temp_file
, -1, temp_fileW
+ 8, sizeof(temp_fileW
)/sizeof(WCHAR
) - 8);
939 /* Try a normal DOS path. */
940 hres
= OleLoadPicturePath(temp_fileW
+ 8, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
942 broken(hres
== E_UNEXPECTED
), /* NT4 */
943 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres
);
945 IPicture_Release(pic
);
948 V_VT(&var
) = VT_BSTR
;
949 V_BSTR(&var
) = SysAllocString(temp_fileW
+ 8);
950 hres
= OleLoadPictureFile(var
, (IDispatch
**)&pic
);
951 ok(hres
== S_OK
, "OleLoadPictureFile error %#x\n", hres
);
952 IPicture_Release(pic
);
955 /* Try a DOS path with tacked on "file:". */
956 hres
= OleLoadPicturePath(temp_fileW
, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
958 broken(hres
== E_UNEXPECTED
), /* NT4 */
959 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres
);
961 IPicture_Release(pic
);
964 V_VT(&var
) = VT_BSTR
;
965 V_BSTR(&var
) = SysAllocString(temp_fileW
);
966 hres
= OleLoadPictureFile(var
, (IDispatch
**)&pic
);
967 ok(hres
== CTL_E_PATHFILEACCESSERROR
, "wrong error %#x\n", hres
);
970 DeleteFileA(temp_file
);
972 /* Try with a nonexistent file. */
973 hres
= OleLoadPicturePath(temp_fileW
+ 8, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
974 ok(hres
== INET_E_RESOURCE_NOT_FOUND
|| /* XP+ */
975 broken(hres
== E_UNEXPECTED
) || /* NT4 */
976 broken(hres
== E_FAIL
), /*Win2k */
977 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres
);
980 V_VT(&var
) = VT_BSTR
;
981 V_BSTR(&var
) = SysAllocString(temp_fileW
+ 8);
982 hres
= OleLoadPictureFile(var
, (IDispatch
**)&pic
);
983 ok(hres
== CTL_E_FILENOTFOUND
, "wrong error %#x\n", hres
);
986 hres
= OleLoadPicturePath(temp_fileW
, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
987 ok(hres
== INET_E_RESOURCE_NOT_FOUND
|| /* XP+ */
988 broken(hres
== E_UNEXPECTED
) || /* NT4 */
989 broken(hres
== E_FAIL
), /* Win2k */
990 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres
);
993 V_VT(&var
) = VT_BSTR
;
994 V_BSTR(&var
) = SysAllocString(temp_fileW
);
995 hres
= OleLoadPictureFile(var
, (IDispatch
**)&pic
);
996 ok(hres
== CTL_E_PATHFILEACCESSERROR
, "wrong error %#x\n", hres
);
999 file
= CreateFileA(temp_file
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
1000 FILE_ATTRIBUTE_NORMAL
, NULL
);
1001 WriteFile(file
, bmpimage
, sizeof(bmpimage
), &size
, NULL
);
1004 /* Try a "file:" URL with slash separators. */
1005 ptr
= temp_fileW
+ 8;
1013 hres
= OleLoadPicturePath(temp_fileW
, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
1015 broken(hres
== E_UNEXPECTED
), /* NT4 */
1016 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres
);
1018 IPicture_Release(pic
);
1021 V_VT(&var
) = VT_BSTR
;
1022 V_BSTR(&var
) = SysAllocString(temp_fileW
);
1023 hres
= OleLoadPictureFile(var
, (IDispatch
**)&pic
);
1024 ok(hres
== CTL_E_PATHFILEACCESSERROR
, "wrong error %#x\n", hres
);
1027 DeleteFileA(temp_file
);
1029 /* Try with a nonexistent file. */
1030 hres
= OleLoadPicturePath(temp_fileW
, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
1031 ok(hres
== INET_E_RESOURCE_NOT_FOUND
|| /* XP+ */
1032 broken(hres
== E_UNEXPECTED
) || /* NT4 */
1033 broken(hres
== E_FAIL
), /* Win2k */
1034 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres
);
1037 V_VT(&var
) = VT_BSTR
;
1038 V_BSTR(&var
) = SysAllocString(temp_fileW
);
1039 hres
= OleLoadPictureFile(var
, (IDispatch
**)&pic
);
1040 ok(hres
== CTL_E_PATHFILEACCESSERROR
, "wrong error %#x\n", hres
);
1044 V_VT(&var
) = VT_INT
;
1046 hres
= OleLoadPictureFile(var
, (IDispatch
**)&pic
);
1047 ok(hres
== CTL_E_FILENOTFOUND
, "wrong error %#x\n", hres
);
1049 if (0) /* crashes under Windows */
1050 hres
= OleLoadPictureFile(var
, NULL
);
1053 static void test_himetric(void)
1055 static const BYTE bmp_bits
[1024];
1056 OLE_XSIZE_HIMETRIC cx
;
1057 OLE_YSIZE_HIMETRIC cy
;
1066 desc
.cbSizeofstruct
= sizeof(desc
);
1067 desc
.picType
= PICTYPE_BITMAP
;
1068 desc
.u
.bmp
.hpal
= NULL
;
1070 hdc
= CreateCompatibleDC(0);
1072 bmp
= CreateBitmap(1.9 * GetDeviceCaps(hdc
, LOGPIXELSX
),
1073 1.9 * GetDeviceCaps(hdc
, LOGPIXELSY
), 1, 1, NULL
);
1075 desc
.u
.bmp
.hbitmap
= bmp
;
1077 /* size in himetric units reported rounded up to next integer value */
1078 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void**)&pic
);
1079 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1082 d
= MulDiv((INT
)(1.9 * GetDeviceCaps(hdc
, LOGPIXELSX
)), 2540, GetDeviceCaps(hdc
, LOGPIXELSX
));
1083 hr
= IPicture_get_Width(pic
, &cx
);
1084 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1085 ok(cx
== d
, "got %d, expected %d\n", cx
, d
);
1088 d
= MulDiv((INT
)(1.9 * GetDeviceCaps(hdc
, LOGPIXELSY
)), 2540, GetDeviceCaps(hdc
, LOGPIXELSY
));
1089 hr
= IPicture_get_Height(pic
, &cy
);
1090 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1091 ok(cy
== d
, "got %d, expected %d\n", cy
, d
);
1094 IPicture_Release(pic
);
1096 /* same thing with icon */
1097 icon
= CreateIcon(NULL
, GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
),
1098 1, 1, bmp_bits
, bmp_bits
);
1099 ok(icon
!= NULL
, "failed to create icon\n");
1101 desc
.picType
= PICTYPE_ICON
;
1102 desc
.u
.icon
.hicon
= icon
;
1104 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void**)&pic
);
1105 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1108 d
= MulDiv(GetSystemMetrics(SM_CXICON
), 2540, GetDeviceCaps(hdc
, LOGPIXELSX
));
1109 hr
= IPicture_get_Width(pic
, &cx
);
1110 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1111 ok(cx
== d
, "got %d, expected %d\n", cx
, d
);
1114 d
= MulDiv(GetSystemMetrics(SM_CYICON
), 2540, GetDeviceCaps(hdc
, LOGPIXELSY
));
1115 hr
= IPicture_get_Height(pic
, &cy
);
1116 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1117 ok(cy
== d
, "got %d, expected %d\n", cy
, d
);
1119 IPicture_Release(pic
);
1125 static void test_load_save_bmp(void)
1133 IPersistStream
*src_stream
;
1134 IStream
*dst_stream
;
1135 LARGE_INTEGER offset
;
1139 desc
.cbSizeofstruct
= sizeof(desc
);
1140 desc
.picType
= PICTYPE_BITMAP
;
1141 desc
.u
.bmp
.hpal
= 0;
1142 desc
.u
.bmp
.hbitmap
= CreateBitmap(1, 1, 1, 1, NULL
);
1143 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void**)&pic
);
1144 ok(hr
== S_OK
, "OleCreatePictureIndirect error %#x\n", hr
);
1147 hr
= IPicture_get_Type(pic
, &type
);
1148 ok(hr
== S_OK
,"get_Type error %#8x\n", hr
);
1149 ok(type
== PICTYPE_BITMAP
,"expected picture type PICTYPE_BITMAP, got %d\n", type
);
1151 hr
= IPicture_get_Handle(pic
, &handle
);
1152 ok(hr
== S_OK
,"get_Handle error %#8x\n", hr
);
1153 ok(IntToPtr(handle
) == desc
.u
.bmp
.hbitmap
, "get_Handle returned wrong handle %#x\n", handle
);
1155 hmem
= GlobalAlloc(GMEM_ZEROINIT
, 4096);
1156 hr
= CreateStreamOnHGlobal(hmem
, FALSE
, &dst_stream
);
1157 ok(hr
== S_OK
, "createstreamonhglobal error %#x\n", hr
);
1160 hr
= IPicture_SaveAsFile(pic
, dst_stream
, TRUE
, &size
);
1161 ok(hr
== S_OK
, "IPicture_SaveasFile error %#x\n", hr
);
1162 ok(size
== 66, "expected 66, got %d\n", size
);
1163 mem
= GlobalLock(hmem
);
1164 ok(!memcmp(&mem
[0], "BM", 2), "got wrong bmp header %04x\n", mem
[0]);
1168 hr
= IPicture_SaveAsFile(pic
, dst_stream
, FALSE
, &size
);
1169 ok(hr
== E_FAIL
, "expected E_FAIL, got %#x\n", hr
);
1170 ok(size
== -1, "expected -1, got %d\n", size
);
1172 offset
.QuadPart
= 0;
1173 hr
= IStream_Seek(dst_stream
, offset
, SEEK_SET
, NULL
);
1174 ok(hr
== S_OK
, "IStream_Seek %#x\n", hr
);
1176 hr
= IPicture_QueryInterface(pic
, &IID_IPersistStream
, (void **)&src_stream
);
1177 ok(hr
== S_OK
, "QueryInterface error %#x\n", hr
);
1179 hr
= IPersistStream_Save(src_stream
, dst_stream
, TRUE
);
1180 ok(hr
== S_OK
, "Save error %#x\n", hr
);
1182 IPersistStream_Release(src_stream
);
1183 IStream_Release(dst_stream
);
1185 mem
= GlobalLock(hmem
);
1186 ok(!memcmp(mem
, "lt\0\0", 4), "got wrong stream header %04x\n", mem
[0]);
1187 ok(mem
[1] == 66, "expected stream size 66, got %u\n", mem
[1]);
1188 ok(!memcmp(&mem
[2], "BM", 2), "got wrong bmp header %04x\n", mem
[2]);
1193 DeleteObject(desc
.u
.bmp
.hbitmap
);
1194 IPicture_Release(pic
);
1197 static void test_load_save_icon(void)
1205 IPersistStream
*src_stream
;
1206 IStream
*dst_stream
;
1207 LARGE_INTEGER offset
;
1211 desc
.cbSizeofstruct
= sizeof(desc
);
1212 desc
.picType
= PICTYPE_ICON
;
1213 desc
.u
.icon
.hicon
= LoadIconA(NULL
, (LPCSTR
)IDI_APPLICATION
);
1214 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void**)&pic
);
1215 ok(hr
== S_OK
, "OleCreatePictureIndirect error %#x\n", hr
);
1218 hr
= IPicture_get_Type(pic
, &type
);
1219 ok(hr
== S_OK
,"get_Type error %#8x\n", hr
);
1220 ok(type
== PICTYPE_ICON
,"expected picture type PICTYPE_ICON, got %d\n", type
);
1222 hr
= IPicture_get_Handle(pic
, &handle
);
1223 ok(hr
== S_OK
,"get_Handle error %#8x\n", hr
);
1224 ok(IntToPtr(handle
) == desc
.u
.icon
.hicon
, "get_Handle returned wrong handle %#x\n", handle
);
1226 hmem
= GlobalAlloc(GMEM_ZEROINIT
, 8192);
1227 hr
= CreateStreamOnHGlobal(hmem
, FALSE
, &dst_stream
);
1228 ok(hr
== S_OK
, "CreateStreamOnHGlobal error %#x\n", hr
);
1231 hr
= IPicture_SaveAsFile(pic
, dst_stream
, TRUE
, &size
);
1232 ok(hr
== S_OK
, "IPicture_SaveasFile error %#x\n", hr
);
1234 ok(size
== 766, "expected 766, got %d\n", size
);
1235 mem
= GlobalLock(hmem
);
1236 ok(mem
[0] == 0x00010000, "got wrong icon header %04x\n", mem
[0]);
1240 hr
= IPicture_SaveAsFile(pic
, dst_stream
, FALSE
, &size
);
1241 ok(hr
== E_FAIL
, "expected E_FAIL, got %#x\n", hr
);
1242 ok(size
== -1, "expected -1, got %d\n", size
);
1244 offset
.QuadPart
= 0;
1245 hr
= IStream_Seek(dst_stream
, offset
, SEEK_SET
, NULL
);
1246 ok(hr
== S_OK
, "IStream_Seek %#x\n", hr
);
1248 hr
= IPicture_QueryInterface(pic
, &IID_IPersistStream
, (void **)&src_stream
);
1249 ok(hr
== S_OK
, "QueryInterface error %#x\n", hr
);
1251 hr
= IPersistStream_Save(src_stream
, dst_stream
, TRUE
);
1252 ok(hr
== S_OK
, "Saveerror %#x\n", hr
);
1254 IPersistStream_Release(src_stream
);
1255 IStream_Release(dst_stream
);
1257 mem
= GlobalLock(hmem
);
1258 ok(!memcmp(mem
, "lt\0\0", 4), "got wrong stream header %04x\n", mem
[0]);
1260 ok(mem
[1] == 766, "expected stream size 766, got %u\n", mem
[1]);
1261 ok(mem
[2] == 0x00010000, "got wrong icon header %04x\n", mem
[2]);
1266 DestroyIcon(desc
.u
.icon
.hicon
);
1267 IPicture_Release(pic
);
1270 static void test_load_save_empty_picture(void)
1278 IPersistStream
*src_stream
;
1279 IStream
*dst_stream
, *stream
;
1280 LARGE_INTEGER offset
;
1284 memset(&pic
, 0, sizeof(pic
));
1285 desc
.cbSizeofstruct
= sizeof(desc
);
1286 desc
.picType
= PICTYPE_NONE
;
1287 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void **)&pic
);
1288 ok(hr
== S_OK
, "OleCreatePictureIndirect error %#x\n", hr
);
1291 hr
= IPicture_get_Type(pic
, &type
);
1292 ok(hr
== S_OK
, "get_Type error %#x\n", hr
);
1293 ok(type
== PICTYPE_NONE
,"expected picture type PICTYPE_NONE, got %d\n", type
);
1295 handle
= (OLE_HANDLE
)0xdeadbeef;
1296 hr
= IPicture_get_Handle(pic
, &handle
);
1297 ok(hr
== S_OK
,"get_Handle error %#8x\n", hr
);
1298 ok(!handle
, "get_Handle returned wrong handle %#x\n", handle
);
1300 hmem
= GlobalAlloc(GMEM_ZEROINIT
, 4096);
1301 hr
= CreateStreamOnHGlobal(hmem
, FALSE
, &dst_stream
);
1302 ok(hr
== S_OK
, "createstreamonhglobal error %#x\n", hr
);
1305 hr
= IPicture_SaveAsFile(pic
, dst_stream
, TRUE
, &size
);
1306 ok(hr
== S_OK
, "IPicture_SaveasFile error %#x\n", hr
);
1307 ok(size
== -1, "expected -1, got %d\n", size
);
1310 hr
= IPicture_SaveAsFile(pic
, dst_stream
, FALSE
, &size
);
1311 ok(hr
== S_OK
, "IPicture_SaveasFile error %#x\n", hr
);
1312 ok(size
== -1, "expected -1, got %d\n", size
);
1314 hr
= IPicture_QueryInterface(pic
, &IID_IPersistStream
, (void **)&src_stream
);
1315 ok(hr
== S_OK
, "QueryInterface error %#x\n", hr
);
1317 hr
= IPersistStream_Save(src_stream
, dst_stream
, TRUE
);
1318 ok(hr
== S_OK
, "Save error %#x\n", hr
);
1320 mem
= GlobalLock(hmem
);
1321 ok(!memcmp(mem
, "lt\0\0", 4), "got wrong stream header %04x\n", mem
[0]);
1322 ok(mem
[1] == 0, "expected stream size 0, got %u\n", mem
[1]);
1325 IPersistStream_Release(src_stream
);
1326 IPicture_Release(pic
);
1328 /* first with statable and seekable stream */
1329 offset
.QuadPart
= 0;
1330 hr
= IStream_Seek(dst_stream
, offset
, SEEK_SET
, NULL
);
1331 ok(hr
== S_OK
, "IStream_Seek %#x\n", hr
);
1334 hr
= pOleLoadPicture(dst_stream
, 0, FALSE
, &IID_IPicture
, (void **)&pic
);
1335 ok(hr
== S_OK
, "OleLoadPicture error %#x\n", hr
);
1336 ok(pic
!= NULL
,"picture should not be not NULL\n");
1340 hr
= IPicture_get_Type(pic
, &type
);
1341 ok(hr
== S_OK
,"get_Type error %#8x\n", hr
);
1342 ok(type
== PICTYPE_NONE
,"expected picture type PICTYPE_NONE, got %d\n", type
);
1344 handle
= (OLE_HANDLE
)0xdeadbeef;
1345 hr
= IPicture_get_Handle(pic
, &handle
);
1346 ok(hr
== S_OK
,"get_Handle error %#8x\n", hr
);
1347 ok(!handle
, "get_Handle returned wrong handle %#x\n", handle
);
1349 IPicture_Release(pic
);
1351 IStream_Release(dst_stream
);
1353 /* again with non-statable and non-seekable stream */
1354 stream
= NoStatStream_Construct(hmem
);
1355 ok(stream
!= NULL
, "failed to create empty image stream\n");
1358 hr
= pOleLoadPicture(stream
, 0, FALSE
, &IID_IPicture
, (void **)&pic
);
1359 ok(hr
== S_OK
, "OleLoadPicture error %#x\n", hr
);
1360 ok(pic
!= NULL
,"picture should not be not NULL\n");
1364 hr
= IPicture_get_Type(pic
, &type
);
1365 ok(hr
== S_OK
,"get_Type error %#8x\n", hr
);
1366 ok(type
== PICTYPE_NONE
,"expected picture type PICTYPE_NONE, got %d\n", type
);
1368 handle
= (OLE_HANDLE
)0xdeadbeef;
1369 hr
= IPicture_get_Handle(pic
, &handle
);
1370 ok(hr
== S_OK
,"get_Handle error %#8x\n", hr
);
1371 ok(!handle
, "get_Handle returned wrong handle %#x\n", handle
);
1373 IPicture_Release(pic
);
1375 /* Non-statable impl always deletes on release */
1376 IStream_Release(stream
);
1379 static void test_load_save_emf(void)
1389 IPersistStream
*src_stream
;
1390 IStream
*dst_stream
;
1391 LARGE_INTEGER offset
;
1395 hdc
= CreateEnhMetaFileA(0, NULL
, NULL
, NULL
);
1396 ok(hdc
!= 0, "CreateEnhMetaFileA failed\n");
1398 desc
.cbSizeofstruct
= sizeof(desc
);
1399 desc
.picType
= PICTYPE_ENHMETAFILE
;
1400 desc
.u
.emf
.hemf
= CloseEnhMetaFile(hdc
);
1401 ok(desc
.u
.emf
.hemf
!= 0, "CloseEnhMetaFile failed\n");
1402 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void**)&pic
);
1403 ok(hr
== S_OK
, "OleCreatePictureIndirect error %#x\n", hr
);
1406 hr
= IPicture_get_Type(pic
, &type
);
1407 ok(hr
== S_OK
,"get_Type error %#8x\n", hr
);
1408 ok(type
== PICTYPE_ENHMETAFILE
,"expected PICTYPE_ENHMETAFILE, got %d\n", type
);
1410 hr
= IPicture_get_Handle(pic
, &handle
);
1411 ok(hr
== S_OK
,"get_Handle error %#8x\n", hr
);
1412 ok(IntToPtr(handle
) == desc
.u
.emf
.hemf
, "get_Handle returned wrong handle %#x\n", handle
);
1414 hmem
= GlobalAlloc(GMEM_MOVEABLE
, 0);
1415 hr
= CreateStreamOnHGlobal(hmem
, FALSE
, &dst_stream
);
1416 ok(hr
== S_OK
, "createstreamonhglobal error %#x\n", hr
);
1419 hr
= IPicture_SaveAsFile(pic
, dst_stream
, TRUE
, &size
);
1420 ok(hr
== S_OK
, "IPicture_SaveasFile error %#x\n", hr
);
1421 ok(size
== 128, "expected 128, got %d\n", size
);
1422 emh
= GlobalLock(hmem
);
1425 ok(emh
->iType
== EMR_HEADER
, "wrong iType %04x\n", emh
->iType
);
1426 ok(emh
->dSignature
== ENHMETA_SIGNATURE
, "wrong dSignature %08x\n", emh
->dSignature
);
1431 hr
= IPicture_SaveAsFile(pic
, dst_stream
, FALSE
, &size
);
1432 ok(hr
== E_FAIL
, "expected E_FAIL, got %#x\n", hr
);
1433 ok(size
== -1, "expected -1, got %d\n", size
);
1435 offset
.QuadPart
= 0;
1436 hr
= IStream_Seek(dst_stream
, offset
, SEEK_SET
, NULL
);
1437 ok(hr
== S_OK
, "IStream_Seek %#x\n", hr
);
1439 hr
= IPicture_QueryInterface(pic
, &IID_IPersistStream
, (void **)&src_stream
);
1440 ok(hr
== S_OK
, "QueryInterface error %#x\n", hr
);
1442 hr
= IPersistStream_Save(src_stream
, dst_stream
, TRUE
);
1443 ok(hr
== S_OK
, "Save error %#x\n", hr
);
1445 IPersistStream_Release(src_stream
);
1446 IStream_Release(dst_stream
);
1448 mem
= GlobalLock(hmem
);
1449 ok(!memcmp(mem
, "lt\0\0", 4), "got wrong stream header %04x\n", mem
[0]);
1450 ok(mem
[1] == 128, "expected 128, got %u\n", mem
[1]);
1451 emh
= (ENHMETAHEADER
*)(mem
+ 2);
1452 ok(emh
->iType
== EMR_HEADER
, "wrong iType %04x\n", emh
->iType
);
1453 ok(emh
->dSignature
== ENHMETA_SIGNATURE
, "wrong dSignature %08x\n", emh
->dSignature
);
1458 DeleteEnhMetaFile(desc
.u
.emf
.hemf
);
1459 IPicture_Release(pic
);
1462 START_TEST(olepicture
)
1464 hOleaut32
= GetModuleHandleA("oleaut32.dll");
1465 pOleLoadPicture
= (void*)GetProcAddress(hOleaut32
, "OleLoadPicture");
1466 pOleLoadPictureEx
= (void*)GetProcAddress(hOleaut32
, "OleLoadPictureEx");
1467 if (!pOleLoadPicture
)
1469 win_skip("OleLoadPicture is not available\n");
1473 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
1474 test_pic(gifimage
, sizeof(gifimage
));
1475 test_pic(jpgimage
, sizeof(jpgimage
));
1476 test_pic(bmpimage
, sizeof(bmpimage
));
1477 test_pic(bmpimage_rle8
, sizeof(bmpimage_rle8
));
1478 test_pic(gif4pixel
, sizeof(gif4pixel
));
1479 /* FIXME: No PNG support in Windows... */
1480 if (0) test_pic(pngimage
, sizeof(pngimage
));
1482 test_empty_image_2();
1483 if (pOleLoadPictureEx
)
1490 win_skip("OleLoadPictureEx is not available\n");
1492 test_OleCreatePictureIndirect();
1494 test_get_Attributes();
1497 test_OleLoadPicturePath();
1499 test_load_save_bmp();
1500 test_load_save_icon();
1501 test_load_save_empty_picture();
1502 test_load_save_emf();
1506 /* Helper functions only ... */
1509 static inline NoStatStreamImpl
*impl_from_IStream(IStream
*iface
)
1511 return CONTAINING_RECORD(iface
, NoStatStreamImpl
, IStream_iface
);
1514 static void NoStatStreamImpl_Destroy(NoStatStreamImpl
* This
)
1516 GlobalFree(This
->supportHandle
);
1517 This
->supportHandle
=0;
1518 HeapFree(GetProcessHeap(), 0, This
);
1521 static ULONG WINAPI
NoStatStreamImpl_AddRef(
1524 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1525 return InterlockedIncrement(&This
->ref
);
1528 static HRESULT WINAPI
NoStatStreamImpl_QueryInterface(
1530 REFIID riid
, /* [in] */
1531 void** ppvObject
) /* [iid_is][out] */
1533 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1534 if (ppvObject
==0) return E_INVALIDARG
;
1537 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IStream
, riid
))
1538 *ppvObject
= &This
->IStream_iface
;
1540 if ((*ppvObject
)==0)
1541 return E_NOINTERFACE
;
1542 NoStatStreamImpl_AddRef(iface
);
1546 static ULONG WINAPI
NoStatStreamImpl_Release(
1549 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1550 ULONG newRef
= InterlockedDecrement(&This
->ref
);
1552 NoStatStreamImpl_Destroy(This
);
1556 static HRESULT WINAPI
NoStatStreamImpl_Read(
1558 void* pv
, /* [length_is][size_is][out] */
1559 ULONG cb
, /* [in] */
1560 ULONG
* pcbRead
) /* [out] */
1562 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1563 void* supportBuffer
;
1564 ULONG bytesReadBuffer
;
1565 ULONG bytesToReadFromBuffer
;
1568 pcbRead
= &bytesReadBuffer
;
1569 bytesToReadFromBuffer
= min( This
->streamSize
.u
.LowPart
- This
->currentPosition
.u
.LowPart
, cb
);
1570 supportBuffer
= GlobalLock(This
->supportHandle
);
1571 memcpy(pv
, (char *) supportBuffer
+This
->currentPosition
.u
.LowPart
, bytesToReadFromBuffer
);
1572 This
->currentPosition
.u
.LowPart
+=bytesToReadFromBuffer
;
1573 *pcbRead
= bytesToReadFromBuffer
;
1574 GlobalUnlock(This
->supportHandle
);
1580 static HRESULT WINAPI
NoStatStreamImpl_Write(
1582 const void* pv
, /* [size_is][in] */
1583 ULONG cb
, /* [in] */
1584 ULONG
* pcbWritten
) /* [out] */
1586 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1587 void* supportBuffer
;
1588 ULARGE_INTEGER newSize
;
1589 ULONG bytesWritten
= 0;
1591 if (pcbWritten
== 0)
1592 pcbWritten
= &bytesWritten
;
1595 newSize
.u
.HighPart
= 0;
1596 newSize
.u
.LowPart
= This
->currentPosition
.u
.LowPart
+ cb
;
1597 if (newSize
.u
.LowPart
> This
->streamSize
.u
.LowPart
)
1598 IStream_SetSize(iface
, newSize
);
1600 supportBuffer
= GlobalLock(This
->supportHandle
);
1601 memcpy((char *) supportBuffer
+This
->currentPosition
.u
.LowPart
, pv
, cb
);
1602 This
->currentPosition
.u
.LowPart
+=cb
;
1604 GlobalUnlock(This
->supportHandle
);
1608 static HRESULT WINAPI
NoStatStreamImpl_Seek(
1610 LARGE_INTEGER dlibMove
, /* [in] */
1611 DWORD dwOrigin
, /* [in] */
1612 ULARGE_INTEGER
* plibNewPosition
) /* [out] */
1614 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1615 ULARGE_INTEGER newPosition
;
1618 case STREAM_SEEK_SET
:
1619 newPosition
.u
.HighPart
= 0;
1620 newPosition
.u
.LowPart
= 0;
1622 case STREAM_SEEK_CUR
:
1623 newPosition
= This
->currentPosition
;
1625 case STREAM_SEEK_END
:
1626 newPosition
= This
->streamSize
;
1629 return STG_E_INVALIDFUNCTION
;
1631 if (dlibMove
.QuadPart
< 0 && newPosition
.QuadPart
< -dlibMove
.QuadPart
)
1632 return STG_E_INVALIDFUNCTION
;
1633 newPosition
.QuadPart
+= dlibMove
.QuadPart
;
1634 if (plibNewPosition
) *plibNewPosition
= newPosition
;
1635 This
->currentPosition
= newPosition
;
1639 static HRESULT WINAPI
NoStatStreamImpl_SetSize(
1641 ULARGE_INTEGER libNewSize
) /* [in] */
1643 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1644 HGLOBAL supportHandle
;
1645 if (libNewSize
.u
.HighPart
!= 0)
1646 return STG_E_INVALIDFUNCTION
;
1647 if (This
->streamSize
.u
.LowPart
== libNewSize
.u
.LowPart
)
1649 supportHandle
= GlobalReAlloc(This
->supportHandle
, libNewSize
.u
.LowPart
, 0);
1650 if (supportHandle
== 0)
1651 return STG_E_MEDIUMFULL
;
1652 This
->supportHandle
= supportHandle
;
1653 This
->streamSize
.u
.LowPart
= libNewSize
.u
.LowPart
;
1657 static HRESULT WINAPI
NoStatStreamImpl_CopyTo(
1659 IStream
* pstm
, /* [unique][in] */
1660 ULARGE_INTEGER cb
, /* [in] */
1661 ULARGE_INTEGER
* pcbRead
, /* [out] */
1662 ULARGE_INTEGER
* pcbWritten
) /* [out] */
1665 BYTE tmpBuffer
[128];
1666 ULONG bytesRead
, bytesWritten
, copySize
;
1667 ULARGE_INTEGER totalBytesRead
;
1668 ULARGE_INTEGER totalBytesWritten
;
1671 return STG_E_INVALIDPOINTER
;
1672 totalBytesRead
.u
.LowPart
= totalBytesRead
.u
.HighPart
= 0;
1673 totalBytesWritten
.u
.LowPart
= totalBytesWritten
.u
.HighPart
= 0;
1675 while ( cb
.u
.LowPart
> 0 )
1677 if ( cb
.u
.LowPart
>= 128 )
1680 copySize
= cb
.u
.LowPart
;
1681 IStream_Read(iface
, tmpBuffer
, copySize
, &bytesRead
);
1682 totalBytesRead
.u
.LowPart
+= bytesRead
;
1683 IStream_Write(pstm
, tmpBuffer
, bytesRead
, &bytesWritten
);
1684 totalBytesWritten
.u
.LowPart
+= bytesWritten
;
1685 if (bytesRead
!= bytesWritten
)
1687 hr
= STG_E_MEDIUMFULL
;
1690 if (bytesRead
!=copySize
)
1693 cb
.u
.LowPart
-= bytesRead
;
1697 pcbRead
->u
.LowPart
= totalBytesRead
.u
.LowPart
;
1698 pcbRead
->u
.HighPart
= totalBytesRead
.u
.HighPart
;
1703 pcbWritten
->u
.LowPart
= totalBytesWritten
.u
.LowPart
;
1704 pcbWritten
->u
.HighPart
= totalBytesWritten
.u
.HighPart
;
1709 static HRESULT WINAPI
NoStatStreamImpl_Commit(IStream
* iface
,DWORD grfCommitFlags
)
1713 static HRESULT WINAPI
NoStatStreamImpl_Revert(IStream
* iface
) { return S_OK
; }
1715 static HRESULT WINAPI
NoStatStreamImpl_LockRegion(
1717 ULARGE_INTEGER libOffset
, /* [in] */
1718 ULARGE_INTEGER cb
, /* [in] */
1719 DWORD dwLockType
) /* [in] */
1724 static HRESULT WINAPI
NoStatStreamImpl_UnlockRegion(
1726 ULARGE_INTEGER libOffset
, /* [in] */
1727 ULARGE_INTEGER cb
, /* [in] */
1728 DWORD dwLockType
) /* [in] */
1733 static HRESULT WINAPI
NoStatStreamImpl_Stat(
1735 STATSTG
* pstatstg
, /* [out] */
1736 DWORD grfStatFlag
) /* [in] */
1741 static HRESULT WINAPI
NoStatStreamImpl_Clone(
1743 IStream
** ppstm
) /* [out] */
1747 static const IStreamVtbl NoStatStreamImpl_Vtbl
;
1750 Build an object that implements IStream, without IStream_Stat capabilities.
1751 Receives a memory handle with data buffer. If memory handle is non-null,
1752 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
1753 In any case the object takes ownership of memory handle and will free it on
1756 static IStream
* NoStatStream_Construct(HGLOBAL hGlobal
)
1758 NoStatStreamImpl
* newStream
;
1760 newStream
= HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl
));
1763 newStream
->IStream_iface
.lpVtbl
= &NoStatStreamImpl_Vtbl
;
1765 newStream
->supportHandle
= hGlobal
;
1767 if (!newStream
->supportHandle
)
1768 newStream
->supportHandle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_NODISCARD
|
1770 newStream
->currentPosition
.u
.HighPart
= 0;
1771 newStream
->currentPosition
.u
.LowPart
= 0;
1772 newStream
->streamSize
.u
.HighPart
= 0;
1773 newStream
->streamSize
.u
.LowPart
= GlobalSize(newStream
->supportHandle
);
1775 return &newStream
->IStream_iface
;
1779 static const IStreamVtbl NoStatStreamImpl_Vtbl
=
1781 NoStatStreamImpl_QueryInterface
,
1782 NoStatStreamImpl_AddRef
,
1783 NoStatStreamImpl_Release
,
1784 NoStatStreamImpl_Read
,
1785 NoStatStreamImpl_Write
,
1786 NoStatStreamImpl_Seek
,
1787 NoStatStreamImpl_SetSize
,
1788 NoStatStreamImpl_CopyTo
,
1789 NoStatStreamImpl_Commit
,
1790 NoStatStreamImpl_Revert
,
1791 NoStatStreamImpl_LockRegion
,
1792 NoStatStreamImpl_UnlockRegion
,
1793 NoStatStreamImpl_Stat
,
1794 NoStatStreamImpl_Clone