[OLEAUT32_WINETEST]
[reactos.git] / rostests / winetests / oleaut32 / olepicture.c
1 /*
2 * OLEPICTURE test program
3 *
4 * Copyright 2005 Marcus Meissner
5 *
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 #include <stdarg.h>
23 #include <stdio.h>
24 #include <math.h>
25 #include <float.h>
26
27 #define COBJMACROS
28 #define NONAMELESSUNION
29
30 #include "wine/test.h"
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winuser.h>
34 #include <wingdi.h>
35 #include <winnls.h>
36 #include <winerror.h>
37 #include <winnt.h>
38
39 #include <wtypes.h>
40 #include <olectl.h>
41 #include <objidl.h>
42
43 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
44
45 #define ole_expect(expr, expect) { \
46 HRESULT r = expr; \
47 ok(r == (expect), #expr " returned %x, expected %s (%x)\n", r, #expect, expect); \
48 }
49
50 #define ole_check(expr) ole_expect(expr, S_OK);
51
52 static HMODULE hOleaut32;
53
54 static HRESULT (WINAPI *pOleLoadPicture)(LPSTREAM,LONG,BOOL,REFIID,LPVOID*);
55 static HRESULT (WINAPI *pOleCreatePictureIndirect)(PICTDESC*,REFIID,BOOL,LPVOID*);
56
57 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
58
59 /* 1x1 pixel gif */
60 static const unsigned char gifimage[35] = {
61 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
62 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
63 0x01,0x00,0x3b
64 };
65
66 /* 1x1 pixel jpg */
67 static const unsigned char jpgimage[285] = {
68 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
69 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
70 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
71 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
72 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
73 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
74 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
75 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
76 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
77 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
78 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
79 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
80 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
81 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
82 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
83 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
84 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
85 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
86 };
87
88 /* 1x1 pixel png */
89 static const unsigned char pngimage[285] = {
90 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
91 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
92 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
93 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
94 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
95 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
96 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
97 };
98
99 /* 1x1 pixel bmp */
100 static const unsigned char bmpimage[66] = {
101 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
102 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
103 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
104 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
105 0x00,0x00
106 };
107
108 /* 2x2 pixel gif */
109 static const unsigned char gif4pixel[42] = {
110 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
111 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
112 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
113 };
114
115 /* APM with an empty metafile with some padding zeros - looks like under Window the
116 * metafile data should be at least 20 bytes */
117 static const unsigned char apmdata[] = {
118 0xd7,0xcd,0xc6,0x9a, 0x00,0x00,0x00,0x00, 0x00,0x00,0xee,0x02, 0xb1,0x03,0xa0,0x05,
119 0x00,0x00,0x00,0x00, 0xee,0x53,0x01,0x00, 0x09,0x00,0x00,0x03, 0x13,0x00,0x00,0x00,
120 0x01,0x00,0x05,0x00, 0x00,0x00,0x00,0x00, 0x03,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
121 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
122 };
123
124 /* MF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
125 static const unsigned char metafile[] = {
126 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
127 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
128 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
129 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
130 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
131 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
132 0x00, 0x00
133 };
134
135 /* EMF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */
136 static const unsigned char enhmetafile[] = {
137 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
142 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
143 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
144 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
147 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
150 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
151 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
152 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
154 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
156 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
157 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
160 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
161 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
162 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
163 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
164 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
165 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
166 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
167 0x14, 0x00, 0x00, 0x00
168 };
169
170
171 struct NoStatStreamImpl
172 {
173 const IStreamVtbl *lpVtbl;
174 LONG ref;
175
176 HGLOBAL supportHandle;
177 ULARGE_INTEGER streamSize;
178 ULARGE_INTEGER currentPosition;
179 };
180 typedef struct NoStatStreamImpl NoStatStreamImpl;
181 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal);
182
183 static void
184 test_pic_with_stream(LPSTREAM stream, unsigned int imgsize)
185 {
186 IPicture* pic = NULL;
187 HRESULT hres;
188 LPVOID pvObj = NULL;
189 OLE_HANDLE handle, hPal;
190 OLE_XSIZE_HIMETRIC width;
191 OLE_YSIZE_HIMETRIC height;
192 short type;
193 DWORD attr;
194 ULONG res;
195
196 pvObj = NULL;
197 hres = pOleLoadPicture(stream, imgsize, TRUE, &IID_IPicture, &pvObj);
198 pic = pvObj;
199
200 ok(hres == S_OK,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres);
201 ok(pic != NULL,"OLP (NULL,..) returns NULL, instead of !NULL\n");
202 if (pic == NULL)
203 return;
204
205 pvObj = NULL;
206 hres = IPicture_QueryInterface (pic, &IID_IPicture, &pvObj);
207
208 ok(hres == S_OK,"IPicture_QI does not return S_OK, but 0x%08x\n", hres);
209 ok(pvObj != NULL,"IPicture_QI does return NULL, instead of a ptr\n");
210
211 IPicture_Release ((IPicture*)pvObj);
212
213 handle = 0;
214 hres = IPicture_get_Handle (pic, &handle);
215 ok(hres == S_OK,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres);
216 ok(handle != 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
217
218 width = 0;
219 hres = IPicture_get_Width (pic, &width);
220 ok(hres == S_OK,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres);
221 ok(width != 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
222
223 height = 0;
224 hres = IPicture_get_Height (pic, &height);
225 ok(hres == S_OK,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres);
226 ok(height != 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
227
228 type = 0;
229 hres = IPicture_get_Type (pic, &type);
230 ok(hres == S_OK,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
231 ok(type == PICTYPE_BITMAP, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type, PICTYPE_BITMAP);
232
233 attr = 0;
234 hres = IPicture_get_Attributes (pic, &attr);
235 ok(hres == S_OK,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres);
236 ok(attr == 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr);
237
238 hPal = 0;
239 hres = IPicture_get_hPal (pic, &hPal);
240 ok(hres == S_OK,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres);
241 /* a single pixel b/w image has no palette */
242 ok(hPal == 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal);
243
244 res = IPicture_Release (pic);
245 ok (res == 0, "refcount after release is %d, but should be 0?\n", res);
246 }
247
248 static void
249 test_pic(const unsigned char *imgdata, unsigned int imgsize)
250 {
251 LPSTREAM stream;
252 HGLOBAL hglob;
253 LPBYTE data;
254 HRESULT hres;
255 LARGE_INTEGER seekto;
256 ULARGE_INTEGER newpos1;
257 DWORD * header;
258 unsigned int i,j;
259
260 /* Let the fun begin */
261 hglob = GlobalAlloc (0, imgsize);
262 data = GlobalLock (hglob);
263 memcpy(data, imgdata, imgsize);
264 GlobalUnlock(hglob); data = NULL;
265
266 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
267 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
268
269 memset(&seekto,0,sizeof(seekto));
270 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
271 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
272 test_pic_with_stream(stream, imgsize);
273
274 IStream_Release(stream);
275
276 /* again with Non Statable and Non Seekable stream */
277 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
278 hglob = 0; /* Non-statable impl always deletes on release */
279 test_pic_with_stream(stream, 0);
280
281 IStream_Release(stream);
282 for (i = 1; i <= 8; i++) {
283 /* more fun!!! */
284 hglob = GlobalAlloc (0, imgsize + i * (2 * sizeof(DWORD)));
285 data = GlobalLock (hglob);
286 header = (DWORD *)data;
287
288 /* multiple copies of header */
289 memcpy(data,"lt\0\0",4);
290 header[1] = imgsize;
291 for (j = 2; j <= i; j++) {
292 memcpy(&(header[2 * (j - 1)]), header, 2 * sizeof(DWORD));
293 }
294 memcpy(data + i * (2 * sizeof(DWORD)), imgdata, imgsize);
295 GlobalUnlock(hglob); data = NULL;
296
297 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
298 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
299
300 memset(&seekto,0,sizeof(seekto));
301 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
302 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
303 test_pic_with_stream(stream, imgsize);
304
305 IStream_Release(stream);
306
307 /* again with Non Statable and Non Seekable stream */
308 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
309 hglob = 0; /* Non-statable impl always deletes on release */
310 test_pic_with_stream(stream, 0);
311
312 IStream_Release(stream);
313 }
314 }
315
316 static void test_empty_image(void) {
317 LPBYTE data;
318 LPSTREAM stream;
319 IPicture* pic = NULL;
320 HRESULT hres;
321 LPVOID pvObj = NULL;
322 HGLOBAL hglob;
323 OLE_HANDLE handle;
324 ULARGE_INTEGER newpos1;
325 LARGE_INTEGER seekto;
326 short type;
327 DWORD attr;
328
329 /* Empty image. Happens occasionally in VB programs. */
330 hglob = GlobalAlloc (0, 8);
331 data = GlobalLock (hglob);
332 memcpy(data,"lt\0\0",4);
333 ((DWORD*)data)[1] = 0;
334 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
335 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
336
337 memset(&seekto,0,sizeof(seekto));
338 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
339 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
340
341 pvObj = NULL;
342 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
343 pic = pvObj;
344 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
345 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
346
347 hres = IPicture_get_Type (pic, &type);
348 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
349 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
350
351 attr = 0xdeadbeef;
352 hres = IPicture_get_Attributes (pic, &attr);
353 ok (hres == S_OK,"empty picture get attributes failed with hres 0x%08x\n", hres);
354 ok (attr == 0,"attr is %d, but should be 0\n", attr);
355
356 hres = IPicture_get_Handle (pic, &handle);
357 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
358 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
359 IPicture_Release (pic);
360 }
361
362 static void test_empty_image_2(void) {
363 LPBYTE data;
364 LPSTREAM stream;
365 IPicture* pic = NULL;
366 HRESULT hres;
367 LPVOID pvObj = NULL;
368 HGLOBAL hglob;
369 ULARGE_INTEGER newpos1;
370 LARGE_INTEGER seekto;
371 short type;
372
373 /* Empty image at random stream position. */
374 hglob = GlobalAlloc (0, 200);
375 data = GlobalLock (hglob);
376 data += 42;
377 memcpy(data,"lt\0\0",4);
378 ((DWORD*)data)[1] = 0;
379 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
380 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
381
382 memset(&seekto,0,sizeof(seekto));
383 seekto.u.LowPart = 42;
384 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
385 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
386
387 pvObj = NULL;
388 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
389 pic = pvObj;
390 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
391 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
392
393 hres = IPicture_get_Type (pic, &type);
394 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
395 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
396
397 IPicture_Release (pic);
398 }
399
400 static void test_Invoke(void)
401 {
402 IPictureDisp *picdisp;
403 HRESULT hr;
404 VARIANTARG vararg;
405 DISPPARAMS dispparams;
406 VARIANT varresult;
407 IStream *stream;
408 HGLOBAL hglob;
409 void *data;
410
411 hglob = GlobalAlloc (0, sizeof(gifimage));
412 data = GlobalLock(hglob);
413 memcpy(data, gifimage, sizeof(gifimage));
414 GlobalUnlock(hglob);
415
416 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
417 ok_ole_success(hr, "CreateStreamOnHGlobal");
418
419 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
420 IStream_Release(stream);
421 ok_ole_success(hr, "OleLoadPicture");
422
423 V_VT(&vararg) = VT_BOOL;
424 V_BOOL(&vararg) = VARIANT_FALSE;
425 dispparams.cNamedArgs = 0;
426 dispparams.rgdispidNamedArgs = NULL;
427 dispparams.cArgs = 1;
428 dispparams.rgvarg = &vararg;
429 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
430 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
431 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
432 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
433
434 dispparams.cArgs = 0;
435 dispparams.rgvarg = NULL;
436 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
437 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
438
439 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
440 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
441
442 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
443 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
444
445 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
446 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
447
448 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
449 ok_ole_success(hr, "IPictureDisp_Invoke");
450 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
451
452 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
453 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
454
455 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
456 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
457
458 dispparams.cArgs = 1;
459 dispparams.rgvarg = &vararg;
460 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
461 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
462
463 dispparams.cArgs = 1;
464 dispparams.rgvarg = &vararg;
465 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
466 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
467
468 IPictureDisp_Release(picdisp);
469 }
470
471 static void test_OleCreatePictureIndirect(void)
472 {
473 IPicture *pict;
474 HRESULT hr;
475 short type;
476 OLE_HANDLE handle;
477
478 if(!pOleCreatePictureIndirect)
479 {
480 win_skip("Skipping OleCreatePictureIndirect tests\n");
481 return;
482 }
483
484 hr = pOleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict);
485 ok(hr == S_OK, "hr %08x\n", hr);
486
487 hr = IPicture_get_Type(pict, &type);
488 ok(hr == S_OK, "hr %08x\n", hr);
489 ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type);
490
491 hr = IPicture_get_Handle(pict, &handle);
492 ok(hr == S_OK, "hr %08x\n", hr);
493 ok(handle == 0, "handle %08x\n", handle);
494
495 IPicture_Release(pict);
496 }
497
498 static void test_apm(void)
499 {
500 OLE_HANDLE handle;
501 LPSTREAM stream;
502 IPicture *pict;
503 HGLOBAL hglob;
504 LPBYTE *data;
505 LONG cxy;
506 BOOL keep;
507 short type;
508
509 hglob = GlobalAlloc (0, sizeof(apmdata));
510 data = GlobalLock(hglob);
511 memcpy(data, apmdata, sizeof(apmdata));
512
513 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
514 ole_check(OleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict));
515
516 ole_check(IPicture_get_Handle(pict, &handle));
517 ok(handle != 0, "handle is null\n");
518
519 ole_check(IPicture_get_Type(pict, &type));
520 expect_eq(type, PICTYPE_METAFILE, short, "%d");
521
522 ole_check(IPicture_get_Height(pict, &cxy));
523 expect_eq(cxy, 1667, LONG, "%d");
524
525 ole_check(IPicture_get_Width(pict, &cxy));
526 expect_eq(cxy, 1323, LONG, "%d");
527
528 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
529 todo_wine expect_eq(keep, FALSE, LONG, "%d");
530
531 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL);
532 IPicture_Release(pict);
533 IStream_Release(stream);
534 }
535
536 static void test_metafile(void)
537 {
538 LPSTREAM stream;
539 IPicture *pict;
540 HGLOBAL hglob;
541 LPBYTE *data;
542
543 hglob = GlobalAlloc (0, sizeof(metafile));
544 data = GlobalLock(hglob);
545 memcpy(data, metafile, sizeof(metafile));
546
547 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
548 /* Windows does not load simple metafiles */
549 ole_expect(OleLoadPictureEx(stream, sizeof(metafile), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict), E_FAIL);
550
551 IStream_Release(stream);
552 }
553
554 static void test_enhmetafile(void)
555 {
556 OLE_HANDLE handle;
557 LPSTREAM stream;
558 IPicture *pict;
559 HGLOBAL hglob;
560 LPBYTE *data;
561 LONG cxy;
562 BOOL keep;
563 short type;
564
565 hglob = GlobalAlloc (0, sizeof(enhmetafile));
566 data = GlobalLock(hglob);
567 memcpy(data, enhmetafile, sizeof(enhmetafile));
568
569 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
570 ole_check(OleLoadPictureEx(stream, sizeof(enhmetafile), TRUE, &IID_IPicture, 10, 10, 0, (LPVOID *)&pict));
571
572 ole_check(IPicture_get_Handle(pict, &handle));
573 ok(handle != 0, "handle is null\n");
574
575 ole_check(IPicture_get_Type(pict, &type));
576 expect_eq(type, PICTYPE_ENHMETAFILE, short, "%d");
577
578 ole_check(IPicture_get_Height(pict, &cxy));
579 expect_eq(cxy, -23, LONG, "%d");
580
581 ole_check(IPicture_get_Width(pict, &cxy));
582 expect_eq(cxy, -25, LONG, "%d");
583
584 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
585 todo_wine expect_eq(keep, FALSE, LONG, "%d");
586
587 IPicture_Release(pict);
588 IStream_Release(stream);
589 }
590
591 static void test_Render(void)
592 {
593 IPicture *pic;
594 HRESULT hres;
595 short type;
596 PICTDESC desc;
597 HDC hdc = GetDC(0);
598
599 /* test IPicture::Render return code on uninitialized picture */
600 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
601 hres = IPicture_get_Type(pic, &type);
602 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
603 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
604 /* zero dimensions */
605 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
606 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
607 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
608 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
609 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
610 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
611 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
612 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
613 hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
614 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
615 hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
616 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
617 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
618 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
619 /* nonzero dimensions, PICTYPE_UNINITIALIZED */
620 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL);
621 ole_expect(hres, S_OK);
622 IPicture_Release(pic);
623
624 desc.cbSizeofstruct = sizeof(PICTDESC);
625 desc.picType = PICTYPE_ICON;
626 desc.u.icon.hicon = LoadIcon(NULL, IDI_APPLICATION);
627 if(!desc.u.icon.hicon){
628 win_skip("LoadIcon failed. Skipping...\n");
629 ReleaseDC(NULL, hdc);
630 return;
631 }
632
633 OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (VOID**)&pic);
634 /* zero dimensions, PICTYPE_ICON */
635 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
636 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
637 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
638 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
639 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
640 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
641 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
642 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
643 hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
644 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
645 hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
646 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
647 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
648 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
649 IPicture_Release(pic);
650
651 ReleaseDC(NULL, hdc);
652 }
653
654 static void test_get_Attributes(void)
655 {
656 IPicture *pic;
657 HRESULT hres;
658 short type;
659 DWORD attr;
660
661 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
662 hres = IPicture_get_Type(pic, &type);
663 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
664 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
665
666 hres = IPicture_get_Attributes(pic, NULL);
667 ole_expect(hres, E_POINTER);
668
669 attr = 0xdeadbeef;
670 hres = IPicture_get_Attributes(pic, &attr);
671 ole_expect(hres, S_OK);
672 ok(attr == 0, "IPicture_get_Attributes does not reset attr to zero, got %d\n", attr);
673
674 IPicture_Release(pic);
675 }
676
677 static void test_get_Handle(void)
678 {
679 IPicture *pic;
680 HRESULT hres;
681
682 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
683
684 hres = IPicture_get_Handle(pic, NULL);
685 ole_expect(hres, E_POINTER);
686
687 IPicture_Release(pic);
688 }
689
690 static void test_get_Type(void)
691 {
692 IPicture *pic;
693 HRESULT hres;
694
695 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
696
697 hres = IPicture_get_Type(pic, NULL);
698 ole_expect(hres, E_POINTER);
699
700 IPicture_Release(pic);
701 }
702
703 START_TEST(olepicture)
704 {
705 hOleaut32 = GetModuleHandleA("oleaut32.dll");
706 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
707 pOleCreatePictureIndirect = (void*)GetProcAddress(hOleaut32, "OleCreatePictureIndirect");
708 if (!pOleLoadPicture)
709 {
710 win_skip("OleLoadPicture is not available\n");
711 return;
712 }
713
714 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
715 test_pic(gifimage, sizeof(gifimage));
716 test_pic(jpgimage, sizeof(jpgimage));
717 test_pic(bmpimage, sizeof(bmpimage));
718 test_pic(gif4pixel, sizeof(gif4pixel));
719 /* FIXME: No PNG support yet in Wine or in older Windows... */
720 if (0) test_pic(pngimage, sizeof(pngimage));
721 test_empty_image();
722 test_empty_image_2();
723 skip("skipping test_apm, see bug 5396\n");
724 //test_apm();
725 test_metafile();
726 skip("skipping test_enhmetafile, see bug 5396\n");
727 //test_enhmetafile();
728
729 test_Invoke();
730 test_OleCreatePictureIndirect();
731 test_Render();
732 test_get_Attributes();
733 test_get_Handle();
734 test_get_Type();
735 }
736
737
738 /* Helper functions only ... */
739
740
741 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
742 {
743 GlobalFree(This->supportHandle);
744 This->supportHandle=0;
745 HeapFree(GetProcessHeap(), 0, This);
746 }
747
748 static ULONG WINAPI NoStatStreamImpl_AddRef(
749 IStream* iface)
750 {
751 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
752 return InterlockedIncrement(&This->ref);
753 }
754
755 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
756 IStream* iface,
757 REFIID riid, /* [in] */
758 void** ppvObject) /* [iid_is][out] */
759 {
760 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
761 if (ppvObject==0) return E_INVALIDARG;
762 *ppvObject = 0;
763 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
764 {
765 *ppvObject = This;
766 }
767 else if (memcmp(&IID_IStream, riid, sizeof(IID_IStream)) == 0)
768 {
769 *ppvObject = This;
770 }
771
772 if ((*ppvObject)==0)
773 return E_NOINTERFACE;
774 NoStatStreamImpl_AddRef(iface);
775 return S_OK;
776 }
777
778 static ULONG WINAPI NoStatStreamImpl_Release(
779 IStream* iface)
780 {
781 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
782 ULONG newRef = InterlockedDecrement(&This->ref);
783 if (newRef==0)
784 NoStatStreamImpl_Destroy(This);
785 return newRef;
786 }
787
788 static HRESULT WINAPI NoStatStreamImpl_Read(
789 IStream* iface,
790 void* pv, /* [length_is][size_is][out] */
791 ULONG cb, /* [in] */
792 ULONG* pcbRead) /* [out] */
793 {
794 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
795 void* supportBuffer;
796 ULONG bytesReadBuffer;
797 ULONG bytesToReadFromBuffer;
798
799 if (pcbRead==0)
800 pcbRead = &bytesReadBuffer;
801 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
802 supportBuffer = GlobalLock(This->supportHandle);
803 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
804 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
805 *pcbRead = bytesToReadFromBuffer;
806 GlobalUnlock(This->supportHandle);
807 if(*pcbRead == cb)
808 return S_OK;
809 return S_FALSE;
810 }
811
812 static HRESULT WINAPI NoStatStreamImpl_Write(
813 IStream* iface,
814 const void* pv, /* [size_is][in] */
815 ULONG cb, /* [in] */
816 ULONG* pcbWritten) /* [out] */
817 {
818 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
819 void* supportBuffer;
820 ULARGE_INTEGER newSize;
821 ULONG bytesWritten = 0;
822
823 if (pcbWritten == 0)
824 pcbWritten = &bytesWritten;
825 if (cb == 0)
826 return S_OK;
827 newSize.u.HighPart = 0;
828 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
829 if (newSize.u.LowPart > This->streamSize.u.LowPart)
830 IStream_SetSize(iface, newSize);
831
832 supportBuffer = GlobalLock(This->supportHandle);
833 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
834 This->currentPosition.u.LowPart+=cb;
835 *pcbWritten = cb;
836 GlobalUnlock(This->supportHandle);
837 return S_OK;
838 }
839
840 static HRESULT WINAPI NoStatStreamImpl_Seek(
841 IStream* iface,
842 LARGE_INTEGER dlibMove, /* [in] */
843 DWORD dwOrigin, /* [in] */
844 ULARGE_INTEGER* plibNewPosition) /* [out] */
845 {
846 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
847 ULARGE_INTEGER newPosition;
848 switch (dwOrigin)
849 {
850 case STREAM_SEEK_SET:
851 newPosition.u.HighPart = 0;
852 newPosition.u.LowPart = 0;
853 break;
854 case STREAM_SEEK_CUR:
855 newPosition = This->currentPosition;
856 break;
857 case STREAM_SEEK_END:
858 newPosition = This->streamSize;
859 break;
860 default:
861 return STG_E_INVALIDFUNCTION;
862 }
863 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
864 return STG_E_INVALIDFUNCTION;
865 newPosition.QuadPart += dlibMove.QuadPart;
866 if (plibNewPosition) *plibNewPosition = newPosition;
867 This->currentPosition = newPosition;
868 return S_OK;
869 }
870
871 static HRESULT WINAPI NoStatStreamImpl_SetSize(
872 IStream* iface,
873 ULARGE_INTEGER libNewSize) /* [in] */
874 {
875 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
876 HGLOBAL supportHandle;
877 if (libNewSize.u.HighPart != 0)
878 return STG_E_INVALIDFUNCTION;
879 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
880 return S_OK;
881 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
882 if (supportHandle == 0)
883 return STG_E_MEDIUMFULL;
884 This->supportHandle = supportHandle;
885 This->streamSize.u.LowPart = libNewSize.u.LowPart;
886 return S_OK;
887 }
888
889 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
890 IStream* iface,
891 IStream* pstm, /* [unique][in] */
892 ULARGE_INTEGER cb, /* [in] */
893 ULARGE_INTEGER* pcbRead, /* [out] */
894 ULARGE_INTEGER* pcbWritten) /* [out] */
895 {
896 HRESULT hr = S_OK;
897 BYTE tmpBuffer[128];
898 ULONG bytesRead, bytesWritten, copySize;
899 ULARGE_INTEGER totalBytesRead;
900 ULARGE_INTEGER totalBytesWritten;
901
902 if ( pstm == 0 )
903 return STG_E_INVALIDPOINTER;
904 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
905 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
906
907 while ( cb.u.LowPart > 0 )
908 {
909 if ( cb.u.LowPart >= 128 )
910 copySize = 128;
911 else
912 copySize = cb.u.LowPart;
913 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
914 totalBytesRead.u.LowPart += bytesRead;
915 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
916 totalBytesWritten.u.LowPart += bytesWritten;
917 if (bytesRead != bytesWritten)
918 {
919 hr = STG_E_MEDIUMFULL;
920 break;
921 }
922 if (bytesRead!=copySize)
923 cb.u.LowPart = 0;
924 else
925 cb.u.LowPart -= bytesRead;
926 }
927 if (pcbRead)
928 {
929 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
930 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
931 }
932
933 if (pcbWritten)
934 {
935 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
936 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
937 }
938 return hr;
939 }
940
941 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
942 {
943 return S_OK;
944 }
945 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
946
947 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
948 IStream* iface,
949 ULARGE_INTEGER libOffset, /* [in] */
950 ULARGE_INTEGER cb, /* [in] */
951 DWORD dwLockType) /* [in] */
952 {
953 return S_OK;
954 }
955
956 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
957 IStream* iface,
958 ULARGE_INTEGER libOffset, /* [in] */
959 ULARGE_INTEGER cb, /* [in] */
960 DWORD dwLockType) /* [in] */
961 {
962 return S_OK;
963 }
964
965 static HRESULT WINAPI NoStatStreamImpl_Stat(
966 IStream* iface,
967 STATSTG* pstatstg, /* [out] */
968 DWORD grfStatFlag) /* [in] */
969 {
970 return E_NOTIMPL;
971 }
972
973 static HRESULT WINAPI NoStatStreamImpl_Clone(
974 IStream* iface,
975 IStream** ppstm) /* [out] */
976 {
977 return E_NOTIMPL;
978 }
979 static const IStreamVtbl NoStatStreamImpl_Vtbl;
980
981 /*
982 Build an object that implements IStream, without IStream_Stat capabilities.
983 Receives a memory handle with data buffer. If memory handle is non-null,
984 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
985 In any case the object takes ownership of memory handle and will free it on
986 object release.
987 */
988 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal)
989 {
990 NoStatStreamImpl* newStream;
991
992 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
993 if (newStream!=0)
994 {
995 newStream->lpVtbl = &NoStatStreamImpl_Vtbl;
996 newStream->ref = 1;
997 newStream->supportHandle = hGlobal;
998
999 if (!newStream->supportHandle)
1000 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
1001 GMEM_SHARE, 0);
1002 newStream->currentPosition.u.HighPart = 0;
1003 newStream->currentPosition.u.LowPart = 0;
1004 newStream->streamSize.u.HighPart = 0;
1005 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
1006 }
1007 return newStream;
1008 }
1009
1010
1011 static const IStreamVtbl NoStatStreamImpl_Vtbl =
1012 {
1013 NoStatStreamImpl_QueryInterface,
1014 NoStatStreamImpl_AddRef,
1015 NoStatStreamImpl_Release,
1016 NoStatStreamImpl_Read,
1017 NoStatStreamImpl_Write,
1018 NoStatStreamImpl_Seek,
1019 NoStatStreamImpl_SetSize,
1020 NoStatStreamImpl_CopyTo,
1021 NoStatStreamImpl_Commit,
1022 NoStatStreamImpl_Revert,
1023 NoStatStreamImpl_LockRegion,
1024 NoStatStreamImpl_UnlockRegion,
1025 NoStatStreamImpl_Stat,
1026 NoStatStreamImpl_Clone
1027 };