oleaut32/tests: Correctly return interface pointer.
[wine.git] / dlls / oleaut32 / tests / olepicture.c
blob4a81e2e9b25466c275720e08e0991a0e1a29c994
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 < sizeof(args)/sizeof(args[0]); 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 void test_OleCreatePictureIndirect(void)
544 OLE_HANDLE handle;
545 IPicture *pict;
546 HRESULT hr;
547 short type;
549 if (0)
551 /* crashes on native */
552 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, NULL);
555 hr = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict);
556 ok(hr == S_OK, "hr %08x\n", hr);
558 type = PICTYPE_NONE;
559 hr = IPicture_get_Type(pict, &type);
560 ok(hr == S_OK, "hr %08x\n", hr);
561 ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type);
563 handle = 0xdeadbeef;
564 hr = IPicture_get_Handle(pict, &handle);
565 ok(hr == S_OK, "hr %08x\n", hr);
566 ok(handle == 0, "handle %08x\n", handle);
568 IPicture_Release(pict);
571 static void test_apm(void)
573 OLE_HANDLE handle;
574 LPSTREAM stream;
575 IPicture *pict;
576 HGLOBAL hglob;
577 LPBYTE *data;
578 LONG cxy;
579 BOOL keep;
580 short type;
582 hglob = GlobalAlloc (0, sizeof(apmdata));
583 data = GlobalLock(hglob);
584 memcpy(data, apmdata, sizeof(apmdata));
586 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
587 ole_check(pOleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict));
589 ole_check(IPicture_get_Handle(pict, &handle));
590 ok(handle != 0, "handle is null\n");
592 ole_check(IPicture_get_Type(pict, &type));
593 expect_eq(type, PICTYPE_METAFILE, short, "%d");
595 ole_check(IPicture_get_Height(pict, &cxy));
596 expect_eq(cxy, 1667, LONG, "%d");
598 ole_check(IPicture_get_Width(pict, &cxy));
599 expect_eq(cxy, 1323, LONG, "%d");
601 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
602 todo_wine expect_eq(keep, FALSE, LONG, "%d");
604 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL);
605 IPicture_Release(pict);
606 IStream_Release(stream);
609 static void test_metafile(void)
611 LPSTREAM stream;
612 IPicture *pict;
613 HGLOBAL hglob;
614 LPBYTE *data;
616 hglob = GlobalAlloc (0, sizeof(metafile));
617 data = GlobalLock(hglob);
618 memcpy(data, metafile, sizeof(metafile));
620 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
621 /* Windows does not load simple metafiles */
622 ole_expect(pOleLoadPictureEx(stream, sizeof(metafile), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict), E_FAIL);
624 IStream_Release(stream);
627 static void test_enhmetafile(void)
629 OLE_HANDLE handle;
630 LPSTREAM stream;
631 IPicture *pict;
632 HGLOBAL hglob;
633 LPBYTE *data;
634 LONG cxy;
635 BOOL keep;
636 short type;
638 hglob = GlobalAlloc (0, sizeof(enhmetafile));
639 data = GlobalLock(hglob);
640 memcpy(data, enhmetafile, sizeof(enhmetafile));
642 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
643 ole_check(pOleLoadPictureEx(stream, sizeof(enhmetafile), TRUE, &IID_IPicture, 10, 10, 0, (LPVOID *)&pict));
645 ole_check(IPicture_get_Handle(pict, &handle));
646 ok(handle != 0, "handle is null\n");
648 ole_check(IPicture_get_Type(pict, &type));
649 expect_eq(type, PICTYPE_ENHMETAFILE, short, "%d");
651 ole_check(IPicture_get_Height(pict, &cxy));
652 expect_eq(cxy, -23, LONG, "%d");
654 ole_check(IPicture_get_Width(pict, &cxy));
655 expect_eq(cxy, -25, LONG, "%d");
657 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
658 todo_wine expect_eq(keep, FALSE, LONG, "%d");
660 IPicture_Release(pict);
661 IStream_Release(stream);
664 static HRESULT picture_render(IPicture *iface, HDC hdc, LONG x, LONG y, LONG cx, LONG cy,
665 OLE_XPOS_HIMETRIC xSrc,
666 OLE_YPOS_HIMETRIC ySrc,
667 OLE_XSIZE_HIMETRIC cxSrc,
668 OLE_YSIZE_HIMETRIC cySrc,
669 const RECT *bounds)
671 VARIANT ret, args[10];
672 HRESULT hr, hr_disp;
673 DISPPARAMS params;
674 IDispatch *disp;
675 int i;
677 hr = IPicture_Render(iface, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, bounds);
679 IPicture_QueryInterface(iface, &IID_IDispatch, (void**)&disp);
681 /* This is broken on 64 bits - accepted pointer argument type is still VT_I4 */
682 for (i = 0; i < sizeof(args)/sizeof(args[0]); i++)
683 V_VT(&args[i]) = VT_I4;
685 /* pack arguments and call */
686 V_INT_PTR(&args[0]) = (INT_PTR)bounds;
687 V_I4(&args[1]) = cySrc;
688 V_I4(&args[2]) = cxSrc;
689 V_I4(&args[3]) = ySrc;
690 V_I4(&args[4]) = xSrc;
691 V_I4(&args[5]) = cy;
692 V_I4(&args[6]) = cx;
693 V_I4(&args[7]) = y;
694 V_I4(&args[8]) = x;
695 V_I4(&args[9]) = HandleToLong(hdc);
697 params.rgvarg = args;
698 params.rgdispidNamedArgs = NULL;
699 params.cArgs = 10;
700 params.cNamedArgs = 0;
702 V_VT(&ret) = VT_EMPTY;
703 hr_disp = IDispatch_Invoke(disp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD,
704 &params, &ret, NULL, NULL);
705 ok(hr == hr_disp, "DISPID_PICT_RENDER returned wrong code, 0x%08x, expected 0x%08x\n",
706 hr_disp, hr);
708 IDispatch_Release(disp);
710 return hr;
713 static void test_Render(void)
715 IPicture *pic;
716 HRESULT hres;
717 short type;
718 PICTDESC desc;
719 OLE_XSIZE_HIMETRIC pWidth;
720 OLE_YSIZE_HIMETRIC pHeight;
721 COLORREF result, expected;
722 HDC hdc = create_render_dc();
724 /* test IPicture::Render return code on uninitialized picture */
725 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
726 hres = IPicture_get_Type(pic, &type);
727 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
728 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
729 /* zero dimensions */
730 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
731 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
732 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
733 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
734 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
735 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
736 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
737 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
738 hres = picture_render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
739 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
740 hres = picture_render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
741 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
742 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
743 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
744 /* nonzero dimensions, PICTYPE_UNINITIALIZED */
745 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL);
746 ole_expect(hres, S_OK);
747 IPicture_Release(pic);
749 desc.cbSizeofstruct = sizeof(PICTDESC);
750 desc.picType = PICTYPE_ICON;
751 desc.u.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
752 if(!desc.u.icon.hicon){
753 win_skip("LoadIcon failed. Skipping...\n");
754 delete_render_dc(hdc);
755 return;
758 OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (VOID**)&pic);
759 /* zero dimensions, PICTYPE_ICON */
760 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
761 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
762 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
763 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
764 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
765 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
766 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
767 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
768 hres = picture_render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
769 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
770 hres = picture_render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
771 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
772 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
773 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
775 /* Check if target size and position is respected */
776 IPicture_get_Width(pic, &pWidth);
777 IPicture_get_Height(pic, &pHeight);
779 SetPixelV(hdc, 0, 0, 0x00223344);
780 SetPixelV(hdc, 5, 5, 0x00223344);
781 SetPixelV(hdc, 10, 10, 0x00223344);
782 expected = GetPixel(hdc, 0, 0);
784 hres = picture_render(pic, hdc, 1, 1, 9, 9, 0, 0, pWidth, -pHeight, NULL);
785 ole_expect(hres, S_OK);
787 if(hres != S_OK) goto done;
789 /* Evaluate the rendered Icon */
790 result = GetPixel(hdc, 0, 0);
791 ok(result == expected,
792 "Color at 0,0 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
793 result = GetPixel(hdc, 5, 5);
794 ok(result != expected,
795 "Color at 5,5 should have changed, but still was 0x%06X\n", expected);
796 result = GetPixel(hdc, 10, 10);
797 ok(result == expected,
798 "Color at 10,10 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
800 done:
801 IPicture_Release(pic);
802 delete_render_dc(hdc);
805 static void test_get_Attributes(void)
807 IPicture *pic;
808 HRESULT hres;
809 short type;
810 DWORD attr;
812 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
813 hres = IPicture_get_Type(pic, &type);
814 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
815 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
817 hres = IPicture_get_Attributes(pic, NULL);
818 ole_expect(hres, E_POINTER);
820 attr = 0xdeadbeef;
821 hres = IPicture_get_Attributes(pic, &attr);
822 ole_expect(hres, S_OK);
823 ok(attr == 0, "IPicture_get_Attributes does not reset attr to zero, got %d\n", attr);
825 IPicture_Release(pic);
828 static void test_get_Handle(void)
830 IPicture *pic;
831 HRESULT hres;
833 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
835 hres = IPicture_get_Handle(pic, NULL);
836 ole_expect(hres, E_POINTER);
838 IPicture_Release(pic);
841 static void test_get_Type(void)
843 IPicture *pic;
844 HRESULT hres;
846 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
848 hres = IPicture_get_Type(pic, NULL);
849 ole_expect(hres, E_POINTER);
851 IPicture_Release(pic);
854 static void test_OleLoadPicturePath(void)
856 static WCHAR emptyW[] = {0};
858 IPicture *pic;
859 HRESULT hres;
860 int i;
861 char temp_path[MAX_PATH];
862 char temp_file[MAX_PATH];
863 WCHAR temp_fileW[MAX_PATH + 5] = {'f','i','l','e',':','/','/','/'};
864 HANDLE file;
865 DWORD size;
866 WCHAR *ptr;
868 const struct
870 LPOLESTR szURLorPath;
871 REFIID riid;
872 IPicture **pic;
873 } invalid_parameters[] =
875 {NULL, NULL, NULL},
876 {NULL, NULL, &pic},
877 {NULL, &IID_IPicture, NULL},
878 {NULL, &IID_IPicture, &pic},
879 {emptyW, NULL, NULL},
880 {emptyW, &IID_IPicture, NULL},
883 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
885 pic = (IPicture *)0xdeadbeef;
886 hres = OleLoadPicturePath(invalid_parameters[i].szURLorPath, NULL, 0, 0,
887 invalid_parameters[i].riid,
888 (void **)invalid_parameters[i].pic);
889 ok(hres == E_INVALIDARG,
890 "[%d] Expected OleLoadPicturePath to return E_INVALIDARG, got 0x%08x\n", i, hres);
891 ok(pic == (IPicture *)0xdeadbeef,
892 "[%d] Expected output pointer to be 0xdeadbeef, got %p\n", i, pic);
895 pic = (IPicture *)0xdeadbeef;
896 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, NULL, (void **)&pic);
897 todo_wine
898 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
899 broken(hres == E_UNEXPECTED) || /* NT4 */
900 broken(hres == E_OUTOFMEMORY), /* Win2k/Win2k3 */
901 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
902 ok(pic == NULL,
903 "Expected the output interface pointer to be NULL, got %p\n", pic);
905 pic = (IPicture *)0xdeadbeef;
906 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
907 todo_wine
908 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */
909 broken(hres == E_UNEXPECTED) || /* NT4 */
910 broken(hres == E_OUTOFMEMORY), /* Win2k/Win2k3 */
911 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres);
912 ok(pic == NULL,
913 "Expected the output interface pointer to be NULL, got %p\n", pic);
915 /* Create a local temporary image file for testing. */
916 GetTempPathA(sizeof(temp_path), temp_path);
917 GetTempFileNameA(temp_path, "bmp", 0, temp_file);
918 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
919 FILE_ATTRIBUTE_NORMAL, NULL);
920 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
921 CloseHandle(file);
923 MultiByteToWideChar(CP_ACP, 0, temp_file, -1, temp_fileW + 8, sizeof(temp_fileW)/sizeof(WCHAR) - 8);
925 /* Try a normal DOS path. */
926 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
927 ok(hres == S_OK ||
928 broken(hres == E_UNEXPECTED), /* NT4 */
929 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
930 if (pic)
931 IPicture_Release(pic);
933 /* Try a DOS path with tacked on "file:". */
934 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
935 ok(hres == S_OK ||
936 broken(hres == E_UNEXPECTED), /* NT4 */
937 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
938 if (pic)
939 IPicture_Release(pic);
941 DeleteFileA(temp_file);
943 /* Try with a nonexistent file. */
944 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic);
945 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
946 broken(hres == E_UNEXPECTED) || /* NT4 */
947 broken(hres == E_FAIL), /*Win2k */
948 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
950 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
951 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
952 broken(hres == E_UNEXPECTED) || /* NT4 */
953 broken(hres == E_FAIL), /* Win2k */
954 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
956 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
957 FILE_ATTRIBUTE_NORMAL, NULL);
958 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL);
959 CloseHandle(file);
961 /* Try a "file:" URL with slash separators. */
962 ptr = temp_fileW + 8;
963 while (*ptr)
965 if (*ptr == '\\')
966 *ptr = '/';
967 ptr++;
970 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
971 ok(hres == S_OK ||
972 broken(hres == E_UNEXPECTED), /* NT4 */
973 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres);
974 if (pic)
975 IPicture_Release(pic);
977 DeleteFileA(temp_file);
979 /* Try with a nonexistent file. */
980 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic);
981 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */
982 broken(hres == E_UNEXPECTED) || /* NT4 */
983 broken(hres == E_FAIL), /* Win2k */
984 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres);
987 static void test_himetric(void)
989 static const BYTE bmp_bits[1024];
990 OLE_XSIZE_HIMETRIC cx;
991 OLE_YSIZE_HIMETRIC cy;
992 IPicture *pic;
993 PICTDESC desc;
994 HBITMAP bmp;
995 HRESULT hr;
996 HICON icon;
997 HDC hdc;
998 INT d;
1000 desc.cbSizeofstruct = sizeof(desc);
1001 desc.picType = PICTYPE_BITMAP;
1002 desc.u.bmp.hpal = NULL;
1004 hdc = CreateCompatibleDC(0);
1006 bmp = CreateBitmap(1.9 * GetDeviceCaps(hdc, LOGPIXELSX),
1007 1.9 * GetDeviceCaps(hdc, LOGPIXELSY), 1, 1, NULL);
1009 desc.u.bmp.hbitmap = bmp;
1011 /* size in himetric units reported rounded up to next integer value */
1012 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1013 ok(hr == S_OK, "got 0x%08x\n", hr);
1015 cx = 0;
1016 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSX)), 2540, GetDeviceCaps(hdc, LOGPIXELSX));
1017 hr = IPicture_get_Width(pic, &cx);
1018 ok(hr == S_OK, "got 0x%08x\n", hr);
1019 ok(cx == d, "got %d, expected %d\n", cx, d);
1021 cy = 0;
1022 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSY)), 2540, GetDeviceCaps(hdc, LOGPIXELSY));
1023 hr = IPicture_get_Height(pic, &cy);
1024 ok(hr == S_OK, "got 0x%08x\n", hr);
1025 ok(cy == d, "got %d, expected %d\n", cy, d);
1027 DeleteObject(bmp);
1028 IPicture_Release(pic);
1030 /* same thing with icon */
1031 icon = CreateIcon(NULL, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
1032 1, 1, bmp_bits, bmp_bits);
1033 ok(icon != NULL, "failed to create icon\n");
1035 desc.picType = PICTYPE_ICON;
1036 desc.u.icon.hicon = icon;
1038 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1039 ok(hr == S_OK, "got 0x%08x\n", hr);
1041 cx = 0;
1042 d = MulDiv(GetSystemMetrics(SM_CXICON), 2540, GetDeviceCaps(hdc, LOGPIXELSX));
1043 hr = IPicture_get_Width(pic, &cx);
1044 ok(hr == S_OK, "got 0x%08x\n", hr);
1045 ok(cx == d, "got %d, expected %d\n", cx, d);
1047 cy = 0;
1048 d = MulDiv(GetSystemMetrics(SM_CYICON), 2540, GetDeviceCaps(hdc, LOGPIXELSY));
1049 hr = IPicture_get_Height(pic, &cy);
1050 ok(hr == S_OK, "got 0x%08x\n", hr);
1051 ok(cy == d, "got %d, expected %d\n", cy, d);
1053 IPicture_Release(pic);
1054 DestroyIcon(icon);
1056 DeleteDC(hdc);
1059 static void test_load_save_bmp(void)
1061 IPicture *pic;
1062 PICTDESC desc;
1063 short type;
1064 OLE_HANDLE handle;
1065 HGLOBAL hmem;
1066 DWORD *mem;
1067 IPersistStream *src_stream;
1068 IStream *dst_stream;
1069 LARGE_INTEGER offset;
1070 HRESULT hr;
1071 LONG size;
1073 desc.cbSizeofstruct = sizeof(desc);
1074 desc.picType = PICTYPE_BITMAP;
1075 desc.u.bmp.hpal = 0;
1076 desc.u.bmp.hbitmap = CreateBitmap(1, 1, 1, 1, NULL);
1077 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1078 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1080 type = -1;
1081 hr = IPicture_get_Type(pic, &type);
1082 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1083 ok(type == PICTYPE_BITMAP,"expected picture type PICTYPE_BITMAP, got %d\n", type);
1085 hr = IPicture_get_Handle(pic, &handle);
1086 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1087 ok(IntToPtr(handle) == desc.u.bmp.hbitmap, "get_Handle returned wrong handle %#x\n", handle);
1089 hmem = GlobalAlloc(GMEM_ZEROINIT, 4096);
1090 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1091 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr);
1093 size = -1;
1094 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size);
1095 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1096 todo_wine
1097 ok(size == 66, "expected 66, got %d\n", size);
1098 mem = GlobalLock(hmem);
1099 todo_wine
1100 ok(!memcmp(&mem[0], "BM", 2), "got wrong bmp header %04x\n", mem[0]);
1101 GlobalUnlock(hmem);
1103 size = -1;
1104 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size);
1105 todo_wine
1106 ok(hr == E_FAIL, "expected E_FAIL, got %#x\n", hr);
1107 todo_wine
1108 ok(size == -1, "expected -1, got %d\n", size);
1110 offset.QuadPart = 0;
1111 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL);
1112 ok(hr == S_OK, "IStream_Seek %#x\n", hr);
1114 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1115 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1117 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1118 ok(hr == S_OK, "Save error %#x\n", hr);
1120 IPersistStream_Release(src_stream);
1121 IStream_Release(dst_stream);
1123 mem = GlobalLock(hmem);
1124 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1125 ok(mem[1] == 66, "expected stream size 66, got %u\n", mem[1]);
1126 ok(!memcmp(&mem[2], "BM", 2), "got wrong bmp header %04x\n", mem[2]);
1128 GlobalUnlock(hmem);
1129 GlobalFree(hmem);
1131 DeleteObject(desc.u.bmp.hbitmap);
1132 IPicture_Release(pic);
1135 static void test_load_save_icon(void)
1137 IPicture *pic;
1138 PICTDESC desc;
1139 short type;
1140 OLE_HANDLE handle;
1141 HGLOBAL hmem;
1142 DWORD *mem;
1143 IPersistStream *src_stream;
1144 IStream *dst_stream;
1145 LARGE_INTEGER offset;
1146 HRESULT hr;
1147 LONG size;
1149 desc.cbSizeofstruct = sizeof(desc);
1150 desc.picType = PICTYPE_ICON;
1151 desc.u.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
1152 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1153 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1155 type = -1;
1156 hr = IPicture_get_Type(pic, &type);
1157 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1158 ok(type == PICTYPE_ICON,"expected picture type PICTYPE_ICON, got %d\n", type);
1160 hr = IPicture_get_Handle(pic, &handle);
1161 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1162 ok(IntToPtr(handle) == desc.u.icon.hicon, "get_Handle returned wrong handle %#x\n", handle);
1164 hmem = GlobalAlloc(GMEM_ZEROINIT, 8192);
1165 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1166 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
1168 size = -1;
1169 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size);
1170 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1171 todo_wine
1172 ok(size == 766, "expected 766, got %d\n", size);
1173 mem = GlobalLock(hmem);
1174 todo_wine
1175 ok(mem[0] == 0x00010000, "got wrong icon header %04x\n", mem[0]);
1176 GlobalUnlock(hmem);
1178 size = -1;
1179 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size);
1180 todo_wine
1181 ok(hr == E_FAIL, "expected E_FAIL, got %#x\n", hr);
1182 todo_wine
1183 ok(size == -1, "expected -1, got %d\n", size);
1185 offset.QuadPart = 0;
1186 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL);
1187 ok(hr == S_OK, "IStream_Seek %#x\n", hr);
1189 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1190 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1192 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1193 ok(hr == S_OK, "Saveerror %#x\n", hr);
1195 IPersistStream_Release(src_stream);
1196 IStream_Release(dst_stream);
1198 mem = GlobalLock(hmem);
1199 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1200 todo_wine
1201 ok(mem[1] == 766, "expected stream size 766, got %u\n", mem[1]);
1202 ok(mem[2] == 0x00010000, "got wrong icon header %04x\n", mem[2]);
1204 GlobalUnlock(hmem);
1205 GlobalFree(hmem);
1207 DestroyIcon(desc.u.icon.hicon);
1208 IPicture_Release(pic);
1211 static void test_load_save_empty_picture(void)
1213 IPicture *pic;
1214 PICTDESC desc;
1215 short type;
1216 OLE_HANDLE handle;
1217 HGLOBAL hmem;
1218 DWORD *mem;
1219 IPersistStream *src_stream;
1220 IStream *dst_stream, *stream;
1221 LARGE_INTEGER offset;
1222 HRESULT hr;
1223 LONG size;
1225 memset(&pic, 0, sizeof(pic));
1226 desc.cbSizeofstruct = sizeof(desc);
1227 desc.picType = PICTYPE_NONE;
1228 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void **)&pic);
1229 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1231 type = -1;
1232 hr = IPicture_get_Type(pic, &type);
1233 ok(hr == S_OK, "get_Type error %#x\n", hr);
1234 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
1236 handle = (OLE_HANDLE)0xdeadbeef;
1237 hr = IPicture_get_Handle(pic, &handle);
1238 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1239 ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
1241 hmem = GlobalAlloc(GMEM_ZEROINIT, 4096);
1242 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1243 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr);
1245 size = -1;
1246 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size);
1247 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1248 todo_wine
1249 ok(size == -1, "expected -1, got %d\n", size);
1251 size = -1;
1252 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size);
1253 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr);
1254 todo_wine
1255 ok(size == -1, "expected -1, got %d\n", size);
1257 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1258 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1260 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1261 ok(hr == S_OK, "Save error %#x\n", hr);
1263 mem = GlobalLock(hmem);
1264 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1265 ok(mem[1] == 0, "expected stream size 0, got %u\n", mem[1]);
1266 GlobalUnlock(hmem);
1268 IPersistStream_Release(src_stream);
1269 IPicture_Release(pic);
1271 /* first with statable and seekable stream */
1272 offset.QuadPart = 0;
1273 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL);
1274 ok(hr == S_OK, "IStream_Seek %#x\n", hr);
1276 pic = NULL;
1277 hr = pOleLoadPicture(dst_stream, 0, FALSE, &IID_IPicture, (void **)&pic);
1278 ok(hr == S_OK, "OleLoadPicture error %#x\n", hr);
1279 ok(pic != NULL,"picture should not be not NULL\n");
1280 if (pic != NULL)
1282 type = -1;
1283 hr = IPicture_get_Type(pic, &type);
1284 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1285 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
1287 handle = (OLE_HANDLE)0xdeadbeef;
1288 hr = IPicture_get_Handle(pic, &handle);
1289 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1290 ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
1292 IPicture_Release(pic);
1294 IStream_Release(dst_stream);
1296 /* again with non-statable and non-seekable stream */
1297 stream = NoStatStream_Construct(hmem);
1298 ok(stream != NULL, "failed to create empty image stream\n");
1300 pic = NULL;
1301 hr = pOleLoadPicture(stream, 0, FALSE, &IID_IPicture, (void **)&pic);
1302 ok(hr == S_OK, "OleLoadPicture error %#x\n", hr);
1303 ok(pic != NULL,"picture should not be not NULL\n");
1304 if (pic != NULL)
1306 type = -1;
1307 hr = IPicture_get_Type(pic, &type);
1308 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1309 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
1311 handle = (OLE_HANDLE)0xdeadbeef;
1312 hr = IPicture_get_Handle(pic, &handle);
1313 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1314 ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
1316 IPicture_Release(pic);
1318 /* Non-statable impl always deletes on release */
1319 IStream_Release(stream);
1322 START_TEST(olepicture)
1324 hOleaut32 = GetModuleHandleA("oleaut32.dll");
1325 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
1326 pOleLoadPictureEx = (void*)GetProcAddress(hOleaut32, "OleLoadPictureEx");
1327 if (!pOleLoadPicture)
1329 win_skip("OleLoadPicture is not available\n");
1330 return;
1333 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
1334 test_pic(gifimage, sizeof(gifimage));
1335 test_pic(jpgimage, sizeof(jpgimage));
1336 test_pic(bmpimage, sizeof(bmpimage));
1337 test_pic(gif4pixel, sizeof(gif4pixel));
1338 /* FIXME: No PNG support in Windows... */
1339 if (0) test_pic(pngimage, sizeof(pngimage));
1340 test_empty_image();
1341 test_empty_image_2();
1342 if (pOleLoadPictureEx)
1344 test_apm();
1345 test_metafile();
1346 test_enhmetafile();
1348 else
1349 win_skip("OleLoadPictureEx is not available\n");
1350 test_Invoke();
1351 test_OleCreatePictureIndirect();
1352 test_Render();
1353 test_get_Attributes();
1354 test_get_Handle();
1355 test_get_Type();
1356 test_OleLoadPicturePath();
1357 test_himetric();
1358 test_load_save_bmp();
1359 test_load_save_icon();
1360 test_load_save_empty_picture();
1364 /* Helper functions only ... */
1367 static inline NoStatStreamImpl *impl_from_IStream(IStream *iface)
1369 return CONTAINING_RECORD(iface, NoStatStreamImpl, IStream_iface);
1372 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
1374 GlobalFree(This->supportHandle);
1375 This->supportHandle=0;
1376 HeapFree(GetProcessHeap(), 0, This);
1379 static ULONG WINAPI NoStatStreamImpl_AddRef(
1380 IStream* iface)
1382 NoStatStreamImpl* const This = impl_from_IStream(iface);
1383 return InterlockedIncrement(&This->ref);
1386 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
1387 IStream* iface,
1388 REFIID riid, /* [in] */
1389 void** ppvObject) /* [iid_is][out] */
1391 NoStatStreamImpl* const This = impl_from_IStream(iface);
1392 if (ppvObject==0) return E_INVALIDARG;
1393 *ppvObject = 0;
1395 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IStream, riid))
1396 *ppvObject = &This->IStream_iface;
1398 if ((*ppvObject)==0)
1399 return E_NOINTERFACE;
1400 NoStatStreamImpl_AddRef(iface);
1401 return S_OK;
1404 static ULONG WINAPI NoStatStreamImpl_Release(
1405 IStream* iface)
1407 NoStatStreamImpl* const This = impl_from_IStream(iface);
1408 ULONG newRef = InterlockedDecrement(&This->ref);
1409 if (newRef==0)
1410 NoStatStreamImpl_Destroy(This);
1411 return newRef;
1414 static HRESULT WINAPI NoStatStreamImpl_Read(
1415 IStream* iface,
1416 void* pv, /* [length_is][size_is][out] */
1417 ULONG cb, /* [in] */
1418 ULONG* pcbRead) /* [out] */
1420 NoStatStreamImpl* const This = impl_from_IStream(iface);
1421 void* supportBuffer;
1422 ULONG bytesReadBuffer;
1423 ULONG bytesToReadFromBuffer;
1425 if (pcbRead==0)
1426 pcbRead = &bytesReadBuffer;
1427 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
1428 supportBuffer = GlobalLock(This->supportHandle);
1429 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
1430 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
1431 *pcbRead = bytesToReadFromBuffer;
1432 GlobalUnlock(This->supportHandle);
1433 if(*pcbRead == cb)
1434 return S_OK;
1435 return S_FALSE;
1438 static HRESULT WINAPI NoStatStreamImpl_Write(
1439 IStream* iface,
1440 const void* pv, /* [size_is][in] */
1441 ULONG cb, /* [in] */
1442 ULONG* pcbWritten) /* [out] */
1444 NoStatStreamImpl* const This = impl_from_IStream(iface);
1445 void* supportBuffer;
1446 ULARGE_INTEGER newSize;
1447 ULONG bytesWritten = 0;
1449 if (pcbWritten == 0)
1450 pcbWritten = &bytesWritten;
1451 if (cb == 0)
1452 return S_OK;
1453 newSize.u.HighPart = 0;
1454 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
1455 if (newSize.u.LowPart > This->streamSize.u.LowPart)
1456 IStream_SetSize(iface, newSize);
1458 supportBuffer = GlobalLock(This->supportHandle);
1459 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
1460 This->currentPosition.u.LowPart+=cb;
1461 *pcbWritten = cb;
1462 GlobalUnlock(This->supportHandle);
1463 return S_OK;
1466 static HRESULT WINAPI NoStatStreamImpl_Seek(
1467 IStream* iface,
1468 LARGE_INTEGER dlibMove, /* [in] */
1469 DWORD dwOrigin, /* [in] */
1470 ULARGE_INTEGER* plibNewPosition) /* [out] */
1472 NoStatStreamImpl* const This = impl_from_IStream(iface);
1473 ULARGE_INTEGER newPosition;
1474 switch (dwOrigin)
1476 case STREAM_SEEK_SET:
1477 newPosition.u.HighPart = 0;
1478 newPosition.u.LowPart = 0;
1479 break;
1480 case STREAM_SEEK_CUR:
1481 newPosition = This->currentPosition;
1482 break;
1483 case STREAM_SEEK_END:
1484 newPosition = This->streamSize;
1485 break;
1486 default:
1487 return STG_E_INVALIDFUNCTION;
1489 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
1490 return STG_E_INVALIDFUNCTION;
1491 newPosition.QuadPart += dlibMove.QuadPart;
1492 if (plibNewPosition) *plibNewPosition = newPosition;
1493 This->currentPosition = newPosition;
1494 return S_OK;
1497 static HRESULT WINAPI NoStatStreamImpl_SetSize(
1498 IStream* iface,
1499 ULARGE_INTEGER libNewSize) /* [in] */
1501 NoStatStreamImpl* const This = impl_from_IStream(iface);
1502 HGLOBAL supportHandle;
1503 if (libNewSize.u.HighPart != 0)
1504 return STG_E_INVALIDFUNCTION;
1505 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
1506 return S_OK;
1507 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
1508 if (supportHandle == 0)
1509 return STG_E_MEDIUMFULL;
1510 This->supportHandle = supportHandle;
1511 This->streamSize.u.LowPart = libNewSize.u.LowPart;
1512 return S_OK;
1515 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
1516 IStream* iface,
1517 IStream* pstm, /* [unique][in] */
1518 ULARGE_INTEGER cb, /* [in] */
1519 ULARGE_INTEGER* pcbRead, /* [out] */
1520 ULARGE_INTEGER* pcbWritten) /* [out] */
1522 HRESULT hr = S_OK;
1523 BYTE tmpBuffer[128];
1524 ULONG bytesRead, bytesWritten, copySize;
1525 ULARGE_INTEGER totalBytesRead;
1526 ULARGE_INTEGER totalBytesWritten;
1528 if ( pstm == 0 )
1529 return STG_E_INVALIDPOINTER;
1530 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
1531 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
1533 while ( cb.u.LowPart > 0 )
1535 if ( cb.u.LowPart >= 128 )
1536 copySize = 128;
1537 else
1538 copySize = cb.u.LowPart;
1539 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
1540 totalBytesRead.u.LowPart += bytesRead;
1541 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
1542 totalBytesWritten.u.LowPart += bytesWritten;
1543 if (bytesRead != bytesWritten)
1545 hr = STG_E_MEDIUMFULL;
1546 break;
1548 if (bytesRead!=copySize)
1549 cb.u.LowPart = 0;
1550 else
1551 cb.u.LowPart -= bytesRead;
1553 if (pcbRead)
1555 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
1556 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
1559 if (pcbWritten)
1561 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
1562 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
1564 return hr;
1567 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
1569 return S_OK;
1571 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
1573 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
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_UnlockRegion(
1583 IStream* iface,
1584 ULARGE_INTEGER libOffset, /* [in] */
1585 ULARGE_INTEGER cb, /* [in] */
1586 DWORD dwLockType) /* [in] */
1588 return S_OK;
1591 static HRESULT WINAPI NoStatStreamImpl_Stat(
1592 IStream* iface,
1593 STATSTG* pstatstg, /* [out] */
1594 DWORD grfStatFlag) /* [in] */
1596 return E_NOTIMPL;
1599 static HRESULT WINAPI NoStatStreamImpl_Clone(
1600 IStream* iface,
1601 IStream** ppstm) /* [out] */
1603 return E_NOTIMPL;
1605 static const IStreamVtbl NoStatStreamImpl_Vtbl;
1608 Build an object that implements IStream, without IStream_Stat capabilities.
1609 Receives a memory handle with data buffer. If memory handle is non-null,
1610 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
1611 In any case the object takes ownership of memory handle and will free it on
1612 object release.
1614 static IStream* NoStatStream_Construct(HGLOBAL hGlobal)
1616 NoStatStreamImpl* newStream;
1618 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
1619 if (newStream!=0)
1621 newStream->IStream_iface.lpVtbl = &NoStatStreamImpl_Vtbl;
1622 newStream->ref = 1;
1623 newStream->supportHandle = hGlobal;
1625 if (!newStream->supportHandle)
1626 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
1627 GMEM_SHARE, 0);
1628 newStream->currentPosition.u.HighPart = 0;
1629 newStream->currentPosition.u.LowPart = 0;
1630 newStream->streamSize.u.HighPart = 0;
1631 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
1633 return &newStream->IStream_iface;
1637 static const IStreamVtbl NoStatStreamImpl_Vtbl =
1639 NoStatStreamImpl_QueryInterface,
1640 NoStatStreamImpl_AddRef,
1641 NoStatStreamImpl_Release,
1642 NoStatStreamImpl_Read,
1643 NoStatStreamImpl_Write,
1644 NoStatStreamImpl_Seek,
1645 NoStatStreamImpl_SetSize,
1646 NoStatStreamImpl_CopyTo,
1647 NoStatStreamImpl_Commit,
1648 NoStatStreamImpl_Revert,
1649 NoStatStreamImpl_LockRegion,
1650 NoStatStreamImpl_UnlockRegion,
1651 NoStatStreamImpl_Stat,
1652 NoStatStreamImpl_Clone