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 GetObjectA(UlongToHandle(handle
), sizeof(BITMAP
), &bmp
);
228 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
;
419 VARIANTARG vararg
, args
[10];
420 DISPPARAMS dispparams
;
428 hglob
= GlobalAlloc (0, sizeof(gifimage
));
429 data
= GlobalLock(hglob
);
430 memcpy(data
, gifimage
, sizeof(gifimage
));
433 hr
= CreateStreamOnHGlobal (hglob
, FALSE
, &stream
);
434 ok_ole_success(hr
, "CreateStreamOnHGlobal");
436 hr
= pOleLoadPicture(stream
, sizeof(gifimage
), TRUE
, &IID_IPictureDisp
, (void **)&picdisp
);
437 IStream_Release(stream
);
439 ok_ole_success(hr
, "OleLoadPicture");
441 V_VT(&vararg
) = VT_BOOL
;
442 V_BOOL(&vararg
) = VARIANT_FALSE
;
443 dispparams
.cNamedArgs
= 0;
444 dispparams
.rgdispidNamedArgs
= NULL
;
445 dispparams
.cArgs
= 1;
446 dispparams
.rgvarg
= &vararg
;
447 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_IPictureDisp
, 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
);
449 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_IUnknown
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
450 ok(hr
== DISP_E_UNKNOWNNAME
, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr
);
452 dispparams
.cArgs
= 0;
453 dispparams
.rgvarg
= NULL
;
454 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
455 ok(hr
== DISP_E_BADPARAMCOUNT
, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr
);
457 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYPUT
, NULL
, NULL
, NULL
, NULL
);
458 ok(hr
== DISP_E_PARAMNOTOPTIONAL
, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr
);
460 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, NULL
, NULL
, NULL
, NULL
);
461 ok(hr
== DISP_E_PARAMNOTOPTIONAL
, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr
);
463 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, NULL
, &varresult
, NULL
, NULL
);
464 ok(hr
== DISP_E_PARAMNOTOPTIONAL
, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr
);
466 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
467 ok_ole_success(hr
, "IPictureDisp_Invoke");
468 ok(V_VT(&varresult
) == VT_I4
, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult
));
470 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_METHOD
, &dispparams
, &varresult
, NULL
, NULL
);
471 ok(hr
== DISP_E_MEMBERNOTFOUND
, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr
);
473 hr
= IPictureDisp_Invoke(picdisp
, 0xdeadbeef, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
474 ok(hr
== DISP_E_MEMBERNOTFOUND
, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr
);
476 dispparams
.cArgs
= 1;
477 dispparams
.rgvarg
= &vararg
;
478 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
479 ok(hr
== DISP_E_BADPARAMCOUNT
, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr
);
481 dispparams
.cArgs
= 1;
482 dispparams
.rgvarg
= &vararg
;
483 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_HPAL
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
484 ok(hr
== DISP_E_BADPARAMCOUNT
, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr
);
486 /* DISPID_PICT_RENDER */
489 for (i
= 0; i
< sizeof(args
)/sizeof(args
[0]); i
++)
490 V_VT(&args
[i
]) = VT_I4
;
501 V_I4(&args
[9]) = HandleToLong(hdc
);
503 dispparams
.rgvarg
= args
;
504 dispparams
.rgdispidNamedArgs
= NULL
;
505 dispparams
.cArgs
= 10;
506 dispparams
.cNamedArgs
= 0;
508 V_VT(&varresult
) = VT_EMPTY
;
509 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_RENDER
, &GUID_NULL
, 0, DISPATCH_METHOD
, &dispparams
, &varresult
, NULL
, NULL
);
510 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
512 /* Try with one argument set to VT_I2, it'd still work if coerced. */
513 V_VT(&args
[3]) = VT_I2
;
514 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_RENDER
, &GUID_NULL
, 0, DISPATCH_METHOD
, &dispparams
, &varresult
, NULL
, NULL
);
515 ok(hr
== DISP_E_TYPEMISMATCH
, "got 0x%08x\n", hr
);
516 V_VT(&args
[3]) = VT_I4
;
518 /* Wrong argument count */
519 dispparams
.cArgs
= 9;
520 hr
= IPictureDisp_Invoke(picdisp
, DISPID_PICT_RENDER
, &GUID_NULL
, 0, DISPATCH_METHOD
, &dispparams
, &varresult
, NULL
, NULL
);
521 ok(hr
== DISP_E_BADPARAMCOUNT
, "got 0x%08x\n", hr
);
523 ReleaseDC(NULL
, hdc
);
524 IPictureDisp_Release(picdisp
);
527 static void test_OleCreatePictureIndirect(void)
536 /* crashes on native */
537 OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, NULL
);
540 hr
= OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (void**)&pict
);
541 ok(hr
== S_OK
, "hr %08x\n", hr
);
544 hr
= IPicture_get_Type(pict
, &type
);
545 ok(hr
== S_OK
, "hr %08x\n", hr
);
546 ok(type
== PICTYPE_UNINITIALIZED
, "type %d\n", type
);
549 hr
= IPicture_get_Handle(pict
, &handle
);
550 ok(hr
== S_OK
, "hr %08x\n", hr
);
551 ok(handle
== 0, "handle %08x\n", handle
);
553 IPicture_Release(pict
);
556 static void test_apm(void)
567 hglob
= GlobalAlloc (0, sizeof(apmdata
));
568 data
= GlobalLock(hglob
);
569 memcpy(data
, apmdata
, sizeof(apmdata
));
571 ole_check(CreateStreamOnHGlobal(hglob
, TRUE
, &stream
));
572 ole_check(pOleLoadPictureEx(stream
, sizeof(apmdata
), TRUE
, &IID_IPicture
, 100, 100, 0, (LPVOID
*)&pict
));
574 ole_check(IPicture_get_Handle(pict
, &handle
));
575 ok(handle
!= 0, "handle is null\n");
577 ole_check(IPicture_get_Type(pict
, &type
));
578 expect_eq(type
, PICTYPE_METAFILE
, short, "%d");
580 ole_check(IPicture_get_Height(pict
, &cxy
));
581 expect_eq(cxy
, 1667, LONG
, "%d");
583 ole_check(IPicture_get_Width(pict
, &cxy
));
584 expect_eq(cxy
, 1323, LONG
, "%d");
586 ole_check(IPicture_get_KeepOriginalFormat(pict
, &keep
));
587 todo_wine
expect_eq(keep
, FALSE
, LONG
, "%d");
589 ole_expect(IPicture_get_hPal(pict
, &handle
), E_FAIL
);
590 IPicture_Release(pict
);
591 IStream_Release(stream
);
594 static void test_metafile(void)
601 hglob
= GlobalAlloc (0, sizeof(metafile
));
602 data
= GlobalLock(hglob
);
603 memcpy(data
, metafile
, sizeof(metafile
));
605 ole_check(CreateStreamOnHGlobal(hglob
, TRUE
, &stream
));
606 /* Windows does not load simple metafiles */
607 ole_expect(pOleLoadPictureEx(stream
, sizeof(metafile
), TRUE
, &IID_IPicture
, 100, 100, 0, (LPVOID
*)&pict
), E_FAIL
);
609 IStream_Release(stream
);
612 static void test_enhmetafile(void)
623 hglob
= GlobalAlloc (0, sizeof(enhmetafile
));
624 data
= GlobalLock(hglob
);
625 memcpy(data
, enhmetafile
, sizeof(enhmetafile
));
627 ole_check(CreateStreamOnHGlobal(hglob
, TRUE
, &stream
));
628 ole_check(pOleLoadPictureEx(stream
, sizeof(enhmetafile
), TRUE
, &IID_IPicture
, 10, 10, 0, (LPVOID
*)&pict
));
630 ole_check(IPicture_get_Handle(pict
, &handle
));
631 ok(handle
!= 0, "handle is null\n");
633 ole_check(IPicture_get_Type(pict
, &type
));
634 expect_eq(type
, PICTYPE_ENHMETAFILE
, short, "%d");
636 ole_check(IPicture_get_Height(pict
, &cxy
));
637 expect_eq(cxy
, -23, LONG
, "%d");
639 ole_check(IPicture_get_Width(pict
, &cxy
));
640 expect_eq(cxy
, -25, LONG
, "%d");
642 ole_check(IPicture_get_KeepOriginalFormat(pict
, &keep
));
643 todo_wine
expect_eq(keep
, FALSE
, LONG
, "%d");
645 IPicture_Release(pict
);
646 IStream_Release(stream
);
649 static HRESULT
picture_render(IPicture
*iface
, HDC hdc
, LONG x
, LONG y
, LONG cx
, LONG cy
,
650 OLE_XPOS_HIMETRIC xSrc
,
651 OLE_YPOS_HIMETRIC ySrc
,
652 OLE_XSIZE_HIMETRIC cxSrc
,
653 OLE_YSIZE_HIMETRIC cySrc
,
656 VARIANT ret
, args
[10];
662 hr
= IPicture_Render(iface
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, bounds
);
664 IPicture_QueryInterface(iface
, &IID_IDispatch
, (void**)&disp
);
666 /* This is broken on 64 bits - accepted pointer argument type is still VT_I4 */
667 for (i
= 0; i
< sizeof(args
)/sizeof(args
[0]); i
++)
668 V_VT(&args
[i
]) = VT_I4
;
670 /* pack arguments and call */
671 V_INT_PTR(&args
[0]) = (INT_PTR
)bounds
;
672 V_I4(&args
[1]) = cySrc
;
673 V_I4(&args
[2]) = cxSrc
;
674 V_I4(&args
[3]) = ySrc
;
675 V_I4(&args
[4]) = xSrc
;
680 V_I4(&args
[9]) = HandleToLong(hdc
);
682 params
.rgvarg
= args
;
683 params
.rgdispidNamedArgs
= NULL
;
685 params
.cNamedArgs
= 0;
687 V_VT(&ret
) = VT_EMPTY
;
688 hr_disp
= IDispatch_Invoke(disp
, DISPID_PICT_RENDER
, &GUID_NULL
, 0, DISPATCH_METHOD
,
689 ¶ms
, &ret
, NULL
, NULL
);
690 ok(hr
== hr_disp
, "DISPID_PICT_RENDER returned wrong code, 0x%08x, expected 0x%08x\n",
693 IDispatch_Release(disp
);
698 static void test_Render(void)
704 OLE_XSIZE_HIMETRIC pWidth
;
705 OLE_YSIZE_HIMETRIC pHeight
;
706 COLORREF result
, expected
;
709 /* test IPicture::Render return code on uninitialized picture */
710 OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (VOID
**)&pic
);
711 hres
= IPicture_get_Type(pic
, &type
);
712 ok(hres
== S_OK
, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres
);
713 ok(type
== PICTYPE_UNINITIALIZED
, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type
);
714 /* zero dimensions */
715 hres
= picture_render(pic
, hdc
, 0, 0, 0, 0, 0, 0, 0, 0, NULL
);
716 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
717 hres
= picture_render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 10, 0, NULL
);
718 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
719 hres
= picture_render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 0, 10, NULL
);
720 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
721 hres
= picture_render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 0, 0, NULL
);
722 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
723 hres
= picture_render(pic
, hdc
, 0, 0, 0, 10, 0, 0, 10, 10, NULL
);
724 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
725 hres
= picture_render(pic
, hdc
, 0, 0, 10, 0, 0, 0, 10, 10, NULL
);
726 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
727 hres
= picture_render(pic
, hdc
, 0, 0, 0, 0, 0, 0, 10, 10, NULL
);
728 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
729 /* nonzero dimensions, PICTYPE_UNINITIALIZED */
730 hres
= picture_render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 10, 10, NULL
);
731 ole_expect(hres
, S_OK
);
732 IPicture_Release(pic
);
734 desc
.cbSizeofstruct
= sizeof(PICTDESC
);
735 desc
.picType
= PICTYPE_ICON
;
736 desc
.u
.icon
.hicon
= LoadIconA(NULL
, (LPCSTR
)IDI_APPLICATION
);
737 if(!desc
.u
.icon
.hicon
){
738 win_skip("LoadIcon failed. Skipping...\n");
739 ReleaseDC(NULL
, hdc
);
743 OleCreatePictureIndirect(&desc
, &IID_IPicture
, TRUE
, (VOID
**)&pic
);
744 /* zero dimensions, PICTYPE_ICON */
745 hres
= picture_render(pic
, hdc
, 0, 0, 0, 0, 0, 0, 0, 0, NULL
);
746 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
747 hres
= picture_render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 10, 0, NULL
);
748 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
749 hres
= picture_render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 0, 10, NULL
);
750 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
751 hres
= picture_render(pic
, hdc
, 0, 0, 10, 10, 0, 0, 0, 0, NULL
);
752 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
753 hres
= picture_render(pic
, hdc
, 0, 0, 0, 10, 0, 0, 10, 10, NULL
);
754 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
755 hres
= picture_render(pic
, hdc
, 0, 0, 10, 0, 0, 0, 10, 10, NULL
);
756 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
757 hres
= picture_render(pic
, hdc
, 0, 0, 0, 0, 0, 0, 10, 10, NULL
);
758 ole_expect(hres
, CTL_E_INVALIDPROPERTYVALUE
);
760 /* Check if target size and position is respected */
761 IPicture_get_Width(pic
, &pWidth
);
762 IPicture_get_Height(pic
, &pHeight
);
764 SetPixelV(hdc
, 0, 0, 0x00223344);
765 SetPixelV(hdc
, 5, 5, 0x00223344);
766 SetPixelV(hdc
, 10, 10, 0x00223344);
767 expected
= GetPixel(hdc
, 0, 0);
769 hres
= picture_render(pic
, hdc
, 1, 1, 9, 9, 0, 0, pWidth
, -pHeight
, NULL
);
770 ole_expect(hres
, S_OK
);
773 IPicture_Release(pic
);
774 ReleaseDC(NULL
, hdc
);
778 /* Evaluate the rendered Icon */
779 result
= GetPixel(hdc
, 0, 0);
780 ok(result
== expected
,
781 "Color at 0,0 should be unchanged 0x%06X, but was 0x%06X\n", expected
, result
);
782 result
= GetPixel(hdc
, 5, 5);
783 ok(result
!= expected
||
784 broken(result
== expected
), /* WinNT 4.0 and older may claim they drew */
785 /* the icon, even if they didn't. */
786 "Color at 5,5 should have changed, but still was 0x%06X\n", expected
);
787 result
= GetPixel(hdc
, 10, 10);
788 ok(result
== expected
,
789 "Color at 10,10 should be unchanged 0x%06X, but was 0x%06X\n", expected
, result
);
791 IPicture_Release(pic
);
792 ReleaseDC(NULL
, hdc
);
795 static void test_get_Attributes(void)
802 OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (VOID
**)&pic
);
803 hres
= IPicture_get_Type(pic
, &type
);
804 ok(hres
== S_OK
, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres
);
805 ok(type
== PICTYPE_UNINITIALIZED
, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type
);
807 hres
= IPicture_get_Attributes(pic
, NULL
);
808 ole_expect(hres
, E_POINTER
);
811 hres
= IPicture_get_Attributes(pic
, &attr
);
812 ole_expect(hres
, S_OK
);
813 ok(attr
== 0, "IPicture_get_Attributes does not reset attr to zero, got %d\n", attr
);
815 IPicture_Release(pic
);
818 static void test_get_Handle(void)
823 OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (VOID
**)&pic
);
825 hres
= IPicture_get_Handle(pic
, NULL
);
826 ole_expect(hres
, E_POINTER
);
828 IPicture_Release(pic
);
831 static void test_get_Type(void)
836 OleCreatePictureIndirect(NULL
, &IID_IPicture
, TRUE
, (VOID
**)&pic
);
838 hres
= IPicture_get_Type(pic
, NULL
);
839 ole_expect(hres
, E_POINTER
);
841 IPicture_Release(pic
);
844 static void test_OleLoadPicturePath(void)
846 static WCHAR emptyW
[] = {0};
851 char temp_path
[MAX_PATH
];
852 char temp_file
[MAX_PATH
];
853 WCHAR temp_fileW
[MAX_PATH
+ 5] = {'f','i','l','e',':','/','/','/'};
861 LPOLESTR szURLorPath
;
864 } invalid_parameters
[] =
868 {NULL
, &IID_IPicture
, NULL
},
869 {NULL
, &IID_IPicture
, &pic
},
870 {emptyW
, NULL
, NULL
},
871 {emptyW
, &IID_IPicture
, NULL
},
874 for (i
= 0; i
< sizeof(invalid_parameters
)/sizeof(invalid_parameters
[0]); i
++)
876 pic
= (IPicture
*)0xdeadbeef;
877 hres
= OleLoadPicturePath(invalid_parameters
[i
].szURLorPath
, NULL
, 0, 0,
878 invalid_parameters
[i
].riid
,
879 (void **)invalid_parameters
[i
].pic
);
880 ok(hres
== E_INVALIDARG
,
881 "[%d] Expected OleLoadPicturePath to return E_INVALIDARG, got 0x%08x\n", i
, hres
);
882 ok(pic
== (IPicture
*)0xdeadbeef,
883 "[%d] Expected output pointer to be 0xdeadbeef, got %p\n", i
, pic
);
886 pic
= (IPicture
*)0xdeadbeef;
887 hres
= OleLoadPicturePath(emptyW
, NULL
, 0, 0, NULL
, (void **)&pic
);
889 ok(hres
== INET_E_UNKNOWN_PROTOCOL
|| /* XP/Vista+ */
890 broken(hres
== E_UNEXPECTED
) || /* NT4 */
891 broken(hres
== E_OUTOFMEMORY
), /* Win2k/Win2k3 */
892 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres
);
894 "Expected the output interface pointer to be NULL, got %p\n", pic
);
896 pic
= (IPicture
*)0xdeadbeef;
897 hres
= OleLoadPicturePath(emptyW
, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
899 ok(hres
== INET_E_UNKNOWN_PROTOCOL
|| /* XP/Vista+ */
900 broken(hres
== E_UNEXPECTED
) || /* NT4 */
901 broken(hres
== E_OUTOFMEMORY
), /* Win2k/Win2k3 */
902 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres
);
904 "Expected the output interface pointer to be NULL, got %p\n", pic
);
906 /* Create a local temporary image file for testing. */
907 GetTempPathA(sizeof(temp_path
), temp_path
);
908 GetTempFileNameA(temp_path
, "bmp", 0, temp_file
);
909 file
= CreateFileA(temp_file
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
910 FILE_ATTRIBUTE_NORMAL
, NULL
);
911 WriteFile(file
, bmpimage
, sizeof(bmpimage
), &size
, NULL
);
914 MultiByteToWideChar(CP_ACP
, 0, temp_file
, -1, temp_fileW
+ 8, sizeof(temp_fileW
)/sizeof(WCHAR
) - 8);
916 /* Try a normal DOS path. */
917 hres
= OleLoadPicturePath(temp_fileW
+ 8, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
919 broken(hres
== E_UNEXPECTED
), /* NT4 */
920 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres
);
922 IPicture_Release(pic
);
925 V_VT(&var
) = VT_BSTR
;
926 V_BSTR(&var
) = SysAllocString(temp_fileW
+ 8);
927 hres
= OleLoadPictureFile(var
, (IDispatch
**)&pic
);
928 ok(hres
== S_OK
, "OleLoadPictureFile error %#x\n", hres
);
929 IPicture_Release(pic
);
932 /* Try a DOS path with tacked on "file:". */
933 hres
= OleLoadPicturePath(temp_fileW
, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
935 broken(hres
== E_UNEXPECTED
), /* NT4 */
936 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres
);
938 IPicture_Release(pic
);
941 V_VT(&var
) = VT_BSTR
;
942 V_BSTR(&var
) = SysAllocString(temp_fileW
);
943 hres
= OleLoadPictureFile(var
, (IDispatch
**)&pic
);
944 ok(hres
== CTL_E_PATHFILEACCESSERROR
, "wrong error %#x\n", hres
);
947 DeleteFileA(temp_file
);
949 /* Try with a nonexistent file. */
950 hres
= OleLoadPicturePath(temp_fileW
+ 8, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
951 ok(hres
== INET_E_RESOURCE_NOT_FOUND
|| /* XP+ */
952 broken(hres
== E_UNEXPECTED
) || /* NT4 */
953 broken(hres
== E_FAIL
), /*Win2k */
954 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres
);
957 V_VT(&var
) = VT_BSTR
;
958 V_BSTR(&var
) = SysAllocString(temp_fileW
+ 8);
959 hres
= OleLoadPictureFile(var
, (IDispatch
**)&pic
);
960 ok(hres
== CTL_E_FILENOTFOUND
, "wrong error %#x\n", hres
);
963 hres
= OleLoadPicturePath(temp_fileW
, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
964 ok(hres
== INET_E_RESOURCE_NOT_FOUND
|| /* XP+ */
965 broken(hres
== E_UNEXPECTED
) || /* NT4 */
966 broken(hres
== E_FAIL
), /* Win2k */
967 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres
);
970 V_VT(&var
) = VT_BSTR
;
971 V_BSTR(&var
) = SysAllocString(temp_fileW
);
972 hres
= OleLoadPictureFile(var
, (IDispatch
**)&pic
);
973 ok(hres
== CTL_E_PATHFILEACCESSERROR
, "wrong error %#x\n", hres
);
976 file
= CreateFileA(temp_file
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
977 FILE_ATTRIBUTE_NORMAL
, NULL
);
978 WriteFile(file
, bmpimage
, sizeof(bmpimage
), &size
, NULL
);
981 /* Try a "file:" URL with slash separators. */
982 ptr
= temp_fileW
+ 8;
990 hres
= OleLoadPicturePath(temp_fileW
, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
992 broken(hres
== E_UNEXPECTED
), /* NT4 */
993 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres
);
995 IPicture_Release(pic
);
998 V_VT(&var
) = VT_BSTR
;
999 V_BSTR(&var
) = SysAllocString(temp_fileW
);
1000 hres
= OleLoadPictureFile(var
, (IDispatch
**)&pic
);
1001 ok(hres
== CTL_E_PATHFILEACCESSERROR
, "wrong error %#x\n", hres
);
1004 DeleteFileA(temp_file
);
1006 /* Try with a nonexistent file. */
1007 hres
= OleLoadPicturePath(temp_fileW
, NULL
, 0, 0, &IID_IPicture
, (void **)&pic
);
1008 ok(hres
== INET_E_RESOURCE_NOT_FOUND
|| /* XP+ */
1009 broken(hres
== E_UNEXPECTED
) || /* NT4 */
1010 broken(hres
== E_FAIL
), /* Win2k */
1011 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres
);
1014 V_VT(&var
) = VT_BSTR
;
1015 V_BSTR(&var
) = SysAllocString(temp_fileW
);
1016 hres
= OleLoadPictureFile(var
, (IDispatch
**)&pic
);
1017 ok(hres
== CTL_E_PATHFILEACCESSERROR
, "wrong error %#x\n", hres
);
1021 V_VT(&var
) = VT_INT
;
1023 hres
= OleLoadPictureFile(var
, (IDispatch
**)&pic
);
1024 ok(hres
== CTL_E_FILENOTFOUND
, "wrong error %#x\n", hres
);
1026 if (0) /* crashes under Windows */
1027 hres
= OleLoadPictureFile(var
, NULL
);
1030 static void test_himetric(void)
1032 static const BYTE bmp_bits
[1024];
1033 OLE_XSIZE_HIMETRIC cx
;
1034 OLE_YSIZE_HIMETRIC cy
;
1043 desc
.cbSizeofstruct
= sizeof(desc
);
1044 desc
.picType
= PICTYPE_BITMAP
;
1045 desc
.u
.bmp
.hpal
= NULL
;
1047 hdc
= CreateCompatibleDC(0);
1049 bmp
= CreateBitmap(1.9 * GetDeviceCaps(hdc
, LOGPIXELSX
),
1050 1.9 * GetDeviceCaps(hdc
, LOGPIXELSY
), 1, 1, NULL
);
1052 desc
.u
.bmp
.hbitmap
= bmp
;
1054 /* size in himetric units reported rounded up to next integer value */
1055 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void**)&pic
);
1056 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1059 d
= MulDiv((INT
)(1.9 * GetDeviceCaps(hdc
, LOGPIXELSX
)), 2540, GetDeviceCaps(hdc
, LOGPIXELSX
));
1060 hr
= IPicture_get_Width(pic
, &cx
);
1061 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1062 ok(cx
== d
, "got %d, expected %d\n", cx
, d
);
1065 d
= MulDiv((INT
)(1.9 * GetDeviceCaps(hdc
, LOGPIXELSY
)), 2540, GetDeviceCaps(hdc
, LOGPIXELSY
));
1066 hr
= IPicture_get_Height(pic
, &cy
);
1067 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1068 ok(cy
== d
, "got %d, expected %d\n", cy
, d
);
1071 IPicture_Release(pic
);
1073 /* same thing with icon */
1074 icon
= CreateIcon(NULL
, GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
),
1075 1, 1, bmp_bits
, bmp_bits
);
1076 ok(icon
!= NULL
, "failed to create icon\n");
1078 desc
.picType
= PICTYPE_ICON
;
1079 desc
.u
.icon
.hicon
= icon
;
1081 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void**)&pic
);
1082 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1085 d
= MulDiv(GetSystemMetrics(SM_CXICON
), 2540, GetDeviceCaps(hdc
, LOGPIXELSX
));
1086 hr
= IPicture_get_Width(pic
, &cx
);
1087 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1088 ok(cx
== d
, "got %d, expected %d\n", cx
, d
);
1091 d
= MulDiv(GetSystemMetrics(SM_CYICON
), 2540, GetDeviceCaps(hdc
, LOGPIXELSY
));
1092 hr
= IPicture_get_Height(pic
, &cy
);
1093 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1094 ok(cy
== d
, "got %d, expected %d\n", cy
, d
);
1096 IPicture_Release(pic
);
1102 static void test_load_save_bmp(void)
1110 IPersistStream
*src_stream
;
1111 IStream
*dst_stream
;
1112 LARGE_INTEGER offset
;
1116 desc
.cbSizeofstruct
= sizeof(desc
);
1117 desc
.picType
= PICTYPE_BITMAP
;
1118 desc
.u
.bmp
.hpal
= 0;
1119 desc
.u
.bmp
.hbitmap
= CreateBitmap(1, 1, 1, 1, NULL
);
1120 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void**)&pic
);
1121 ok(hr
== S_OK
, "OleCreatePictureIndirect error %#x\n", hr
);
1124 hr
= IPicture_get_Type(pic
, &type
);
1125 ok(hr
== S_OK
,"get_Type error %#8x\n", hr
);
1126 ok(type
== PICTYPE_BITMAP
,"expected picture type PICTYPE_BITMAP, got %d\n", type
);
1128 hr
= IPicture_get_Handle(pic
, &handle
);
1129 ok(hr
== S_OK
,"get_Handle error %#8x\n", hr
);
1130 ok(IntToPtr(handle
) == desc
.u
.bmp
.hbitmap
, "get_Handle returned wrong handle %#x\n", handle
);
1132 hmem
= GlobalAlloc(GMEM_ZEROINIT
, 4096);
1133 hr
= CreateStreamOnHGlobal(hmem
, FALSE
, &dst_stream
);
1134 ok(hr
== S_OK
, "createstreamonhglobal error %#x\n", hr
);
1137 hr
= IPicture_SaveAsFile(pic
, dst_stream
, TRUE
, &size
);
1138 ok(hr
== S_OK
, "IPicture_SaveasFile error %#x\n", hr
);
1139 ok(size
== 66, "expected 66, got %d\n", size
);
1140 mem
= GlobalLock(hmem
);
1141 ok(!memcmp(&mem
[0], "BM", 2), "got wrong bmp header %04x\n", mem
[0]);
1145 hr
= IPicture_SaveAsFile(pic
, dst_stream
, FALSE
, &size
);
1146 ok(hr
== E_FAIL
, "expected E_FAIL, got %#x\n", hr
);
1147 ok(size
== -1, "expected -1, got %d\n", size
);
1149 offset
.QuadPart
= 0;
1150 hr
= IStream_Seek(dst_stream
, offset
, SEEK_SET
, NULL
);
1151 ok(hr
== S_OK
, "IStream_Seek %#x\n", hr
);
1153 hr
= IPicture_QueryInterface(pic
, &IID_IPersistStream
, (void **)&src_stream
);
1154 ok(hr
== S_OK
, "QueryInterface error %#x\n", hr
);
1156 hr
= IPersistStream_Save(src_stream
, dst_stream
, TRUE
);
1157 ok(hr
== S_OK
, "Save error %#x\n", hr
);
1159 IPersistStream_Release(src_stream
);
1160 IStream_Release(dst_stream
);
1162 mem
= GlobalLock(hmem
);
1163 ok(!memcmp(mem
, "lt\0\0", 4), "got wrong stream header %04x\n", mem
[0]);
1164 ok(mem
[1] == 66, "expected stream size 66, got %u\n", mem
[1]);
1165 ok(!memcmp(&mem
[2], "BM", 2), "got wrong bmp header %04x\n", mem
[2]);
1170 DeleteObject(desc
.u
.bmp
.hbitmap
);
1171 IPicture_Release(pic
);
1174 static void test_load_save_icon(void)
1182 IPersistStream
*src_stream
;
1183 IStream
*dst_stream
;
1184 LARGE_INTEGER offset
;
1188 desc
.cbSizeofstruct
= sizeof(desc
);
1189 desc
.picType
= PICTYPE_ICON
;
1190 desc
.u
.icon
.hicon
= LoadIconA(NULL
, (LPCSTR
)IDI_APPLICATION
);
1191 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void**)&pic
);
1192 ok(hr
== S_OK
, "OleCreatePictureIndirect error %#x\n", hr
);
1195 hr
= IPicture_get_Type(pic
, &type
);
1196 ok(hr
== S_OK
,"get_Type error %#8x\n", hr
);
1197 ok(type
== PICTYPE_ICON
,"expected picture type PICTYPE_ICON, got %d\n", type
);
1199 hr
= IPicture_get_Handle(pic
, &handle
);
1200 ok(hr
== S_OK
,"get_Handle error %#8x\n", hr
);
1201 ok(IntToPtr(handle
) == desc
.u
.icon
.hicon
, "get_Handle returned wrong handle %#x\n", handle
);
1203 hmem
= GlobalAlloc(GMEM_ZEROINIT
, 8192);
1204 hr
= CreateStreamOnHGlobal(hmem
, FALSE
, &dst_stream
);
1205 ok(hr
== S_OK
, "CreateStreamOnHGlobal error %#x\n", hr
);
1208 hr
= IPicture_SaveAsFile(pic
, dst_stream
, TRUE
, &size
);
1209 ok(hr
== S_OK
, "IPicture_SaveasFile error %#x\n", hr
);
1211 ok(size
== 766, "expected 766, got %d\n", size
);
1212 mem
= GlobalLock(hmem
);
1213 ok(mem
[0] == 0x00010000, "got wrong icon header %04x\n", mem
[0]);
1217 hr
= IPicture_SaveAsFile(pic
, dst_stream
, FALSE
, &size
);
1218 ok(hr
== E_FAIL
, "expected E_FAIL, got %#x\n", hr
);
1219 ok(size
== -1, "expected -1, got %d\n", size
);
1221 offset
.QuadPart
= 0;
1222 hr
= IStream_Seek(dst_stream
, offset
, SEEK_SET
, NULL
);
1223 ok(hr
== S_OK
, "IStream_Seek %#x\n", hr
);
1225 hr
= IPicture_QueryInterface(pic
, &IID_IPersistStream
, (void **)&src_stream
);
1226 ok(hr
== S_OK
, "QueryInterface error %#x\n", hr
);
1228 hr
= IPersistStream_Save(src_stream
, dst_stream
, TRUE
);
1229 ok(hr
== S_OK
, "Saveerror %#x\n", hr
);
1231 IPersistStream_Release(src_stream
);
1232 IStream_Release(dst_stream
);
1234 mem
= GlobalLock(hmem
);
1235 ok(!memcmp(mem
, "lt\0\0", 4), "got wrong stream header %04x\n", mem
[0]);
1237 ok(mem
[1] == 766, "expected stream size 766, got %u\n", mem
[1]);
1238 ok(mem
[2] == 0x00010000, "got wrong icon header %04x\n", mem
[2]);
1243 DestroyIcon(desc
.u
.icon
.hicon
);
1244 IPicture_Release(pic
);
1247 static void test_load_save_empty_picture(void)
1255 IPersistStream
*src_stream
;
1256 IStream
*dst_stream
, *stream
;
1257 LARGE_INTEGER offset
;
1261 memset(&pic
, 0, sizeof(pic
));
1262 desc
.cbSizeofstruct
= sizeof(desc
);
1263 desc
.picType
= PICTYPE_NONE
;
1264 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void **)&pic
);
1265 ok(hr
== S_OK
, "OleCreatePictureIndirect error %#x\n", hr
);
1268 hr
= IPicture_get_Type(pic
, &type
);
1269 ok(hr
== S_OK
, "get_Type error %#x\n", hr
);
1270 ok(type
== PICTYPE_NONE
,"expected picture type PICTYPE_NONE, got %d\n", type
);
1272 handle
= (OLE_HANDLE
)0xdeadbeef;
1273 hr
= IPicture_get_Handle(pic
, &handle
);
1274 ok(hr
== S_OK
,"get_Handle error %#8x\n", hr
);
1275 ok(!handle
, "get_Handle returned wrong handle %#x\n", handle
);
1277 hmem
= GlobalAlloc(GMEM_ZEROINIT
, 4096);
1278 hr
= CreateStreamOnHGlobal(hmem
, FALSE
, &dst_stream
);
1279 ok(hr
== S_OK
, "createstreamonhglobal error %#x\n", hr
);
1282 hr
= IPicture_SaveAsFile(pic
, dst_stream
, TRUE
, &size
);
1283 ok(hr
== S_OK
, "IPicture_SaveasFile error %#x\n", hr
);
1284 ok(size
== -1, "expected -1, got %d\n", size
);
1287 hr
= IPicture_SaveAsFile(pic
, dst_stream
, FALSE
, &size
);
1288 ok(hr
== S_OK
, "IPicture_SaveasFile error %#x\n", hr
);
1289 ok(size
== -1, "expected -1, got %d\n", size
);
1291 hr
= IPicture_QueryInterface(pic
, &IID_IPersistStream
, (void **)&src_stream
);
1292 ok(hr
== S_OK
, "QueryInterface error %#x\n", hr
);
1294 hr
= IPersistStream_Save(src_stream
, dst_stream
, TRUE
);
1295 ok(hr
== S_OK
, "Save error %#x\n", hr
);
1297 mem
= GlobalLock(hmem
);
1298 ok(!memcmp(mem
, "lt\0\0", 4), "got wrong stream header %04x\n", mem
[0]);
1299 ok(mem
[1] == 0, "expected stream size 0, got %u\n", mem
[1]);
1302 IPersistStream_Release(src_stream
);
1303 IPicture_Release(pic
);
1305 /* first with statable and seekable stream */
1306 offset
.QuadPart
= 0;
1307 hr
= IStream_Seek(dst_stream
, offset
, SEEK_SET
, NULL
);
1308 ok(hr
== S_OK
, "IStream_Seek %#x\n", hr
);
1311 hr
= pOleLoadPicture(dst_stream
, 0, FALSE
, &IID_IPicture
, (void **)&pic
);
1312 ok(hr
== S_OK
, "OleLoadPicture error %#x\n", hr
);
1313 ok(pic
!= NULL
,"picture should not be not NULL\n");
1317 hr
= IPicture_get_Type(pic
, &type
);
1318 ok(hr
== S_OK
,"get_Type error %#8x\n", hr
);
1319 ok(type
== PICTYPE_NONE
,"expected picture type PICTYPE_NONE, got %d\n", type
);
1321 handle
= (OLE_HANDLE
)0xdeadbeef;
1322 hr
= IPicture_get_Handle(pic
, &handle
);
1323 ok(hr
== S_OK
,"get_Handle error %#8x\n", hr
);
1324 ok(!handle
, "get_Handle returned wrong handle %#x\n", handle
);
1326 IPicture_Release(pic
);
1328 IStream_Release(dst_stream
);
1330 /* again with non-statable and non-seekable stream */
1331 stream
= NoStatStream_Construct(hmem
);
1332 ok(stream
!= NULL
, "failed to create empty image stream\n");
1335 hr
= pOleLoadPicture(stream
, 0, FALSE
, &IID_IPicture
, (void **)&pic
);
1336 ok(hr
== S_OK
, "OleLoadPicture error %#x\n", hr
);
1337 ok(pic
!= NULL
,"picture should not be not NULL\n");
1341 hr
= IPicture_get_Type(pic
, &type
);
1342 ok(hr
== S_OK
,"get_Type error %#8x\n", hr
);
1343 ok(type
== PICTYPE_NONE
,"expected picture type PICTYPE_NONE, got %d\n", type
);
1345 handle
= (OLE_HANDLE
)0xdeadbeef;
1346 hr
= IPicture_get_Handle(pic
, &handle
);
1347 ok(hr
== S_OK
,"get_Handle error %#8x\n", hr
);
1348 ok(!handle
, "get_Handle returned wrong handle %#x\n", handle
);
1350 IPicture_Release(pic
);
1352 /* Non-statable impl always deletes on release */
1353 IStream_Release(stream
);
1356 static void test_load_save_emf(void)
1366 IPersistStream
*src_stream
;
1367 IStream
*dst_stream
;
1368 LARGE_INTEGER offset
;
1372 hdc
= CreateEnhMetaFileA(0, NULL
, NULL
, NULL
);
1373 ok(hdc
!= 0, "CreateEnhMetaFileA failed\n");
1375 desc
.cbSizeofstruct
= sizeof(desc
);
1376 desc
.picType
= PICTYPE_ENHMETAFILE
;
1377 desc
.u
.emf
.hemf
= CloseEnhMetaFile(hdc
);
1378 ok(desc
.u
.emf
.hemf
!= 0, "CloseEnhMetaFile failed\n");
1379 hr
= OleCreatePictureIndirect(&desc
, &IID_IPicture
, FALSE
, (void**)&pic
);
1380 ok(hr
== S_OK
, "OleCreatePictureIndirect error %#x\n", hr
);
1383 hr
= IPicture_get_Type(pic
, &type
);
1384 ok(hr
== S_OK
,"get_Type error %#8x\n", hr
);
1385 ok(type
== PICTYPE_ENHMETAFILE
,"expected PICTYPE_ENHMETAFILE, got %d\n", type
);
1387 hr
= IPicture_get_Handle(pic
, &handle
);
1388 ok(hr
== S_OK
,"get_Handle error %#8x\n", hr
);
1389 ok(IntToPtr(handle
) == desc
.u
.emf
.hemf
, "get_Handle returned wrong handle %#x\n", handle
);
1391 hmem
= GlobalAlloc(GMEM_MOVEABLE
, 0);
1392 hr
= CreateStreamOnHGlobal(hmem
, FALSE
, &dst_stream
);
1393 ok(hr
== S_OK
, "createstreamonhglobal error %#x\n", hr
);
1396 hr
= IPicture_SaveAsFile(pic
, dst_stream
, TRUE
, &size
);
1397 ok(hr
== S_OK
, "IPicture_SaveasFile error %#x\n", hr
);
1398 ok(size
== 128, "expected 128, got %d\n", size
);
1399 emh
= GlobalLock(hmem
);
1402 ok(emh
->iType
== EMR_HEADER
, "wrong iType %04x\n", emh
->iType
);
1403 ok(emh
->dSignature
== ENHMETA_SIGNATURE
, "wrong dSignature %08x\n", emh
->dSignature
);
1408 hr
= IPicture_SaveAsFile(pic
, dst_stream
, FALSE
, &size
);
1409 ok(hr
== E_FAIL
, "expected E_FAIL, got %#x\n", hr
);
1410 ok(size
== -1, "expected -1, got %d\n", size
);
1412 offset
.QuadPart
= 0;
1413 hr
= IStream_Seek(dst_stream
, offset
, SEEK_SET
, NULL
);
1414 ok(hr
== S_OK
, "IStream_Seek %#x\n", hr
);
1416 hr
= IPicture_QueryInterface(pic
, &IID_IPersistStream
, (void **)&src_stream
);
1417 ok(hr
== S_OK
, "QueryInterface error %#x\n", hr
);
1419 hr
= IPersistStream_Save(src_stream
, dst_stream
, TRUE
);
1420 ok(hr
== S_OK
, "Save error %#x\n", hr
);
1422 IPersistStream_Release(src_stream
);
1423 IStream_Release(dst_stream
);
1425 mem
= GlobalLock(hmem
);
1426 ok(!memcmp(mem
, "lt\0\0", 4), "got wrong stream header %04x\n", mem
[0]);
1427 ok(mem
[1] == 128, "expected 128, got %u\n", mem
[1]);
1428 emh
= (ENHMETAHEADER
*)(mem
+ 2);
1429 ok(emh
->iType
== EMR_HEADER
, "wrong iType %04x\n", emh
->iType
);
1430 ok(emh
->dSignature
== ENHMETA_SIGNATURE
, "wrong dSignature %08x\n", emh
->dSignature
);
1435 DeleteEnhMetaFile(desc
.u
.emf
.hemf
);
1436 IPicture_Release(pic
);
1439 START_TEST(olepicture
)
1441 hOleaut32
= GetModuleHandleA("oleaut32.dll");
1442 pOleLoadPicture
= (void*)GetProcAddress(hOleaut32
, "OleLoadPicture");
1443 pOleLoadPictureEx
= (void*)GetProcAddress(hOleaut32
, "OleLoadPictureEx");
1444 if (!pOleLoadPicture
)
1446 win_skip("OleLoadPicture is not available\n");
1450 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
1451 test_pic(gifimage
, sizeof(gifimage
));
1452 test_pic(jpgimage
, sizeof(jpgimage
));
1453 test_pic(bmpimage
, sizeof(bmpimage
));
1454 test_pic(gif4pixel
, sizeof(gif4pixel
));
1455 /* FIXME: No PNG support in Windows... */
1456 if (0) test_pic(pngimage
, sizeof(pngimage
));
1458 test_empty_image_2();
1459 if (pOleLoadPictureEx
)
1466 win_skip("OleLoadPictureEx is not available\n");
1468 test_OleCreatePictureIndirect();
1470 test_get_Attributes();
1473 test_OleLoadPicturePath();
1475 test_load_save_bmp();
1476 test_load_save_icon();
1477 test_load_save_empty_picture();
1478 test_load_save_emf();
1482 /* Helper functions only ... */
1485 static inline NoStatStreamImpl
*impl_from_IStream(IStream
*iface
)
1487 return CONTAINING_RECORD(iface
, NoStatStreamImpl
, IStream_iface
);
1490 static void NoStatStreamImpl_Destroy(NoStatStreamImpl
* This
)
1492 GlobalFree(This
->supportHandle
);
1493 This
->supportHandle
=0;
1494 HeapFree(GetProcessHeap(), 0, This
);
1497 static ULONG WINAPI
NoStatStreamImpl_AddRef(
1500 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1501 return InterlockedIncrement(&This
->ref
);
1504 static HRESULT WINAPI
NoStatStreamImpl_QueryInterface(
1506 REFIID riid
, /* [in] */
1507 void** ppvObject
) /* [iid_is][out] */
1509 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1510 if (ppvObject
==0) return E_INVALIDARG
;
1512 if (IsEqualIID(&IID_IUnknown
, riid
))
1516 else if (IsEqualIID(&IID_IStream
, riid
))
1521 if ((*ppvObject
)==0)
1522 return E_NOINTERFACE
;
1523 NoStatStreamImpl_AddRef(iface
);
1527 static ULONG WINAPI
NoStatStreamImpl_Release(
1530 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1531 ULONG newRef
= InterlockedDecrement(&This
->ref
);
1533 NoStatStreamImpl_Destroy(This
);
1537 static HRESULT WINAPI
NoStatStreamImpl_Read(
1539 void* pv
, /* [length_is][size_is][out] */
1540 ULONG cb
, /* [in] */
1541 ULONG
* pcbRead
) /* [out] */
1543 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1544 void* supportBuffer
;
1545 ULONG bytesReadBuffer
;
1546 ULONG bytesToReadFromBuffer
;
1549 pcbRead
= &bytesReadBuffer
;
1550 bytesToReadFromBuffer
= min( This
->streamSize
.u
.LowPart
- This
->currentPosition
.u
.LowPart
, cb
);
1551 supportBuffer
= GlobalLock(This
->supportHandle
);
1552 memcpy(pv
, (char *) supportBuffer
+This
->currentPosition
.u
.LowPart
, bytesToReadFromBuffer
);
1553 This
->currentPosition
.u
.LowPart
+=bytesToReadFromBuffer
;
1554 *pcbRead
= bytesToReadFromBuffer
;
1555 GlobalUnlock(This
->supportHandle
);
1561 static HRESULT WINAPI
NoStatStreamImpl_Write(
1563 const void* pv
, /* [size_is][in] */
1564 ULONG cb
, /* [in] */
1565 ULONG
* pcbWritten
) /* [out] */
1567 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1568 void* supportBuffer
;
1569 ULARGE_INTEGER newSize
;
1570 ULONG bytesWritten
= 0;
1572 if (pcbWritten
== 0)
1573 pcbWritten
= &bytesWritten
;
1576 newSize
.u
.HighPart
= 0;
1577 newSize
.u
.LowPart
= This
->currentPosition
.u
.LowPart
+ cb
;
1578 if (newSize
.u
.LowPart
> This
->streamSize
.u
.LowPart
)
1579 IStream_SetSize(iface
, newSize
);
1581 supportBuffer
= GlobalLock(This
->supportHandle
);
1582 memcpy((char *) supportBuffer
+This
->currentPosition
.u
.LowPart
, pv
, cb
);
1583 This
->currentPosition
.u
.LowPart
+=cb
;
1585 GlobalUnlock(This
->supportHandle
);
1589 static HRESULT WINAPI
NoStatStreamImpl_Seek(
1591 LARGE_INTEGER dlibMove
, /* [in] */
1592 DWORD dwOrigin
, /* [in] */
1593 ULARGE_INTEGER
* plibNewPosition
) /* [out] */
1595 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1596 ULARGE_INTEGER newPosition
;
1599 case STREAM_SEEK_SET
:
1600 newPosition
.u
.HighPart
= 0;
1601 newPosition
.u
.LowPart
= 0;
1603 case STREAM_SEEK_CUR
:
1604 newPosition
= This
->currentPosition
;
1606 case STREAM_SEEK_END
:
1607 newPosition
= This
->streamSize
;
1610 return STG_E_INVALIDFUNCTION
;
1612 if (dlibMove
.QuadPart
< 0 && newPosition
.QuadPart
< -dlibMove
.QuadPart
)
1613 return STG_E_INVALIDFUNCTION
;
1614 newPosition
.QuadPart
+= dlibMove
.QuadPart
;
1615 if (plibNewPosition
) *plibNewPosition
= newPosition
;
1616 This
->currentPosition
= newPosition
;
1620 static HRESULT WINAPI
NoStatStreamImpl_SetSize(
1622 ULARGE_INTEGER libNewSize
) /* [in] */
1624 NoStatStreamImpl
* const This
= impl_from_IStream(iface
);
1625 HGLOBAL supportHandle
;
1626 if (libNewSize
.u
.HighPart
!= 0)
1627 return STG_E_INVALIDFUNCTION
;
1628 if (This
->streamSize
.u
.LowPart
== libNewSize
.u
.LowPart
)
1630 supportHandle
= GlobalReAlloc(This
->supportHandle
, libNewSize
.u
.LowPart
, 0);
1631 if (supportHandle
== 0)
1632 return STG_E_MEDIUMFULL
;
1633 This
->supportHandle
= supportHandle
;
1634 This
->streamSize
.u
.LowPart
= libNewSize
.u
.LowPart
;
1638 static HRESULT WINAPI
NoStatStreamImpl_CopyTo(
1640 IStream
* pstm
, /* [unique][in] */
1641 ULARGE_INTEGER cb
, /* [in] */
1642 ULARGE_INTEGER
* pcbRead
, /* [out] */
1643 ULARGE_INTEGER
* pcbWritten
) /* [out] */
1646 BYTE tmpBuffer
[128];
1647 ULONG bytesRead
, bytesWritten
, copySize
;
1648 ULARGE_INTEGER totalBytesRead
;
1649 ULARGE_INTEGER totalBytesWritten
;
1652 return STG_E_INVALIDPOINTER
;
1653 totalBytesRead
.u
.LowPart
= totalBytesRead
.u
.HighPart
= 0;
1654 totalBytesWritten
.u
.LowPart
= totalBytesWritten
.u
.HighPart
= 0;
1656 while ( cb
.u
.LowPart
> 0 )
1658 if ( cb
.u
.LowPart
>= 128 )
1661 copySize
= cb
.u
.LowPart
;
1662 IStream_Read(iface
, tmpBuffer
, copySize
, &bytesRead
);
1663 totalBytesRead
.u
.LowPart
+= bytesRead
;
1664 IStream_Write(pstm
, tmpBuffer
, bytesRead
, &bytesWritten
);
1665 totalBytesWritten
.u
.LowPart
+= bytesWritten
;
1666 if (bytesRead
!= bytesWritten
)
1668 hr
= STG_E_MEDIUMFULL
;
1671 if (bytesRead
!=copySize
)
1674 cb
.u
.LowPart
-= bytesRead
;
1678 pcbRead
->u
.LowPart
= totalBytesRead
.u
.LowPart
;
1679 pcbRead
->u
.HighPart
= totalBytesRead
.u
.HighPart
;
1684 pcbWritten
->u
.LowPart
= totalBytesWritten
.u
.LowPart
;
1685 pcbWritten
->u
.HighPart
= totalBytesWritten
.u
.HighPart
;
1690 static HRESULT WINAPI
NoStatStreamImpl_Commit(IStream
* iface
,DWORD grfCommitFlags
)
1694 static HRESULT WINAPI
NoStatStreamImpl_Revert(IStream
* iface
) { return S_OK
; }
1696 static HRESULT WINAPI
NoStatStreamImpl_LockRegion(
1698 ULARGE_INTEGER libOffset
, /* [in] */
1699 ULARGE_INTEGER cb
, /* [in] */
1700 DWORD dwLockType
) /* [in] */
1705 static HRESULT WINAPI
NoStatStreamImpl_UnlockRegion(
1707 ULARGE_INTEGER libOffset
, /* [in] */
1708 ULARGE_INTEGER cb
, /* [in] */
1709 DWORD dwLockType
) /* [in] */
1714 static HRESULT WINAPI
NoStatStreamImpl_Stat(
1716 STATSTG
* pstatstg
, /* [out] */
1717 DWORD grfStatFlag
) /* [in] */
1722 static HRESULT WINAPI
NoStatStreamImpl_Clone(
1724 IStream
** ppstm
) /* [out] */
1728 static const IStreamVtbl NoStatStreamImpl_Vtbl
;
1731 Build an object that implements IStream, without IStream_Stat capabilities.
1732 Receives a memory handle with data buffer. If memory handle is non-null,
1733 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
1734 In any case the object takes ownership of memory handle and will free it on
1737 static IStream
* NoStatStream_Construct(HGLOBAL hGlobal
)
1739 NoStatStreamImpl
* newStream
;
1741 newStream
= HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl
));
1744 newStream
->IStream_iface
.lpVtbl
= &NoStatStreamImpl_Vtbl
;
1746 newStream
->supportHandle
= hGlobal
;
1748 if (!newStream
->supportHandle
)
1749 newStream
->supportHandle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_NODISCARD
|
1751 newStream
->currentPosition
.u
.HighPart
= 0;
1752 newStream
->currentPosition
.u
.LowPart
= 0;
1753 newStream
->streamSize
.u
.HighPart
= 0;
1754 newStream
->streamSize
.u
.LowPart
= GlobalSize(newStream
->supportHandle
);
1756 return &newStream
->IStream_iface
;
1760 static const IStreamVtbl NoStatStreamImpl_Vtbl
=
1762 NoStatStreamImpl_QueryInterface
,
1763 NoStatStreamImpl_AddRef
,
1764 NoStatStreamImpl_Release
,
1765 NoStatStreamImpl_Read
,
1766 NoStatStreamImpl_Write
,
1767 NoStatStreamImpl_Seek
,
1768 NoStatStreamImpl_SetSize
,
1769 NoStatStreamImpl_CopyTo
,
1770 NoStatStreamImpl_Commit
,
1771 NoStatStreamImpl_Revert
,
1772 NoStatStreamImpl_LockRegion
,
1773 NoStatStreamImpl_UnlockRegion
,
1774 NoStatStreamImpl_Stat
,
1775 NoStatStreamImpl_Clone