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
= LoadLibraryA("oleaut32.dll");
430 pOleLoadPicture
= (void*)GetProcAddress(hOleaut32
, "OleLoadPicture");
431 pOleCreatePictureIndirect
= (void*)GetProcAddress(hOleaut32
, "OleCreatePictureIndirect");
432 if (!pOleLoadPicture
)
435 /* Test regular 1x1 pixel images of gif, jpg, bmp type */
436 test_pic(gifimage
, sizeof(gifimage
));
437 test_pic(jpgimage
, sizeof(jpgimage
));
438 test_pic(bmpimage
, sizeof(bmpimage
));
439 test_pic(gif4pixel
, sizeof(gif4pixel
));
440 /* FIXME: No PNG support yet in Wine or in older Windows... */
441 if (0) test_pic(pngimage
, sizeof(pngimage
));
443 test_empty_image_2();
446 test_OleCreatePictureIndirect();
450 /* Helper functions only ... */
453 static void NoStatStreamImpl_Destroy(NoStatStreamImpl
* This
)
455 GlobalFree(This
->supportHandle
);
456 This
->supportHandle
=0;
457 HeapFree(GetProcessHeap(), 0, This
);
460 static ULONG WINAPI
NoStatStreamImpl_AddRef(
463 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
464 return InterlockedIncrement(&This
->ref
);
467 static HRESULT WINAPI
NoStatStreamImpl_QueryInterface(
469 REFIID riid
, /* [in] */
470 void** ppvObject
) /* [iid_is][out] */
472 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
473 if (ppvObject
==0) return E_INVALIDARG
;
475 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
477 *ppvObject
= (IStream
*)This
;
479 else if (memcmp(&IID_IStream
, riid
, sizeof(IID_IStream
)) == 0)
481 *ppvObject
= (IStream
*)This
;
485 return E_NOINTERFACE
;
486 NoStatStreamImpl_AddRef(iface
);
490 static ULONG WINAPI
NoStatStreamImpl_Release(
493 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
494 ULONG newRef
= InterlockedDecrement(&This
->ref
);
496 NoStatStreamImpl_Destroy(This
);
500 static HRESULT WINAPI
NoStatStreamImpl_Read(
502 void* pv
, /* [length_is][size_is][out] */
504 ULONG
* pcbRead
) /* [out] */
506 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
508 ULONG bytesReadBuffer
;
509 ULONG bytesToReadFromBuffer
;
512 pcbRead
= &bytesReadBuffer
;
513 bytesToReadFromBuffer
= min( This
->streamSize
.u
.LowPart
- This
->currentPosition
.u
.LowPart
, cb
);
514 supportBuffer
= GlobalLock(This
->supportHandle
);
515 memcpy(pv
, (char *) supportBuffer
+This
->currentPosition
.u
.LowPart
, bytesToReadFromBuffer
);
516 This
->currentPosition
.u
.LowPart
+=bytesToReadFromBuffer
;
517 *pcbRead
= bytesToReadFromBuffer
;
518 GlobalUnlock(This
->supportHandle
);
524 static HRESULT WINAPI
NoStatStreamImpl_Write(
526 const void* pv
, /* [size_is][in] */
528 ULONG
* pcbWritten
) /* [out] */
530 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
532 ULARGE_INTEGER newSize
;
533 ULONG bytesWritten
= 0;
536 pcbWritten
= &bytesWritten
;
539 newSize
.u
.HighPart
= 0;
540 newSize
.u
.LowPart
= This
->currentPosition
.u
.LowPart
+ cb
;
541 if (newSize
.u
.LowPart
> This
->streamSize
.u
.LowPart
)
542 IStream_SetSize(iface
, newSize
);
544 supportBuffer
= GlobalLock(This
->supportHandle
);
545 memcpy((char *) supportBuffer
+This
->currentPosition
.u
.LowPart
, pv
, cb
);
546 This
->currentPosition
.u
.LowPart
+=cb
;
548 GlobalUnlock(This
->supportHandle
);
552 static HRESULT WINAPI
NoStatStreamImpl_Seek(
554 LARGE_INTEGER dlibMove
, /* [in] */
555 DWORD dwOrigin
, /* [in] */
556 ULARGE_INTEGER
* plibNewPosition
) /* [out] */
558 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
559 ULARGE_INTEGER newPosition
;
562 case STREAM_SEEK_SET
:
563 newPosition
.u
.HighPart
= 0;
564 newPosition
.u
.LowPart
= 0;
566 case STREAM_SEEK_CUR
:
567 newPosition
= This
->currentPosition
;
569 case STREAM_SEEK_END
:
570 newPosition
= This
->streamSize
;
573 return STG_E_INVALIDFUNCTION
;
575 if (dlibMove
.QuadPart
< 0 && newPosition
.QuadPart
< -dlibMove
.QuadPart
)
576 return STG_E_INVALIDFUNCTION
;
577 newPosition
.QuadPart
+= dlibMove
.QuadPart
;
578 if (plibNewPosition
) *plibNewPosition
= newPosition
;
579 This
->currentPosition
= newPosition
;
583 static HRESULT WINAPI
NoStatStreamImpl_SetSize(
585 ULARGE_INTEGER libNewSize
) /* [in] */
587 NoStatStreamImpl
* const This
=(NoStatStreamImpl
*)iface
;
588 HGLOBAL supportHandle
;
589 if (libNewSize
.u
.HighPart
!= 0)
590 return STG_E_INVALIDFUNCTION
;
591 if (This
->streamSize
.u
.LowPart
== libNewSize
.u
.LowPart
)
593 supportHandle
= GlobalReAlloc(This
->supportHandle
, libNewSize
.u
.LowPart
, 0);
594 if (supportHandle
== 0)
595 return STG_E_MEDIUMFULL
;
596 This
->supportHandle
= supportHandle
;
597 This
->streamSize
.u
.LowPart
= libNewSize
.u
.LowPart
;
601 static HRESULT WINAPI
NoStatStreamImpl_CopyTo(
603 IStream
* pstm
, /* [unique][in] */
604 ULARGE_INTEGER cb
, /* [in] */
605 ULARGE_INTEGER
* pcbRead
, /* [out] */
606 ULARGE_INTEGER
* pcbWritten
) /* [out] */
610 ULONG bytesRead
, bytesWritten
, copySize
;
611 ULARGE_INTEGER totalBytesRead
;
612 ULARGE_INTEGER totalBytesWritten
;
615 return STG_E_INVALIDPOINTER
;
616 totalBytesRead
.u
.LowPart
= totalBytesRead
.u
.HighPart
= 0;
617 totalBytesWritten
.u
.LowPart
= totalBytesWritten
.u
.HighPart
= 0;
619 while ( cb
.u
.LowPart
> 0 )
621 if ( cb
.u
.LowPart
>= 128 )
624 copySize
= cb
.u
.LowPart
;
625 IStream_Read(iface
, tmpBuffer
, copySize
, &bytesRead
);
626 totalBytesRead
.u
.LowPart
+= bytesRead
;
627 IStream_Write(pstm
, tmpBuffer
, bytesRead
, &bytesWritten
);
628 totalBytesWritten
.u
.LowPart
+= bytesWritten
;
629 if (bytesRead
!= bytesWritten
)
631 hr
= STG_E_MEDIUMFULL
;
634 if (bytesRead
!=copySize
)
637 cb
.u
.LowPart
-= bytesRead
;
641 pcbRead
->u
.LowPart
= totalBytesRead
.u
.LowPart
;
642 pcbRead
->u
.HighPart
= totalBytesRead
.u
.HighPart
;
647 pcbWritten
->u
.LowPart
= totalBytesWritten
.u
.LowPart
;
648 pcbWritten
->u
.HighPart
= totalBytesWritten
.u
.HighPart
;
653 static HRESULT WINAPI
NoStatStreamImpl_Commit(IStream
* iface
,DWORD grfCommitFlags
)
657 static HRESULT WINAPI
NoStatStreamImpl_Revert(IStream
* iface
) { return S_OK
; }
659 static HRESULT WINAPI
NoStatStreamImpl_LockRegion(
661 ULARGE_INTEGER libOffset
, /* [in] */
662 ULARGE_INTEGER cb
, /* [in] */
663 DWORD dwLockType
) /* [in] */
668 static HRESULT WINAPI
NoStatStreamImpl_UnlockRegion(
670 ULARGE_INTEGER libOffset
, /* [in] */
671 ULARGE_INTEGER cb
, /* [in] */
672 DWORD dwLockType
) /* [in] */
677 static HRESULT WINAPI
NoStatStreamImpl_Stat(
679 STATSTG
* pstatstg
, /* [out] */
680 DWORD grfStatFlag
) /* [in] */
685 static HRESULT WINAPI
NoStatStreamImpl_Clone(
687 IStream
** ppstm
) /* [out] */
691 static const IStreamVtbl NoStatStreamImpl_Vtbl
;
694 Build an object that implements IStream, without IStream_Stat capabilities.
695 Receives a memory handle with data buffer. If memory handle is non-null,
696 it is assumed to be unlocked, otherwise an internal memory handle is allocated.
697 In any case the object takes ownership of memory handle and will free it on
700 static NoStatStreamImpl
* NoStatStreamImpl_Construct(HGLOBAL hGlobal
)
702 NoStatStreamImpl
* newStream
;
704 newStream
= HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl
));
707 newStream
->lpVtbl
= &NoStatStreamImpl_Vtbl
;
709 newStream
->supportHandle
= hGlobal
;
711 if (!newStream
->supportHandle
)
712 newStream
->supportHandle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_NODISCARD
|
714 newStream
->currentPosition
.u
.HighPart
= 0;
715 newStream
->currentPosition
.u
.LowPart
= 0;
716 newStream
->streamSize
.u
.HighPart
= 0;
717 newStream
->streamSize
.u
.LowPart
= GlobalSize(newStream
->supportHandle
);
723 static const IStreamVtbl NoStatStreamImpl_Vtbl
=
725 NoStatStreamImpl_QueryInterface
,
726 NoStatStreamImpl_AddRef
,
727 NoStatStreamImpl_Release
,
728 NoStatStreamImpl_Read
,
729 NoStatStreamImpl_Write
,
730 NoStatStreamImpl_Seek
,
731 NoStatStreamImpl_SetSize
,
732 NoStatStreamImpl_CopyTo
,
733 NoStatStreamImpl_Commit
,
734 NoStatStreamImpl_Revert
,
735 NoStatStreamImpl_LockRegion
,
736 NoStatStreamImpl_UnlockRegion
,
737 NoStatStreamImpl_Stat
,
738 NoStatStreamImpl_Clone