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*);
47 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
50 static const unsigned char gifimage[35] = {
51 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
52 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
57 static const unsigned char jpgimage[285] = {
58 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
59 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
60 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
61 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
62 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
63 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
64 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
65 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,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,0xff,0xc0,
68 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
69 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
70 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
71 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
72 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
73 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
74 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
75 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
79 static const unsigned char pngimage[285] = {
80 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
81 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
82 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
83 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
84 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
85 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
86 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
90 static const unsigned char bmpimage[66] = {
91 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
92 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
93 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
94 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
99 static const unsigned char gif4pixel[42] = {
100 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
101 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
102 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
105 struct NoStatStreamImpl
107 const IStreamVtbl *lpVtbl;
110 HGLOBAL supportHandle;
111 ULARGE_INTEGER streamSize;
112 ULARGE_INTEGER currentPosition;
114 typedef struct NoStatStreamImpl NoStatStreamImpl;
115 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal);
118 test_pic_with_stream(LPSTREAM stream, unsigned int imgsize)
120 IPicture* pic = NULL;
123 OLE_HANDLE handle, hPal;
124 OLE_XSIZE_HIMETRIC width;
125 OLE_YSIZE_HIMETRIC height;
131 hres = pOleLoadPicture(stream, imgsize, TRUE, &IID_IPicture, &pvObj);
134 ok(hres == S_OK,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres);
135 ok(pic != NULL,"OLP (NULL,..) returns NULL, instead of !NULL\n");
140 hres = IPicture_QueryInterface (pic, &IID_IPicture, &pvObj);
142 ok(hres == S_OK,"IPicture_QI does not return S_OK, but 0x%08x\n", hres);
143 ok(pvObj != NULL,"IPicture_QI does return NULL, instead of a ptr\n");
145 IPicture_Release ((IPicture*)pvObj);
148 hres = IPicture_get_Handle (pic, &handle);
149 ok(hres == S_OK,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres);
150 ok(handle != 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
153 hres = IPicture_get_Width (pic, &width);
154 ok(hres == S_OK,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres);
155 ok(width != 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
158 hres = IPicture_get_Height (pic, &height);
159 ok(hres == S_OK,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres);
160 ok(height != 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
163 hres = IPicture_get_Type (pic, &type);
164 ok(hres == S_OK,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
165 ok(type == PICTYPE_BITMAP, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type, PICTYPE_BITMAP);
168 hres = IPicture_get_Attributes (pic, &attr);
169 ok(hres == S_OK,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres);
170 ok(attr == 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr);
173 hres = IPicture_get_hPal (pic, &hPal);
174 ok(hres == S_OK,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres);
175 /* a single pixel b/w image has no palette */
176 ok(hPal == 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal);
178 res = IPicture_Release (pic);
179 ok (res == 0, "refcount after release is %d, but should be 0?\n", res);
183 test_pic(const unsigned char *imgdata, unsigned int imgsize)
189 LARGE_INTEGER seekto;
190 ULARGE_INTEGER newpos1;
194 /* Let the fun begin */
195 hglob = GlobalAlloc (0, imgsize);
196 data = GlobalLock (hglob);
197 memcpy(data, imgdata, imgsize);
198 GlobalUnlock(hglob); data = NULL;
200 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
201 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
203 memset(&seekto,0,sizeof(seekto));
204 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
205 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
206 test_pic_with_stream(stream, imgsize);
208 IStream_Release(stream);
210 /* again with Non Statable and Non Seekable stream */
211 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
212 hglob = 0; /* Non-statable impl always deletes on release */
213 test_pic_with_stream(stream, 0);
215 IStream_Release(stream);
216 for (i = 1; i <= 8; i++) {
218 hglob = GlobalAlloc (0, imgsize + i * (2 * sizeof(DWORD)));
219 data = GlobalLock (hglob);
220 header = (DWORD *)data;
222 /* multiple copies of header */
223 memcpy(data,"lt\0\0",4);
225 for (j = 2; j <= i; j++) {
226 memcpy(&(header[2 * (j - 1)]), header, 2 * sizeof(DWORD));
228 memcpy(data + i * (2 * sizeof(DWORD)), imgdata, imgsize);
229 GlobalUnlock(hglob); data = NULL;
231 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
232 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
234 memset(&seekto,0,sizeof(seekto));
235 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
236 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
237 test_pic_with_stream(stream, imgsize);
239 IStream_Release(stream);
241 /* again with Non Statable and Non Seekable stream */
242 stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
243 hglob = 0; /* Non-statable impl always deletes on release */
244 test_pic_with_stream(stream, 0);
246 IStream_Release(stream);
250 static void test_empty_image(void) {
253 IPicture* pic = NULL;
258 ULARGE_INTEGER newpos1;
259 LARGE_INTEGER seekto;
262 /* Empty image. Happens occasionally in VB programs. */
263 hglob = GlobalAlloc (0, 8);
264 data = GlobalLock (hglob);
265 memcpy(data,"lt\0\0",4);
266 ((DWORD*)data)[1] = 0;
267 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
268 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
270 memset(&seekto,0,sizeof(seekto));
271 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
272 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
275 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
277 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
278 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
280 hres = IPicture_get_Type (pic, &type);
281 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
282 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
284 hres = IPicture_get_Handle (pic, &handle);
285 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
286 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
287 IPicture_Release (pic);
290 static void test_empty_image_2(void) {
293 IPicture* pic = NULL;
297 ULARGE_INTEGER newpos1;
298 LARGE_INTEGER seekto;
301 /* Empty image at random stream position. */
302 hglob = GlobalAlloc (0, 200);
303 data = GlobalLock (hglob);
305 memcpy(data,"lt\0\0",4);
306 ((DWORD*)data)[1] = 0;
307 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
308 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
310 memset(&seekto,0,sizeof(seekto));
311 seekto.u.LowPart = 42;
312 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
313 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
316 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
318 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
319 ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
321 hres = IPicture_get_Type (pic, &type);
322 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
323 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
325 IPicture_Release (pic);
328 static void test_Invoke(void)
330 IPictureDisp *picdisp;
333 DISPPARAMS dispparams;
339 hglob = GlobalAlloc (0, sizeof(gifimage));
340 data = GlobalLock(hglob);
341 memcpy(data, gifimage, sizeof(gifimage));
344 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
345 ok_ole_success(hr, "CreateStreamOnHGlobal");
347 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
348 IStream_Release(stream);
349 ok_ole_success(hr, "OleLoadPicture");
351 V_VT(&vararg) = VT_BOOL;
352 V_BOOL(&vararg) = VARIANT_FALSE;
353 dispparams.cNamedArgs = 0;
354 dispparams.rgdispidNamedArgs = NULL;
355 dispparams.cArgs = 1;
356 dispparams.rgvarg = &vararg;
357 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
358 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
359 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
360 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
362 dispparams.cArgs = 0;
363 dispparams.rgvarg = NULL;
364 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
365 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
367 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
368 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
370 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
371 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
373 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
374 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
376 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
377 ok_ole_success(hr, "IPictureDisp_Invoke");
378 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
380 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
381 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
383 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
384 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
386 dispparams.cArgs = 1;
387 dispparams.rgvarg = &vararg;
388 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
389 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
391 dispparams.cArgs = 1;
392 dispparams.rgvarg = &vararg;
393 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
394 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
396 IPictureDisp_Release(picdisp);
399 START_TEST(olepicture)
401 hOleaut32 = LoadLibraryA("oleaut32.dll");
402 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
403 if (!pOleLoadPicture)
406 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
407 test_pic(gifimage, sizeof(gifimage));
408 test_pic(jpgimage, sizeof(jpgimage));
409 test_pic(bmpimage, sizeof(bmpimage));
410 test_pic(gif4pixel, sizeof(gif4pixel));
411 /* FIXME: No PNG support yet in Wine or in older Windows... */
412 if (0) test_pic(pngimage, sizeof(pngimage));
414 test_empty_image_2();
420 /* Helper functions only ... */
423 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
425 GlobalFree(This->supportHandle);
426 This->supportHandle=0;
427 HeapFree(GetProcessHeap(), 0, This);
430 static ULONG WINAPI NoStatStreamImpl_AddRef(
433 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
434 return InterlockedIncrement(&This->ref);
437 static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
439 REFIID riid, /* [in] */
440 void** ppvObject) /* [iid_is][out] */
442 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
443 if (ppvObject==0) return E_INVALIDARG;
445 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
447 *ppvObject = (IStream*)This;
449 else if (memcmp(&IID_IStream, riid, sizeof(IID_IStream)) == 0)
451 *ppvObject = (IStream*)This;
455 return E_NOINTERFACE;
456 NoStatStreamImpl_AddRef(iface);
460 static ULONG WINAPI NoStatStreamImpl_Release(
463 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
464 ULONG newRef = InterlockedDecrement(&This->ref);
466 NoStatStreamImpl_Destroy(This);
470 static HRESULT WINAPI NoStatStreamImpl_Read(
472 void* pv, /* [length_is][size_is][out] */
474 ULONG* pcbRead) /* [out] */
476 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
478 ULONG bytesReadBuffer;
479 ULONG bytesToReadFromBuffer;
482 pcbRead = &bytesReadBuffer;
483 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
484 supportBuffer = GlobalLock(This->supportHandle);
485 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
486 This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
487 *pcbRead = bytesToReadFromBuffer;
488 GlobalUnlock(This->supportHandle);
494 static HRESULT WINAPI NoStatStreamImpl_Write(
496 const void* pv, /* [size_is][in] */
498 ULONG* pcbWritten) /* [out] */
500 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
502 ULARGE_INTEGER newSize;
503 ULONG bytesWritten = 0;
506 pcbWritten = &bytesWritten;
509 newSize.u.HighPart = 0;
510 newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
511 if (newSize.u.LowPart > This->streamSize.u.LowPart)
512 IStream_SetSize(iface, newSize);
514 supportBuffer = GlobalLock(This->supportHandle);
515 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
516 This->currentPosition.u.LowPart+=cb;
518 GlobalUnlock(This->supportHandle);
522 static HRESULT WINAPI NoStatStreamImpl_Seek(
524 LARGE_INTEGER dlibMove, /* [in] */
525 DWORD dwOrigin, /* [in] */
526 ULARGE_INTEGER* plibNewPosition) /* [out] */
528 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
529 ULARGE_INTEGER newPosition;
532 case STREAM_SEEK_SET:
533 newPosition.u.HighPart = 0;
534 newPosition.u.LowPart = 0;
536 case STREAM_SEEK_CUR:
537 newPosition = This->currentPosition;
539 case STREAM_SEEK_END:
540 newPosition = This->streamSize;
543 return STG_E_INVALIDFUNCTION;
545 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
546 return STG_E_INVALIDFUNCTION;
547 newPosition.QuadPart += dlibMove.QuadPart;
548 if (plibNewPosition) *plibNewPosition = newPosition;
549 This->currentPosition = newPosition;
553 static HRESULT WINAPI NoStatStreamImpl_SetSize(
555 ULARGE_INTEGER libNewSize) /* [in] */
557 NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
558 HGLOBAL supportHandle;
559 if (libNewSize.u.HighPart != 0)
560 return STG_E_INVALIDFUNCTION;
561 if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
563 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
564 if (supportHandle == 0)
565 return STG_E_MEDIUMFULL;
566 This->supportHandle = supportHandle;
567 This->streamSize.u.LowPart = libNewSize.u.LowPart;
571 static HRESULT WINAPI NoStatStreamImpl_CopyTo(
573 IStream* pstm, /* [unique][in] */
574 ULARGE_INTEGER cb, /* [in] */
575 ULARGE_INTEGER* pcbRead, /* [out] */
576 ULARGE_INTEGER* pcbWritten) /* [out] */
580 ULONG bytesRead, bytesWritten, copySize;
581 ULARGE_INTEGER totalBytesRead;
582 ULARGE_INTEGER totalBytesWritten;
585 return STG_E_INVALIDPOINTER;
586 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
587 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
589 while ( cb.u.LowPart > 0 )
591 if ( cb.u.LowPart >= 128 )
594 copySize = cb.u.LowPart;
595 IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
596 totalBytesRead.u.LowPart += bytesRead;
597 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
598 totalBytesWritten.u.LowPart += bytesWritten;
599 if (bytesRead != bytesWritten)
601 hr = STG_E_MEDIUMFULL;
604 if (bytesRead!=copySize)
607 cb.u.LowPart -= bytesRead;
611 pcbRead->u.LowPart = totalBytesRead.u.LowPart;
612 pcbRead->u.HighPart = totalBytesRead.u.HighPart;
617 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
618 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
623 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
627 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
629 static HRESULT WINAPI NoStatStreamImpl_LockRegion(
631 ULARGE_INTEGER libOffset, /* [in] */
632 ULARGE_INTEGER cb, /* [in] */
633 DWORD dwLockType) /* [in] */
638 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
640 ULARGE_INTEGER libOffset, /* [in] */
641 ULARGE_INTEGER cb, /* [in] */
642 DWORD dwLockType) /* [in] */
647 static HRESULT WINAPI NoStatStreamImpl_Stat(
649 STATSTG* pstatstg, /* [out] */
650 DWORD grfStatFlag) /* [in] */
655 static HRESULT WINAPI NoStatStreamImpl_Clone(
657 IStream** ppstm) /* [out] */
661 static const IStreamVtbl NoStatStreamImpl_Vtbl;
664 Build an object that implements IStream, without IStream_Stat capabilities.
665 Receives a memory handle with data buffer. If memory handle is non-null,
666 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
667 In any case the object takes ownership of memory handle and will free it on
670 static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal)
672 NoStatStreamImpl* newStream;
674 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
677 newStream->lpVtbl = &NoStatStreamImpl_Vtbl;
679 newStream->supportHandle = hGlobal;
681 if (!newStream->supportHandle)
682 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
684 newStream->currentPosition.u.HighPart = 0;
685 newStream->currentPosition.u.LowPart = 0;
686 newStream->streamSize.u.HighPart = 0;
687 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
693 static const IStreamVtbl NoStatStreamImpl_Vtbl =
695 NoStatStreamImpl_QueryInterface,
696 NoStatStreamImpl_AddRef,
697 NoStatStreamImpl_Release,
698 NoStatStreamImpl_Read,
699 NoStatStreamImpl_Write,
700 NoStatStreamImpl_Seek,
701 NoStatStreamImpl_SetSize,
702 NoStatStreamImpl_CopyTo,
703 NoStatStreamImpl_Commit,
704 NoStatStreamImpl_Revert,
705 NoStatStreamImpl_LockRegion,
706 NoStatStreamImpl_UnlockRegion,
707 NoStatStreamImpl_Stat,
708 NoStatStreamImpl_Clone