[BRANCHES]
[reactos.git] / rostests / winetests / oleaut32 / olepicture.c
1 /*
2 * OLEPICTURE test program
3 *
4 * Copyright 2005 Marcus Meissner
5 * Copyright 2012 Dmitry Timoshkov
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #define WIN32_NO_STATUS
23 #define _INC_WINDOWS
24 #define COM_NO_WINDOWS_H
25
26 //#include <stdarg.h>
27 #include <stdio.h>
28 //#include <math.h>
29 //#include <float.h>
30
31 #define COBJMACROS
32 #define CONST_VTABLE
33 #define NONAMELESSUNION
34
35 #include <wine/test.h>
36 //#include <windef.h>
37 //#include <winbase.h>
38 //#include <winuser.h>
39 #include <wingdi.h>
40 #include <winnls.h>
41 //#include <winerror.h>
42 //#include <winnt.h>
43 #include <ole2.h>
44 //#include <urlmon.h>
45 //#include <wtypes.h>
46 #include <olectl.h>
47 //#include <objidl.h>
48
49 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
50
51 #define ole_expect(expr, expect) { \
52 HRESULT r = expr; \
53 ok(r == (expect), #expr " returned %x, expected %s (%x)\n", r, #expect, expect); \
54 }
55
56 #define ole_check(expr) ole_expect(expr, S_OK);
57
58 static HMODULE hOleaut32;
59
60 static HRESULT (WINAPI *pOleLoadPicture)(LPSTREAM,LONG,BOOL,REFIID,LPVOID*);
61 static HRESULT (WINAPI *pOleLoadPictureEx)(LPSTREAM,LONG,BOOL,REFIID,DWORD,DWORD,DWORD,LPVOID*);
62
63 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
64
65 /* 1x1 pixel gif */
66 static const unsigned char gifimage[35] = {
67 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
68 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
69 0x01,0x00,0x3b
70 };
71
72 /* 1x1 pixel jpg */
73 static const unsigned char jpgimage[285] = {
74 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
75 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
76 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
77 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
78 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
79 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
80 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
81 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
82 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
83 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
84 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
85 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
86 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
87 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
88 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
89 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
90 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
91 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
92 };
93
94 /* 1x1 pixel png */
95 static const unsigned char pngimage[285] = {
96 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
97 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
98 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
99 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
100 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
101 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
102 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
103 };
104
105 /* 1x1 pixel bmp */
106 static const unsigned char bmpimage[66] = {
107 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
108 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
109 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
110 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
111 0x00,0x00
112 };
113
114 /* 2x2 pixel gif */
115 static const unsigned char gif4pixel[42] = {
116 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
117 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
118 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
119 };
120
121 /* APM with an empty metafile with some padding zeros - looks like under Window the
122 * metafile data should be at least 20 bytes */
123 static const unsigned char apmdata[] = {
124 0xd7,0xcd,0xc6,0x9a, 0x00,0x00,0x00,0x00, 0x00,0x00,0xee,0x02, 0xb1,0x03,0xa0,0x05,
125 0x00,0x00,0x00,0x00, 0xee,0x53,0x01,0x00, 0x09,0x00,0x00,0x03, 0x13,0x00,0x00,0x00,
126 0x01,0x00,0x05,0x00, 0x00,0x00,0x00,0x00, 0x03,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
127 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
128 };
129
130 /* MF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
131 static const unsigned char metafile[] = {
132 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
133 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
134 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
135 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
136 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
137 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
138 0x00, 0x00
139 };
140
141 /* EMF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
142 static const unsigned char enhmetafile[] = {
143 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
148 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
149 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
150 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
153 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
156 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
157 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
158 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
160 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
161 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
162 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
163 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
166 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
167 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
168 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
169 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
170 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
171 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
172 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
173 0x14, 0x00, 0x00, 0x00
174 };
175
176
177 typedef struct NoStatStreamImpl
178 {
179 IStream IStream_iface;
180 LONG ref;
181
182 HGLOBAL supportHandle;
183 ULARGE_INTEGER streamSize;
184 ULARGE_INTEGER currentPosition;
185 } NoStatStreamImpl;
186
187 static IStream* NoStatStream_Construct(HGLOBAL hGlobal);
188
189 static void
190 test_pic_with_stream(LPSTREAM stream, unsigned int imgsize)
191 {
192 IPicture* pic = NULL;
193 HRESULT hres;
194 LPVOID pvObj = NULL;
195 OLE_HANDLE handle, hPal;
196 OLE_XSIZE_HIMETRIC width;
197 OLE_YSIZE_HIMETRIC height;
198 short type;
199 DWORD attr;
200 ULONG res;
201
202 pvObj = NULL;
203 hres = pOleLoadPicture(stream, imgsize, TRUE, &IID_IPicture, &pvObj);
204 pic = pvObj;
205
206 ok(hres == S_OK,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres);
207 ok(pic != NULL,"OLP (NULL,..) returns NULL, instead of !NULL\n");
208 if (pic == NULL)
209 return;
210
211 pvObj = NULL;
212 hres = IPicture_QueryInterface (pic, &IID_IPicture, &pvObj);
213
214 ok(hres == S_OK,"IPicture_QI does not return S_OK, but 0x%08x\n", hres);
215 ok(pvObj != NULL,"IPicture_QI does return NULL, instead of a ptr\n");
216
217 IPicture_Release ((IPicture*)pvObj);
218
219 handle = 0;
220 hres = IPicture_get_Handle (pic, &handle);
221 ok(hres == S_OK,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres);
222 ok(handle != 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
223
224 if (handle)
225 {
226 BITMAP bmp;
227 GetObjectA(UlongToHandle(handle), sizeof(BITMAP), &bmp);
228 todo_wine ok(bmp.bmBits != 0, "not a dib\n");
229 }
230
231 width = 0;
232 hres = IPicture_get_Width (pic, &width);
233 ok(hres == S_OK,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres);
234 ok(width != 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
235
236 height = 0;
237 hres = IPicture_get_Height (pic, &height);
238 ok(hres == S_OK,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres);
239 ok(height != 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
240
241 type = 0;
242 hres = IPicture_get_Type (pic, &type);
243 ok(hres == S_OK,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
244 ok(type == PICTYPE_BITMAP, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type, PICTYPE_BITMAP);
245
246 attr = 0;
247 hres = IPicture_get_Attributes (pic, &attr);
248 ok(hres == S_OK,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres);
249 ok(attr == 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr);
250
251 hPal = 0;
252 hres = IPicture_get_hPal (pic, &hPal);
253 ok(hres == S_OK,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres);
254 /* a single pixel b/w image has no palette */
255 ok(hPal == 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal);
256
257 res = IPicture_Release (pic);
258 ok (res == 0, "refcount after release is %d, but should be 0?\n", res);
259 }
260
261 static void
262 test_pic(const unsigned char *imgdata, unsigned int imgsize)
263 {
264 LPSTREAM stream;
265 HGLOBAL hglob;
266 LPBYTE data;
267 HRESULT hres;
268 LARGE_INTEGER seekto;
269 ULARGE_INTEGER newpos1;
270 DWORD * header;
271 unsigned int i,j;
272
273 /* Let the fun begin */
274 hglob = GlobalAlloc (0, imgsize);
275 data = GlobalLock (hglob);
276 memcpy(data, imgdata, imgsize);
277 GlobalUnlock(hglob); data = NULL;
278
279 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
280 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
281
282 memset(&seekto,0,sizeof(seekto));
283 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
284 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
285 test_pic_with_stream(stream, imgsize);
286
287 IStream_Release(stream);
288
289 /* again with Non Statable and Non Seekable stream */
290 stream = NoStatStream_Construct(hglob);
291 hglob = 0; /* Non-statable impl always deletes on release */
292 test_pic_with_stream(stream, 0);
293
294 IStream_Release(stream);
295 for (i = 1; i <= 8; i++) {
296 /* more fun!!! */
297 hglob = GlobalAlloc (0, imgsize + i * (2 * sizeof(DWORD)));
298 data = GlobalLock (hglob);
299 header = (DWORD *)data;
300
301 /* multiple copies of header */
302 memcpy(data,"lt\0\0",4);
303 header[1] = imgsize;
304 for (j = 2; j <= i; j++) {
305 memcpy(&(header[2 * (j - 1)]), header, 2 * sizeof(DWORD));
306 }
307 memcpy(data + i * (2 * sizeof(DWORD)), imgdata, imgsize);
308 GlobalUnlock(hglob); data = NULL;
309
310 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
311 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
312
313 memset(&seekto,0,sizeof(seekto));
314 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
315 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
316 test_pic_with_stream(stream, imgsize);
317
318 IStream_Release(stream);
319
320 /* again with Non Statable and Non Seekable stream */
321 stream = NoStatStream_Construct(hglob);
322 hglob = 0; /* Non-statable impl always deletes on release */
323 test_pic_with_stream(stream, 0);
324
325 IStream_Release(stream);
326 }
327 }
328
329 static void test_empty_image(void) {
330 LPBYTE data;
331 LPSTREAM stream;
332 IPicture* pic = NULL;
333 HRESULT hres;
334 LPVOID pvObj = NULL;
335 HGLOBAL hglob;
336 OLE_HANDLE handle;
337 ULARGE_INTEGER newpos1;
338 LARGE_INTEGER seekto;
339 short type;
340 DWORD attr;
341
342 /* Empty image. Happens occasionally in VB programs. */
343 hglob = GlobalAlloc (0, 8);
344 data = GlobalLock (hglob);
345 memcpy(data,"lt\0\0",4);
346 ((DWORD*)data)[1] = 0;
347 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
348 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
349
350 memset(&seekto,0,sizeof(seekto));
351 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
352 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
353
354 pvObj = NULL;
355 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
356 pic = pvObj;
357 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
358 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
359
360 hres = IPicture_get_Type (pic, &type);
361 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
362 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
363
364 attr = 0xdeadbeef;
365 hres = IPicture_get_Attributes (pic, &attr);
366 ok (hres == S_OK,"empty picture get attributes failed with hres 0x%08x\n", hres);
367 ok (attr == 0,"attr is %d, but should be 0\n", attr);
368
369 hres = IPicture_get_Handle (pic, &handle);
370 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
371 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
372 IPicture_Release (pic);
373 IStream_Release (stream);
374 }
375
376 static void test_empty_image_2(void) {
377 LPBYTE data;
378 LPSTREAM stream;
379 IPicture* pic = NULL;
380 HRESULT hres;
381 LPVOID pvObj = NULL;
382 HGLOBAL hglob;
383 ULARGE_INTEGER newpos1;
384 LARGE_INTEGER seekto;
385 short type;
386
387 /* Empty image at random stream position. */
388 hglob = GlobalAlloc (0, 200);
389 data = GlobalLock (hglob);
390 data += 42;
391 memcpy(data,"lt\0\0",4);
392 ((DWORD*)data)[1] = 0;
393 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
394 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
395
396 memset(&seekto,0,sizeof(seekto));
397 seekto.u.LowPart = 42;
398 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
399 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
400
401 pvObj = NULL;
402 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
403 pic = pvObj;
404 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
405 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
406
407 hres = IPicture_get_Type (pic, &type);
408 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
409 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
410
411 IPicture_Release (pic);
412 IStream_Release (stream);
413 }
414
415 static void test_Invoke(void)
416 {
417 IPictureDisp *picdisp;
418 HRESULT hr;
419 VARIANTARG vararg, args[10];
420 DISPPARAMS dispparams;
421 VARIANT varresult;
422 IStream *stream;
423 HGLOBAL hglob;
424 void *data;
425 HDC hdc;
426 int i;
427
428 hglob = GlobalAlloc (0, sizeof(gifimage));
429 data = GlobalLock(hglob);
430 memcpy(data, gifimage, sizeof(gifimage));
431 GlobalUnlock(hglob);
432
433 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
434 ok_ole_success(hr, "CreateStreamOnHGlobal");
435
436 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
437 IStream_Release(stream);
438 GlobalFree(hglob);
439 ok_ole_success(hr, "OleLoadPicture");
440
441 V_VT(&vararg) = VT_BOOL;
442 V_BOOL(&vararg) = VARIANT_FALSE;
443 dispparams.cNamedArgs = 0;
444 dispparams.rgdispidNamedArgs = NULL;
445 dispparams.cArgs = 1;
446 dispparams.rgvarg = &vararg;
447 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
448 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
449 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
450 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
451
452 dispparams.cArgs = 0;
453 dispparams.rgvarg = NULL;
454 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
455 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
456
457 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
458 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
459
460 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
461 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
462
463 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
464 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
465
466 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
467 ok_ole_success(hr, "IPictureDisp_Invoke");
468 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
469
470 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
471 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
472
473 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
474 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
475
476 dispparams.cArgs = 1;
477 dispparams.rgvarg = &vararg;
478 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
479 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
480
481 dispparams.cArgs = 1;
482 dispparams.rgvarg = &vararg;
483 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
484 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
485
486 /* DISPID_PICT_RENDER */
487 hdc = GetDC(0);
488
489 for (i = 0; i < sizeof(args)/sizeof(args[0]); i++)
490 V_VT(&args[i]) = VT_I4;
491
492 V_I4(&args[0]) = 0;
493 V_I4(&args[1]) = 10;
494 V_I4(&args[2]) = 10;
495 V_I4(&args[3]) = 0;
496 V_I4(&args[4]) = 0;
497 V_I4(&args[5]) = 10;
498 V_I4(&args[6]) = 10;
499 V_I4(&args[7]) = 0;
500 V_I4(&args[8]) = 0;
501 V_I4(&args[9]) = HandleToLong(hdc);
502
503 dispparams.rgvarg = args;
504 dispparams.rgdispidNamedArgs = NULL;
505 dispparams.cArgs = 10;
506 dispparams.cNamedArgs = 0;
507
508 V_VT(&varresult) = VT_EMPTY;
509 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
510 ok(hr == S_OK, "got 0x%08x\n", hr);
511
512 /* Try with one argument set to VT_I2, it'd still work if coerced. */
513 V_VT(&args[3]) = VT_I2;
514 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
515 ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr);
516 V_VT(&args[3]) = VT_I4;
517
518 /* Wrong argument count */
519 dispparams.cArgs = 9;
520 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
521 ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
522
523 ReleaseDC(NULL, hdc);
524 IPictureDisp_Release(picdisp);
525 }
526
527 static void test_OleCreatePictureIndirect(void)
528 {
529 OLE_HANDLE handle;
530 IPicture *pict;
531 HRESULT hr;
532 short type;
533
534 if (0)
535 {
536 /* crashes on native */
537 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, NULL);
538 }
539
540 hr = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict);
541 ok(hr == S_OK, "hr %08x\n", hr);
542
543 type = PICTYPE_NONE;
544 hr = IPicture_get_Type(pict, &type);
545 ok(hr == S_OK, "hr %08x\n", hr);
546 ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type);
547
548 handle = 0xdeadbeef;
549 hr = IPicture_get_Handle(pict, &handle);
550 ok(hr == S_OK, "hr %08x\n", hr);
551 ok(handle == 0, "handle %08x\n", handle);
552
553 IPicture_Release(pict);
554 }
555
556 static void test_apm(void)
557 {
558 OLE_HANDLE handle;
559 LPSTREAM stream;
560 IPicture *pict;
561 HGLOBAL hglob;
562 LPBYTE *data;
563 LONG cxy;
564 BOOL keep;
565 short type;
566
567 if(!winetest_interactive) {
568 skip("ROSTESTS-2: oleaut_winetest:olepicture crashes with Page Fault.\n");
569 return;
570 }
571
572 hglob = GlobalAlloc (0, sizeof(apmdata));
573 data = GlobalLock(hglob);
574 memcpy(data, apmdata, sizeof(apmdata));
575
576 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
577 ole_check(pOleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict));
578
579 ole_check(IPicture_get_Handle(pict, &handle));
580 ok(handle != 0, "handle is null\n");
581
582 ole_check(IPicture_get_Type(pict, &type));
583 expect_eq(type, PICTYPE_METAFILE, short, "%d");
584
585 ole_check(IPicture_get_Height(pict, &cxy));
586 expect_eq(cxy, 1667, LONG, "%d");
587
588 ole_check(IPicture_get_Width(pict, &cxy));
589 expect_eq(cxy, 1323, LONG, "%d");
590
591 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
592 todo_wine expect_eq(keep, FALSE, LONG, "%d");
593
594 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL);
595 IPicture_Release(pict);
596 IStream_Release(stream);
597 }
598
599 static void test_metafile(void)
600 {
601 LPSTREAM stream;
602 IPicture *pict;
603 HGLOBAL hglob;
604 LPBYTE *data;
605
606 hglob = GlobalAlloc (0, sizeof(metafile));
607 data = GlobalLock(hglob);
608 memcpy(data, metafile, sizeof(metafile));
609
610 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
611 /* Windows does not load simple metafiles */
612 ole_expect(pOleLoadPictureEx(stream, sizeof(metafile), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict), E_FAIL);
613
614 IStream_Release(stream);
615 }
616
617 static void test_enhmetafile(void)
618 {
619 OLE_HANDLE handle;
620 LPSTREAM stream;
621 IPicture *pict;
622 HGLOBAL hglob;
623 LPBYTE *data;
624 LONG cxy;
625 BOOL keep;
626 short type;
627
628 if(!winetest_interactive) {
629 skip("ROSTESTS-2: oleaut_winetest:olepicture crashes with Page Fault.\n");
630 return;
631 }
632
633 hglob = GlobalAlloc (0, sizeof(enhmetafile));
634 data = GlobalLock(hglob);
635 memcpy(data, enhmetafile, sizeof(enhmetafile));
636
637 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
638 ole_check(pOleLoadPictureEx(stream, sizeof(enhmetafile), TRUE, &IID_IPicture, 10, 10, 0, (LPVOID *)&pict));
639
640 ole_check(IPicture_get_Handle(pict, &handle));
641 ok(handle != 0, "handle is null\n");
642
643 ole_check(IPicture_get_Type(pict, &type));
644 expect_eq(type, PICTYPE_ENHMETAFILE, short, "%d");
645
646 ole_check(IPicture_get_Height(pict, &cxy));
647 expect_eq(cxy, -23, LONG, "%d");
648
649 ole_check(IPicture_get_Width(pict, &cxy));
650 expect_eq(cxy, -25, LONG, "%d");
651
652 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
653 todo_wine expect_eq(keep, FALSE, LONG, "%d");
654
655 IPicture_Release(pict);
656 IStream_Release(stream);
657 }
658
659 static HRESULT picture_render(IPicture *iface, HDC hdc, LONG x, LONG y, LONG cx, LONG cy,
660 OLE_XPOS_HIMETRIC xSrc,
661 OLE_YPOS_HIMETRIC ySrc,
662 OLE_XSIZE_HIMETRIC cxSrc,
663 OLE_YSIZE_HIMETRIC cySrc,
664 const RECT *bounds)
665 {
666 VARIANT ret, args[10];
667 HRESULT hr, hr_disp;
668 DISPPARAMS params;
669 IDispatch *disp;
670 int i;
671
672 hr = IPicture_Render(iface, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, bounds);
673
674 IPicture_QueryInterface(iface, &IID_IDispatch, (void**)&disp);
675
676 /* This is broken on 64 bits - accepted pointer argument type is still VT_I4 */
677 for (i = 0; i < sizeof(args)/sizeof(args[0]); i++)
678 V_VT(&args[i]) = VT_I4;
679
680 /* pack arguments and call */
681 V_INT_PTR(&args[0]) = (INT_PTR)bounds;
682 V_I4(&args[1]) = cySrc;
683 V_I4(&args[2]) = cxSrc;
684 V_I4(&args[3]) = ySrc;
685 V_I4(&args[4]) = xSrc;
686 V_I4(&args[5]) = cy;
687 V_I4(&args[6]) = cx;
688 V_I4(&args[7]) = y;
689 V_I4(&args[8]) = x;
690 V_I4(&args[9]) = HandleToLong(hdc);
691
692 params.rgvarg = args;
693 params.rgdispidNamedArgs = NULL;
694 params.cArgs = 10;
695 params.cNamedArgs = 0;
696
697 V_VT(&ret) = VT_EMPTY;
698 hr_disp = IDispatch_Invoke(disp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD,
699 &params, &ret, NULL, NULL);
700 ok(hr == hr_disp, "DISPID_PICT_RENDER returned wrong code, 0x%08x, expected 0x%08x\n",
701 hr_disp, hr);
702
703 IDispatch_Release(disp);
704
705 return hr;
706 }
707
708 static void test_Render(void)
709 {
710 IPicture *pic;
711 HRESULT hres;
712 short type;
713 PICTDESC desc;
714 OLE_XSIZE_HIMETRIC pWidth;
715 OLE_YSIZE_HIMETRIC pHeight;
716 COLORREF result, expected;
717 HDC hdc = GetDC(0);
718
719 /* test IPicture::Render return code on uninitialized picture */
720 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
721 hres = IPicture_get_Type(pic, &type);
722 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
723 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
724 /* zero dimensions */
725 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
726 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
727 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
728 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
729 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
730 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
731 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
732 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
733 hres = picture_render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
734 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
735 hres = picture_render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
736 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
737 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
738 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
739 /* nonzero dimensions, PICTYPE_UNINITIALIZED */
740 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL);
741 ole_expect(hres, S_OK);
742 IPicture_Release(pic);
743
744 desc.cbSizeofstruct = sizeof(PICTDESC);
745 desc.picType = PICTYPE_ICON;
746 desc.u.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
747 if(!desc.u.icon.hicon){
748 win_skip("LoadIcon failed. Skipping...\n");
749 ReleaseDC(NULL, hdc);
750 return;
751 }
752
753 OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (VOID**)&pic);
754 /* zero dimensions, PICTYPE_ICON */
755 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
756 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
757 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
758 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
759 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
760 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
761 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
762 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
763 hres = picture_render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
764 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
765 hres = picture_render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
766 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
767 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
768 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
769
770 /* Check if target size and position is respected */
771 IPicture_get_Width(pic, &pWidth);
772 IPicture_get_Height(pic, &pHeight);
773
774 SetPixelV(hdc, 0, 0, 0x00223344);
775 SetPixelV(hdc, 5, 5, 0x00223344);
776 SetPixelV(hdc, 10, 10, 0x00223344);
777 expected = GetPixel(hdc, 0, 0);
778
779 hres = picture_render(pic, hdc, 1, 1, 9, 9, 0, 0, pWidth, -pHeight, NULL);
780 ole_expect(hres, S_OK);
781
782 if(hres != S_OK) {
783 IPicture_Release(pic);
784 ReleaseDC(NULL, hdc);
785 return;
786 }
787
788 /* Evaluate the rendered Icon */
789 result = GetPixel(hdc, 0, 0);
790 ok(result == expected,
791 "Color at 0,0 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
792 result = GetPixel(hdc, 5, 5);
793 ok(result != expected ||
794 broken(result == expected), /* WinNT 4.0 and older may claim they drew */
795 /* the icon, even if they didn't. */
796 "Color at 5,5 should have changed, but still was 0x%06X\n", expected);
797 result = GetPixel(hdc, 10, 10);
798 ok(result == expected,
799 "Color at 10,10 should be unchanged 0x%06X, but was 0x%06X\n", expected, result);
800
801 IPicture_Release(pic);
802 ReleaseDC(NULL, hdc);
803 }
804
805 static void test_get_Attributes(void)
806 {
807 IPicture *pic;
808 HRESULT hres;
809 short type;
810 DWORD attr;
811
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);
816
817 hres = IPicture_get_Attributes(pic, NULL);
818 ole_expect(hres, E_POINTER);
819
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);
824
825 IPicture_Release(pic);
826 }
827
828 static void test_get_Handle(void)
829 {
830 IPicture *pic;
831 HRESULT hres;
832
833 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
834
835 hres = IPicture_get_Handle(pic, NULL);
836 ole_expect(hres, E_POINTER);
837
838 IPicture_Release(pic);
839 }
840
841 static void test_get_Type(void)
842 {
843 IPicture *pic;
844 HRESULT hres;
845
846 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
847
848 hres = IPicture_get_Type(pic, NULL);
849 ole_expect(hres, E_POINTER);
850
851 IPicture_Release(pic);
852 }
853
854 static void test_OleLoadPicturePath(void)
855 {
856 static WCHAR emptyW[] = {0};
857
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;
867
868 const struct
869 {
870 LPOLESTR szURLorPath;
871 REFIID riid;
872 IPicture **pic;
873 } invalid_parameters[] =
874 {
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},
881 };
882
883 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
884 {
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);
893 }
894
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);
904
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);
914
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);
922
923 MultiByteToWideChar(CP_ACP, 0, temp_file, -1, temp_fileW + 8, sizeof(temp_fileW)/sizeof(WCHAR) - 8);
924
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);
932
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);
940
941 DeleteFileA(temp_file);
942
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);
949
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);
955
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);
960
961 /* Try a "file:" URL with slash separators. */
962 ptr = temp_fileW + 8;
963 while (*ptr)
964 {
965 if (*ptr == '\\')
966 *ptr = '/';
967 ptr++;
968 }
969
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);
976
977 DeleteFileA(temp_file);
978
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);
985 }
986
987 static void test_himetric(void)
988 {
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;
999
1000 desc.cbSizeofstruct = sizeof(desc);
1001 desc.picType = PICTYPE_BITMAP;
1002 desc.u.bmp.hpal = NULL;
1003
1004 hdc = CreateCompatibleDC(0);
1005
1006 bmp = CreateBitmap(1.9 * GetDeviceCaps(hdc, LOGPIXELSX),
1007 1.9 * GetDeviceCaps(hdc, LOGPIXELSY), 1, 1, NULL);
1008
1009 desc.u.bmp.hbitmap = bmp;
1010
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);
1014
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);
1020
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);
1026
1027 DeleteObject(bmp);
1028 IPicture_Release(pic);
1029
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");
1034
1035 desc.picType = PICTYPE_ICON;
1036 desc.u.icon.hicon = icon;
1037
1038 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1039 ok(hr == S_OK, "got 0x%08x\n", hr);
1040
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);
1046
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);
1052
1053 IPicture_Release(pic);
1054 DestroyIcon(icon);
1055
1056 DeleteDC(hdc);
1057 }
1058
1059 static void test_load_save_bmp(void)
1060 {
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 HRESULT hr;
1070
1071 desc.cbSizeofstruct = sizeof(desc);
1072 desc.picType = PICTYPE_BITMAP;
1073 desc.u.bmp.hpal = 0;
1074 desc.u.bmp.hbitmap = CreateBitmap(1, 1, 1, 1, NULL);
1075 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1076 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1077
1078 type = -1;
1079 hr = IPicture_get_Type(pic, &type);
1080 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1081 ok(type == PICTYPE_BITMAP,"expected picture type PICTYPE_BITMAP, got %d\n", type);
1082
1083 hr = IPicture_get_Handle(pic, &handle);
1084 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1085 ok(IntToPtr(handle) == desc.u.bmp.hbitmap, "get_Handle returned wrong handle %#x\n", handle);
1086
1087 hmem = GlobalAlloc(GMEM_ZEROINIT, 4096);
1088 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1089 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr);
1090
1091 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1092 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1093
1094 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1095 ok(hr == S_OK, "Save error %#x\n", hr);
1096
1097 IPersistStream_Release(src_stream);
1098 IStream_Release(dst_stream);
1099
1100 mem = GlobalLock(hmem);
1101 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1102 ok(mem[1] == 66, "expected stream size 66, got %u\n", mem[1]);
1103 ok(!memcmp(&mem[2], "BM", 2), "got wrong bmp header %04x\n", mem[2]);
1104
1105 GlobalUnlock(hmem);
1106 GlobalFree(hmem);
1107
1108 DeleteObject(desc.u.bmp.hbitmap);
1109 IPicture_Release(pic);
1110 }
1111
1112 static void test_load_save_icon(void)
1113 {
1114 IPicture *pic;
1115 PICTDESC desc;
1116 short type;
1117 OLE_HANDLE handle;
1118 HGLOBAL hmem;
1119 DWORD *mem;
1120 IPersistStream *src_stream;
1121 IStream *dst_stream;
1122 HRESULT hr;
1123
1124 desc.cbSizeofstruct = sizeof(desc);
1125 desc.picType = PICTYPE_ICON;
1126 desc.u.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
1127 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
1128 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1129
1130 type = -1;
1131 hr = IPicture_get_Type(pic, &type);
1132 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1133 ok(type == PICTYPE_ICON,"expected picture type PICTYPE_ICON, got %d\n", type);
1134
1135 hr = IPicture_get_Handle(pic, &handle);
1136 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1137 ok(IntToPtr(handle) == desc.u.icon.hicon, "get_Handle returned wrong handle %#x\n", handle);
1138
1139 hmem = GlobalAlloc(GMEM_ZEROINIT, 8192);
1140 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1141 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
1142
1143 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1144 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1145
1146 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1147 ok(hr == S_OK, "Saveerror %#x\n", hr);
1148
1149 IPersistStream_Release(src_stream);
1150 IStream_Release(dst_stream);
1151
1152 mem = GlobalLock(hmem);
1153 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1154 todo_wine
1155 ok(mem[1] == 766, "expected stream size 766, got %u\n", mem[1]);
1156 ok(mem[2] == 0x00010000, "got wrong icon header %04x\n", mem[2]);
1157
1158 GlobalUnlock(hmem);
1159 GlobalFree(hmem);
1160
1161 DestroyIcon(desc.u.icon.hicon);
1162 IPicture_Release(pic);
1163 }
1164
1165 static void test_load_save_empty_picture(void)
1166 {
1167 IPicture *pic;
1168 PICTDESC desc;
1169 short type;
1170 OLE_HANDLE handle;
1171 HGLOBAL hmem;
1172 DWORD *mem;
1173 IPersistStream *src_stream;
1174 IStream *dst_stream, *stream;
1175 LARGE_INTEGER offset;
1176 HRESULT hr;
1177
1178 memset(&pic, 0, sizeof(pic));
1179 desc.cbSizeofstruct = sizeof(desc);
1180 desc.picType = PICTYPE_NONE;
1181 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void **)&pic);
1182 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
1183
1184 type = -1;
1185 hr = IPicture_get_Type(pic, &type);
1186 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1187 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
1188
1189 handle = (OLE_HANDLE)0xdeadbeef;
1190 hr = IPicture_get_Handle(pic, &handle);
1191 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1192 ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
1193
1194 hmem = GlobalAlloc(GMEM_ZEROINIT, 4096);
1195 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream);
1196 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr);
1197
1198 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream);
1199 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1200
1201 hr = IPersistStream_Save(src_stream, dst_stream, TRUE);
1202 ok(hr == S_OK, "Save error %#x\n", hr);
1203
1204 mem = GlobalLock(hmem);
1205 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]);
1206 ok(mem[1] == 0, "expected stream size 0, got %u\n", mem[1]);
1207 GlobalUnlock(hmem);
1208
1209 IPersistStream_Release(src_stream);
1210 IPicture_Release(pic);
1211
1212 /* first with statable and seekable stream */
1213 offset.QuadPart = 0;
1214 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL);
1215 ok(hr == S_OK, "IStream_Seek %#x\n", hr);
1216
1217 pic = NULL;
1218 hr = pOleLoadPicture(dst_stream, 0, FALSE, &IID_IPicture, (void **)&pic);
1219 ok(hr == S_OK, "OleLoadPicture error %#x\n", hr);
1220 ok(pic != NULL,"picture should not be not NULL\n");
1221 if (pic != NULL)
1222 {
1223 type = -1;
1224 hr = IPicture_get_Type(pic, &type);
1225 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1226 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
1227
1228 handle = (OLE_HANDLE)0xdeadbeef;
1229 hr = IPicture_get_Handle(pic, &handle);
1230 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1231 ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
1232
1233 IPicture_Release(pic);
1234 }
1235 IStream_Release(dst_stream);
1236
1237 /* again with non-statable and non-seekable stream */
1238 stream = NoStatStream_Construct(hmem);
1239 ok(stream != NULL, "failed to create empty image stream\n");
1240
1241 pic = NULL;
1242 hr = pOleLoadPicture(stream, 0, FALSE, &IID_IPicture, (void **)&pic);
1243 ok(hr == S_OK, "OleLoadPicture error %#x\n", hr);
1244 ok(pic != NULL,"picture should not be not NULL\n");
1245 if (pic != NULL)
1246 {
1247 type = -1;
1248 hr = IPicture_get_Type(pic, &type);
1249 ok(hr == S_OK,"get_Type error %#8x\n", hr);
1250 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
1251
1252 handle = (OLE_HANDLE)0xdeadbeef;
1253 hr = IPicture_get_Handle(pic, &handle);
1254 ok(hr == S_OK,"get_Handle error %#8x\n", hr);
1255 ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
1256
1257 IPicture_Release(pic);
1258 }
1259 /* Non-statable impl always deletes on release */
1260 IStream_Release(stream);
1261 }
1262
1263 START_TEST(olepicture)
1264 {
1265 hOleaut32 = GetModuleHandleA("oleaut32.dll");
1266 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
1267 pOleLoadPictureEx = (void*)GetProcAddress(hOleaut32, "OleLoadPictureEx");
1268 if (!pOleLoadPicture)
1269 {
1270 win_skip("OleLoadPicture is not available\n");
1271 return;
1272 }
1273
1274 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
1275 test_pic(gifimage, sizeof(gifimage));
1276 test_pic(jpgimage, sizeof(jpgimage));
1277 test_pic(bmpimage, sizeof(bmpimage));
1278 test_pic(gif4pixel, sizeof(gif4pixel));
1279 /* FIXME: No PNG support in Windows... */
1280 if (0) test_pic(pngimage, sizeof(pngimage));
1281 test_empty_image();
1282 test_empty_image_2();
1283 if (pOleLoadPictureEx)
1284 {
1285 test_apm();
1286 test_metafile();
1287 test_enhmetafile();
1288 }
1289 else
1290 win_skip("OleLoadPictureEx is not available\n");
1291 test_Invoke();
1292 test_OleCreatePictureIndirect();
1293 test_Render();
1294 test_get_Attributes();
1295 test_get_Handle();
1296 test_get_Type();
1297 test_OleLoadPicturePath();
1298 test_himetric();
1299 test_load_save_bmp();
1300 test_load_save_icon();
1301 test_load_save_empty_picture();
1302 }
1303
1304
1305 /* Helper functions only ... */
1306
1307
1308 static inline NoStatStreamImpl *impl_from_IStream(IStream *iface)
1309 {
1310 return CONTAINING_RECORD(iface, NoStatStreamImpl, IStream_iface);
1311 }
1312
1313 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
1314 {
1315 GlobalFree(This->supportHandle);
1316 This->supportHandle=0;
1317 HeapFree(GetProcessHeap(), 0, This);
1318 }
1319
1320 static ULONG WINAPI NoStatStreamImpl_AddRef(
1321 IStream* iface)
1322 {
1323 NoStatStreamImpl* const This = impl_from_IStream(iface);
1324 return InterlockedIncrement(&This->ref);
1325 }
1326
1327 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
1328 IStream* iface,
1329 REFIID riid, /* [in] */
1330 void** ppvObject) /* [iid_is][out] */
1331 {
1332 NoStatStreamImpl* const This = impl_from_IStream(iface);
1333 if (ppvObject==0) return E_INVALIDARG;
1334 *ppvObject = 0;
1335 if (IsEqualIID(&IID_IUnknown, riid))
1336 {
1337 *ppvObject = This;
1338 }
1339 else if (IsEqualIID(&IID_IStream, riid))
1340 {
1341 *ppvObject = This;
1342 }
1343
1344 if ((*ppvObject)==0)
1345 return E_NOINTERFACE;
1346 NoStatStreamImpl_AddRef(iface);
1347 return S_OK;
1348 }
1349
1350 static ULONG WINAPI NoStatStreamImpl_Release(
1351 IStream* iface)
1352 {
1353 NoStatStreamImpl* const This = impl_from_IStream(iface);
1354 ULONG newRef = InterlockedDecrement(&This->ref);
1355 if (newRef==0)
1356 NoStatStreamImpl_Destroy(This);
1357 return newRef;
1358 }
1359
1360 static HRESULT WINAPI NoStatStreamImpl_Read(
1361 IStream* iface,
1362 void* pv, /* [length_is][size_is][out] */
1363 ULONG cb, /* [in] */
1364 ULONG* pcbRead) /* [out] */
1365 {
1366 NoStatStreamImpl* const This = impl_from_IStream(iface);
1367 void* supportBuffer;
1368 ULONG bytesReadBuffer;
1369 ULONG bytesToReadFromBuffer;
1370
1371 if (pcbRead==0)
1372 pcbRead = &bytesReadBuffer;
1373 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
1374 supportBuffer = GlobalLock(This->supportHandle);
1375 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
1376 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
1377 *pcbRead = bytesToReadFromBuffer;
1378 GlobalUnlock(This->supportHandle);
1379 if(*pcbRead == cb)
1380 return S_OK;
1381 return S_FALSE;
1382 }
1383
1384 static HRESULT WINAPI NoStatStreamImpl_Write(
1385 IStream* iface,
1386 const void* pv, /* [size_is][in] */
1387 ULONG cb, /* [in] */
1388 ULONG* pcbWritten) /* [out] */
1389 {
1390 NoStatStreamImpl* const This = impl_from_IStream(iface);
1391 void* supportBuffer;
1392 ULARGE_INTEGER newSize;
1393 ULONG bytesWritten = 0;
1394
1395 if (pcbWritten == 0)
1396 pcbWritten = &bytesWritten;
1397 if (cb == 0)
1398 return S_OK;
1399 newSize.u.HighPart = 0;
1400 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
1401 if (newSize.u.LowPart > This->streamSize.u.LowPart)
1402 IStream_SetSize(iface, newSize);
1403
1404 supportBuffer = GlobalLock(This->supportHandle);
1405 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
1406 This->currentPosition.u.LowPart+=cb;
1407 *pcbWritten = cb;
1408 GlobalUnlock(This->supportHandle);
1409 return S_OK;
1410 }
1411
1412 static HRESULT WINAPI NoStatStreamImpl_Seek(
1413 IStream* iface,
1414 LARGE_INTEGER dlibMove, /* [in] */
1415 DWORD dwOrigin, /* [in] */
1416 ULARGE_INTEGER* plibNewPosition) /* [out] */
1417 {
1418 NoStatStreamImpl* const This = impl_from_IStream(iface);
1419 ULARGE_INTEGER newPosition;
1420 switch (dwOrigin)
1421 {
1422 case STREAM_SEEK_SET:
1423 newPosition.u.HighPart = 0;
1424 newPosition.u.LowPart = 0;
1425 break;
1426 case STREAM_SEEK_CUR:
1427 newPosition = This->currentPosition;
1428 break;
1429 case STREAM_SEEK_END:
1430 newPosition = This->streamSize;
1431 break;
1432 default:
1433 return STG_E_INVALIDFUNCTION;
1434 }
1435 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
1436 return STG_E_INVALIDFUNCTION;
1437 newPosition.QuadPart += dlibMove.QuadPart;
1438 if (plibNewPosition) *plibNewPosition = newPosition;
1439 This->currentPosition = newPosition;
1440 return S_OK;
1441 }
1442
1443 static HRESULT WINAPI NoStatStreamImpl_SetSize(
1444 IStream* iface,
1445 ULARGE_INTEGER libNewSize) /* [in] */
1446 {
1447 NoStatStreamImpl* const This = impl_from_IStream(iface);
1448 HGLOBAL supportHandle;
1449 if (libNewSize.u.HighPart != 0)
1450 return STG_E_INVALIDFUNCTION;
1451 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
1452 return S_OK;
1453 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
1454 if (supportHandle == 0)
1455 return STG_E_MEDIUMFULL;
1456 This->supportHandle = supportHandle;
1457 This->streamSize.u.LowPart = libNewSize.u.LowPart;
1458 return S_OK;
1459 }
1460
1461 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
1462 IStream* iface,
1463 IStream* pstm, /* [unique][in] */
1464 ULARGE_INTEGER cb, /* [in] */
1465 ULARGE_INTEGER* pcbRead, /* [out] */
1466 ULARGE_INTEGER* pcbWritten) /* [out] */
1467 {
1468 HRESULT hr = S_OK;
1469 BYTE tmpBuffer[128];
1470 ULONG bytesRead, bytesWritten, copySize;
1471 ULARGE_INTEGER totalBytesRead;
1472 ULARGE_INTEGER totalBytesWritten;
1473
1474 if ( pstm == 0 )
1475 return STG_E_INVALIDPOINTER;
1476 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
1477 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
1478
1479 while ( cb.u.LowPart > 0 )
1480 {
1481 if ( cb.u.LowPart >= 128 )
1482 copySize = 128;
1483 else
1484 copySize = cb.u.LowPart;
1485 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
1486 totalBytesRead.u.LowPart += bytesRead;
1487 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
1488 totalBytesWritten.u.LowPart += bytesWritten;
1489 if (bytesRead != bytesWritten)
1490 {
1491 hr = STG_E_MEDIUMFULL;
1492 break;
1493 }
1494 if (bytesRead!=copySize)
1495 cb.u.LowPart = 0;
1496 else
1497 cb.u.LowPart -= bytesRead;
1498 }
1499 if (pcbRead)
1500 {
1501 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
1502 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
1503 }
1504
1505 if (pcbWritten)
1506 {
1507 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
1508 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
1509 }
1510 return hr;
1511 }
1512
1513 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
1514 {
1515 return S_OK;
1516 }
1517 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
1518
1519 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
1520 IStream* iface,
1521 ULARGE_INTEGER libOffset, /* [in] */
1522 ULARGE_INTEGER cb, /* [in] */
1523 DWORD dwLockType) /* [in] */
1524 {
1525 return S_OK;
1526 }
1527
1528 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
1529 IStream* iface,
1530 ULARGE_INTEGER libOffset, /* [in] */
1531 ULARGE_INTEGER cb, /* [in] */
1532 DWORD dwLockType) /* [in] */
1533 {
1534 return S_OK;
1535 }
1536
1537 static HRESULT WINAPI NoStatStreamImpl_Stat(
1538 IStream* iface,
1539 STATSTG* pstatstg, /* [out] */
1540 DWORD grfStatFlag) /* [in] */
1541 {
1542 return E_NOTIMPL;
1543 }
1544
1545 static HRESULT WINAPI NoStatStreamImpl_Clone(
1546 IStream* iface,
1547 IStream** ppstm) /* [out] */
1548 {
1549 return E_NOTIMPL;
1550 }
1551 static const IStreamVtbl NoStatStreamImpl_Vtbl;
1552
1553 /*
1554 Build an object that implements IStream, without IStream_Stat capabilities.
1555 Receives a memory handle with data buffer. If memory handle is non-null,
1556 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
1557 In any case the object takes ownership of memory handle and will free it on
1558 object release.
1559 */
1560 static IStream* NoStatStream_Construct(HGLOBAL hGlobal)
1561 {
1562 NoStatStreamImpl* newStream;
1563
1564 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
1565 if (newStream!=0)
1566 {
1567 newStream->IStream_iface.lpVtbl = &NoStatStreamImpl_Vtbl;
1568 newStream->ref = 1;
1569 newStream->supportHandle = hGlobal;
1570
1571 if (!newStream->supportHandle)
1572 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
1573 GMEM_SHARE, 0);
1574 newStream->currentPosition.u.HighPart = 0;
1575 newStream->currentPosition.u.LowPart = 0;
1576 newStream->streamSize.u.HighPart = 0;
1577 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
1578 }
1579 return &newStream->IStream_iface;
1580 }
1581
1582
1583 static const IStreamVtbl NoStatStreamImpl_Vtbl =
1584 {
1585 NoStatStreamImpl_QueryInterface,
1586 NoStatStreamImpl_AddRef,
1587 NoStatStreamImpl_Release,
1588 NoStatStreamImpl_Read,
1589 NoStatStreamImpl_Write,
1590 NoStatStreamImpl_Seek,
1591 NoStatStreamImpl_SetSize,
1592 NoStatStreamImpl_CopyTo,
1593 NoStatStreamImpl_Commit,
1594 NoStatStreamImpl_Revert,
1595 NoStatStreamImpl_LockRegion,
1596 NoStatStreamImpl_UnlockRegion,
1597 NoStatStreamImpl_Stat,
1598 NoStatStreamImpl_Clone
1599 };