2 * Copyright 2009 Tony Wasserka
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "wine/debug.h"
28 #include "wincodecs_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
32 /******************************************
33 * StreamOnMemory implementation
35 * Used by IWICStream_InitializeFromMemory
38 typedef struct StreamOnMemory
{
39 const IStreamVtbl
*lpVtbl
;
46 CRITICAL_SECTION lock
; /* must be held when pbMemory or dwCurPos is accessed */
49 static HRESULT WINAPI
StreamOnMemory_QueryInterface(IStream
*iface
,
50 REFIID iid
, void **ppv
)
52 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
54 if (!ppv
) return E_INVALIDARG
;
56 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IStream
, iid
) ||
57 IsEqualIID(&IID_ISequentialStream
, iid
))
60 IUnknown_AddRef((IUnknown
*)*ppv
);
70 static ULONG WINAPI
StreamOnMemory_AddRef(IStream
*iface
)
72 StreamOnMemory
*This
= (StreamOnMemory
*)iface
;
73 ULONG ref
= InterlockedIncrement(&This
->ref
);
75 TRACE("(%p) refcount=%u\n", iface
, ref
);
80 static ULONG WINAPI
StreamOnMemory_Release(IStream
*iface
)
82 StreamOnMemory
*This
= (StreamOnMemory
*)iface
;
83 ULONG ref
= InterlockedDecrement(&This
->ref
);
85 TRACE("(%p) refcount=%u\n", iface
, ref
);
88 This
->lock
.DebugInfo
->Spare
[0] = 0;
89 DeleteCriticalSection(&This
->lock
);
90 HeapFree(GetProcessHeap(), 0, This
);
95 static HRESULT WINAPI
StreamOnMemory_Read(IStream
*iface
,
96 void *pv
, ULONG cb
, ULONG
*pcbRead
)
98 StreamOnMemory
*This
= (StreamOnMemory
*)iface
;
100 TRACE("(%p)\n", This
);
102 if (!pv
) return E_INVALIDARG
;
104 EnterCriticalSection(&This
->lock
);
105 uBytesRead
= min(cb
, This
->dwMemsize
- This
->dwCurPos
);
106 memcpy(pv
, This
->pbMemory
+ This
->dwCurPos
, uBytesRead
);
107 This
->dwCurPos
+= uBytesRead
;
108 LeaveCriticalSection(&This
->lock
);
110 if (pcbRead
) *pcbRead
= uBytesRead
;
115 static HRESULT WINAPI
StreamOnMemory_Write(IStream
*iface
,
116 void const *pv
, ULONG cb
, ULONG
*pcbWritten
)
118 StreamOnMemory
*This
= (StreamOnMemory
*)iface
;
120 TRACE("(%p)\n", This
);
122 if (!pv
) return E_INVALIDARG
;
124 EnterCriticalSection(&This
->lock
);
125 if (cb
> This
->dwMemsize
- This
->dwCurPos
) {
126 hr
= STG_E_MEDIUMFULL
;
129 memcpy(This
->pbMemory
+ This
->dwCurPos
, pv
, cb
);
130 This
->dwCurPos
+= cb
;
132 if (pcbWritten
) *pcbWritten
= cb
;
134 LeaveCriticalSection(&This
->lock
);
139 static HRESULT WINAPI
StreamOnMemory_Seek(IStream
*iface
,
140 LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
142 StreamOnMemory
*This
= (StreamOnMemory
*)iface
;
143 LARGE_INTEGER NewPosition
;
145 TRACE("(%p)\n", This
);
147 EnterCriticalSection(&This
->lock
);
148 if (dwOrigin
== STREAM_SEEK_SET
) NewPosition
.QuadPart
= dlibMove
.QuadPart
;
149 else if (dwOrigin
== STREAM_SEEK_CUR
) NewPosition
.QuadPart
= This
->dwCurPos
+ dlibMove
.QuadPart
;
150 else if (dwOrigin
== STREAM_SEEK_END
) NewPosition
.QuadPart
= This
->dwMemsize
+ dlibMove
.QuadPart
;
151 else hr
= E_INVALIDARG
;
154 if (NewPosition
.u
.HighPart
) hr
= HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW
);
155 else if (NewPosition
.QuadPart
> This
->dwMemsize
) hr
= E_INVALIDARG
;
156 else if (NewPosition
.QuadPart
< 0) hr
= E_INVALIDARG
;
160 This
->dwCurPos
= NewPosition
.u
.LowPart
;
162 if(plibNewPosition
) plibNewPosition
->QuadPart
= This
->dwCurPos
;
164 LeaveCriticalSection(&This
->lock
);
169 /* SetSize isn't implemented in the native windowscodecs DLL either */
170 static HRESULT WINAPI
StreamOnMemory_SetSize(IStream
*iface
,
171 ULARGE_INTEGER libNewSize
)
173 TRACE("(%p)\n", iface
);
177 /* CopyTo isn't implemented in the native windowscodecs DLL either */
178 static HRESULT WINAPI
StreamOnMemory_CopyTo(IStream
*iface
,
179 IStream
*pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
181 TRACE("(%p)\n", iface
);
185 /* Commit isn't implemented in the native windowscodecs DLL either */
186 static HRESULT WINAPI
StreamOnMemory_Commit(IStream
*iface
,
187 DWORD grfCommitFlags
)
189 TRACE("(%p)\n", iface
);
193 /* Revert isn't implemented in the native windowscodecs DLL either */
194 static HRESULT WINAPI
StreamOnMemory_Revert(IStream
*iface
)
196 TRACE("(%p)\n", iface
);
200 /* LockRegion isn't implemented in the native windowscodecs DLL either */
201 static HRESULT WINAPI
StreamOnMemory_LockRegion(IStream
*iface
,
202 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
204 TRACE("(%p)\n", iface
);
208 /* UnlockRegion isn't implemented in the native windowscodecs DLL either */
209 static HRESULT WINAPI
StreamOnMemory_UnlockRegion(IStream
*iface
,
210 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
212 TRACE("(%p)\n", iface
);
216 static HRESULT WINAPI
StreamOnMemory_Stat(IStream
*iface
,
217 STATSTG
*pstatstg
, DWORD grfStatFlag
)
219 StreamOnMemory
*This
= (StreamOnMemory
*)iface
;
220 TRACE("(%p)\n", This
);
222 if (!pstatstg
) return E_INVALIDARG
;
224 ZeroMemory(pstatstg
, sizeof(STATSTG
));
225 pstatstg
->type
= STGTY_STREAM
;
226 pstatstg
->cbSize
.QuadPart
= This
->dwMemsize
;
231 /* Clone isn't implemented in the native windowscodecs DLL either */
232 static HRESULT WINAPI
StreamOnMemory_Clone(IStream
*iface
,
235 TRACE("(%p)\n", iface
);
240 const IStreamVtbl StreamOnMemory_Vtbl
=
242 /*** IUnknown methods ***/
243 StreamOnMemory_QueryInterface
,
244 StreamOnMemory_AddRef
,
245 StreamOnMemory_Release
,
246 /*** ISequentialStream methods ***/
248 StreamOnMemory_Write
,
249 /*** IStream methods ***/
251 StreamOnMemory_SetSize
,
252 StreamOnMemory_CopyTo
,
253 StreamOnMemory_Commit
,
254 StreamOnMemory_Revert
,
255 StreamOnMemory_LockRegion
,
256 StreamOnMemory_UnlockRegion
,
258 StreamOnMemory_Clone
,
261 /******************************************
262 * StreamOnStreamRange implementation
264 * Used by IWICStream_InitializeFromIStreamRegion
267 typedef struct StreamOnStreamRange
{
268 const IStreamVtbl
*lpVtbl
;
273 ULARGE_INTEGER offset
;
274 ULARGE_INTEGER max_size
;
276 CRITICAL_SECTION lock
;
277 } StreamOnStreamRange
;
279 static HRESULT WINAPI
StreamOnStreamRange_QueryInterface(IStream
*iface
,
280 REFIID iid
, void **ppv
)
282 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
284 if (!ppv
) return E_INVALIDARG
;
286 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IStream
, iid
) ||
287 IsEqualIID(&IID_ISequentialStream
, iid
))
290 IUnknown_AddRef((IUnknown
*)*ppv
);
296 return E_NOINTERFACE
;
300 static ULONG WINAPI
StreamOnStreamRange_AddRef(IStream
*iface
)
302 StreamOnStreamRange
*This
= (StreamOnStreamRange
*)iface
;
303 ULONG ref
= InterlockedIncrement(&This
->ref
);
305 TRACE("(%p) refcount=%u\n", iface
, ref
);
310 static ULONG WINAPI
StreamOnStreamRange_Release(IStream
*iface
)
312 StreamOnStreamRange
*This
= (StreamOnStreamRange
*)iface
;
313 ULONG ref
= InterlockedDecrement(&This
->ref
);
315 TRACE("(%p) refcount=%u\n", iface
, ref
);
318 This
->lock
.DebugInfo
->Spare
[0] = 0;
319 DeleteCriticalSection(&This
->lock
);
320 IStream_Release(This
->stream
);
321 HeapFree(GetProcessHeap(), 0, This
);
326 static HRESULT WINAPI
StreamOnStreamRange_Read(IStream
*iface
,
327 void *pv
, ULONG cb
, ULONG
*pcbRead
)
329 StreamOnStreamRange
*This
= (StreamOnStreamRange
*)iface
;
332 ULARGE_INTEGER OldPosition
;
333 LARGE_INTEGER SetPosition
;
334 TRACE("(%p)\n", This
);
336 if (!pv
) return E_INVALIDARG
;
338 EnterCriticalSection(&This
->lock
);
339 SetPosition
.QuadPart
= 0;
340 hr
= IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_CUR
, &OldPosition
);
343 SetPosition
.QuadPart
= This
->pos
.QuadPart
+ This
->offset
.QuadPart
;
344 hr
= IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_SET
, NULL
);
348 if (This
->pos
.QuadPart
+ cb
> This
->max_size
.QuadPart
)
350 /* This would read past the end of the stream. */
351 if (This
->pos
.QuadPart
> This
->max_size
.QuadPart
)
354 cb
= This
->max_size
.QuadPart
- This
->pos
.QuadPart
;
356 hr
= IStream_Read(This
->stream
, pv
, cb
, &uBytesRead
);
357 SetPosition
.QuadPart
= OldPosition
.QuadPart
;
358 IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_SET
, NULL
);
361 This
->pos
.QuadPart
+= uBytesRead
;
362 LeaveCriticalSection(&This
->lock
);
364 if (pcbRead
) *pcbRead
= uBytesRead
;
369 static HRESULT WINAPI
StreamOnStreamRange_Write(IStream
*iface
,
370 void const *pv
, ULONG cb
, ULONG
*pcbWritten
)
372 StreamOnStreamRange
*This
= (StreamOnStreamRange
*)iface
;
374 ULARGE_INTEGER OldPosition
;
375 LARGE_INTEGER SetPosition
;
376 ULONG uBytesWritten
=0;
377 TRACE("(%p)\n", This
);
379 if (!pv
) return E_INVALIDARG
;
381 EnterCriticalSection(&This
->lock
);
382 SetPosition
.QuadPart
= 0;
383 hr
= IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_CUR
, &OldPosition
);
386 SetPosition
.QuadPart
= This
->pos
.QuadPart
+ This
->offset
.QuadPart
;
387 hr
= IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_SET
, NULL
);
391 if (This
->pos
.QuadPart
+ cb
> This
->max_size
.QuadPart
)
393 /* This would read past the end of the stream. */
394 if (This
->pos
.QuadPart
> This
->max_size
.QuadPart
)
397 cb
= This
->max_size
.QuadPart
- This
->pos
.QuadPart
;
399 hr
= IStream_Write(This
->stream
, pv
, cb
, &uBytesWritten
);
400 SetPosition
.QuadPart
= OldPosition
.QuadPart
;
401 IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_SET
, NULL
);
404 This
->pos
.QuadPart
+= uBytesWritten
;
405 LeaveCriticalSection(&This
->lock
);
407 if (pcbWritten
) *pcbWritten
= uBytesWritten
;
412 static HRESULT WINAPI
StreamOnStreamRange_Seek(IStream
*iface
,
413 LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
415 StreamOnStreamRange
*This
= (StreamOnStreamRange
*)iface
;
416 ULARGE_INTEGER NewPosition
, actual_size
;
419 TRACE("(%p)\n", This
);
421 EnterCriticalSection(&This
->lock
);
422 actual_size
= This
->max_size
;
423 if (dwOrigin
== STREAM_SEEK_SET
)
424 NewPosition
.QuadPart
= dlibMove
.QuadPart
;
425 else if (dwOrigin
== STREAM_SEEK_CUR
)
426 NewPosition
.QuadPart
= This
->pos
.QuadPart
+ dlibMove
.QuadPart
;
427 else if (dwOrigin
== STREAM_SEEK_END
)
429 hr
= IStream_Stat(This
->stream
, &statstg
, STATFLAG_NONAME
);
432 if (This
->max_size
.QuadPart
+ This
->offset
.QuadPart
> statstg
.cbSize
.QuadPart
)
433 actual_size
.QuadPart
= statstg
.cbSize
.QuadPart
- This
->offset
.QuadPart
;
434 NewPosition
.QuadPart
= dlibMove
.QuadPart
+ actual_size
.QuadPart
;
437 else hr
= E_INVALIDARG
;
439 if (SUCCEEDED(hr
) && (NewPosition
.u
.HighPart
!= 0 || NewPosition
.QuadPart
> actual_size
.QuadPart
))
440 hr
= WINCODEC_ERR_VALUEOUTOFRANGE
;
443 This
->pos
.QuadPart
= NewPosition
.QuadPart
;
445 if(plibNewPosition
) plibNewPosition
->QuadPart
= This
->pos
.QuadPart
;
447 LeaveCriticalSection(&This
->lock
);
452 /* SetSize isn't implemented in the native windowscodecs DLL either */
453 static HRESULT WINAPI
StreamOnStreamRange_SetSize(IStream
*iface
,
454 ULARGE_INTEGER libNewSize
)
456 TRACE("(%p)\n", iface
);
460 /* CopyTo isn't implemented in the native windowscodecs DLL either */
461 static HRESULT WINAPI
StreamOnStreamRange_CopyTo(IStream
*iface
,
462 IStream
*pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
464 TRACE("(%p)\n", iface
);
468 /* Commit isn't implemented in the native windowscodecs DLL either */
469 static HRESULT WINAPI
StreamOnStreamRange_Commit(IStream
*iface
,
470 DWORD grfCommitFlags
)
472 TRACE("(%p)\n", iface
);
476 /* Revert isn't implemented in the native windowscodecs DLL either */
477 static HRESULT WINAPI
StreamOnStreamRange_Revert(IStream
*iface
)
479 TRACE("(%p)\n", iface
);
483 /* LockRegion isn't implemented in the native windowscodecs DLL either */
484 static HRESULT WINAPI
StreamOnStreamRange_LockRegion(IStream
*iface
,
485 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
487 TRACE("(%p)\n", iface
);
491 /* UnlockRegion isn't implemented in the native windowscodecs DLL either */
492 static HRESULT WINAPI
StreamOnStreamRange_UnlockRegion(IStream
*iface
,
493 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
495 TRACE("(%p)\n", iface
);
499 static HRESULT WINAPI
StreamOnStreamRange_Stat(IStream
*iface
,
500 STATSTG
*pstatstg
, DWORD grfStatFlag
)
502 StreamOnStreamRange
*This
= (StreamOnStreamRange
*)iface
;
504 TRACE("(%p)\n", This
);
506 if (!pstatstg
) return E_INVALIDARG
;
508 EnterCriticalSection(&This
->lock
);
509 hr
= IStream_Stat(This
->stream
, pstatstg
, grfStatFlag
);
512 pstatstg
->cbSize
.QuadPart
-= This
->offset
.QuadPart
;
513 if (This
->max_size
.QuadPart
< pstatstg
->cbSize
.QuadPart
)
514 pstatstg
->cbSize
.QuadPart
= This
->max_size
.QuadPart
;
517 LeaveCriticalSection(&This
->lock
);
522 /* Clone isn't implemented in the native windowscodecs DLL either */
523 static HRESULT WINAPI
StreamOnStreamRange_Clone(IStream
*iface
,
526 TRACE("(%p)\n", iface
);
531 const IStreamVtbl StreamOnStreamRange_Vtbl
=
533 /*** IUnknown methods ***/
534 StreamOnStreamRange_QueryInterface
,
535 StreamOnStreamRange_AddRef
,
536 StreamOnStreamRange_Release
,
537 /*** ISequentialStream methods ***/
538 StreamOnStreamRange_Read
,
539 StreamOnStreamRange_Write
,
540 /*** IStream methods ***/
541 StreamOnStreamRange_Seek
,
542 StreamOnStreamRange_SetSize
,
543 StreamOnStreamRange_CopyTo
,
544 StreamOnStreamRange_Commit
,
545 StreamOnStreamRange_Revert
,
546 StreamOnStreamRange_LockRegion
,
547 StreamOnStreamRange_UnlockRegion
,
548 StreamOnStreamRange_Stat
,
549 StreamOnStreamRange_Clone
,
553 /******************************************
554 * IWICStream implementation
557 typedef struct IWICStreamImpl
559 const IWICStreamVtbl
*lpVtbl
;
565 static HRESULT WINAPI
IWICStreamImpl_QueryInterface(IWICStream
*iface
,
566 REFIID iid
, void **ppv
)
568 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
569 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
571 if (!ppv
) return E_INVALIDARG
;
573 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IStream
, iid
) ||
574 IsEqualIID(&IID_ISequentialStream
, iid
) || IsEqualIID(&IID_IWICStream
, iid
))
577 IUnknown_AddRef((IUnknown
*)*ppv
);
583 return E_NOINTERFACE
;
587 static ULONG WINAPI
IWICStreamImpl_AddRef(IWICStream
*iface
)
589 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
590 ULONG ref
= InterlockedIncrement(&This
->ref
);
592 TRACE("(%p) refcount=%u\n", iface
, ref
);
597 static ULONG WINAPI
IWICStreamImpl_Release(IWICStream
*iface
)
599 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
600 ULONG ref
= InterlockedDecrement(&This
->ref
);
602 TRACE("(%p) refcount=%u\n", iface
, ref
);
605 if (This
->pStream
) IStream_Release(This
->pStream
);
606 HeapFree(GetProcessHeap(), 0, This
);
611 static HRESULT WINAPI
IWICStreamImpl_Read(IWICStream
*iface
,
612 void *pv
, ULONG cb
, ULONG
*pcbRead
)
614 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
615 TRACE("(%p): relay\n", This
);
617 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
618 return IStream_Read(This
->pStream
, pv
, cb
, pcbRead
);
621 static HRESULT WINAPI
IWICStreamImpl_Write(IWICStream
*iface
,
622 void const *pv
, ULONG cb
, ULONG
*pcbWritten
)
624 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
625 TRACE("(%p): relay\n", This
);
627 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
628 return IStream_Write(This
->pStream
, pv
, cb
, pcbWritten
);
631 static HRESULT WINAPI
IWICStreamImpl_Seek(IWICStream
*iface
,
632 LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
634 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
635 TRACE("(%p): relay\n", This
);
637 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
638 return IStream_Seek(This
->pStream
, dlibMove
, dwOrigin
, plibNewPosition
);
641 static HRESULT WINAPI
IWICStreamImpl_SetSize(IWICStream
*iface
,
642 ULARGE_INTEGER libNewSize
)
644 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
645 TRACE("(%p): relay\n", This
);
647 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
648 return IStream_SetSize(This
->pStream
, libNewSize
);
651 static HRESULT WINAPI
IWICStreamImpl_CopyTo(IWICStream
*iface
,
652 IStream
*pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
654 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
655 TRACE("(%p): relay\n", This
);
657 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
658 return IStream_CopyTo(This
->pStream
, pstm
, cb
, pcbRead
, pcbWritten
);
661 static HRESULT WINAPI
IWICStreamImpl_Commit(IWICStream
*iface
,
662 DWORD grfCommitFlags
)
664 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
665 TRACE("(%p): relay\n", This
);
667 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
668 return IStream_Commit(This
->pStream
, grfCommitFlags
);
671 static HRESULT WINAPI
IWICStreamImpl_Revert(IWICStream
*iface
)
673 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
674 TRACE("(%p): relay\n", This
);
676 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
677 return IStream_Revert(This
->pStream
);
680 static HRESULT WINAPI
IWICStreamImpl_LockRegion(IWICStream
*iface
,
681 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
683 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
684 TRACE("(%p): relay\n", This
);
686 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
687 return IStream_LockRegion(This
->pStream
, libOffset
, cb
, dwLockType
);
690 static HRESULT WINAPI
IWICStreamImpl_UnlockRegion(IWICStream
*iface
,
691 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
693 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
694 TRACE("(%p): relay\n", This
);
696 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
697 return IStream_UnlockRegion(This
->pStream
, libOffset
, cb
, dwLockType
);
700 static HRESULT WINAPI
IWICStreamImpl_Stat(IWICStream
*iface
,
701 STATSTG
*pstatstg
, DWORD grfStatFlag
)
703 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
704 TRACE("(%p): relay\n", This
);
706 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
707 return IStream_Stat(This
->pStream
, pstatstg
, grfStatFlag
);
710 static HRESULT WINAPI
IWICStreamImpl_Clone(IWICStream
*iface
,
713 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
714 TRACE("(%p): relay\n", This
);
716 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
717 return IStream_Clone(This
->pStream
, ppstm
);
720 static HRESULT WINAPI
IWICStreamImpl_InitializeFromIStream(IWICStream
*iface
,
723 FIXME("(%p): stub\n", iface
);
727 static HRESULT WINAPI
IWICStreamImpl_InitializeFromFilename(IWICStream
*iface
,
728 LPCWSTR wzFileName
, DWORD dwDesiredAccess
)
730 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
735 TRACE("(%p, %s, %u)\n", iface
, debugstr_w(wzFileName
), dwDesiredAccess
);
737 if (This
->pStream
) return WINCODEC_ERR_WRONGSTATE
;
739 if(dwDesiredAccess
& GENERIC_WRITE
)
740 dwMode
= STGM_SHARE_DENY_WRITE
| STGM_WRITE
| STGM_CREATE
;
741 else if(dwDesiredAccess
& GENERIC_READ
)
742 dwMode
= STGM_SHARE_DENY_WRITE
| STGM_READ
| STGM_FAILIFTHERE
;
746 hr
= SHCreateStreamOnFileW(wzFileName
, dwMode
, &stream
);
750 if (InterlockedCompareExchangePointer((void**)&This
->pStream
, stream
, NULL
))
752 /* Some other thread set the stream first. */
753 IStream_Release(stream
);
754 hr
= WINCODEC_ERR_WRONGSTATE
;
761 /******************************************
762 * IWICStream_InitializeFromMemory
764 * Initializes the internal IStream object to retrieve its data from a memory chunk.
767 * pbBuffer [I] pointer to the memory chunk
768 * cbBufferSize [I] number of bytes to use from the memory chunk
772 * FAILURE: E_INVALIDARG, if pbBuffer is NULL
773 * E_OUTOFMEMORY, if we run out of memory
774 * WINCODEC_ERR_WRONGSTATE, if the IStream object has already been initialized before
777 static HRESULT WINAPI
IWICStreamImpl_InitializeFromMemory(IWICStream
*iface
,
778 BYTE
*pbBuffer
, DWORD cbBufferSize
)
780 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
781 StreamOnMemory
*pObject
;
782 TRACE("(%p,%p)\n", iface
, pbBuffer
);
784 if (!pbBuffer
) return E_INVALIDARG
;
785 if (This
->pStream
) return WINCODEC_ERR_WRONGSTATE
;
787 pObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnMemory
));
788 if (!pObject
) return E_OUTOFMEMORY
;
790 pObject
->lpVtbl
= &StreamOnMemory_Vtbl
;
792 pObject
->pbMemory
= pbBuffer
;
793 pObject
->dwMemsize
= cbBufferSize
;
794 pObject
->dwCurPos
= 0;
795 InitializeCriticalSection(&pObject
->lock
);
796 pObject
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": StreamOnMemory.lock");
798 if (InterlockedCompareExchangePointer((void**)&This
->pStream
, pObject
, NULL
))
800 /* Some other thread set the stream first. */
801 IStream_Release((IStream
*)pObject
);
802 return WINCODEC_ERR_WRONGSTATE
;
808 static HRESULT WINAPI
IWICStreamImpl_InitializeFromIStreamRegion(IWICStream
*iface
,
809 IStream
*pIStream
, ULARGE_INTEGER ulOffset
, ULARGE_INTEGER ulMaxSize
)
811 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
812 StreamOnStreamRange
*pObject
;
813 TRACE("(%p,%p)\n", iface
, pIStream
);
815 if (!pIStream
) return E_INVALIDARG
;
816 if (This
->pStream
) return WINCODEC_ERR_WRONGSTATE
;
818 pObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnStreamRange
));
819 if (!pObject
) return E_OUTOFMEMORY
;
821 pObject
->lpVtbl
= &StreamOnStreamRange_Vtbl
;
823 IStream_AddRef(pIStream
);
824 pObject
->stream
= pIStream
;
825 pObject
->pos
.QuadPart
= 0;
826 pObject
->offset
= ulOffset
;
827 pObject
->max_size
= ulMaxSize
;
828 InitializeCriticalSection(&pObject
->lock
);
829 pObject
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": StreamOnStreamRange.lock");
831 if (InterlockedCompareExchangePointer((void**)&This
->pStream
, pObject
, NULL
))
833 /* Some other thread set the stream first. */
834 IStream_Release((IStream
*)pObject
);
835 return WINCODEC_ERR_WRONGSTATE
;
842 const IWICStreamVtbl WICStream_Vtbl
=
844 /*** IUnknown methods ***/
845 IWICStreamImpl_QueryInterface
,
846 IWICStreamImpl_AddRef
,
847 IWICStreamImpl_Release
,
848 /*** ISequentialStream methods ***/
850 IWICStreamImpl_Write
,
851 /*** IStream methods ***/
853 IWICStreamImpl_SetSize
,
854 IWICStreamImpl_CopyTo
,
855 IWICStreamImpl_Commit
,
856 IWICStreamImpl_Revert
,
857 IWICStreamImpl_LockRegion
,
858 IWICStreamImpl_UnlockRegion
,
860 IWICStreamImpl_Clone
,
861 /*** IWICStream methods ***/
862 IWICStreamImpl_InitializeFromIStream
,
863 IWICStreamImpl_InitializeFromFilename
,
864 IWICStreamImpl_InitializeFromMemory
,
865 IWICStreamImpl_InitializeFromIStreamRegion
,
868 HRESULT
StreamImpl_Create(IWICStream
**stream
)
870 IWICStreamImpl
*pObject
;
872 if( !stream
) return E_INVALIDARG
;
874 pObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(IWICStreamImpl
));
877 return E_OUTOFMEMORY
;
880 pObject
->lpVtbl
= &WICStream_Vtbl
;
882 pObject
->pStream
= NULL
;
884 *stream
= (IWICStream
*)pObject
;