wined3d: Pass a wined3d_device_context to wined3d_cs_emit_blt_sub_resource().
[wine/zf.git] / dlls / oleaut32 / tests / olepicture.c
blob6a5f7ee042882cbe23cdab390a72fbc6f84cc912
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
172 static HBITMAP stock_bm;
174 static HDC create_render_dc( void )
176 HDC dc = CreateCompatibleDC( NULL );
177 BITMAPINFO info = {{sizeof(info.bmiHeader), 100, 100, 1, 32, BI_RGB }};
178 void *bits;
179 HBITMAP dib = CreateDIBSection( NULL, &info, DIB_RGB_COLORS, &bits, NULL, 0 );
181 stock_bm = SelectObject( dc, dib );
182 return dc;
185 static void delete_render_dc( HDC dc )
187 HBITMAP dib = SelectObject( dc, stock_bm );
188 DeleteObject( dib );
189 DeleteDC( dc );
192 typedef struct NoStatStreamImpl
194 IStream IStream_iface;
195 LONG ref;
197 HGLOBAL supportHandle;
198 ULARGE_INTEGER streamSize;
199 ULARGE_INTEGER currentPosition;
200 } NoStatStreamImpl;
202 static IStream* NoStatStream_Construct(HGLOBAL hGlobal);
204 static void
205 test_pic_with_stream(LPSTREAM stream, unsigned int imgsize)
207 IPicture* pic = NULL;
208 HRESULT hres;
209 LPVOID pvObj = NULL;
210 OLE_HANDLE handle, hPal;
211 OLE_XSIZE_HIMETRIC width;
212 OLE_YSIZE_HIMETRIC height;
213 short type;
214 DWORD attr;
215 ULONG res;
217 pvObj = NULL;
218 hres = pOleLoadPicture(stream, imgsize, TRUE, &IID_IPicture, &pvObj);
219 pic = pvObj;
221 ok(hres == S_OK,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres);
222 ok(pic != NULL,"OLP (NULL,..) returns NULL, instead of !NULL\n");
223 if (pic == NULL)
224 return;
226 pvObj = NULL;
227 hres = IPicture_QueryInterface (pic, &IID_IPicture, &pvObj);
229 ok(hres == S_OK,"IPicture_QI does not return S_OK, but 0x%08x\n", hres);
230 ok(pvObj != NULL,"IPicture_QI does return NULL, instead of a ptr\n");
232 IPicture_Release ((IPicture*)pvObj);
234 handle = 0;
235 hres = IPicture_get_Handle (pic, &handle);
236 ok(hres == S_OK,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres);
237 ok(handle != 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
239 if (handle)
241 BITMAP bmp;
242 GetObjectA(UlongToHandle(handle), sizeof(BITMAP), &bmp);
243 todo_wine ok(bmp.bmBits != 0, "not a dib\n");
246 width = 0;
247 hres = IPicture_get_Width (pic, &width);
248 ok(hres == S_OK,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres);
249 ok(width != 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
251 height = 0;
252 hres = IPicture_get_Height (pic, &height);
253 ok(hres == S_OK,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres);
254 ok(height != 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
256 type = 0;
257 hres = IPicture_get_Type (pic, &type);
258 ok(hres == S_OK,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
259 ok(type == PICTYPE_BITMAP, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type, PICTYPE_BITMAP);
261 attr = 0;
262 hres = IPicture_get_Attributes (pic, &attr);
263 ok(hres == S_OK,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres);
264 ok(attr == 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr);
266 hPal = 0;
267 hres = IPicture_get_hPal (pic, &hPal);
268 ok(hres == S_OK,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres);
269 /* a single pixel b/w image has no palette */
270 ok(hPal == 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal);
272 res = IPicture_Release (pic);
273 ok (res == 0, "refcount after release is %d, but should be 0?\n", res);
276 static void
277 test_pic(const unsigned char *imgdata, unsigned int imgsize)
279 LPSTREAM stream;
280 HGLOBAL hglob;
281 LPBYTE data;
282 HRESULT hres;
283 LARGE_INTEGER seekto;
284 ULARGE_INTEGER newpos1;
285 DWORD * header;
286 unsigned int i,j;
288 /* Let the fun begin */
289 hglob = GlobalAlloc (0, imgsize);
290 data = GlobalLock (hglob);
291 memcpy(data, imgdata, imgsize);
292 GlobalUnlock(hglob); data = NULL;
294 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
295 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
297 memset(&seekto,0,sizeof(seekto));
298 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
299 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
300 test_pic_with_stream(stream, imgsize);
302 IStream_Release(stream);
304 /* again with Non Statable and Non Seekable stream */
305 stream = NoStatStream_Construct(hglob);
306 hglob = 0; /* Non-statable impl always deletes on release */
307 test_pic_with_stream(stream, 0);
309 IStream_Release(stream);
310 for (i = 1; i <= 8; i++) {
311 /* more fun!!! */
312 hglob = GlobalAlloc (0, imgsize + i * (2 * sizeof(DWORD)));
313 data = GlobalLock (hglob);
314 header = (DWORD *)data;
316 /* multiple copies of header */
317 memcpy(data,"lt\0\0",4);
318 header[1] = imgsize;
319 for (j = 2; j <= i; j++) {
320 memcpy(&(header[2 * (j - 1)]), header, 2 * sizeof(DWORD));
322 memcpy(data + i * (2 * sizeof(DWORD)), imgdata, imgsize);
323 GlobalUnlock(hglob); data = NULL;
325 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
326 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
328 memset(&seekto,0,sizeof(seekto));
329 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
330 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
331 test_pic_with_stream(stream, imgsize);
333 IStream_Release(stream);
335 /* again with Non Statable and Non Seekable stream */
336 stream = NoStatStream_Construct(hglob);
337 hglob = 0; /* Non-statable impl always deletes on release */
338 test_pic_with_stream(stream, 0);
340 IStream_Release(stream);
344 static void test_empty_image(void) {
345 LPBYTE data;
346 LPSTREAM stream;
347 IPicture* pic = NULL;
348 HRESULT hres;
349 LPVOID pvObj = NULL;
350 HGLOBAL hglob;
351 OLE_HANDLE handle;
352 ULARGE_INTEGER newpos1;
353 LARGE_INTEGER seekto;
354 short type;
355 DWORD attr;
357 /* Empty image. Happens occasionally in VB programs. */
358 hglob = GlobalAlloc (0, 8);
359 data = GlobalLock (hglob);
360 memcpy(data,"lt\0\0",4);
361 ((DWORD*)data)[1] = 0;
362 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
363 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
365 memset(&seekto,0,sizeof(seekto));
366 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
367 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
369 pvObj = NULL;
370 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
371 pic = pvObj;
372 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
373 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
375 hres = IPicture_get_Type (pic, &type);
376 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
377 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
379 attr = 0xdeadbeef;
380 hres = IPicture_get_Attributes (pic, &attr);
381 ok (hres == S_OK,"empty picture get attributes failed with hres 0x%08x\n", hres);
382 ok (attr == 0,"attr is %d, but should be 0\n", attr);
384 hres = IPicture_get_Handle (pic, &handle);
385 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
386 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
387 IPicture_Release (pic);
388 IStream_Release (stream);
391 static void test_empty_image_2(void) {
392 LPBYTE data;
393 LPSTREAM stream;
394 IPicture* pic = NULL;
395 HRESULT hres;
396 LPVOID pvObj = NULL;
397 HGLOBAL hglob;
398 ULARGE_INTEGER newpos1;
399 LARGE_INTEGER seekto;
400 short type;
402 /* Empty image at random stream position. */
403 hglob = GlobalAlloc (0, 200);
404 data = GlobalLock (hglob);
405 data += 42;
406 memcpy(data,"lt\0\0",4);
407 ((DWORD*)data)[1] = 0;
408 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
409 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
411 memset(&seekto,0,sizeof(seekto));
412 seekto.u.LowPart = 42;
413 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
414 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
416 pvObj = NULL;
417 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
418 pic = pvObj;
419 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
420 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
422 hres = IPicture_get_Type (pic, &type);
423 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
424 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
426 IPicture_Release (pic);
427 IStream_Release (stream);
430 static void test_Invoke(void)
432 IPictureDisp *picdisp;
433 HRESULT hr;
434 VARIANTARG vararg, args[10];
435 DISPPARAMS dispparams;
436 VARIANT varresult;
437 IStream *stream;
438 HGLOBAL hglob;
439 void *data;
440 HDC hdc;
441 int i;
443 hglob = GlobalAlloc (0, sizeof(gifimage));
444 data = GlobalLock(hglob);
445 memcpy(data, gifimage, sizeof(gifimage));
446 GlobalUnlock(hglob);
448 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
449 ok_ole_success(hr, "CreateStreamOnHGlobal");
451 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
452 IStream_Release(stream);
453 GlobalFree(hglob);
454 ok_ole_success(hr, "OleLoadPicture");
456 V_VT(&vararg) = VT_BOOL;
457 V_BOOL(&vararg) = VARIANT_FALSE;
458 dispparams.cNamedArgs = 0;
459 dispparams.rgdispidNamedArgs = NULL;
460 dispparams.cArgs = 1;
461 dispparams.rgvarg = &vararg;
462 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
463 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
464 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
465 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
467 dispparams.cArgs = 0;
468 dispparams.rgvarg = NULL;
469 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
470 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
472 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
473 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
475 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
476 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
478 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
479 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
481 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
482 ok_ole_success(hr, "IPictureDisp_Invoke");
483 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
485 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
486 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
488 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
489 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
491 dispparams.cArgs = 1;
492 dispparams.rgvarg = &vararg;
493 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
494 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
496 dispparams.cArgs = 1;
497 dispparams.rgvarg = &vararg;
498 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
499 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
501 /* DISPID_PICT_RENDER */
502 hdc = create_render_dc();
504 for (i = 0; i < ARRAY_SIZE(args); i++)
505 V_VT(&args[i]) = VT_I4;
507 V_I4(&args[0]) = 0;
508 V_I4(&args[1]) = 10;
509 V_I4(&args[2]) = 10;
510 V_I4(&args[3]) = 0;
511 V_I4(&args[4]) = 0;
512 V_I4(&args[5]) = 10;
513 V_I4(&args[6]) = 10;
514 V_I4(&args[7]) = 0;
515 V_I4(&args[8]) = 0;
516 V_I4(&args[9]) = HandleToLong(hdc);
518 dispparams.rgvarg = args;
519 dispparams.rgdispidNamedArgs = NULL;
520 dispparams.cArgs = 10;
521 dispparams.cNamedArgs = 0;
523 V_VT(&varresult) = VT_EMPTY;
524 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
525 ok(hr == S_OK, "got 0x%08x\n", hr);
527 /* Try with one argument set to VT_I2, it'd still work if coerced. */
528 V_VT(&args[3]) = VT_I2;
529 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
530 ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr);
531 V_VT(&args[3]) = VT_I4;
533 /* Wrong argument count */
534 dispparams.cArgs = 9;
535 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
536 ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
538 delete_render_dc(hdc);
539 IPictureDisp_Release(picdisp);
542 static HRESULT create_picture(short type, IPicture **pict)
544 PICTDESC desc;
546 desc.cbSizeofstruct = sizeof(desc);
547 desc.picType = type;
549 switch (type)
551 case PICTYPE_UNINITIALIZED:
552 return OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)pict);
554 case PICTYPE_NONE:
555 break;
557 case PICTYPE_BITMAP:
558 desc.u.bmp.hbitmap = CreateBitmap(1, 1, 1, 1, NULL);
559 desc.u.bmp.hpal = (HPALETTE)0xbeefdead;
560 break;
562 case PICTYPE_ICON:
563 desc.u.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
564 break;
566 case PICTYPE_METAFILE:
568 HDC hdc = CreateMetaFileA(NULL);
569 desc.u.wmf.hmeta = CloseMetaFile(hdc);
570 desc.u.wmf.xExt = 1;
571 desc.u.wmf.yExt = 1;
572 break;
575 case PICTYPE_ENHMETAFILE:
577 HDC hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
578 desc.u.emf.hemf = CloseEnhMetaFile(hdc);
579 break;
582 default:
583 ok(0, "picture type %d is not supported\n", type);
584 return E_NOTIMPL;
587 return OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (void **)pict);
590 static void test_OleCreatePictureIndirect(void)
592 PICTDESC desc;
593 OLE_HANDLE handle;
594 IPicture *pict;
595 HRESULT hr;
596 short type, i;
598 if (0)
600 /* crashes on native */
601 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, NULL);
604 desc.cbSizeofstruct = sizeof(desc);
605 desc.picType = PICTYPE_UNINITIALIZED;
606 pict = (void *)0xdeadbeef;
607 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (void **)&pict);
608 ok(hr == E_UNEXPECTED, "got %#x\n", hr);
609 ok(pict == NULL, "got %p\n", pict);
611 for (i = PICTYPE_UNINITIALIZED; i <= PICTYPE_ENHMETAFILE; i++)
613 hr = create_picture(i, &pict);
614 ok(hr == S_OK, "%d: got %#x\n", i, hr);
616 type = 0xdead;
617 hr = IPicture_get_Type(pict, &type);
618 ok(hr == S_OK, "%d: got %#x\n", i, hr);
619 ok(type == i, "%d: got %d\n", i, type);
621 handle = 0xdeadbeef;
622 hr = IPicture_get_Handle(pict, &handle);
623 ok(hr == S_OK, "%d: got %#x\n", i, hr);
624 if (type == PICTYPE_UNINITIALIZED || type == PICTYPE_NONE)
625 ok(handle == 0, "%d: got %#x\n", i, handle);
626 else
627 ok(handle != 0 && handle != 0xdeadbeef, "%d: got %#x\n", i, handle);
629 handle = 0xdeadbeef;
630 hr = IPicture_get_hPal(pict, &handle);
631 if (type == PICTYPE_BITMAP)
633 ok(hr == S_OK, "%d: got %#x\n", i, hr);
634 ok(handle == 0xbeefdead, "%d: got %#x\n", i, handle);
636 else
638 ok(hr == E_FAIL, "%d: got %#x\n", i, hr);
639 ok(handle == 0xdeadbeef || handle == 0 /* win64 */, "%d: got %#x\n", i, handle);
642 hr = IPicture_set_hPal(pict, HandleToUlong(GetStockObject(DEFAULT_PALETTE)));
643 if (type == PICTYPE_BITMAP)
644 ok(hr == S_OK, "%d: got %#x\n", i, hr);
645 else
646 ok(hr == E_FAIL, "%d: got %#x\n", i, hr);
648 IPicture_Release(pict);
652 static void test_apm(void)
654 OLE_HANDLE handle;
655 LPSTREAM stream;
656 IPicture *pict;
657 HGLOBAL hglob;
658 LPBYTE *data;
659 LONG cxy;
660 BOOL keep;
661 short type;
663 hglob = GlobalAlloc (0, sizeof(apmdata));
664 data = GlobalLock(hglob);
665 memcpy(data, apmdata, sizeof(apmdata));
667 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
668 ole_check(pOleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict));
670 ole_check(IPicture_get_Handle(pict, &handle));
671 ok(handle != 0, "handle is null\n");
673 ole_check(IPicture_get_Type(pict, &type));
674 expect_eq(type, PICTYPE_METAFILE, short, "%d");
676 ole_check(IPicture_get_Height(pict, &cxy));
677 expect_eq(cxy, 1667, LONG, "%d");
679 ole_check(IPicture_get_Width(pict, &cxy));
680 expect_eq(cxy, 1323, LONG, "%d");
682 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
683 todo_wine expect_eq(keep, FALSE, LONG, "%d");
685 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL);
686 IPicture_Release(pict);
687 IStream_Release(stream);
690 static void test_metafile(void)
692 LPSTREAM stream;
693 IPicture *pict;
694 HGLOBAL hglob;
695 LPBYTE *data;
697 hglob = GlobalAlloc (0, sizeof(metafile));
698 data = GlobalLock(hglob);
699 memcpy(data, metafile, sizeof(metafile));
701 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
702 /* Windows does not load simple metafiles */
703 ole_expect(pOleLoadPictureEx(stream, sizeof(metafile), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict), E_FAIL);
705 IStream_Release(stream);
708 static void test_enhmetafile(void)
710 OLE_HANDLE handle;
711 LPSTREAM stream;
712 IPicture *pict;
713 HGLOBAL hglob;
714 LPBYTE *data;
715 LONG cxy;
716 BOOL keep;
717 short type;
719 hglob = GlobalAlloc (0, sizeof(enhmetafile));
720 data = GlobalLock(hglob);
721 memcpy(data, enhmetafile, sizeof(enhmetafile));
723 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
724 ole_check(pOleLoadPictureEx(stream, sizeof(enhmetafile), TRUE, &IID_IPicture, 10, 10, 0, (LPVOID *)&pict));
726 ole_check(IPicture_get_Handle(pict, &handle));
727 ok(handle != 0, "handle is null\n");
729 ole_check(IPicture_get_Type(pict, &type));
730 expect_eq(type, PICTYPE_ENHMETAFILE, short, "%d");
732 ole_check(IPicture_get_Height(pict, &cxy));
733 expect_eq(cxy, -23, LONG, "%d");
735 ole_check(IPicture_get_Width(pict, &cxy));
736 expect_eq(cxy, -25, LONG, "%d");
738 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
739 todo_wine expect_eq(keep, FALSE, LONG, "%d");
741 IPicture_Release(pict);
742 IStream_Release(stream);
745 static HRESULT picture_render(IPicture *iface, HDC hdc, LONG x, LONG y, LONG cx, LONG cy,
746 OLE_XPOS_HIMETRIC xSrc,
747 OLE_YPOS_HIMETRIC ySrc,
748 OLE_XSIZE_HIMETRIC cxSrc,
749 OLE_YSIZE_HIMETRIC cySrc,
750 const RECT *bounds)
752 VARIANT ret, args[10];
753 HRESULT hr, hr_disp;
754 DISPPARAMS params;
755 IDispatch *disp;
756 int i;
758 hr = IPicture_Render(iface, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, bounds);
760 IPicture_QueryInterface(iface, &IID_IDispatch, (void**)&disp);
762 /* This is broken on 64 bits - accepted pointer argument type is still VT_I4 */
763 for (i = 0; i < ARRAY_SIZE(args); i++)
764 V_VT(&args[i]) = VT_I4;
766 /* pack arguments and call */
767 V_INT_PTR(&args[0]) = (INT_PTR)bounds;
768 V_I4(&args[1]) = cySrc;
769 V_I4(&args[2]) = cxSrc;
770 V_I4(&args[3]) = ySrc;
771 V_I4(&args[4]) = xSrc;
772 V_I4(&args[5]) = cy;
773 V_I4(&args[6]) = cx;
774 V_I4(&args[7]) = y;
775 V_I4(&args[8]) = x;
776 V_I4(&args[9]) = HandleToLong(hdc);
778 params.rgvarg = args;
779 params.rgdispidNamedArgs = NULL;
780 params.cArgs = 10;
781 params.cNamedArgs = 0;
783 V_VT(&ret) = VT_EMPTY;
784 hr_disp = IDispatch_Invoke(disp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD,
785 &params, &ret, NULL, NULL);
786 ok(hr == hr_disp, "DISPID_PICT_RENDER returned wrong code, 0x%08x, expected 0x%08x\n",
787 hr_disp, hr);
789 IDispatch_Release(disp);
791 return hr;
794 static void test_Render(void)
796 IPicture *pic;
797 HRESULT hres;
798 short type;
799 PICTDESC desc;
800 OLE_XSIZE_HIMETRIC pWidth;
801 OLE_YSIZE_HIMETRIC pHeight;
802 COLORREF result, expected;
803 HDC hdc = create_render_dc();
805 /* test IPicture::Render return code on uninitialized picture */
806 hres = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)&pic);
807 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres);
808 hres = IPicture_get_Type(pic, &type);
809 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
810 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
811 /* zero dimensions */
812 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
813 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
814 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
815 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
816 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
817 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
818 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
819 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
820 hres = picture_render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
821 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
822 hres = picture_render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
823 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
824 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
825 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
826 /* nonzero dimensions, PICTYPE_UNINITIALIZED */
827 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL);
828 ole_expect(hres, S_OK);
829 IPicture_Release(pic);
831 desc.cbSizeofstruct = sizeof(PICTDESC);
832 desc.picType = PICTYPE_ICON;
833 desc.u.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
834 if(!desc.u.icon.hicon){
835 win_skip("LoadIcon failed. Skipping...\n");
836 delete_render_dc(hdc);
837 return;
840 hres = OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (void **)&pic);
841 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres);
842 /* zero dimensions, PICTYPE_ICON */
843 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
844 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
845 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
846 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
847 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
848 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
849 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
850 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
851 hres = picture_render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
852 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
853 hres = picture_render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
854 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
855 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
856 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
858 /* Check if target size and position is respected */
859 IPicture_get_Width(pic, &pWidth);
860 IPicture_get_Height(pic, &pHeight);
862 SetPixelV(hdc, 0, 0, 0x00223344);
863 SetPixelV(hdc, 5, 5, 0x00223344);
864 SetPixelV(hdc, 10, 10, 0x00223344);
865 expected = GetPixel(hdc, 0, 0);
867 hres = picture_render(pic, hdc, 1, 1, 9, 9, 0, pHeight, pWidth, -pHeight, NULL);
868 ole_expect(hres, S_OK);
870 if(hres != S_OK) goto done;
872 /* Evaluate the rendered Icon */
873 result = GetPixel(hdc, 0, 0);
874 ok(result == expected,
875 "Color at 0,0 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
876 result = GetPixel(hdc, 5, 5);
877 ok(result != expected,
878 "Color at 5,5 should have changed, but still was 0x%06X\n", expected);
879 result = GetPixel(hdc, 10, 10);
880 ok(result == expected,
881 "Color at 10,10 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
883 done:
884 IPicture_Release(pic);
885 delete_render_dc(hdc);
888 static void test_get_Attributes(void)
890 IPicture *pic;
891 HRESULT hres;
892 short type;
893 DWORD attr;
895 hres = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)&pic);
896 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres);
897 hres = IPicture_get_Type(pic, &type);
898 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
899 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
901 hres = IPicture_get_Attributes(pic, NULL);
902 ole_expect(hres, E_POINTER);
904 attr = 0xdeadbeef;
905 hres = IPicture_get_Attributes(pic, &attr);
906 ole_expect(hres, S_OK);
907 ok(attr == 0, "IPicture_get_Attributes does not reset attr to zero, got %d\n", attr);
909 IPicture_Release(pic);
912 static void test_get_Handle(void)
914 IPicture *pic;
915 HRESULT hres;
917 hres = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)&pic);
918 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres);
919 hres = IPicture_get_Handle(pic, NULL);
920 ole_expect(hres, E_POINTER);
922 IPicture_Release(pic);
925 static void test_get_Type(void)
927 IPicture *pic;
928 HRESULT hres;
930 hres = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)&pic);
931 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres);
933 hres = IPicture_get_Type(pic, NULL);
934 ole_expect(hres, E_POINTER);
936 IPicture_Release(pic);
939 static void test_OleLoadPicturePath(void)
941 static WCHAR emptyW[] = {0};
943 IPicture *pic;
944 HRESULT hres;
945 int i;
946 char temp_path[MAX_PATH];
947 char temp_file[MAX_PATH];
948 WCHAR temp_fileW[MAX_PATH + 5] = {'f','i','l','e',':','/','/','/'};
949 HANDLE file;
950 DWORD size;
951 WCHAR *ptr;
953 const struct
955 LPOLESTR szURLorPath;
956 REFIID riid;
957 IPicture **pic;
958 } invalid_parameters[] =
960 {NULL, NULL, NULL},
961 {NULL, NULL, &pic},
962 {NULL, &IID_IPicture, NULL},
963 {NULL, &IID_IPicture, &pic},
964 {emptyW, NULL, NULL},
965 {emptyW, &IID_IPicture, NULL},
968 for (i = 0; i < ARRAY_SIZE(invalid_parameters); i++)
970 pic = (IPicture *)0xdeadbeef;
971 hres = OleLoadPicturePath(invalid_parameters[i].szURLorPath, NULL, 0, 0,
972 invalid_parameters[i].riid,
973 (void **)invalid_parameters[i].pic);
974 ok(hres == E_INVALIDARG,
975 "[%d] Expected OleLoadPicturePath to return E_INVALIDARG, got 0x%08x\n", i, hres);
976 ok(pic == (IPicture *)0xdeadbeef,
977 "[%d] Expected output pointer to be 0xdeadbeef, got %p\n", i, pic);
980 pic = (IPicture *)0xdeadbeef;
981 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, NULL, (void **)&pic);
982 todo_wine
983 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
984 broken(hres == E_UNEXPECTED) || /* NT4 */
985 broken(hres == E_OUTOFMEMORY), /* Win2k/Win2k3 */
986 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
987 ok(pic == NULL,
988 "Expected the output interface pointer to be NULL, got %p\n", pic);
990 pic = (IPicture *)0xdeadbeef;
991 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
992 todo_wine
993 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
994 broken(hres == E_UNEXPECTED) || /* NT4 */
995 broken(hres == E_OUTOFMEMORY), /* Win2k/Win2k3 */
996 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
997 ok(pic == NULL,
998 "Expected the output interface pointer to be NULL, got %p\n", pic);
1000 /* Create a local temporary image file for testing. */
1001 GetTempPathA(sizeof(temp_path), temp_path);
1002 GetTempFileNameA(temp_path, "bmp", 0, temp_file);
1003 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1004 FILE_ATTRIBUTE_NORMAL, NULL);
1005 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
1006 CloseHandle(file);
1008 MultiByteToWideChar(CP_ACP, 0, temp_file, -1, temp_fileW + 8, ARRAY_SIZE(temp_fileW) - 8);
1010 /* Try a normal DOS path. */
1011 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
1012 ok(hres == S_OK ||
1013 broken(hres == E_UNEXPECTED), /* NT4 */
1014 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
1015 if (pic)
1016 IPicture_Release(pic);
1018 /* Try a DOS path with tacked on "file:". */
1019 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
1020 ok(hres == S_OK ||
1021 broken(hres == E_UNEXPECTED), /* NT4 */
1022 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
1023 if (pic)
1024 IPicture_Release(pic);
1026 DeleteFileA(temp_file);
1028 /* Try with a nonexistent file. */
1029 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
1030 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
1031 broken(hres == E_UNEXPECTED) || /* NT4 */
1032 broken(hres == E_FAIL), /*Win2k */
1033 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
1035 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
1036 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
1037 broken(hres == E_UNEXPECTED) || /* NT4 */
1038 broken(hres == E_FAIL), /* Win2k */
1039 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
1041 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1042 FILE_ATTRIBUTE_NORMAL, NULL);
1043 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
1044 CloseHandle(file);
1046 /* Try a "file:" URL with slash separators. */
1047 ptr = temp_fileW + 8;
1048 while (*ptr)
1050 if (*ptr == '\\')
1051 *ptr = '/';
1052 ptr++;
1055 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
1056 ok(hres == S_OK ||
1057 broken(hres == E_UNEXPECTED), /* NT4 */
1058 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
1059 if (pic)
1060 IPicture_Release(pic);
1062 DeleteFileA(temp_file);
1064 /* Try with a nonexistent file. */
1065 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
1066 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
1067 broken(hres == E_UNEXPECTED) || /* NT4 */
1068 broken(hres == E_FAIL), /* Win2k */
1069 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
1072 static void test_himetric(void)
1074 static const BYTE bmp_bits[1024];
1075 OLE_XSIZE_HIMETRIC cx;
1076 OLE_YSIZE_HIMETRIC cy;
1077 IPicture *pic;
1078 PICTDESC desc;
1079 HBITMAP bmp;
1080 HRESULT hr;
1081 HICON icon;
1082 HDC hdc;
1083 INT d;
1085 desc.cbSizeofstruct = sizeof(desc);
1086 desc.picType = PICTYPE_BITMAP;
1087 desc.u.bmp.hpal = NULL;
1089 hdc = CreateCompatibleDC(0);
1091 bmp = CreateBitmap(1.9 * GetDeviceCaps(hdc, LOGPIXELSX),
1092 1.9 * GetDeviceCaps(hdc, LOGPIXELSY), 1, 1, NULL);
1094 desc.u.bmp.hbitmap = bmp;
1096 /* size in himetric units reported rounded up to next integer value */
1097 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1098 ok(hr == S_OK, "got 0x%08x\n", hr);
1100 cx = 0;
1101 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSX)), 2540, GetDeviceCaps(hdc, LOGPIXELSX));
1102 hr = IPicture_get_Width(pic, &cx);
1103 ok(hr == S_OK, "got 0x%08x\n", hr);
1104 ok(cx == d, "got %d, expected %d\n", cx, d);
1106 cy = 0;
1107 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSY)), 2540, GetDeviceCaps(hdc, LOGPIXELSY));
1108 hr = IPicture_get_Height(pic, &cy);
1109 ok(hr == S_OK, "got 0x%08x\n", hr);
1110 ok(cy == d, "got %d, expected %d\n", cy, d);
1112 DeleteObject(bmp);
1113 IPicture_Release(pic);
1115 /* same thing with icon */
1116 icon = CreateIcon(NULL, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
1117 1, 1, bmp_bits, bmp_bits);
1118 ok(icon != NULL, "failed to create icon\n");
1120 desc.picType = PICTYPE_ICON;
1121 desc.u.icon.hicon = icon;
1123 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1124 ok(hr == S_OK, "got 0x%08x\n", hr);
1126 cx = 0;
1127 d = MulDiv(GetSystemMetrics(SM_CXICON), 2540, GetDeviceCaps(hdc, LOGPIXELSX));
1128 hr = IPicture_get_Width(pic, &cx);
1129 ok(hr == S_OK, "got 0x%08x\n", hr);
1130 ok(cx == d, "got %d, expected %d\n", cx, d);
1132 cy = 0;
1133 d = MulDiv(GetSystemMetrics(SM_CYICON), 2540, GetDeviceCaps(hdc, LOGPIXELSY));
1134 hr = IPicture_get_Height(pic, &cy);
1135 ok(hr == S_OK, "got 0x%08x\n", hr);
1136 ok(cy == d, "got %d, expected %d\n", cy, d);
1138 IPicture_Release(pic);
1139 DestroyIcon(icon);
1141 DeleteDC(hdc);
1144 static void test_load_save_bmp(void)
1146 IPicture *pic;
1147 PICTDESC desc;
1148 short type;
1149 OLE_HANDLE handle;
1150 HGLOBAL hmem;
1151 DWORD *mem;
1152 IPersistStream *src_stream;
1153 IStream *dst_stream;
1154 LARGE_INTEGER offset;
1155 HRESULT hr;
1156 LONG size;
1158 desc.cbSizeofstruct = sizeof(desc);
1159 desc.picType = PICTYPE_BITMAP;
1160 desc.u.bmp.hpal = 0;
1161 desc.u.bmp.hbitmap = CreateBitmap(1, 1, 1, 1, NULL);
1162 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1163 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1165 type = -1;
1166 hr = IPicture_get_Type(pic, &type);
1167 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1168 ok(type == PICTYPE_BITMAP,"expected picture type PICTYPE_BITMAP, got %d\n", type);
1170 hr = IPicture_get_Handle(pic, &handle);
1171 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1172 ok(IntToPtr(handle) == desc.u.bmp.hbitmap, "get_Handle returned wrong handle %#x\n", handle);
1174 hmem = GlobalAlloc(GMEM_ZEROINIT, 4096);
1175 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1176 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr);
1178 size = -1;
1179 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size);
1180 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1181 todo_wine
1182 ok(size == 66, "expected 66, got %d\n", size);
1183 mem = GlobalLock(hmem);
1184 todo_wine
1185 ok(!memcmp(&mem[0], "BM", 2), "got wrong bmp header %04x\n", mem[0]);
1186 GlobalUnlock(hmem);
1188 size = -1;
1189 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size);
1190 todo_wine
1191 ok(hr == E_FAIL, "expected E_FAIL, got %#x\n", hr);
1192 todo_wine
1193 ok(size == -1, "expected -1, got %d\n", size);
1195 offset.QuadPart = 0;
1196 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL);
1197 ok(hr == S_OK, "IStream_Seek %#x\n", hr);
1199 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1200 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1202 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1203 ok(hr == S_OK, "Save error %#x\n", hr);
1205 IPersistStream_Release(src_stream);
1206 IStream_Release(dst_stream);
1208 mem = GlobalLock(hmem);
1209 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1210 ok(mem[1] == 66, "expected stream size 66, got %u\n", mem[1]);
1211 ok(!memcmp(&mem[2], "BM", 2), "got wrong bmp header %04x\n", mem[2]);
1213 GlobalUnlock(hmem);
1214 GlobalFree(hmem);
1216 DeleteObject(desc.u.bmp.hbitmap);
1217 IPicture_Release(pic);
1220 static void test_load_save_icon(void)
1222 IPicture *pic;
1223 PICTDESC desc;
1224 short type;
1225 OLE_HANDLE handle;
1226 HGLOBAL hmem;
1227 DWORD *mem;
1228 IPersistStream *src_stream;
1229 IStream *dst_stream;
1230 LARGE_INTEGER offset;
1231 HRESULT hr;
1232 LONG size;
1234 desc.cbSizeofstruct = sizeof(desc);
1235 desc.picType = PICTYPE_ICON;
1236 desc.u.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
1237 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1238 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1240 type = -1;
1241 hr = IPicture_get_Type(pic, &type);
1242 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1243 ok(type == PICTYPE_ICON,"expected picture type PICTYPE_ICON, got %d\n", type);
1245 hr = IPicture_get_Handle(pic, &handle);
1246 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1247 ok(IntToPtr(handle) == desc.u.icon.hicon, "get_Handle returned wrong handle %#x\n", handle);
1249 hmem = GlobalAlloc(GMEM_ZEROINIT, 8192);
1250 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1251 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
1253 size = -1;
1254 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size);
1255 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1256 todo_wine
1257 ok(size == 766, "expected 766, got %d\n", size);
1258 mem = GlobalLock(hmem);
1259 todo_wine
1260 ok(mem[0] == 0x00010000, "got wrong icon header %04x\n", mem[0]);
1261 GlobalUnlock(hmem);
1263 size = -1;
1264 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size);
1265 todo_wine
1266 ok(hr == E_FAIL, "expected E_FAIL, got %#x\n", hr);
1267 todo_wine
1268 ok(size == -1, "expected -1, got %d\n", size);
1270 offset.QuadPart = 0;
1271 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL);
1272 ok(hr == S_OK, "IStream_Seek %#x\n", hr);
1274 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1275 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1277 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1278 ok(hr == S_OK, "Saveerror %#x\n", hr);
1280 IPersistStream_Release(src_stream);
1281 IStream_Release(dst_stream);
1283 mem = GlobalLock(hmem);
1284 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1285 todo_wine
1286 ok(mem[1] == 766, "expected stream size 766, got %u\n", mem[1]);
1287 ok(mem[2] == 0x00010000, "got wrong icon header %04x\n", mem[2]);
1289 GlobalUnlock(hmem);
1290 GlobalFree(hmem);
1292 DestroyIcon(desc.u.icon.hicon);
1293 IPicture_Release(pic);
1296 static void test_load_save_empty_picture(void)
1298 IPicture *pic;
1299 PICTDESC desc;
1300 short type;
1301 OLE_HANDLE handle;
1302 HGLOBAL hmem;
1303 DWORD *mem;
1304 IPersistStream *src_stream;
1305 IStream *dst_stream, *stream;
1306 LARGE_INTEGER offset;
1307 HRESULT hr;
1308 LONG size;
1310 memset(&pic, 0, sizeof(pic));
1311 desc.cbSizeofstruct = sizeof(desc);
1312 desc.picType = PICTYPE_NONE;
1313 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void **)&pic);
1314 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1316 type = -1;
1317 hr = IPicture_get_Type(pic, &type);
1318 ok(hr == S_OK, "get_Type error %#x\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 hmem = GlobalAlloc(GMEM_ZEROINIT, 4096);
1327 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1328 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr);
1330 size = -1;
1331 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size);
1332 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1333 todo_wine
1334 ok(size == -1, "expected -1, got %d\n", size);
1336 size = -1;
1337 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size);
1338 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1339 todo_wine
1340 ok(size == -1, "expected -1, got %d\n", size);
1342 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1343 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1345 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1346 ok(hr == S_OK, "Save error %#x\n", hr);
1348 mem = GlobalLock(hmem);
1349 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1350 ok(mem[1] == 0, "expected stream size 0, got %u\n", mem[1]);
1351 GlobalUnlock(hmem);
1353 IPersistStream_Release(src_stream);
1354 IPicture_Release(pic);
1356 /* first with statable and seekable stream */
1357 offset.QuadPart = 0;
1358 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL);
1359 ok(hr == S_OK, "IStream_Seek %#x\n", hr);
1361 pic = NULL;
1362 hr = pOleLoadPicture(dst_stream, 0, FALSE, &IID_IPicture, (void **)&pic);
1363 ok(hr == S_OK, "OleLoadPicture error %#x\n", hr);
1364 ok(pic != NULL,"picture should not be not NULL\n");
1365 if (pic != NULL)
1367 type = -1;
1368 hr = IPicture_get_Type(pic, &type);
1369 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1370 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
1372 handle = (OLE_HANDLE)0xdeadbeef;
1373 hr = IPicture_get_Handle(pic, &handle);
1374 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1375 ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
1377 IPicture_Release(pic);
1379 IStream_Release(dst_stream);
1381 /* again with non-statable and non-seekable stream */
1382 stream = NoStatStream_Construct(hmem);
1383 ok(stream != NULL, "failed to create empty image stream\n");
1385 pic = NULL;
1386 hr = pOleLoadPicture(stream, 0, FALSE, &IID_IPicture, (void **)&pic);
1387 ok(hr == S_OK, "OleLoadPicture error %#x\n", hr);
1388 ok(pic != NULL,"picture should not be not NULL\n");
1389 if (pic != NULL)
1391 type = -1;
1392 hr = IPicture_get_Type(pic, &type);
1393 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1394 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
1396 handle = (OLE_HANDLE)0xdeadbeef;
1397 hr = IPicture_get_Handle(pic, &handle);
1398 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1399 ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
1401 IPicture_Release(pic);
1403 /* Non-statable impl always deletes on release */
1404 IStream_Release(stream);
1407 START_TEST(olepicture)
1409 hOleaut32 = GetModuleHandleA("oleaut32.dll");
1410 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
1411 pOleLoadPictureEx = (void*)GetProcAddress(hOleaut32, "OleLoadPictureEx");
1412 if (!pOleLoadPicture)
1414 win_skip("OleLoadPicture is not available\n");
1415 return;
1418 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
1419 test_pic(gifimage, sizeof(gifimage));
1420 test_pic(jpgimage, sizeof(jpgimage));
1421 test_pic(bmpimage, sizeof(bmpimage));
1422 test_pic(gif4pixel, sizeof(gif4pixel));
1423 /* FIXME: No PNG support in Windows... */
1424 if (0) test_pic(pngimage, sizeof(pngimage));
1425 test_empty_image();
1426 test_empty_image_2();
1427 if (pOleLoadPictureEx)
1429 test_apm();
1430 test_metafile();
1431 test_enhmetafile();
1433 else
1434 win_skip("OleLoadPictureEx is not available\n");
1435 test_Invoke();
1436 test_OleCreatePictureIndirect();
1437 test_Render();
1438 test_get_Attributes();
1439 test_get_Handle();
1440 test_get_Type();
1441 test_OleLoadPicturePath();
1442 test_himetric();
1443 test_load_save_bmp();
1444 test_load_save_icon();
1445 test_load_save_empty_picture();
1449 /* Helper functions only ... */
1452 static inline NoStatStreamImpl *impl_from_IStream(IStream *iface)
1454 return CONTAINING_RECORD(iface, NoStatStreamImpl, IStream_iface);
1457 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
1459 GlobalFree(This->supportHandle);
1460 This->supportHandle=0;
1461 HeapFree(GetProcessHeap(), 0, This);
1464 static ULONG WINAPI NoStatStreamImpl_AddRef(
1465 IStream* iface)
1467 NoStatStreamImpl* const This = impl_from_IStream(iface);
1468 return InterlockedIncrement(&This->ref);
1471 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
1472 IStream* iface,
1473 REFIID riid, /* [in] */
1474 void** ppvObject) /* [iid_is][out] */
1476 NoStatStreamImpl* const This = impl_from_IStream(iface);
1477 if (ppvObject==0) return E_INVALIDARG;
1478 *ppvObject = 0;
1480 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IStream, riid))
1481 *ppvObject = &This->IStream_iface;
1483 if ((*ppvObject)==0)
1484 return E_NOINTERFACE;
1485 NoStatStreamImpl_AddRef(iface);
1486 return S_OK;
1489 static ULONG WINAPI NoStatStreamImpl_Release(
1490 IStream* iface)
1492 NoStatStreamImpl* const This = impl_from_IStream(iface);
1493 ULONG newRef = InterlockedDecrement(&This->ref);
1494 if (newRef==0)
1495 NoStatStreamImpl_Destroy(This);
1496 return newRef;
1499 static HRESULT WINAPI NoStatStreamImpl_Read(
1500 IStream* iface,
1501 void* pv, /* [length_is][size_is][out] */
1502 ULONG cb, /* [in] */
1503 ULONG* pcbRead) /* [out] */
1505 NoStatStreamImpl* const This = impl_from_IStream(iface);
1506 void* supportBuffer;
1507 ULONG bytesReadBuffer;
1508 ULONG bytesToReadFromBuffer;
1510 if (pcbRead==0)
1511 pcbRead = &bytesReadBuffer;
1512 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
1513 supportBuffer = GlobalLock(This->supportHandle);
1514 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
1515 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
1516 *pcbRead = bytesToReadFromBuffer;
1517 GlobalUnlock(This->supportHandle);
1518 if(*pcbRead == cb)
1519 return S_OK;
1520 return S_FALSE;
1523 static HRESULT WINAPI NoStatStreamImpl_Write(
1524 IStream* iface,
1525 const void* pv, /* [size_is][in] */
1526 ULONG cb, /* [in] */
1527 ULONG* pcbWritten) /* [out] */
1529 NoStatStreamImpl* const This = impl_from_IStream(iface);
1530 void* supportBuffer;
1531 ULARGE_INTEGER newSize;
1532 ULONG bytesWritten = 0;
1534 if (pcbWritten == 0)
1535 pcbWritten = &bytesWritten;
1536 if (cb == 0)
1537 return S_OK;
1538 newSize.u.HighPart = 0;
1539 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
1540 if (newSize.u.LowPart > This->streamSize.u.LowPart)
1541 IStream_SetSize(iface, newSize);
1543 supportBuffer = GlobalLock(This->supportHandle);
1544 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
1545 This->currentPosition.u.LowPart+=cb;
1546 *pcbWritten = cb;
1547 GlobalUnlock(This->supportHandle);
1548 return S_OK;
1551 static HRESULT WINAPI NoStatStreamImpl_Seek(
1552 IStream* iface,
1553 LARGE_INTEGER dlibMove, /* [in] */
1554 DWORD dwOrigin, /* [in] */
1555 ULARGE_INTEGER* plibNewPosition) /* [out] */
1557 NoStatStreamImpl* const This = impl_from_IStream(iface);
1558 ULARGE_INTEGER newPosition;
1559 switch (dwOrigin)
1561 case STREAM_SEEK_SET:
1562 newPosition.u.HighPart = 0;
1563 newPosition.u.LowPart = 0;
1564 break;
1565 case STREAM_SEEK_CUR:
1566 newPosition = This->currentPosition;
1567 break;
1568 case STREAM_SEEK_END:
1569 newPosition = This->streamSize;
1570 break;
1571 default:
1572 return STG_E_INVALIDFUNCTION;
1574 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
1575 return STG_E_INVALIDFUNCTION;
1576 newPosition.QuadPart += dlibMove.QuadPart;
1577 if (plibNewPosition) *plibNewPosition = newPosition;
1578 This->currentPosition = newPosition;
1579 return S_OK;
1582 static HRESULT WINAPI NoStatStreamImpl_SetSize(
1583 IStream* iface,
1584 ULARGE_INTEGER libNewSize) /* [in] */
1586 NoStatStreamImpl* const This = impl_from_IStream(iface);
1587 HGLOBAL supportHandle;
1588 if (libNewSize.u.HighPart != 0)
1589 return STG_E_INVALIDFUNCTION;
1590 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
1591 return S_OK;
1592 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
1593 if (supportHandle == 0)
1594 return STG_E_MEDIUMFULL;
1595 This->supportHandle = supportHandle;
1596 This->streamSize.u.LowPart = libNewSize.u.LowPart;
1597 return S_OK;
1600 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
1601 IStream* iface,
1602 IStream* pstm, /* [unique][in] */
1603 ULARGE_INTEGER cb, /* [in] */
1604 ULARGE_INTEGER* pcbRead, /* [out] */
1605 ULARGE_INTEGER* pcbWritten) /* [out] */
1607 HRESULT hr = S_OK;
1608 BYTE tmpBuffer[128];
1609 ULONG bytesRead, bytesWritten, copySize;
1610 ULARGE_INTEGER totalBytesRead;
1611 ULARGE_INTEGER totalBytesWritten;
1613 if ( pstm == 0 )
1614 return STG_E_INVALIDPOINTER;
1615 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
1616 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
1618 while ( cb.u.LowPart > 0 )
1620 if ( cb.u.LowPart >= 128 )
1621 copySize = 128;
1622 else
1623 copySize = cb.u.LowPart;
1624 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
1625 totalBytesRead.u.LowPart += bytesRead;
1626 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
1627 totalBytesWritten.u.LowPart += bytesWritten;
1628 if (bytesRead != bytesWritten)
1630 hr = STG_E_MEDIUMFULL;
1631 break;
1633 if (bytesRead!=copySize)
1634 cb.u.LowPart = 0;
1635 else
1636 cb.u.LowPart -= bytesRead;
1638 if (pcbRead)
1640 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
1641 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
1644 if (pcbWritten)
1646 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
1647 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
1649 return hr;
1652 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
1654 return S_OK;
1656 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
1658 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
1659 IStream* iface,
1660 ULARGE_INTEGER libOffset, /* [in] */
1661 ULARGE_INTEGER cb, /* [in] */
1662 DWORD dwLockType) /* [in] */
1664 return S_OK;
1667 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
1668 IStream* iface,
1669 ULARGE_INTEGER libOffset, /* [in] */
1670 ULARGE_INTEGER cb, /* [in] */
1671 DWORD dwLockType) /* [in] */
1673 return S_OK;
1676 static HRESULT WINAPI NoStatStreamImpl_Stat(
1677 IStream* iface,
1678 STATSTG* pstatstg, /* [out] */
1679 DWORD grfStatFlag) /* [in] */
1681 return E_NOTIMPL;
1684 static HRESULT WINAPI NoStatStreamImpl_Clone(
1685 IStream* iface,
1686 IStream** ppstm) /* [out] */
1688 return E_NOTIMPL;
1690 static const IStreamVtbl NoStatStreamImpl_Vtbl;
1693 Build an object that implements IStream, without IStream_Stat capabilities.
1694 Receives a memory handle with data buffer. If memory handle is non-null,
1695 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
1696 In any case the object takes ownership of memory handle and will free it on
1697 object release.
1699 static IStream* NoStatStream_Construct(HGLOBAL hGlobal)
1701 NoStatStreamImpl* newStream;
1703 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
1704 if (newStream!=0)
1706 newStream->IStream_iface.lpVtbl = &NoStatStreamImpl_Vtbl;
1707 newStream->ref = 1;
1708 newStream->supportHandle = hGlobal;
1710 if (!newStream->supportHandle)
1711 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
1712 GMEM_SHARE, 0);
1713 newStream->currentPosition.u.HighPart = 0;
1714 newStream->currentPosition.u.LowPart = 0;
1715 newStream->streamSize.u.HighPart = 0;
1716 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
1718 return &newStream->IStream_iface;
1722 static const IStreamVtbl NoStatStreamImpl_Vtbl =
1724 NoStatStreamImpl_QueryInterface,
1725 NoStatStreamImpl_AddRef,
1726 NoStatStreamImpl_Release,
1727 NoStatStreamImpl_Read,
1728 NoStatStreamImpl_Write,
1729 NoStatStreamImpl_Seek,
1730 NoStatStreamImpl_SetSize,
1731 NoStatStreamImpl_CopyTo,
1732 NoStatStreamImpl_Commit,
1733 NoStatStreamImpl_Revert,
1734 NoStatStreamImpl_LockRegion,
1735 NoStatStreamImpl_UnlockRegion,
1736 NoStatStreamImpl_Stat,
1737 NoStatStreamImpl_Clone