sync oleaut32_winetest with wine 1.1.12
[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
328 /* Empty image. Happens occasionally in VB programs. */
329 hglob = GlobalAlloc (0, 8);
330 data = GlobalLock (hglob);
331 memcpy(data,"lt\0\0",4);
332 ((DWORD*)data)[1] = 0;
333 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
334 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
335
336 memset(&seekto,0,sizeof(seekto));
337 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
338 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
339
340 pvObj = NULL;
341 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
342 pic = pvObj;
343 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
344 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
345
346 hres = IPicture_get_Type (pic, &type);
347 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
348 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
349
350 hres = IPicture_get_Handle (pic, &handle);
351 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
352 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
353 IPicture_Release (pic);
354 }
355
356 static void test_empty_image_2(void) {
357 LPBYTE data;
358 LPSTREAM stream;
359 IPicture* pic = NULL;
360 HRESULT hres;
361 LPVOID pvObj = NULL;
362 HGLOBAL hglob;
363 ULARGE_INTEGER newpos1;
364 LARGE_INTEGER seekto;
365 short type;
366
367 /* Empty image at random stream position. */
368 hglob = GlobalAlloc (0, 200);
369 data = GlobalLock (hglob);
370 data += 42;
371 memcpy(data,"lt\0\0",4);
372 ((DWORD*)data)[1] = 0;
373 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
374 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
375
376 memset(&seekto,0,sizeof(seekto));
377 seekto.u.LowPart = 42;
378 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
379 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
380
381 pvObj = NULL;
382 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
383 pic = pvObj;
384 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
385 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
386
387 hres = IPicture_get_Type (pic, &type);
388 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
389 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
390
391 IPicture_Release (pic);
392 }
393
394 static void test_Invoke(void)
395 {
396 IPictureDisp *picdisp;
397 HRESULT hr;
398 VARIANTARG vararg;
399 DISPPARAMS dispparams;
400 VARIANT varresult;
401 IStream *stream;
402 HGLOBAL hglob;
403 void *data;
404
405 hglob = GlobalAlloc (0, sizeof(gifimage));
406 data = GlobalLock(hglob);
407 memcpy(data, gifimage, sizeof(gifimage));
408 GlobalUnlock(hglob);
409
410 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
411 ok_ole_success(hr, "CreateStreamOnHGlobal");
412
413 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
414 IStream_Release(stream);
415 ok_ole_success(hr, "OleLoadPicture");
416
417 V_VT(&vararg) = VT_BOOL;
418 V_BOOL(&vararg) = VARIANT_FALSE;
419 dispparams.cNamedArgs = 0;
420 dispparams.rgdispidNamedArgs = NULL;
421 dispparams.cArgs = 1;
422 dispparams.rgvarg = &vararg;
423 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
424 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
425 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
426 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
427
428 dispparams.cArgs = 0;
429 dispparams.rgvarg = NULL;
430 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
431 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
432
433 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
434 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
435
436 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
437 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
438
439 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, 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, &dispparams, &varresult, NULL, NULL);
443 ok_ole_success(hr, "IPictureDisp_Invoke");
444 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
445
446 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
447 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
448
449 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
450 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
451
452 dispparams.cArgs = 1;
453 dispparams.rgvarg = &vararg;
454 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
455 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
456
457 dispparams.cArgs = 1;
458 dispparams.rgvarg = &vararg;
459 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
460 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
461
462 IPictureDisp_Release(picdisp);
463 }
464
465 static void test_OleCreatePictureIndirect(void)
466 {
467 IPicture *pict;
468 HRESULT hr;
469 short type;
470 OLE_HANDLE handle;
471
472 if(!pOleCreatePictureIndirect)
473 {
474 skip("Skipping OleCreatePictureIndirect tests\n");
475 return;
476 }
477
478 hr = pOleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict);
479 ok(hr == S_OK, "hr %08x\n", hr);
480
481 hr = IPicture_get_Type(pict, &type);
482 ok(hr == S_OK, "hr %08x\n", hr);
483 ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type);
484
485 hr = IPicture_get_Handle(pict, &handle);
486 ok(hr == S_OK, "hr %08x\n", hr);
487 ok(handle == 0, "handle %08x\n", handle);
488
489 IPicture_Release(pict);
490 }
491
492 static void test_apm()
493 {
494 OLE_HANDLE handle;
495 LPSTREAM stream;
496 IPicture *pict;
497 HGLOBAL hglob;
498 LPBYTE *data;
499 LONG cxy;
500 BOOL keep;
501 short type;
502
503 hglob = GlobalAlloc (0, sizeof(apmdata));
504 data = GlobalLock(hglob);
505 memcpy(data, apmdata, sizeof(apmdata));
506
507 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
508 ole_check(OleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict));
509
510 ole_check(IPicture_get_Handle(pict, &handle));
511 ok(handle != 0, "handle is null\n");
512
513 ole_check(IPicture_get_Type(pict, &type));
514 expect_eq(type, PICTYPE_METAFILE, short, "%d");
515
516 ole_check(IPicture_get_Height(pict, &cxy));
517 expect_eq(cxy, 1667, LONG, "%d");
518
519 ole_check(IPicture_get_Width(pict, &cxy));
520 expect_eq(cxy, 1323, LONG, "%d");
521
522 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
523 todo_wine expect_eq(keep, FALSE, LONG, "%d");
524
525 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL);
526 IPicture_Release(pict);
527 IStream_Release(stream);
528 }
529
530 static void test_metafile(void)
531 {
532 LPSTREAM stream;
533 IPicture *pict;
534 HGLOBAL hglob;
535 LPBYTE *data;
536
537 hglob = GlobalAlloc (0, sizeof(metafile));
538 data = GlobalLock(hglob);
539 memcpy(data, metafile, sizeof(metafile));
540
541 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
542 /* Windows does not load simple metafiles */
543 ole_expect(OleLoadPictureEx(stream, sizeof(metafile), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict), E_FAIL);
544
545 IStream_Release(stream);
546 }
547
548 static void test_enhmetafile(void)
549 {
550 OLE_HANDLE handle;
551 LPSTREAM stream;
552 IPicture *pict;
553 HGLOBAL hglob;
554 LPBYTE *data;
555 LONG cxy;
556 BOOL keep;
557 short type;
558
559 hglob = GlobalAlloc (0, sizeof(enhmetafile));
560 data = GlobalLock(hglob);
561 memcpy(data, enhmetafile, sizeof(enhmetafile));
562
563 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
564 ole_check(OleLoadPictureEx(stream, sizeof(enhmetafile), TRUE, &IID_IPicture, 10, 10, 0, (LPVOID *)&pict));
565
566 ole_check(IPicture_get_Handle(pict, &handle));
567 ok(handle != 0, "handle is null\n");
568
569 ole_check(IPicture_get_Type(pict, &type));
570 expect_eq(type, PICTYPE_ENHMETAFILE, short, "%d");
571
572 ole_check(IPicture_get_Height(pict, &cxy));
573 expect_eq(cxy, -23, LONG, "%d");
574
575 ole_check(IPicture_get_Width(pict, &cxy));
576 expect_eq(cxy, -25, LONG, "%d");
577
578 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
579 todo_wine expect_eq(keep, FALSE, LONG, "%d");
580
581 IPicture_Release(pict);
582 IStream_Release(stream);
583 }
584
585 static void test_Render(void)
586 {
587 IPicture *pic;
588 HRESULT hres;
589 short type;
590 PICTDESC desc;
591 HDC hdc = GetDC(0);
592
593 /* test IPicture::Render return code on uninitialized picture */
594 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (VOID**)&pic);
595 hres = IPicture_get_Type(pic, &type);
596 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
597 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
598 /* zero dimensions */
599 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
600 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
601 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
602 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
603 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
604 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
605 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
606 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
607 hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
608 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
609 hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
610 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
611 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
612 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
613 /* nonzero dimensions, PICTYPE_UNINITIALIZED */
614 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL);
615 ole_expect(hres, S_OK);
616 IPicture_Release(pic);
617
618 desc.cbSizeofstruct = sizeof(PICTDESC);
619 desc.picType = PICTYPE_ICON;
620 desc.u.icon.hicon = LoadIcon(NULL, IDI_APPLICATION);
621 if(!desc.u.icon.hicon){
622 win_skip("LoadIcon failed. Skipping...\n");
623 ReleaseDC(NULL, hdc);
624 return;
625 }
626
627 OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (VOID**)&pic);
628 /* zero dimensions, PICTYPE_ICON */
629 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
630 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
631 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
632 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
633 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
634 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
635 hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
636 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
637 hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
638 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
639 hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
640 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
641 hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
642 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
643 IPicture_Release(pic);
644
645 ReleaseDC(NULL, hdc);
646 }
647
648 START_TEST(olepicture)
649 {
650 hOleaut32 = GetModuleHandleA("oleaut32.dll");
651 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
652 pOleCreatePictureIndirect = (void*)GetProcAddress(hOleaut32, "OleCreatePictureIndirect");
653 if (!pOleLoadPicture)
654 {
655 skip("OleLoadPicture is not available\n");
656 return;
657 }
658
659 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
660 test_pic(gifimage, sizeof(gifimage));
661 test_pic(jpgimage, sizeof(jpgimage));
662 test_pic(bmpimage, sizeof(bmpimage));
663 test_pic(gif4pixel, sizeof(gif4pixel));
664 /* FIXME: No PNG support yet in Wine or in older Windows... */
665 if (0) test_pic(pngimage, sizeof(pngimage));
666 test_empty_image();
667 test_empty_image_2();
668 test_apm();
669 test_metafile();
670 test_enhmetafile();
671
672 test_Invoke();
673 test_OleCreatePictureIndirect();
674 test_Render();
675 }
676
677
678 /* Helper functions only ... */
679
680
681 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
682 {
683 GlobalFree(This->supportHandle);
684 This->supportHandle=0;
685 HeapFree(GetProcessHeap(), 0, This);
686 }
687
688 static ULONG WINAPI NoStatStreamImpl_AddRef(
689 IStream* iface)
690 {
691 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
692 return InterlockedIncrement(&This->ref);
693 }
694
695 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
696 IStream* iface,
697 REFIID riid, /* [in] */
698 void** ppvObject) /* [iid_is][out] */
699 {
700 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
701 if (ppvObject==0) return E_INVALIDARG;
702 *ppvObject = 0;
703 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
704 {
705 *ppvObject = (IStream*)This;
706 }
707 else if (memcmp(&IID_IStream, riid, sizeof(IID_IStream)) == 0)
708 {
709 *ppvObject = (IStream*)This;
710 }
711
712 if ((*ppvObject)==0)
713 return E_NOINTERFACE;
714 NoStatStreamImpl_AddRef(iface);
715 return S_OK;
716 }
717
718 static ULONG WINAPI NoStatStreamImpl_Release(
719 IStream* iface)
720 {
721 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
722 ULONG newRef = InterlockedDecrement(&This->ref);
723 if (newRef==0)
724 NoStatStreamImpl_Destroy(This);
725 return newRef;
726 }
727
728 static HRESULT WINAPI NoStatStreamImpl_Read(
729 IStream* iface,
730 void* pv, /* [length_is][size_is][out] */
731 ULONG cb, /* [in] */
732 ULONG* pcbRead) /* [out] */
733 {
734 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
735 void* supportBuffer;
736 ULONG bytesReadBuffer;
737 ULONG bytesToReadFromBuffer;
738
739 if (pcbRead==0)
740 pcbRead = &bytesReadBuffer;
741 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
742 supportBuffer = GlobalLock(This->supportHandle);
743 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
744 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
745 *pcbRead = bytesToReadFromBuffer;
746 GlobalUnlock(This->supportHandle);
747 if(*pcbRead == cb)
748 return S_OK;
749 return S_FALSE;
750 }
751
752 static HRESULT WINAPI NoStatStreamImpl_Write(
753 IStream* iface,
754 const void* pv, /* [size_is][in] */
755 ULONG cb, /* [in] */
756 ULONG* pcbWritten) /* [out] */
757 {
758 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
759 void* supportBuffer;
760 ULARGE_INTEGER newSize;
761 ULONG bytesWritten = 0;
762
763 if (pcbWritten == 0)
764 pcbWritten = &bytesWritten;
765 if (cb == 0)
766 return S_OK;
767 newSize.u.HighPart = 0;
768 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
769 if (newSize.u.LowPart > This->streamSize.u.LowPart)
770 IStream_SetSize(iface, newSize);
771
772 supportBuffer = GlobalLock(This->supportHandle);
773 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
774 This->currentPosition.u.LowPart+=cb;
775 *pcbWritten = cb;
776 GlobalUnlock(This->supportHandle);
777 return S_OK;
778 }
779
780 static HRESULT WINAPI NoStatStreamImpl_Seek(
781 IStream* iface,
782 LARGE_INTEGER dlibMove, /* [in] */
783 DWORD dwOrigin, /* [in] */
784 ULARGE_INTEGER* plibNewPosition) /* [out] */
785 {
786 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
787 ULARGE_INTEGER newPosition;
788 switch (dwOrigin)
789 {
790 case STREAM_SEEK_SET:
791 newPosition.u.HighPart = 0;
792 newPosition.u.LowPart = 0;
793 break;
794 case STREAM_SEEK_CUR:
795 newPosition = This->currentPosition;
796 break;
797 case STREAM_SEEK_END:
798 newPosition = This->streamSize;
799 break;
800 default:
801 return STG_E_INVALIDFUNCTION;
802 }
803 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
804 return STG_E_INVALIDFUNCTION;
805 newPosition.QuadPart += dlibMove.QuadPart;
806 if (plibNewPosition) *plibNewPosition = newPosition;
807 This->currentPosition = newPosition;
808 return S_OK;
809 }
810
811 static HRESULT WINAPI NoStatStreamImpl_SetSize(
812 IStream* iface,
813 ULARGE_INTEGER libNewSize) /* [in] */
814 {
815 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
816 HGLOBAL supportHandle;
817 if (libNewSize.u.HighPart != 0)
818 return STG_E_INVALIDFUNCTION;
819 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
820 return S_OK;
821 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
822 if (supportHandle == 0)
823 return STG_E_MEDIUMFULL;
824 This->supportHandle = supportHandle;
825 This->streamSize.u.LowPart = libNewSize.u.LowPart;
826 return S_OK;
827 }
828
829 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
830 IStream* iface,
831 IStream* pstm, /* [unique][in] */
832 ULARGE_INTEGER cb, /* [in] */
833 ULARGE_INTEGER* pcbRead, /* [out] */
834 ULARGE_INTEGER* pcbWritten) /* [out] */
835 {
836 HRESULT hr = S_OK;
837 BYTE tmpBuffer[128];
838 ULONG bytesRead, bytesWritten, copySize;
839 ULARGE_INTEGER totalBytesRead;
840 ULARGE_INTEGER totalBytesWritten;
841
842 if ( pstm == 0 )
843 return STG_E_INVALIDPOINTER;
844 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
845 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
846
847 while ( cb.u.LowPart > 0 )
848 {
849 if ( cb.u.LowPart >= 128 )
850 copySize = 128;
851 else
852 copySize = cb.u.LowPart;
853 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
854 totalBytesRead.u.LowPart += bytesRead;
855 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
856 totalBytesWritten.u.LowPart += bytesWritten;
857 if (bytesRead != bytesWritten)
858 {
859 hr = STG_E_MEDIUMFULL;
860 break;
861 }
862 if (bytesRead!=copySize)
863 cb.u.LowPart = 0;
864 else
865 cb.u.LowPart -= bytesRead;
866 }
867 if (pcbRead)
868 {
869 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
870 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
871 }
872
873 if (pcbWritten)
874 {
875 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
876 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
877 }
878 return hr;
879 }
880
881 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
882 {
883 return S_OK;
884 }
885 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
886
887 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
888 IStream* iface,
889 ULARGE_INTEGER libOffset, /* [in] */
890 ULARGE_INTEGER cb, /* [in] */
891 DWORD dwLockType) /* [in] */
892 {
893 return S_OK;
894 }
895
896 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
897 IStream* iface,
898 ULARGE_INTEGER libOffset, /* [in] */
899 ULARGE_INTEGER cb, /* [in] */
900 DWORD dwLockType) /* [in] */
901 {
902 return S_OK;
903 }
904
905 static HRESULT WINAPI NoStatStreamImpl_Stat(
906 IStream* iface,
907 STATSTG* pstatstg, /* [out] */
908 DWORD grfStatFlag) /* [in] */
909 {
910 return E_NOTIMPL;
911 }
912
913 static HRESULT WINAPI NoStatStreamImpl_Clone(
914 IStream* iface,
915 IStream** ppstm) /* [out] */
916 {
917 return E_NOTIMPL;
918 }
919 static const IStreamVtbl NoStatStreamImpl_Vtbl;
920
921 /*
922 Build an object that implements IStream, without IStream_Stat capabilities.
923 Receives a memory handle with data buffer. If memory handle is non-null,
924 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
925 In any case the object takes ownership of memory handle and will free it on
926 object release.
927 */
928 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal)
929 {
930 NoStatStreamImpl* newStream;
931
932 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
933 if (newStream!=0)
934 {
935 newStream->lpVtbl = &NoStatStreamImpl_Vtbl;
936 newStream->ref = 1;
937 newStream->supportHandle = hGlobal;
938
939 if (!newStream->supportHandle)
940 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
941 GMEM_SHARE, 0);
942 newStream->currentPosition.u.HighPart = 0;
943 newStream->currentPosition.u.LowPart = 0;
944 newStream->streamSize.u.HighPart = 0;
945 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
946 }
947 return newStream;
948 }
949
950
951 static const IStreamVtbl NoStatStreamImpl_Vtbl =
952 {
953 NoStatStreamImpl_QueryInterface,
954 NoStatStreamImpl_AddRef,
955 NoStatStreamImpl_Release,
956 NoStatStreamImpl_Read,
957 NoStatStreamImpl_Write,
958 NoStatStreamImpl_Seek,
959 NoStatStreamImpl_SetSize,
960 NoStatStreamImpl_CopyTo,
961 NoStatStreamImpl_Commit,
962 NoStatStreamImpl_Revert,
963 NoStatStreamImpl_LockRegion,
964 NoStatStreamImpl_UnlockRegion,
965 NoStatStreamImpl_Stat,
966 NoStatStreamImpl_Clone
967 };