wined3d: Pass a texture and sub-resource index to wined3d_volume_download_data().
[wine.git] / dlls / oleaut32 / tests / olepicture.c
blob09032980e5fb190834d2db8f231031d1106adb1e
1 /*
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 #include <stdarg.h>
23 #include <stdio.h>
24 #include <math.h>
25 #include <float.h>
27 #define COBJMACROS
28 #define CONST_VTABLE
29 #define NONAMELESSUNION
31 #include "wine/test.h"
32 #include <windef.h>
33 #include <winbase.h>
34 #include <winuser.h>
35 #include <wingdi.h>
36 #include <winnls.h>
37 #include <winerror.h>
38 #include <winnt.h>
40 #include <urlmon.h>
41 #include <wtypes.h>
42 #include <olectl.h>
43 #include <objidl.h>
45 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
47 #define ole_expect(expr, expect) { \
48 HRESULT r = expr; \
49 ok(r == (expect), #expr " returned %x, expected %s (%x)\n", r, #expect, expect); \
52 #define ole_check(expr) ole_expect(expr, S_OK);
54 static HMODULE hOleaut32;
56 static HRESULT (WINAPI *pOleLoadPicture)(LPSTREAM,LONG,BOOL,REFIID,LPVOID*);
57 static HRESULT (WINAPI *pOleLoadPictureEx)(LPSTREAM,LONG,BOOL,REFIID,DWORD,DWORD,DWORD,LPVOID*);
59 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
61 /* 1x1 pixel gif */
62 static const unsigned char gifimage[35] = {
63 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
64 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
65 0x01,0x00,0x3b
68 /* 1x1 pixel jpg */
69 static const unsigned char jpgimage[285] = {
70 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
71 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
72 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
73 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
74 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
75 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
76 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
77 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
78 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
79 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
80 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
81 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
82 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
83 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
84 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
85 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
86 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
87 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
90 /* 1x1 pixel png */
91 static const unsigned char pngimage[285] = {
92 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
93 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
94 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
95 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
96 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
97 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
98 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
101 /* 1x1 pixel bmp */
102 static const unsigned char bmpimage[66] = {
103 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
104 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
105 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
106 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
107 0x00,0x00
110 /* 2x2 pixel gif */
111 static const unsigned char gif4pixel[42] = {
112 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
113 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
114 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
117 /* APM with an empty metafile with some padding zeros - looks like under Window the
118 * metafile data should be at least 20 bytes */
119 static const unsigned char apmdata[] = {
120 0xd7,0xcd,0xc6,0x9a, 0x00,0x00,0x00,0x00, 0x00,0x00,0xee,0x02, 0xb1,0x03,0xa0,0x05,
121 0x00,0x00,0x00,0x00, 0xee,0x53,0x01,0x00, 0x09,0x00,0x00,0x03, 0x13,0x00,0x00,0x00,
122 0x01,0x00,0x05,0x00, 0x00,0x00,0x00,0x00, 0x03,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
123 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
126 /* MF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
127 static const unsigned char metafile[] = {
128 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
129 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
131 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
132 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
133 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
134 0x00, 0x00
137 /* EMF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
138 static const unsigned char enhmetafile[] = {
139 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
144 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
145 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
146 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
149 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
152 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
153 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
154 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
156 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
158 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
159 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
162 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
163 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
164 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
165 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
166 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
167 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
168 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
169 0x14, 0x00, 0x00, 0x00
173 typedef struct NoStatStreamImpl
175 IStream IStream_iface;
176 LONG ref;
178 HGLOBAL supportHandle;
179 ULARGE_INTEGER streamSize;
180 ULARGE_INTEGER currentPosition;
181 } NoStatStreamImpl;
183 static IStream* NoStatStream_Construct(HGLOBAL hGlobal);
185 static void
186 test_pic_with_stream(LPSTREAM stream, unsigned int imgsize)
188 IPicture* pic = NULL;
189 HRESULT hres;
190 LPVOID pvObj = NULL;
191 OLE_HANDLE handle, hPal;
192 OLE_XSIZE_HIMETRIC width;
193 OLE_YSIZE_HIMETRIC height;
194 short type;
195 DWORD attr;
196 ULONG res;
198 pvObj = NULL;
199 hres = pOleLoadPicture(stream, imgsize, TRUE, &IID_IPicture, &pvObj);
200 pic = pvObj;
202 ok(hres == S_OK,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres);
203 ok(pic != NULL,"OLP (NULL,..) returns NULL, instead of !NULL\n");
204 if (pic == NULL)
205 return;
207 pvObj = NULL;
208 hres = IPicture_QueryInterface (pic, &IID_IPicture, &pvObj);
210 ok(hres == S_OK,"IPicture_QI does not return S_OK, but 0x%08x\n", hres);
211 ok(pvObj != NULL,"IPicture_QI does return NULL, instead of a ptr\n");
213 IPicture_Release ((IPicture*)pvObj);
215 handle = 0;
216 hres = IPicture_get_Handle (pic, &handle);
217 ok(hres == S_OK,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres);
218 ok(handle != 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
220 if (handle)
222 BITMAP bmp;
223 GetObjectA(UlongToHandle(handle), sizeof(BITMAP), &bmp);
224 todo_wine ok(bmp.bmBits != 0, "not a dib\n");
227 width = 0;
228 hres = IPicture_get_Width (pic, &width);
229 ok(hres == S_OK,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres);
230 ok(width != 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
232 height = 0;
233 hres = IPicture_get_Height (pic, &height);
234 ok(hres == S_OK,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres);
235 ok(height != 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
237 type = 0;
238 hres = IPicture_get_Type (pic, &type);
239 ok(hres == S_OK,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
240 ok(type == PICTYPE_BITMAP, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type, PICTYPE_BITMAP);
242 attr = 0;
243 hres = IPicture_get_Attributes (pic, &attr);
244 ok(hres == S_OK,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres);
245 ok(attr == 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr);
247 hPal = 0;
248 hres = IPicture_get_hPal (pic, &hPal);
249 ok(hres == S_OK,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres);
250 /* a single pixel b/w image has no palette */
251 ok(hPal == 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal);
253 res = IPicture_Release (pic);
254 ok (res == 0, "refcount after release is %d, but should be 0?\n", res);
257 static void
258 test_pic(const unsigned char *imgdata, unsigned int imgsize)
260 LPSTREAM stream;
261 HGLOBAL hglob;
262 LPBYTE data;
263 HRESULT hres;
264 LARGE_INTEGER seekto;
265 ULARGE_INTEGER newpos1;
266 DWORD * header;
267 unsigned int i,j;
269 /* Let the fun begin */
270 hglob = GlobalAlloc (0, imgsize);
271 data = GlobalLock (hglob);
272 memcpy(data, imgdata, imgsize);
273 GlobalUnlock(hglob); data = NULL;
275 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
276 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
278 memset(&seekto,0,sizeof(seekto));
279 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
280 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
281 test_pic_with_stream(stream, imgsize);
283 IStream_Release(stream);
285 /* again with Non Statable and Non Seekable stream */
286 stream = NoStatStream_Construct(hglob);
287 hglob = 0; /* Non-statable impl always deletes on release */
288 test_pic_with_stream(stream, 0);
290 IStream_Release(stream);
291 for (i = 1; i <= 8; i++) {
292 /* more fun!!! */
293 hglob = GlobalAlloc (0, imgsize + i * (2 * sizeof(DWORD)));
294 data = GlobalLock (hglob);
295 header = (DWORD *)data;
297 /* multiple copies of header */
298 memcpy(data,"lt\0\0",4);
299 header[1] = imgsize;
300 for (j = 2; j <= i; j++) {
301 memcpy(&(header[2 * (j - 1)]), header, 2 * sizeof(DWORD));
303 memcpy(data + i * (2 * sizeof(DWORD)), imgdata, imgsize);
304 GlobalUnlock(hglob); data = NULL;
306 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
307 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
309 memset(&seekto,0,sizeof(seekto));
310 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
311 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
312 test_pic_with_stream(stream, imgsize);
314 IStream_Release(stream);
316 /* again with Non Statable and Non Seekable stream */
317 stream = NoStatStream_Construct(hglob);
318 hglob = 0; /* Non-statable impl always deletes on release */
319 test_pic_with_stream(stream, 0);
321 IStream_Release(stream);
325 static void test_empty_image(void) {
326 LPBYTE data;
327 LPSTREAM stream;
328 IPicture* pic = NULL;
329 HRESULT hres;
330 LPVOID pvObj = NULL;
331 HGLOBAL hglob;
332 OLE_HANDLE handle;
333 ULARGE_INTEGER newpos1;
334 LARGE_INTEGER seekto;
335 short type;
336 DWORD attr;
338 /* Empty image. Happens occasionally in VB programs. */
339 hglob = GlobalAlloc (0, 8);
340 data = GlobalLock (hglob);
341 memcpy(data,"lt\0\0",4);
342 ((DWORD*)data)[1] = 0;
343 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
344 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
346 memset(&seekto,0,sizeof(seekto));
347 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
348 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
350 pvObj = NULL;
351 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
352 pic = pvObj;
353 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
354 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
356 hres = IPicture_get_Type (pic, &type);
357 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
358 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
360 attr = 0xdeadbeef;
361 hres = IPicture_get_Attributes (pic, &attr);
362 ok (hres == S_OK,"empty picture get attributes failed with hres 0x%08x\n", hres);
363 ok (attr == 0,"attr is %d, but should be 0\n", attr);
365 hres = IPicture_get_Handle (pic, &handle);
366 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
367 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
368 IPicture_Release (pic);
369 IStream_Release (stream);
372 static void test_empty_image_2(void) {
373 LPBYTE data;
374 LPSTREAM stream;
375 IPicture* pic = NULL;
376 HRESULT hres;
377 LPVOID pvObj = NULL;
378 HGLOBAL hglob;
379 ULARGE_INTEGER newpos1;
380 LARGE_INTEGER seekto;
381 short type;
383 /* Empty image at random stream position. */
384 hglob = GlobalAlloc (0, 200);
385 data = GlobalLock (hglob);
386 data += 42;
387 memcpy(data,"lt\0\0",4);
388 ((DWORD*)data)[1] = 0;
389 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
390 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
392 memset(&seekto,0,sizeof(seekto));
393 seekto.u.LowPart = 42;
394 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
395 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
397 pvObj = NULL;
398 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
399 pic = pvObj;
400 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
401 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
403 hres = IPicture_get_Type (pic, &type);
404 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
405 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
407 IPicture_Release (pic);
408 IStream_Release (stream);
411 static void test_Invoke(void)
413 IPictureDisp *picdisp;
414 HRESULT hr;
415 VARIANTARG vararg, args[10];
416 DISPPARAMS dispparams;
417 VARIANT varresult;
418 IStream *stream;
419 HGLOBAL hglob;
420 void *data;
421 HDC hdc;
422 int i;
424 hglob = GlobalAlloc (0, sizeof(gifimage));
425 data = GlobalLock(hglob);
426 memcpy(data, gifimage, sizeof(gifimage));
427 GlobalUnlock(hglob);
429 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
430 ok_ole_success(hr, "CreateStreamOnHGlobal");
432 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
433 IStream_Release(stream);
434 GlobalFree(hglob);
435 ok_ole_success(hr, "OleLoadPicture");
437 V_VT(&vararg) = VT_BOOL;
438 V_BOOL(&vararg) = VARIANT_FALSE;
439 dispparams.cNamedArgs = 0;
440 dispparams.rgdispidNamedArgs = NULL;
441 dispparams.cArgs = 1;
442 dispparams.rgvarg = &vararg;
443 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
444 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
445 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
446 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
448 dispparams.cArgs = 0;
449 dispparams.rgvarg = NULL;
450 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
451 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
453 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
454 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
456 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
457 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
459 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
460 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
462 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
463 ok_ole_success(hr, "IPictureDisp_Invoke");
464 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
466 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
467 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
469 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
470 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
472 dispparams.cArgs = 1;
473 dispparams.rgvarg = &vararg;
474 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
475 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
477 dispparams.cArgs = 1;
478 dispparams.rgvarg = &vararg;
479 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
480 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
482 /* DISPID_PICT_RENDER */
483 hdc = GetDC(0);
485 for (i = 0; i < sizeof(args)/sizeof(args[0]); i++)
486 V_VT(&args[i]) = VT_I4;
488 V_I4(&args[0]) = 0;
489 V_I4(&args[1]) = 10;
490 V_I4(&args[2]) = 10;
491 V_I4(&args[3]) = 0;
492 V_I4(&args[4]) = 0;
493 V_I4(&args[5]) = 10;
494 V_I4(&args[6]) = 10;
495 V_I4(&args[7]) = 0;
496 V_I4(&args[8]) = 0;
497 V_I4(&args[9]) = HandleToLong(hdc);
499 dispparams.rgvarg = args;
500 dispparams.rgdispidNamedArgs = NULL;
501 dispparams.cArgs = 10;
502 dispparams.cNamedArgs = 0;
504 V_VT(&varresult) = VT_EMPTY;
505 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
506 ok(hr == S_OK, "got 0x%08x\n", hr);
508 /* Try with one argument set to VT_I2, it'd still work if coerced. */
509 V_VT(&args[3]) = VT_I2;
510 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
511 ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr);
512 V_VT(&args[3]) = VT_I4;
514 /* Wrong argument count */
515 dispparams.cArgs = 9;
516 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
517 ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
519 ReleaseDC(NULL, hdc);
520 IPictureDisp_Release(picdisp);
523 static void test_OleCreatePictureIndirect(void)
525 OLE_HANDLE handle;
526 IPicture *pict;
527 HRESULT hr;
528 short type;
530 if (0)
532 /* crashes on native */
533 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, NULL);
536 hr = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict);
537 ok(hr == S_OK, "hr %08x\n", hr);
539 type = PICTYPE_NONE;
540 hr = IPicture_get_Type(pict, &type);
541 ok(hr == S_OK, "hr %08x\n", hr);
542 ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type);
544 handle = 0xdeadbeef;
545 hr = IPicture_get_Handle(pict, &handle);
546 ok(hr == S_OK, "hr %08x\n", hr);
547 ok(handle == 0, "handle %08x\n", handle);
549 IPicture_Release(pict);
552 static void test_apm(void)
554 OLE_HANDLE handle;
555 LPSTREAM stream;
556 IPicture *pict;
557 HGLOBAL hglob;
558 LPBYTE *data;
559 LONG cxy;
560 BOOL keep;
561 short type;
563 hglob = GlobalAlloc (0, sizeof(apmdata));
564 data = GlobalLock(hglob);
565 memcpy(data, apmdata, sizeof(apmdata));
567 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
568 ole_check(pOleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict));
570 ole_check(IPicture_get_Handle(pict, &handle));
571 ok(handle != 0, "handle is null\n");
573 ole_check(IPicture_get_Type(pict, &type));
574 expect_eq(type, PICTYPE_METAFILE, short, "%d");
576 ole_check(IPicture_get_Height(pict, &cxy));
577 expect_eq(cxy, 1667, LONG, "%d");
579 ole_check(IPicture_get_Width(pict, &cxy));
580 expect_eq(cxy, 1323, LONG, "%d");
582 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
583 todo_wine expect_eq(keep, FALSE, LONG, "%d");
585 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL);
586 IPicture_Release(pict);
587 IStream_Release(stream);
590 static void test_metafile(void)
592 LPSTREAM stream;
593 IPicture *pict;
594 HGLOBAL hglob;
595 LPBYTE *data;
597 hglob = GlobalAlloc (0, sizeof(metafile));
598 data = GlobalLock(hglob);
599 memcpy(data, metafile, sizeof(metafile));
601 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
602 /* Windows does not load simple metafiles */
603 ole_expect(pOleLoadPictureEx(stream, sizeof(metafile), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict), E_FAIL);
605 IStream_Release(stream);
608 static void test_enhmetafile(void)
610 OLE_HANDLE handle;
611 LPSTREAM stream;
612 IPicture *pict;
613 HGLOBAL hglob;
614 LPBYTE *data;
615 LONG cxy;
616 BOOL keep;
617 short type;
619 hglob = GlobalAlloc (0, sizeof(enhmetafile));
620 data = GlobalLock(hglob);
621 memcpy(data, enhmetafile, sizeof(enhmetafile));
623 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
624 ole_check(pOleLoadPictureEx(stream, sizeof(enhmetafile), TRUE, &IID_IPicture, 10, 10, 0, (LPVOID *)&pict));
626 ole_check(IPicture_get_Handle(pict, &handle));
627 ok(handle != 0, "handle is null\n");
629 ole_check(IPicture_get_Type(pict, &type));
630 expect_eq(type, PICTYPE_ENHMETAFILE, short, "%d");
632 ole_check(IPicture_get_Height(pict, &cxy));
633 expect_eq(cxy, -23, LONG, "%d");
635 ole_check(IPicture_get_Width(pict, &cxy));
636 expect_eq(cxy, -25, LONG, "%d");
638 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
639 todo_wine expect_eq(keep, FALSE, LONG, "%d");
641 IPicture_Release(pict);
642 IStream_Release(stream);
645 static HRESULT picture_render(IPicture *iface, HDC hdc, LONG x, LONG y, LONG cx, LONG cy,
646 OLE_XPOS_HIMETRIC xSrc,
647 OLE_YPOS_HIMETRIC ySrc,
648 OLE_XSIZE_HIMETRIC cxSrc,
649 OLE_YSIZE_HIMETRIC cySrc,
650 const RECT *bounds)
652 VARIANT ret, args[10];
653 HRESULT hr, hr_disp;
654 DISPPARAMS params;
655 IDispatch *disp;
656 int i;
658 hr = IPicture_Render(iface, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, bounds);
660 IPicture_QueryInterface(iface, &IID_IDispatch, (void**)&disp);
662 /* This is broken on 64 bits - accepted pointer argument type is still VT_I4 */
663 for (i = 0; i < sizeof(args)/sizeof(args[0]); i++)
664 V_VT(&args[i]) = VT_I4;
666 /* pack arguments and call */
667 V_INT_PTR(&args[0]) = (INT_PTR)bounds;
668 V_I4(&args[1]) = cySrc;
669 V_I4(&args[2]) = cxSrc;
670 V_I4(&args[3]) = ySrc;
671 V_I4(&args[4]) = xSrc;
672 V_I4(&args[5]) = cy;
673 V_I4(&args[6]) = cx;
674 V_I4(&args[7]) = y;
675 V_I4(&args[8]) = x;
676 V_I4(&args[9]) = HandleToLong(hdc);
678 params.rgvarg = args;
679 params.rgdispidNamedArgs = NULL;
680 params.cArgs = 10;
681 params.cNamedArgs = 0;
683 V_VT(&ret) = VT_EMPTY;
684 hr_disp = IDispatch_Invoke(disp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD,
685 &params, &ret, NULL, NULL);
686 ok(hr == hr_disp, "DISPID_PICT_RENDER returned wrong code, 0x%08x, expected 0x%08x\n",
687 hr_disp, hr);
689 IDispatch_Release(disp);
691 return hr;
694 static void test_Render(void)
696 IPicture *pic;
697 HRESULT hres;
698 short type;
699 PICTDESC desc;
700 OLE_XSIZE_HIMETRIC pWidth;
701 OLE_YSIZE_HIMETRIC pHeight;
702 COLORREF result, expected;
703 HDC hdc = GetDC(0);
705 /* test IPicture::Render return code on uninitialized picture */
706 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
707 hres = IPicture_get_Type(pic, &type);
708 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
709 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
710 /* zero dimensions */
711 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
712 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
713 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
714 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
715 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
716 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
717 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
718 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
719 hres = picture_render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
720 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
721 hres = picture_render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
722 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
723 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
724 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
725 /* nonzero dimensions, PICTYPE_UNINITIALIZED */
726 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL);
727 ole_expect(hres, S_OK);
728 IPicture_Release(pic);
730 desc.cbSizeofstruct = sizeof(PICTDESC);
731 desc.picType = PICTYPE_ICON;
732 desc.u.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
733 if(!desc.u.icon.hicon){
734 win_skip("LoadIcon failed. Skipping...\n");
735 ReleaseDC(NULL, hdc);
736 return;
739 OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (VOID**)&pic);
740 /* zero dimensions, PICTYPE_ICON */
741 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
742 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
743 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
744 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
745 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
746 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
747 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
748 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
749 hres = picture_render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
750 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
751 hres = picture_render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
752 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
753 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
754 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
756 /* Check if target size and position is respected */
757 IPicture_get_Width(pic, &pWidth);
758 IPicture_get_Height(pic, &pHeight);
760 SetPixelV(hdc, 0, 0, 0x00223344);
761 SetPixelV(hdc, 5, 5, 0x00223344);
762 SetPixelV(hdc, 10, 10, 0x00223344);
763 expected = GetPixel(hdc, 0, 0);
765 hres = picture_render(pic, hdc, 1, 1, 9, 9, 0, 0, pWidth, -pHeight, NULL);
766 ole_expect(hres, S_OK);
768 if(hres != S_OK) {
769 IPicture_Release(pic);
770 ReleaseDC(NULL, hdc);
771 return;
774 /* Evaluate the rendered Icon */
775 result = GetPixel(hdc, 0, 0);
776 ok(result == expected,
777 "Color at 0,0 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
778 result = GetPixel(hdc, 5, 5);
779 ok(result != expected ||
780 broken(result == expected), /* WinNT 4.0 and older may claim they drew */
781 /* the icon, even if they didn't. */
782 "Color at 5,5 should have changed, but still was 0x%06X\n", expected);
783 result = GetPixel(hdc, 10, 10);
784 ok(result == expected,
785 "Color at 10,10 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
787 IPicture_Release(pic);
788 ReleaseDC(NULL, hdc);
791 static void test_get_Attributes(void)
793 IPicture *pic;
794 HRESULT hres;
795 short type;
796 DWORD attr;
798 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
799 hres = IPicture_get_Type(pic, &type);
800 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
801 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
803 hres = IPicture_get_Attributes(pic, NULL);
804 ole_expect(hres, E_POINTER);
806 attr = 0xdeadbeef;
807 hres = IPicture_get_Attributes(pic, &attr);
808 ole_expect(hres, S_OK);
809 ok(attr == 0, "IPicture_get_Attributes does not reset attr to zero, got %d\n", attr);
811 IPicture_Release(pic);
814 static void test_get_Handle(void)
816 IPicture *pic;
817 HRESULT hres;
819 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
821 hres = IPicture_get_Handle(pic, NULL);
822 ole_expect(hres, E_POINTER);
824 IPicture_Release(pic);
827 static void test_get_Type(void)
829 IPicture *pic;
830 HRESULT hres;
832 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
834 hres = IPicture_get_Type(pic, NULL);
835 ole_expect(hres, E_POINTER);
837 IPicture_Release(pic);
840 static void test_OleLoadPicturePath(void)
842 static WCHAR emptyW[] = {0};
844 IPicture *pic;
845 HRESULT hres;
846 int i;
847 char temp_path[MAX_PATH];
848 char temp_file[MAX_PATH];
849 WCHAR temp_fileW[MAX_PATH + 5] = {'f','i','l','e',':','/','/','/'};
850 HANDLE file;
851 DWORD size;
852 WCHAR *ptr;
854 const struct
856 LPOLESTR szURLorPath;
857 REFIID riid;
858 IPicture **pic;
859 } invalid_parameters[] =
861 {NULL, NULL, NULL},
862 {NULL, NULL, &pic},
863 {NULL, &IID_IPicture, NULL},
864 {NULL, &IID_IPicture, &pic},
865 {emptyW, NULL, NULL},
866 {emptyW, &IID_IPicture, NULL},
869 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
871 pic = (IPicture *)0xdeadbeef;
872 hres = OleLoadPicturePath(invalid_parameters[i].szURLorPath, NULL, 0, 0,
873 invalid_parameters[i].riid,
874 (void **)invalid_parameters[i].pic);
875 ok(hres == E_INVALIDARG,
876 "[%d] Expected OleLoadPicturePath to return E_INVALIDARG, got 0x%08x\n", i, hres);
877 ok(pic == (IPicture *)0xdeadbeef,
878 "[%d] Expected output pointer to be 0xdeadbeef, got %p\n", i, pic);
881 pic = (IPicture *)0xdeadbeef;
882 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, NULL, (void **)&pic);
883 todo_wine
884 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
885 broken(hres == E_UNEXPECTED) || /* NT4 */
886 broken(hres == E_OUTOFMEMORY), /* Win2k/Win2k3 */
887 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
888 ok(pic == NULL,
889 "Expected the output interface pointer to be NULL, got %p\n", pic);
891 pic = (IPicture *)0xdeadbeef;
892 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
893 todo_wine
894 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
895 broken(hres == E_UNEXPECTED) || /* NT4 */
896 broken(hres == E_OUTOFMEMORY), /* Win2k/Win2k3 */
897 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
898 ok(pic == NULL,
899 "Expected the output interface pointer to be NULL, got %p\n", pic);
901 /* Create a local temporary image file for testing. */
902 GetTempPathA(sizeof(temp_path), temp_path);
903 GetTempFileNameA(temp_path, "bmp", 0, temp_file);
904 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
905 FILE_ATTRIBUTE_NORMAL, NULL);
906 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
907 CloseHandle(file);
909 MultiByteToWideChar(CP_ACP, 0, temp_file, -1, temp_fileW + 8, sizeof(temp_fileW)/sizeof(WCHAR) - 8);
911 /* Try a normal DOS path. */
912 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
913 ok(hres == S_OK ||
914 broken(hres == E_UNEXPECTED), /* NT4 */
915 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
916 if (pic)
917 IPicture_Release(pic);
919 /* Try a DOS path with tacked on "file:". */
920 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
921 ok(hres == S_OK ||
922 broken(hres == E_UNEXPECTED), /* NT4 */
923 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
924 if (pic)
925 IPicture_Release(pic);
927 DeleteFileA(temp_file);
929 /* Try with a nonexistent file. */
930 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
931 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
932 broken(hres == E_UNEXPECTED) || /* NT4 */
933 broken(hres == E_FAIL), /*Win2k */
934 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
936 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
937 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
938 broken(hres == E_UNEXPECTED) || /* NT4 */
939 broken(hres == E_FAIL), /* Win2k */
940 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
942 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
943 FILE_ATTRIBUTE_NORMAL, NULL);
944 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
945 CloseHandle(file);
947 /* Try a "file:" URL with slash separators. */
948 ptr = temp_fileW + 8;
949 while (*ptr)
951 if (*ptr == '\\')
952 *ptr = '/';
953 ptr++;
956 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
957 ok(hres == S_OK ||
958 broken(hres == E_UNEXPECTED), /* NT4 */
959 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
960 if (pic)
961 IPicture_Release(pic);
963 DeleteFileA(temp_file);
965 /* Try with a nonexistent file. */
966 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
967 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
968 broken(hres == E_UNEXPECTED) || /* NT4 */
969 broken(hres == E_FAIL), /* Win2k */
970 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
973 static void test_himetric(void)
975 static const BYTE bmp_bits[1024];
976 OLE_XSIZE_HIMETRIC cx;
977 OLE_YSIZE_HIMETRIC cy;
978 IPicture *pic;
979 PICTDESC desc;
980 HBITMAP bmp;
981 HRESULT hr;
982 HICON icon;
983 HDC hdc;
984 INT d;
986 desc.cbSizeofstruct = sizeof(desc);
987 desc.picType = PICTYPE_BITMAP;
988 desc.u.bmp.hpal = NULL;
990 hdc = CreateCompatibleDC(0);
992 bmp = CreateBitmap(1.9 * GetDeviceCaps(hdc, LOGPIXELSX),
993 1.9 * GetDeviceCaps(hdc, LOGPIXELSY), 1, 1, NULL);
995 desc.u.bmp.hbitmap = bmp;
997 /* size in himetric units reported rounded up to next integer value */
998 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
999 ok(hr == S_OK, "got 0x%08x\n", hr);
1001 cx = 0;
1002 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSX)), 2540, GetDeviceCaps(hdc, LOGPIXELSX));
1003 hr = IPicture_get_Width(pic, &cx);
1004 ok(hr == S_OK, "got 0x%08x\n", hr);
1005 ok(cx == d, "got %d, expected %d\n", cx, d);
1007 cy = 0;
1008 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSY)), 2540, GetDeviceCaps(hdc, LOGPIXELSY));
1009 hr = IPicture_get_Height(pic, &cy);
1010 ok(hr == S_OK, "got 0x%08x\n", hr);
1011 ok(cy == d, "got %d, expected %d\n", cy, d);
1013 DeleteObject(bmp);
1014 IPicture_Release(pic);
1016 /* same thing with icon */
1017 icon = CreateIcon(NULL, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
1018 1, 1, bmp_bits, bmp_bits);
1019 ok(icon != NULL, "failed to create icon\n");
1021 desc.picType = PICTYPE_ICON;
1022 desc.u.icon.hicon = icon;
1024 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1025 ok(hr == S_OK, "got 0x%08x\n", hr);
1027 cx = 0;
1028 d = MulDiv(GetSystemMetrics(SM_CXICON), 2540, GetDeviceCaps(hdc, LOGPIXELSX));
1029 hr = IPicture_get_Width(pic, &cx);
1030 ok(hr == S_OK, "got 0x%08x\n", hr);
1031 ok(cx == d, "got %d, expected %d\n", cx, d);
1033 cy = 0;
1034 d = MulDiv(GetSystemMetrics(SM_CYICON), 2540, GetDeviceCaps(hdc, LOGPIXELSY));
1035 hr = IPicture_get_Height(pic, &cy);
1036 ok(hr == S_OK, "got 0x%08x\n", hr);
1037 ok(cy == d, "got %d, expected %d\n", cy, d);
1039 IPicture_Release(pic);
1040 DestroyIcon(icon);
1042 DeleteDC(hdc);
1045 static void test_load_save_bmp(void)
1047 IPicture *pic;
1048 PICTDESC desc;
1049 short type;
1050 OLE_HANDLE handle;
1051 HGLOBAL hmem;
1052 DWORD *mem;
1053 IPersistStream *src_stream;
1054 IStream *dst_stream;
1055 LARGE_INTEGER offset;
1056 HRESULT hr;
1057 LONG size;
1059 desc.cbSizeofstruct = sizeof(desc);
1060 desc.picType = PICTYPE_BITMAP;
1061 desc.u.bmp.hpal = 0;
1062 desc.u.bmp.hbitmap = CreateBitmap(1, 1, 1, 1, NULL);
1063 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1064 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1066 type = -1;
1067 hr = IPicture_get_Type(pic, &type);
1068 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1069 ok(type == PICTYPE_BITMAP,"expected picture type PICTYPE_BITMAP, got %d\n", type);
1071 hr = IPicture_get_Handle(pic, &handle);
1072 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1073 ok(IntToPtr(handle) == desc.u.bmp.hbitmap, "get_Handle returned wrong handle %#x\n", handle);
1075 hmem = GlobalAlloc(GMEM_ZEROINIT, 4096);
1076 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1077 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr);
1079 size = -1;
1080 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size);
1081 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1082 todo_wine
1083 ok(size == 66, "expected 66, got %d\n", size);
1084 mem = GlobalLock(hmem);
1085 todo_wine
1086 ok(!memcmp(&mem[0], "BM", 2), "got wrong bmp header %04x\n", mem[0]);
1087 GlobalUnlock(hmem);
1089 size = -1;
1090 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size);
1091 todo_wine
1092 ok(hr == E_FAIL, "expected E_FAIL, got %#x\n", hr);
1093 todo_wine
1094 ok(size == -1, "expected -1, got %d\n", size);
1096 offset.QuadPart = 0;
1097 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL);
1098 ok(hr == S_OK, "IStream_Seek %#x\n", hr);
1100 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1101 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1103 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1104 ok(hr == S_OK, "Save error %#x\n", hr);
1106 IPersistStream_Release(src_stream);
1107 IStream_Release(dst_stream);
1109 mem = GlobalLock(hmem);
1110 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1111 ok(mem[1] == 66, "expected stream size 66, got %u\n", mem[1]);
1112 ok(!memcmp(&mem[2], "BM", 2), "got wrong bmp header %04x\n", mem[2]);
1114 GlobalUnlock(hmem);
1115 GlobalFree(hmem);
1117 DeleteObject(desc.u.bmp.hbitmap);
1118 IPicture_Release(pic);
1121 static void test_load_save_icon(void)
1123 IPicture *pic;
1124 PICTDESC desc;
1125 short type;
1126 OLE_HANDLE handle;
1127 HGLOBAL hmem;
1128 DWORD *mem;
1129 IPersistStream *src_stream;
1130 IStream *dst_stream;
1131 LARGE_INTEGER offset;
1132 HRESULT hr;
1133 LONG size;
1135 desc.cbSizeofstruct = sizeof(desc);
1136 desc.picType = PICTYPE_ICON;
1137 desc.u.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
1138 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1139 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1141 type = -1;
1142 hr = IPicture_get_Type(pic, &type);
1143 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1144 ok(type == PICTYPE_ICON,"expected picture type PICTYPE_ICON, got %d\n", type);
1146 hr = IPicture_get_Handle(pic, &handle);
1147 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1148 ok(IntToPtr(handle) == desc.u.icon.hicon, "get_Handle returned wrong handle %#x\n", handle);
1150 hmem = GlobalAlloc(GMEM_ZEROINIT, 8192);
1151 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1152 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
1154 size = -1;
1155 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size);
1156 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1157 todo_wine
1158 ok(size == 766, "expected 766, got %d\n", size);
1159 mem = GlobalLock(hmem);
1160 todo_wine
1161 ok(mem[0] == 0x00010000, "got wrong icon header %04x\n", mem[0]);
1162 GlobalUnlock(hmem);
1164 size = -1;
1165 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size);
1166 todo_wine
1167 ok(hr == E_FAIL, "expected E_FAIL, got %#x\n", hr);
1168 todo_wine
1169 ok(size == -1, "expected -1, got %d\n", size);
1171 offset.QuadPart = 0;
1172 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL);
1173 ok(hr == S_OK, "IStream_Seek %#x\n", hr);
1175 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1176 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1178 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1179 ok(hr == S_OK, "Saveerror %#x\n", hr);
1181 IPersistStream_Release(src_stream);
1182 IStream_Release(dst_stream);
1184 mem = GlobalLock(hmem);
1185 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1186 todo_wine
1187 ok(mem[1] == 766, "expected stream size 766, got %u\n", mem[1]);
1188 ok(mem[2] == 0x00010000, "got wrong icon header %04x\n", mem[2]);
1190 GlobalUnlock(hmem);
1191 GlobalFree(hmem);
1193 DestroyIcon(desc.u.icon.hicon);
1194 IPicture_Release(pic);
1197 static void test_load_save_empty_picture(void)
1199 IPicture *pic;
1200 PICTDESC desc;
1201 short type;
1202 OLE_HANDLE handle;
1203 HGLOBAL hmem;
1204 DWORD *mem;
1205 IPersistStream *src_stream;
1206 IStream *dst_stream, *stream;
1207 LARGE_INTEGER offset;
1208 HRESULT hr;
1209 LONG size;
1211 memset(&pic, 0, sizeof(pic));
1212 desc.cbSizeofstruct = sizeof(desc);
1213 desc.picType = PICTYPE_NONE;
1214 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void **)&pic);
1215 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1217 type = -1;
1218 hr = IPicture_get_Type(pic, &type);
1219 ok(hr == S_OK, "get_Type error %#x\n", hr);
1220 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
1222 handle = (OLE_HANDLE)0xdeadbeef;
1223 hr = IPicture_get_Handle(pic, &handle);
1224 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1225 ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
1227 hmem = GlobalAlloc(GMEM_ZEROINIT, 4096);
1228 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1229 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr);
1231 size = -1;
1232 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size);
1233 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1234 todo_wine
1235 ok(size == -1, "expected -1, got %d\n", size);
1237 size = -1;
1238 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size);
1239 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1240 todo_wine
1241 ok(size == -1, "expected -1, got %d\n", size);
1243 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1244 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1246 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1247 ok(hr == S_OK, "Save error %#x\n", hr);
1249 mem = GlobalLock(hmem);
1250 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1251 ok(mem[1] == 0, "expected stream size 0, got %u\n", mem[1]);
1252 GlobalUnlock(hmem);
1254 IPersistStream_Release(src_stream);
1255 IPicture_Release(pic);
1257 /* first with statable and seekable stream */
1258 offset.QuadPart = 0;
1259 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL);
1260 ok(hr == S_OK, "IStream_Seek %#x\n", hr);
1262 pic = NULL;
1263 hr = pOleLoadPicture(dst_stream, 0, FALSE, &IID_IPicture, (void **)&pic);
1264 ok(hr == S_OK, "OleLoadPicture error %#x\n", hr);
1265 ok(pic != NULL,"picture should not be not NULL\n");
1266 if (pic != NULL)
1268 type = -1;
1269 hr = IPicture_get_Type(pic, &type);
1270 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1271 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
1273 handle = (OLE_HANDLE)0xdeadbeef;
1274 hr = IPicture_get_Handle(pic, &handle);
1275 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1276 ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
1278 IPicture_Release(pic);
1280 IStream_Release(dst_stream);
1282 /* again with non-statable and non-seekable stream */
1283 stream = NoStatStream_Construct(hmem);
1284 ok(stream != NULL, "failed to create empty image stream\n");
1286 pic = NULL;
1287 hr = pOleLoadPicture(stream, 0, FALSE, &IID_IPicture, (void **)&pic);
1288 ok(hr == S_OK, "OleLoadPicture error %#x\n", hr);
1289 ok(pic != NULL,"picture should not be not NULL\n");
1290 if (pic != NULL)
1292 type = -1;
1293 hr = IPicture_get_Type(pic, &type);
1294 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1295 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
1297 handle = (OLE_HANDLE)0xdeadbeef;
1298 hr = IPicture_get_Handle(pic, &handle);
1299 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1300 ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
1302 IPicture_Release(pic);
1304 /* Non-statable impl always deletes on release */
1305 IStream_Release(stream);
1308 START_TEST(olepicture)
1310 hOleaut32 = GetModuleHandleA("oleaut32.dll");
1311 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
1312 pOleLoadPictureEx = (void*)GetProcAddress(hOleaut32, "OleLoadPictureEx");
1313 if (!pOleLoadPicture)
1315 win_skip("OleLoadPicture is not available\n");
1316 return;
1319 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
1320 test_pic(gifimage, sizeof(gifimage));
1321 test_pic(jpgimage, sizeof(jpgimage));
1322 test_pic(bmpimage, sizeof(bmpimage));
1323 test_pic(gif4pixel, sizeof(gif4pixel));
1324 /* FIXME: No PNG support in Windows... */
1325 if (0) test_pic(pngimage, sizeof(pngimage));
1326 test_empty_image();
1327 test_empty_image_2();
1328 if (pOleLoadPictureEx)
1330 test_apm();
1331 test_metafile();
1332 test_enhmetafile();
1334 else
1335 win_skip("OleLoadPictureEx is not available\n");
1336 test_Invoke();
1337 test_OleCreatePictureIndirect();
1338 test_Render();
1339 test_get_Attributes();
1340 test_get_Handle();
1341 test_get_Type();
1342 test_OleLoadPicturePath();
1343 test_himetric();
1344 test_load_save_bmp();
1345 test_load_save_icon();
1346 test_load_save_empty_picture();
1350 /* Helper functions only ... */
1353 static inline NoStatStreamImpl *impl_from_IStream(IStream *iface)
1355 return CONTAINING_RECORD(iface, NoStatStreamImpl, IStream_iface);
1358 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
1360 GlobalFree(This->supportHandle);
1361 This->supportHandle=0;
1362 HeapFree(GetProcessHeap(), 0, This);
1365 static ULONG WINAPI NoStatStreamImpl_AddRef(
1366 IStream* iface)
1368 NoStatStreamImpl* const This = impl_from_IStream(iface);
1369 return InterlockedIncrement(&This->ref);
1372 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
1373 IStream* iface,
1374 REFIID riid, /* [in] */
1375 void** ppvObject) /* [iid_is][out] */
1377 NoStatStreamImpl* const This = impl_from_IStream(iface);
1378 if (ppvObject==0) return E_INVALIDARG;
1379 *ppvObject = 0;
1380 if (IsEqualIID(&IID_IUnknown, riid))
1382 *ppvObject = This;
1384 else if (IsEqualIID(&IID_IStream, riid))
1386 *ppvObject = This;
1389 if ((*ppvObject)==0)
1390 return E_NOINTERFACE;
1391 NoStatStreamImpl_AddRef(iface);
1392 return S_OK;
1395 static ULONG WINAPI NoStatStreamImpl_Release(
1396 IStream* iface)
1398 NoStatStreamImpl* const This = impl_from_IStream(iface);
1399 ULONG newRef = InterlockedDecrement(&This->ref);
1400 if (newRef==0)
1401 NoStatStreamImpl_Destroy(This);
1402 return newRef;
1405 static HRESULT WINAPI NoStatStreamImpl_Read(
1406 IStream* iface,
1407 void* pv, /* [length_is][size_is][out] */
1408 ULONG cb, /* [in] */
1409 ULONG* pcbRead) /* [out] */
1411 NoStatStreamImpl* const This = impl_from_IStream(iface);
1412 void* supportBuffer;
1413 ULONG bytesReadBuffer;
1414 ULONG bytesToReadFromBuffer;
1416 if (pcbRead==0)
1417 pcbRead = &bytesReadBuffer;
1418 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
1419 supportBuffer = GlobalLock(This->supportHandle);
1420 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
1421 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
1422 *pcbRead = bytesToReadFromBuffer;
1423 GlobalUnlock(This->supportHandle);
1424 if(*pcbRead == cb)
1425 return S_OK;
1426 return S_FALSE;
1429 static HRESULT WINAPI NoStatStreamImpl_Write(
1430 IStream* iface,
1431 const void* pv, /* [size_is][in] */
1432 ULONG cb, /* [in] */
1433 ULONG* pcbWritten) /* [out] */
1435 NoStatStreamImpl* const This = impl_from_IStream(iface);
1436 void* supportBuffer;
1437 ULARGE_INTEGER newSize;
1438 ULONG bytesWritten = 0;
1440 if (pcbWritten == 0)
1441 pcbWritten = &bytesWritten;
1442 if (cb == 0)
1443 return S_OK;
1444 newSize.u.HighPart = 0;
1445 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
1446 if (newSize.u.LowPart > This->streamSize.u.LowPart)
1447 IStream_SetSize(iface, newSize);
1449 supportBuffer = GlobalLock(This->supportHandle);
1450 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
1451 This->currentPosition.u.LowPart+=cb;
1452 *pcbWritten = cb;
1453 GlobalUnlock(This->supportHandle);
1454 return S_OK;
1457 static HRESULT WINAPI NoStatStreamImpl_Seek(
1458 IStream* iface,
1459 LARGE_INTEGER dlibMove, /* [in] */
1460 DWORD dwOrigin, /* [in] */
1461 ULARGE_INTEGER* plibNewPosition) /* [out] */
1463 NoStatStreamImpl* const This = impl_from_IStream(iface);
1464 ULARGE_INTEGER newPosition;
1465 switch (dwOrigin)
1467 case STREAM_SEEK_SET:
1468 newPosition.u.HighPart = 0;
1469 newPosition.u.LowPart = 0;
1470 break;
1471 case STREAM_SEEK_CUR:
1472 newPosition = This->currentPosition;
1473 break;
1474 case STREAM_SEEK_END:
1475 newPosition = This->streamSize;
1476 break;
1477 default:
1478 return STG_E_INVALIDFUNCTION;
1480 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
1481 return STG_E_INVALIDFUNCTION;
1482 newPosition.QuadPart += dlibMove.QuadPart;
1483 if (plibNewPosition) *plibNewPosition = newPosition;
1484 This->currentPosition = newPosition;
1485 return S_OK;
1488 static HRESULT WINAPI NoStatStreamImpl_SetSize(
1489 IStream* iface,
1490 ULARGE_INTEGER libNewSize) /* [in] */
1492 NoStatStreamImpl* const This = impl_from_IStream(iface);
1493 HGLOBAL supportHandle;
1494 if (libNewSize.u.HighPart != 0)
1495 return STG_E_INVALIDFUNCTION;
1496 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
1497 return S_OK;
1498 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
1499 if (supportHandle == 0)
1500 return STG_E_MEDIUMFULL;
1501 This->supportHandle = supportHandle;
1502 This->streamSize.u.LowPart = libNewSize.u.LowPart;
1503 return S_OK;
1506 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
1507 IStream* iface,
1508 IStream* pstm, /* [unique][in] */
1509 ULARGE_INTEGER cb, /* [in] */
1510 ULARGE_INTEGER* pcbRead, /* [out] */
1511 ULARGE_INTEGER* pcbWritten) /* [out] */
1513 HRESULT hr = S_OK;
1514 BYTE tmpBuffer[128];
1515 ULONG bytesRead, bytesWritten, copySize;
1516 ULARGE_INTEGER totalBytesRead;
1517 ULARGE_INTEGER totalBytesWritten;
1519 if ( pstm == 0 )
1520 return STG_E_INVALIDPOINTER;
1521 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
1522 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
1524 while ( cb.u.LowPart > 0 )
1526 if ( cb.u.LowPart >= 128 )
1527 copySize = 128;
1528 else
1529 copySize = cb.u.LowPart;
1530 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
1531 totalBytesRead.u.LowPart += bytesRead;
1532 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
1533 totalBytesWritten.u.LowPart += bytesWritten;
1534 if (bytesRead != bytesWritten)
1536 hr = STG_E_MEDIUMFULL;
1537 break;
1539 if (bytesRead!=copySize)
1540 cb.u.LowPart = 0;
1541 else
1542 cb.u.LowPart -= bytesRead;
1544 if (pcbRead)
1546 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
1547 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
1550 if (pcbWritten)
1552 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
1553 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
1555 return hr;
1558 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
1560 return S_OK;
1562 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
1564 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
1565 IStream* iface,
1566 ULARGE_INTEGER libOffset, /* [in] */
1567 ULARGE_INTEGER cb, /* [in] */
1568 DWORD dwLockType) /* [in] */
1570 return S_OK;
1573 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
1574 IStream* iface,
1575 ULARGE_INTEGER libOffset, /* [in] */
1576 ULARGE_INTEGER cb, /* [in] */
1577 DWORD dwLockType) /* [in] */
1579 return S_OK;
1582 static HRESULT WINAPI NoStatStreamImpl_Stat(
1583 IStream* iface,
1584 STATSTG* pstatstg, /* [out] */
1585 DWORD grfStatFlag) /* [in] */
1587 return E_NOTIMPL;
1590 static HRESULT WINAPI NoStatStreamImpl_Clone(
1591 IStream* iface,
1592 IStream** ppstm) /* [out] */
1594 return E_NOTIMPL;
1596 static const IStreamVtbl NoStatStreamImpl_Vtbl;
1599 Build an object that implements IStream, without IStream_Stat capabilities.
1600 Receives a memory handle with data buffer. If memory handle is non-null,
1601 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
1602 In any case the object takes ownership of memory handle and will free it on
1603 object release.
1605 static IStream* NoStatStream_Construct(HGLOBAL hGlobal)
1607 NoStatStreamImpl* newStream;
1609 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
1610 if (newStream!=0)
1612 newStream->IStream_iface.lpVtbl = &NoStatStreamImpl_Vtbl;
1613 newStream->ref = 1;
1614 newStream->supportHandle = hGlobal;
1616 if (!newStream->supportHandle)
1617 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
1618 GMEM_SHARE, 0);
1619 newStream->currentPosition.u.HighPart = 0;
1620 newStream->currentPosition.u.LowPart = 0;
1621 newStream->streamSize.u.HighPart = 0;
1622 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
1624 return &newStream->IStream_iface;
1628 static const IStreamVtbl NoStatStreamImpl_Vtbl =
1630 NoStatStreamImpl_QueryInterface,
1631 NoStatStreamImpl_AddRef,
1632 NoStatStreamImpl_Release,
1633 NoStatStreamImpl_Read,
1634 NoStatStreamImpl_Write,
1635 NoStatStreamImpl_Seek,
1636 NoStatStreamImpl_SetSize,
1637 NoStatStreamImpl_CopyTo,
1638 NoStatStreamImpl_Commit,
1639 NoStatStreamImpl_Revert,
1640 NoStatStreamImpl_LockRegion,
1641 NoStatStreamImpl_UnlockRegion,
1642 NoStatStreamImpl_Stat,
1643 NoStatStreamImpl_Clone