2 * OLEPICTURE test program
4 * Copyright 2005 Marcus Meissner
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include <wine/test.h>
43 static HMODULE hOleaut32;
45 static HRESULT (WINAPI *pOleLoadPicture)(LPSTREAM,LONG,BOOL,REFIID,LPVOID*);
46 static HRESULT (WINAPI *pOleCreatePictureIndirect)(PICTDESC*,REFIID,BOOL,LPVOID*);
48 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
51 static const unsigned char gifimage[35] = {
52 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
53 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
58 static const unsigned char jpgimage[285] = {
59 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
60 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
61 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
62 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
63 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
64 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
65 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
66 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
67 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
68 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
69 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
70 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
71 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
72 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
73 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
74 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
75 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
76 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
80 static const unsigned char pngimage[285] = {
81 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
82 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
83 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
84 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
85 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
86 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
87 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
91 static const unsigned char bmpimage[66] = {
92 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
93 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
94 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
95 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
100 static const unsigned char gif4pixel[42] = {
101 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
102 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
103 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
106 struct NoStatStreamImpl
108 const IStreamVtbl *lpVtbl;
111 HGLOBAL supportHandle;
112 ULARGE_INTEGER streamSize;
113 ULARGE_INTEGER currentPosition;
115 typedef struct NoStatStreamImpl NoStatStreamImpl;
116 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal);
119 test_pic_with_stream(LPSTREAM stream, unsigned int imgsize)
121 IPicture* pic = NULL;
124 OLE_HANDLE handle, hPal;
125 OLE_XSIZE_HIMETRIC width;
126 OLE_YSIZE_HIMETRIC height;
132 hres = pOleLoadPicture(stream, imgsize, TRUE, &IID_IPicture, &pvObj);
135 ok(hres == S_OK,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres);
136 ok(pic != NULL,"OLP (NULL,..) returns NULL, instead of !NULL\n");
141 hres = IPicture_QueryInterface (pic, &IID_IPicture, &pvObj);
143 ok(hres == S_OK,"IPicture_QI does not return S_OK, but 0x%08x\n", hres);
144 ok(pvObj != NULL,"IPicture_QI does return NULL, instead of a ptr\n");
146 IPicture_Release ((IPicture*)pvObj);
149 hres = IPicture_get_Handle (pic, &handle);
150 ok(hres == S_OK,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres);
151 ok(handle != 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
154 hres = IPicture_get_Width (pic, &width);
155 ok(hres == S_OK,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres);
156 ok(width != 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
159 hres = IPicture_get_Height (pic, &height);
160 ok(hres == S_OK,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres);
161 ok(height != 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
164 hres = IPicture_get_Type (pic, &type);
165 ok(hres == S_OK,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
166 ok(type == PICTYPE_BITMAP, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type, PICTYPE_BITMAP);
169 hres = IPicture_get_Attributes (pic, &attr);
170 ok(hres == S_OK,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres);
171 ok(attr == 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr);
174 hres = IPicture_get_hPal (pic, &hPal);
175 ok(hres == S_OK,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres);
176 /* a single pixel b/w image has no palette */
177 ok(hPal == 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal);
179 res = IPicture_Release (pic);
180 ok (res == 0, "refcount after release is %d, but should be 0?\n", res);
184 test_pic(const unsigned char *imgdata, unsigned int imgsize)
190 LARGE_INTEGER seekto;
191 ULARGE_INTEGER newpos1;
195 /* Let the fun begin */
196 hglob = GlobalAlloc (0, imgsize);
197 data = GlobalLock (hglob);
198 memcpy(data, imgdata, imgsize);
199 GlobalUnlock(hglob); data = NULL;
201 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
202 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
204 memset(&seekto,0,sizeof(seekto));
205 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
206 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
207 test_pic_with_stream(stream, imgsize);
209 IStream_Release(stream);
211 /* again with Non Statable and Non Seekable stream */
212 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
213 hglob = 0; /* Non-statable impl always deletes on release */
214 test_pic_with_stream(stream, 0);
216 IStream_Release(stream);
217 for (i = 1; i <= 8; i++) {
219 hglob = GlobalAlloc (0, imgsize + i * (2 * sizeof(DWORD)));
220 data = GlobalLock (hglob);
221 header = (DWORD *)data;
223 /* multiple copies of header */
224 memcpy(data,"lt\0\0",4);
226 for (j = 2; j <= i; j++) {
227 memcpy(&(header[2 * (j - 1)]), header, 2 * sizeof(DWORD));
229 memcpy(data + i * (2 * sizeof(DWORD)), imgdata, imgsize);
230 GlobalUnlock(hglob); data = NULL;
232 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
233 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
235 memset(&seekto,0,sizeof(seekto));
236 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
237 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
238 test_pic_with_stream(stream, imgsize);
240 IStream_Release(stream);
242 /* again with Non Statable and Non Seekable stream */
243 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
244 hglob = 0; /* Non-statable impl always deletes on release */
245 test_pic_with_stream(stream, 0);
247 IStream_Release(stream);
251 static void test_empty_image(void) {
254 IPicture* pic = NULL;
259 ULARGE_INTEGER newpos1;
260 LARGE_INTEGER seekto;
263 /* Empty image. Happens occasionally in VB programs. */
264 hglob = GlobalAlloc (0, 8);
265 data = GlobalLock (hglob);
266 memcpy(data,"lt\0\0",4);
267 ((DWORD*)data)[1] = 0;
268 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
269 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
271 memset(&seekto,0,sizeof(seekto));
272 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
273 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
276 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
278 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
279 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
281 hres = IPicture_get_Type (pic, &type);
282 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
283 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
285 hres = IPicture_get_Handle (pic, &handle);
286 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
287 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
288 IPicture_Release (pic);
291 static void test_empty_image_2(void) {
294 IPicture* pic = NULL;
298 ULARGE_INTEGER newpos1;
299 LARGE_INTEGER seekto;
302 /* Empty image at random stream position. */
303 hglob = GlobalAlloc (0, 200);
304 data = GlobalLock (hglob);
306 memcpy(data,"lt\0\0",4);
307 ((DWORD*)data)[1] = 0;
308 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
309 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
311 memset(&seekto,0,sizeof(seekto));
312 seekto.u.LowPart = 42;
313 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
314 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
317 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
319 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
320 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
322 hres = IPicture_get_Type (pic, &type);
323 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
324 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
326 IPicture_Release (pic);
329 static void test_Invoke(void)
331 IPictureDisp *picdisp;
334 DISPPARAMS dispparams;
340 hglob = GlobalAlloc (0, sizeof(gifimage));
341 data = GlobalLock(hglob);
342 memcpy(data, gifimage, sizeof(gifimage));
345 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
346 ok_ole_success(hr, "CreateStreamOnHGlobal");
348 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
349 IStream_Release(stream);
350 ok_ole_success(hr, "OleLoadPicture");
352 V_VT(&vararg) = VT_BOOL;
353 V_BOOL(&vararg) = VARIANT_FALSE;
354 dispparams.cNamedArgs = 0;
355 dispparams.rgdispidNamedArgs = NULL;
356 dispparams.cArgs = 1;
357 dispparams.rgvarg = &vararg;
358 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
359 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
360 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
361 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
363 dispparams.cArgs = 0;
364 dispparams.rgvarg = NULL;
365 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
366 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
368 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
369 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
371 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
372 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
374 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
375 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
377 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
378 ok_ole_success(hr, "IPictureDisp_Invoke");
379 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
381 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
382 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
384 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
385 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
387 dispparams.cArgs = 1;
388 dispparams.rgvarg = &vararg;
389 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
390 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
392 dispparams.cArgs = 1;
393 dispparams.rgvarg = &vararg;
394 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
395 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
397 IPictureDisp_Release(picdisp);
400 static void test_OleCreatePictureIndirect(void)
407 if(!pOleCreatePictureIndirect)
409 skip("Skipping OleCreatePictureIndirect tests\n");
413 hr = pOleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict);
414 ok(hr == S_OK, "hr %08x\n", hr);
416 hr = IPicture_get_Type(pict, &type);
417 ok(hr == S_OK, "hr %08x\n", hr);
418 ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type);
420 hr = IPicture_get_Handle(pict, &handle);
421 ok(hr == S_OK, "hr %08x\n", hr);
422 ok(handle == 0, "handle %08x\n", handle);
424 IPicture_Release(pict);
427 START_TEST(olepicture)
429 hOleaut32 = GetModuleHandleA("oleaut32.dll");
430 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
431 pOleCreatePictureIndirect = (void*)GetProcAddress(hOleaut32, "OleCreatePictureIndirect");
432 if (!pOleLoadPicture)
434 skip("OleLoadPicture is not available\n");
438 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
439 test_pic(gifimage, sizeof(gifimage));
440 test_pic(jpgimage, sizeof(jpgimage));
441 test_pic(bmpimage, sizeof(bmpimage));
442 test_pic(gif4pixel, sizeof(gif4pixel));
443 /* FIXME: No PNG support yet in Wine or in older Windows... */
444 if (0) test_pic(pngimage, sizeof(pngimage));
446 test_empty_image_2();
449 test_OleCreatePictureIndirect();
453 /* Helper functions only ... */
456 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
458 GlobalFree(This->supportHandle);
459 This->supportHandle=0;
460 HeapFree(GetProcessHeap(), 0, This);
463 static ULONG WINAPI NoStatStreamImpl_AddRef(
466 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
467 return InterlockedIncrement(&This->ref);
470 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
472 REFIID riid, /* [in] */
473 void** ppvObject) /* [iid_is][out] */
475 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
476 if (ppvObject==0) return E_INVALIDARG;
478 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
480 *ppvObject = (IStream*)This;
482 else if (memcmp(&IID_IStream, riid, sizeof(IID_IStream)) == 0)
484 *ppvObject = (IStream*)This;
488 return E_NOINTERFACE;
489 NoStatStreamImpl_AddRef(iface);
493 static ULONG WINAPI NoStatStreamImpl_Release(
496 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
497 ULONG newRef = InterlockedDecrement(&This->ref);
499 NoStatStreamImpl_Destroy(This);
503 static HRESULT WINAPI NoStatStreamImpl_Read(
505 void* pv, /* [length_is][size_is][out] */
507 ULONG* pcbRead) /* [out] */
509 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
511 ULONG bytesReadBuffer;
512 ULONG bytesToReadFromBuffer;
515 pcbRead = &bytesReadBuffer;
516 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
517 supportBuffer = GlobalLock(This->supportHandle);
518 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
519 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
520 *pcbRead = bytesToReadFromBuffer;
521 GlobalUnlock(This->supportHandle);
527 static HRESULT WINAPI NoStatStreamImpl_Write(
529 const void* pv, /* [size_is][in] */
531 ULONG* pcbWritten) /* [out] */
533 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
535 ULARGE_INTEGER newSize;
536 ULONG bytesWritten = 0;
539 pcbWritten = &bytesWritten;
542 newSize.u.HighPart = 0;
543 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
544 if (newSize.u.LowPart > This->streamSize.u.LowPart)
545 IStream_SetSize(iface, newSize);
547 supportBuffer = GlobalLock(This->supportHandle);
548 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
549 This->currentPosition.u.LowPart+=cb;
551 GlobalUnlock(This->supportHandle);
555 static HRESULT WINAPI NoStatStreamImpl_Seek(
557 LARGE_INTEGER dlibMove, /* [in] */
558 DWORD dwOrigin, /* [in] */
559 ULARGE_INTEGER* plibNewPosition) /* [out] */
561 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
562 ULARGE_INTEGER newPosition;
565 case STREAM_SEEK_SET:
566 newPosition.u.HighPart = 0;
567 newPosition.u.LowPart = 0;
569 case STREAM_SEEK_CUR:
570 newPosition = This->currentPosition;
572 case STREAM_SEEK_END:
573 newPosition = This->streamSize;
576 return STG_E_INVALIDFUNCTION;
578 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
579 return STG_E_INVALIDFUNCTION;
580 newPosition.QuadPart += dlibMove.QuadPart;
581 if (plibNewPosition) *plibNewPosition = newPosition;
582 This->currentPosition = newPosition;
586 static HRESULT WINAPI NoStatStreamImpl_SetSize(
588 ULARGE_INTEGER libNewSize) /* [in] */
590 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
591 HGLOBAL supportHandle;
592 if (libNewSize.u.HighPart != 0)
593 return STG_E_INVALIDFUNCTION;
594 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
596 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
597 if (supportHandle == 0)
598 return STG_E_MEDIUMFULL;
599 This->supportHandle = supportHandle;
600 This->streamSize.u.LowPart = libNewSize.u.LowPart;
604 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
606 IStream* pstm, /* [unique][in] */
607 ULARGE_INTEGER cb, /* [in] */
608 ULARGE_INTEGER* pcbRead, /* [out] */
609 ULARGE_INTEGER* pcbWritten) /* [out] */
613 ULONG bytesRead, bytesWritten, copySize;
614 ULARGE_INTEGER totalBytesRead;
615 ULARGE_INTEGER totalBytesWritten;
618 return STG_E_INVALIDPOINTER;
619 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
620 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
622 while ( cb.u.LowPart > 0 )
624 if ( cb.u.LowPart >= 128 )
627 copySize = cb.u.LowPart;
628 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
629 totalBytesRead.u.LowPart += bytesRead;
630 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
631 totalBytesWritten.u.LowPart += bytesWritten;
632 if (bytesRead != bytesWritten)
634 hr = STG_E_MEDIUMFULL;
637 if (bytesRead!=copySize)
640 cb.u.LowPart -= bytesRead;
644 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
645 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
650 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
651 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
656 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
660 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
662 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
664 ULARGE_INTEGER libOffset, /* [in] */
665 ULARGE_INTEGER cb, /* [in] */
666 DWORD dwLockType) /* [in] */
671 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
673 ULARGE_INTEGER libOffset, /* [in] */
674 ULARGE_INTEGER cb, /* [in] */
675 DWORD dwLockType) /* [in] */
680 static HRESULT WINAPI NoStatStreamImpl_Stat(
682 STATSTG* pstatstg, /* [out] */
683 DWORD grfStatFlag) /* [in] */
688 static HRESULT WINAPI NoStatStreamImpl_Clone(
690 IStream** ppstm) /* [out] */
694 static const IStreamVtbl NoStatStreamImpl_Vtbl;
697 Build an object that implements IStream, without IStream_Stat capabilities.
698 Receives a memory handle with data buffer. If memory handle is non-null,
699 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
700 In any case the object takes ownership of memory handle and will free it on
703 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal)
705 NoStatStreamImpl* newStream;
707 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
710 newStream->lpVtbl = &NoStatStreamImpl_Vtbl;
712 newStream->supportHandle = hGlobal;
714 if (!newStream->supportHandle)
715 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
717 newStream->currentPosition.u.HighPart = 0;
718 newStream->currentPosition.u.LowPart = 0;
719 newStream->streamSize.u.HighPart = 0;
720 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
726 static const IStreamVtbl NoStatStreamImpl_Vtbl =
728 NoStatStreamImpl_QueryInterface,
729 NoStatStreamImpl_AddRef,
730 NoStatStreamImpl_Release,
731 NoStatStreamImpl_Read,
732 NoStatStreamImpl_Write,
733 NoStatStreamImpl_Seek,
734 NoStatStreamImpl_SetSize,
735 NoStatStreamImpl_CopyTo,
736 NoStatStreamImpl_Commit,
737 NoStatStreamImpl_Revert,
738 NoStatStreamImpl_LockRegion,
739 NoStatStreamImpl_UnlockRegion,
740 NoStatStreamImpl_Stat,
741 NoStatStreamImpl_Clone