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 IStream IStream_iface
;
46 CRITICAL_SECTION lock
; /* must be held when pbMemory or dwCurPos is accessed */
49 static inline StreamOnMemory
*StreamOnMemory_from_IStream(IStream
*iface
)
51 return CONTAINING_RECORD(iface
, StreamOnMemory
, IStream_iface
);
54 static HRESULT WINAPI
StreamOnMemory_QueryInterface(IStream
*iface
,
55 REFIID iid
, void **ppv
)
57 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
59 if (!ppv
) return E_INVALIDARG
;
61 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IStream
, iid
) ||
62 IsEqualIID(&IID_ISequentialStream
, iid
))
65 IUnknown_AddRef((IUnknown
*)*ppv
);
75 static ULONG WINAPI
StreamOnMemory_AddRef(IStream
*iface
)
77 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
78 ULONG ref
= InterlockedIncrement(&This
->ref
);
80 TRACE("(%p) refcount=%u\n", iface
, ref
);
85 static ULONG WINAPI
StreamOnMemory_Release(IStream
*iface
)
87 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
88 ULONG ref
= InterlockedDecrement(&This
->ref
);
90 TRACE("(%p) refcount=%u\n", iface
, ref
);
93 This
->lock
.DebugInfo
->Spare
[0] = 0;
94 DeleteCriticalSection(&This
->lock
);
95 HeapFree(GetProcessHeap(), 0, This
);
100 static HRESULT WINAPI
StreamOnMemory_Read(IStream
*iface
,
101 void *pv
, ULONG cb
, ULONG
*pcbRead
)
103 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
105 TRACE("(%p)\n", This
);
107 if (!pv
) return E_INVALIDARG
;
109 EnterCriticalSection(&This
->lock
);
110 uBytesRead
= min(cb
, This
->dwMemsize
- This
->dwCurPos
);
111 memmove(pv
, This
->pbMemory
+ This
->dwCurPos
, uBytesRead
);
112 This
->dwCurPos
+= uBytesRead
;
113 LeaveCriticalSection(&This
->lock
);
115 if (pcbRead
) *pcbRead
= uBytesRead
;
120 static HRESULT WINAPI
StreamOnMemory_Write(IStream
*iface
,
121 void const *pv
, ULONG cb
, ULONG
*pcbWritten
)
123 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
125 TRACE("(%p)\n", This
);
127 if (!pv
) return E_INVALIDARG
;
129 EnterCriticalSection(&This
->lock
);
130 if (cb
> This
->dwMemsize
- This
->dwCurPos
) {
131 hr
= STG_E_MEDIUMFULL
;
134 memmove(This
->pbMemory
+ This
->dwCurPos
, pv
, cb
);
135 This
->dwCurPos
+= cb
;
137 if (pcbWritten
) *pcbWritten
= cb
;
139 LeaveCriticalSection(&This
->lock
);
144 static HRESULT WINAPI
StreamOnMemory_Seek(IStream
*iface
,
145 LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
147 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
148 LARGE_INTEGER NewPosition
;
150 TRACE("(%p)\n", This
);
152 EnterCriticalSection(&This
->lock
);
153 if (dwOrigin
== STREAM_SEEK_SET
) NewPosition
.QuadPart
= dlibMove
.QuadPart
;
154 else if (dwOrigin
== STREAM_SEEK_CUR
) NewPosition
.QuadPart
= This
->dwCurPos
+ dlibMove
.QuadPart
;
155 else if (dwOrigin
== STREAM_SEEK_END
) NewPosition
.QuadPart
= This
->dwMemsize
+ dlibMove
.QuadPart
;
156 else hr
= E_INVALIDARG
;
159 if (NewPosition
.u
.HighPart
) hr
= HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW
);
160 else if (NewPosition
.QuadPart
> This
->dwMemsize
) hr
= E_INVALIDARG
;
161 else if (NewPosition
.QuadPart
< 0) hr
= E_INVALIDARG
;
165 This
->dwCurPos
= NewPosition
.u
.LowPart
;
167 if(plibNewPosition
) plibNewPosition
->QuadPart
= This
->dwCurPos
;
169 LeaveCriticalSection(&This
->lock
);
174 /* SetSize isn't implemented in the native windowscodecs DLL either */
175 static HRESULT WINAPI
StreamOnMemory_SetSize(IStream
*iface
,
176 ULARGE_INTEGER libNewSize
)
178 TRACE("(%p)\n", iface
);
182 /* CopyTo isn't implemented in the native windowscodecs DLL either */
183 static HRESULT WINAPI
StreamOnMemory_CopyTo(IStream
*iface
,
184 IStream
*pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
186 TRACE("(%p)\n", iface
);
190 /* Commit isn't implemented in the native windowscodecs DLL either */
191 static HRESULT WINAPI
StreamOnMemory_Commit(IStream
*iface
,
192 DWORD grfCommitFlags
)
194 TRACE("(%p)\n", iface
);
198 /* Revert isn't implemented in the native windowscodecs DLL either */
199 static HRESULT WINAPI
StreamOnMemory_Revert(IStream
*iface
)
201 TRACE("(%p)\n", iface
);
205 /* LockRegion isn't implemented in the native windowscodecs DLL either */
206 static HRESULT WINAPI
StreamOnMemory_LockRegion(IStream
*iface
,
207 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
209 TRACE("(%p)\n", iface
);
213 /* UnlockRegion isn't implemented in the native windowscodecs DLL either */
214 static HRESULT WINAPI
StreamOnMemory_UnlockRegion(IStream
*iface
,
215 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
217 TRACE("(%p)\n", iface
);
221 static HRESULT WINAPI
StreamOnMemory_Stat(IStream
*iface
,
222 STATSTG
*pstatstg
, DWORD grfStatFlag
)
224 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
225 TRACE("(%p)\n", This
);
227 if (!pstatstg
) return E_INVALIDARG
;
229 ZeroMemory(pstatstg
, sizeof(STATSTG
));
230 pstatstg
->type
= STGTY_STREAM
;
231 pstatstg
->cbSize
.QuadPart
= This
->dwMemsize
;
236 /* Clone isn't implemented in the native windowscodecs DLL either */
237 static HRESULT WINAPI
StreamOnMemory_Clone(IStream
*iface
,
240 TRACE("(%p)\n", iface
);
245 static const IStreamVtbl StreamOnMemory_Vtbl
=
247 /*** IUnknown methods ***/
248 StreamOnMemory_QueryInterface
,
249 StreamOnMemory_AddRef
,
250 StreamOnMemory_Release
,
251 /*** ISequentialStream methods ***/
253 StreamOnMemory_Write
,
254 /*** IStream methods ***/
256 StreamOnMemory_SetSize
,
257 StreamOnMemory_CopyTo
,
258 StreamOnMemory_Commit
,
259 StreamOnMemory_Revert
,
260 StreamOnMemory_LockRegion
,
261 StreamOnMemory_UnlockRegion
,
263 StreamOnMemory_Clone
,
266 /******************************************
267 * StreamOnStreamRange implementation
269 * Used by IWICStream_InitializeFromIStreamRegion
272 typedef struct StreamOnStreamRange
{
273 IStream IStream_iface
;
278 ULARGE_INTEGER offset
;
279 ULARGE_INTEGER max_size
;
281 CRITICAL_SECTION lock
;
282 } StreamOnStreamRange
;
284 static inline StreamOnStreamRange
*StreamOnStreamRange_from_IStream(IStream
*iface
)
286 return CONTAINING_RECORD(iface
, StreamOnStreamRange
, IStream_iface
);
289 static HRESULT WINAPI
StreamOnStreamRange_QueryInterface(IStream
*iface
,
290 REFIID iid
, void **ppv
)
292 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
294 if (!ppv
) return E_INVALIDARG
;
296 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IStream
, iid
) ||
297 IsEqualIID(&IID_ISequentialStream
, iid
))
300 IUnknown_AddRef((IUnknown
*)*ppv
);
306 return E_NOINTERFACE
;
310 static ULONG WINAPI
StreamOnStreamRange_AddRef(IStream
*iface
)
312 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
313 ULONG ref
= InterlockedIncrement(&This
->ref
);
315 TRACE("(%p) refcount=%u\n", iface
, ref
);
320 static ULONG WINAPI
StreamOnStreamRange_Release(IStream
*iface
)
322 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
323 ULONG ref
= InterlockedDecrement(&This
->ref
);
325 TRACE("(%p) refcount=%u\n", iface
, ref
);
328 This
->lock
.DebugInfo
->Spare
[0] = 0;
329 DeleteCriticalSection(&This
->lock
);
330 IStream_Release(This
->stream
);
331 HeapFree(GetProcessHeap(), 0, This
);
336 static HRESULT WINAPI
StreamOnStreamRange_Read(IStream
*iface
,
337 void *pv
, ULONG cb
, ULONG
*pcbRead
)
339 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
342 ULARGE_INTEGER OldPosition
;
343 LARGE_INTEGER SetPosition
;
344 TRACE("(%p)\n", This
);
346 if (!pv
) return E_INVALIDARG
;
348 EnterCriticalSection(&This
->lock
);
349 SetPosition
.QuadPart
= 0;
350 hr
= IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_CUR
, &OldPosition
);
353 SetPosition
.QuadPart
= This
->pos
.QuadPart
+ This
->offset
.QuadPart
;
354 hr
= IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_SET
, NULL
);
358 if (This
->pos
.QuadPart
+ cb
> This
->max_size
.QuadPart
)
360 /* This would read past the end of the stream. */
361 if (This
->pos
.QuadPart
> This
->max_size
.QuadPart
)
364 cb
= This
->max_size
.QuadPart
- This
->pos
.QuadPart
;
366 hr
= IStream_Read(This
->stream
, pv
, cb
, &uBytesRead
);
367 SetPosition
.QuadPart
= OldPosition
.QuadPart
;
368 IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_SET
, NULL
);
371 This
->pos
.QuadPart
+= uBytesRead
;
372 LeaveCriticalSection(&This
->lock
);
374 if (SUCCEEDED(hr
) && pcbRead
) *pcbRead
= uBytesRead
;
379 static HRESULT WINAPI
StreamOnStreamRange_Write(IStream
*iface
,
380 void const *pv
, ULONG cb
, ULONG
*pcbWritten
)
382 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
384 ULARGE_INTEGER OldPosition
;
385 LARGE_INTEGER SetPosition
;
386 ULONG uBytesWritten
=0;
387 TRACE("(%p)\n", This
);
389 if (!pv
) return E_INVALIDARG
;
391 EnterCriticalSection(&This
->lock
);
392 SetPosition
.QuadPart
= 0;
393 hr
= IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_CUR
, &OldPosition
);
396 SetPosition
.QuadPart
= This
->pos
.QuadPart
+ This
->offset
.QuadPart
;
397 hr
= IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_SET
, NULL
);
401 if (This
->pos
.QuadPart
+ cb
> This
->max_size
.QuadPart
)
403 /* This would read past the end of the stream. */
404 if (This
->pos
.QuadPart
> This
->max_size
.QuadPart
)
407 cb
= This
->max_size
.QuadPart
- This
->pos
.QuadPart
;
409 hr
= IStream_Write(This
->stream
, pv
, cb
, &uBytesWritten
);
410 SetPosition
.QuadPart
= OldPosition
.QuadPart
;
411 IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_SET
, NULL
);
414 This
->pos
.QuadPart
+= uBytesWritten
;
415 LeaveCriticalSection(&This
->lock
);
417 if (SUCCEEDED(hr
) && pcbWritten
) *pcbWritten
= uBytesWritten
;
422 static HRESULT WINAPI
StreamOnStreamRange_Seek(IStream
*iface
,
423 LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
425 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
426 ULARGE_INTEGER NewPosition
, actual_size
;
429 TRACE("(%p)\n", This
);
431 EnterCriticalSection(&This
->lock
);
432 actual_size
= This
->max_size
;
433 if (dwOrigin
== STREAM_SEEK_SET
)
434 NewPosition
.QuadPart
= dlibMove
.QuadPart
;
435 else if (dwOrigin
== STREAM_SEEK_CUR
)
436 NewPosition
.QuadPart
= This
->pos
.QuadPart
+ dlibMove
.QuadPart
;
437 else if (dwOrigin
== STREAM_SEEK_END
)
439 hr
= IStream_Stat(This
->stream
, &statstg
, STATFLAG_NONAME
);
442 if (This
->max_size
.QuadPart
+ This
->offset
.QuadPart
> statstg
.cbSize
.QuadPart
)
443 actual_size
.QuadPart
= statstg
.cbSize
.QuadPart
- This
->offset
.QuadPart
;
444 NewPosition
.QuadPart
= dlibMove
.QuadPart
+ actual_size
.QuadPart
;
447 else hr
= E_INVALIDARG
;
449 if (SUCCEEDED(hr
) && (NewPosition
.u
.HighPart
!= 0 || NewPosition
.QuadPart
> actual_size
.QuadPart
))
450 hr
= WINCODEC_ERR_VALUEOUTOFRANGE
;
453 This
->pos
.QuadPart
= NewPosition
.QuadPart
;
455 if(plibNewPosition
) plibNewPosition
->QuadPart
= This
->pos
.QuadPart
;
457 LeaveCriticalSection(&This
->lock
);
462 /* SetSize isn't implemented in the native windowscodecs DLL either */
463 static HRESULT WINAPI
StreamOnStreamRange_SetSize(IStream
*iface
,
464 ULARGE_INTEGER libNewSize
)
466 TRACE("(%p)\n", iface
);
470 /* CopyTo isn't implemented in the native windowscodecs DLL either */
471 static HRESULT WINAPI
StreamOnStreamRange_CopyTo(IStream
*iface
,
472 IStream
*pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
474 TRACE("(%p)\n", iface
);
478 /* Commit isn't implemented in the native windowscodecs DLL either */
479 static HRESULT WINAPI
StreamOnStreamRange_Commit(IStream
*iface
,
480 DWORD grfCommitFlags
)
482 TRACE("(%p)\n", iface
);
486 /* Revert isn't implemented in the native windowscodecs DLL either */
487 static HRESULT WINAPI
StreamOnStreamRange_Revert(IStream
*iface
)
489 TRACE("(%p)\n", iface
);
493 /* LockRegion isn't implemented in the native windowscodecs DLL either */
494 static HRESULT WINAPI
StreamOnStreamRange_LockRegion(IStream
*iface
,
495 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
497 TRACE("(%p)\n", iface
);
501 /* UnlockRegion isn't implemented in the native windowscodecs DLL either */
502 static HRESULT WINAPI
StreamOnStreamRange_UnlockRegion(IStream
*iface
,
503 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
505 TRACE("(%p)\n", iface
);
509 static HRESULT WINAPI
StreamOnStreamRange_Stat(IStream
*iface
,
510 STATSTG
*pstatstg
, DWORD grfStatFlag
)
512 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
514 TRACE("(%p)\n", This
);
516 if (!pstatstg
) return E_INVALIDARG
;
518 EnterCriticalSection(&This
->lock
);
519 hr
= IStream_Stat(This
->stream
, pstatstg
, grfStatFlag
);
522 pstatstg
->cbSize
.QuadPart
-= This
->offset
.QuadPart
;
523 if (This
->max_size
.QuadPart
< pstatstg
->cbSize
.QuadPart
)
524 pstatstg
->cbSize
.QuadPart
= This
->max_size
.QuadPart
;
527 LeaveCriticalSection(&This
->lock
);
532 /* Clone isn't implemented in the native windowscodecs DLL either */
533 static HRESULT WINAPI
StreamOnStreamRange_Clone(IStream
*iface
,
536 TRACE("(%p)\n", iface
);
541 static const IStreamVtbl StreamOnStreamRange_Vtbl
=
543 /*** IUnknown methods ***/
544 StreamOnStreamRange_QueryInterface
,
545 StreamOnStreamRange_AddRef
,
546 StreamOnStreamRange_Release
,
547 /*** ISequentialStream methods ***/
548 StreamOnStreamRange_Read
,
549 StreamOnStreamRange_Write
,
550 /*** IStream methods ***/
551 StreamOnStreamRange_Seek
,
552 StreamOnStreamRange_SetSize
,
553 StreamOnStreamRange_CopyTo
,
554 StreamOnStreamRange_Commit
,
555 StreamOnStreamRange_Revert
,
556 StreamOnStreamRange_LockRegion
,
557 StreamOnStreamRange_UnlockRegion
,
558 StreamOnStreamRange_Stat
,
559 StreamOnStreamRange_Clone
,
563 /******************************************
564 * IWICStream implementation
567 typedef struct IWICStreamImpl
569 IWICStream IWICStream_iface
;
575 static inline IWICStreamImpl
*impl_from_IWICStream(IWICStream
*iface
)
577 return CONTAINING_RECORD(iface
, IWICStreamImpl
, IWICStream_iface
);
580 static HRESULT WINAPI
IWICStreamImpl_QueryInterface(IWICStream
*iface
,
581 REFIID iid
, void **ppv
)
583 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
584 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
586 if (!ppv
) return E_INVALIDARG
;
588 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IStream
, iid
) ||
589 IsEqualIID(&IID_ISequentialStream
, iid
) || IsEqualIID(&IID_IWICStream
, iid
))
592 IUnknown_AddRef((IUnknown
*)*ppv
);
598 return E_NOINTERFACE
;
602 static ULONG WINAPI
IWICStreamImpl_AddRef(IWICStream
*iface
)
604 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
605 ULONG ref
= InterlockedIncrement(&This
->ref
);
607 TRACE("(%p) refcount=%u\n", iface
, ref
);
612 static ULONG WINAPI
IWICStreamImpl_Release(IWICStream
*iface
)
614 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
615 ULONG ref
= InterlockedDecrement(&This
->ref
);
617 TRACE("(%p) refcount=%u\n", iface
, ref
);
620 if (This
->pStream
) IStream_Release(This
->pStream
);
621 HeapFree(GetProcessHeap(), 0, This
);
626 static HRESULT WINAPI
IWICStreamImpl_Read(IWICStream
*iface
,
627 void *pv
, ULONG cb
, ULONG
*pcbRead
)
629 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
630 TRACE("(%p): relay\n", This
);
632 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
633 return IStream_Read(This
->pStream
, pv
, cb
, pcbRead
);
636 static HRESULT WINAPI
IWICStreamImpl_Write(IWICStream
*iface
,
637 void const *pv
, ULONG cb
, ULONG
*pcbWritten
)
639 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
640 TRACE("(%p): relay\n", This
);
642 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
643 return IStream_Write(This
->pStream
, pv
, cb
, pcbWritten
);
646 static HRESULT WINAPI
IWICStreamImpl_Seek(IWICStream
*iface
,
647 LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
649 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
650 TRACE("(%p): relay\n", This
);
652 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
653 return IStream_Seek(This
->pStream
, dlibMove
, dwOrigin
, plibNewPosition
);
656 static HRESULT WINAPI
IWICStreamImpl_SetSize(IWICStream
*iface
,
657 ULARGE_INTEGER libNewSize
)
659 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
660 TRACE("(%p): relay\n", This
);
662 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
663 return IStream_SetSize(This
->pStream
, libNewSize
);
666 static HRESULT WINAPI
IWICStreamImpl_CopyTo(IWICStream
*iface
,
667 IStream
*pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
669 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
670 TRACE("(%p): relay\n", This
);
672 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
673 return IStream_CopyTo(This
->pStream
, pstm
, cb
, pcbRead
, pcbWritten
);
676 static HRESULT WINAPI
IWICStreamImpl_Commit(IWICStream
*iface
,
677 DWORD grfCommitFlags
)
679 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
680 TRACE("(%p): relay\n", This
);
682 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
683 return IStream_Commit(This
->pStream
, grfCommitFlags
);
686 static HRESULT WINAPI
IWICStreamImpl_Revert(IWICStream
*iface
)
688 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
689 TRACE("(%p): relay\n", This
);
691 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
692 return IStream_Revert(This
->pStream
);
695 static HRESULT WINAPI
IWICStreamImpl_LockRegion(IWICStream
*iface
,
696 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
698 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
699 TRACE("(%p): relay\n", This
);
701 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
702 return IStream_LockRegion(This
->pStream
, libOffset
, cb
, dwLockType
);
705 static HRESULT WINAPI
IWICStreamImpl_UnlockRegion(IWICStream
*iface
,
706 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
708 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
709 TRACE("(%p): relay\n", This
);
711 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
712 return IStream_UnlockRegion(This
->pStream
, libOffset
, cb
, dwLockType
);
715 static HRESULT WINAPI
IWICStreamImpl_Stat(IWICStream
*iface
,
716 STATSTG
*pstatstg
, DWORD grfStatFlag
)
718 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
719 TRACE("(%p): relay\n", This
);
721 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
722 return IStream_Stat(This
->pStream
, pstatstg
, grfStatFlag
);
725 static HRESULT WINAPI
IWICStreamImpl_Clone(IWICStream
*iface
,
728 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
729 TRACE("(%p): relay\n", This
);
731 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
732 return IStream_Clone(This
->pStream
, ppstm
);
735 static HRESULT WINAPI
IWICStreamImpl_InitializeFromIStream(IWICStream
*iface
,
738 ULARGE_INTEGER offset
, size
;
739 TRACE("(%p): relay\n", iface
);
742 size
.u
.LowPart
= 0xffffffff;
743 size
.u
.HighPart
= 0xffffffff;
744 return IWICStream_InitializeFromIStreamRegion(iface
, pIStream
, offset
, size
);
747 static HRESULT WINAPI
IWICStreamImpl_InitializeFromFilename(IWICStream
*iface
,
748 LPCWSTR wzFileName
, DWORD dwDesiredAccess
)
750 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
755 TRACE("(%p, %s, %u)\n", iface
, debugstr_w(wzFileName
), dwDesiredAccess
);
757 if (This
->pStream
) return WINCODEC_ERR_WRONGSTATE
;
759 if(dwDesiredAccess
& GENERIC_WRITE
)
760 dwMode
= STGM_SHARE_DENY_WRITE
| STGM_WRITE
| STGM_CREATE
;
761 else if(dwDesiredAccess
& GENERIC_READ
)
762 dwMode
= STGM_SHARE_DENY_WRITE
| STGM_READ
| STGM_FAILIFTHERE
;
766 hr
= SHCreateStreamOnFileW(wzFileName
, dwMode
, &stream
);
770 if (InterlockedCompareExchangePointer((void**)&This
->pStream
, stream
, NULL
))
772 /* Some other thread set the stream first. */
773 IStream_Release(stream
);
774 hr
= WINCODEC_ERR_WRONGSTATE
;
781 /******************************************
782 * IWICStream_InitializeFromMemory
784 * Initializes the internal IStream object to retrieve its data from a memory chunk.
787 * pbBuffer [I] pointer to the memory chunk
788 * cbBufferSize [I] number of bytes to use from the memory chunk
792 * FAILURE: E_INVALIDARG, if pbBuffer is NULL
793 * E_OUTOFMEMORY, if we run out of memory
794 * WINCODEC_ERR_WRONGSTATE, if the IStream object has already been initialized before
797 static HRESULT WINAPI
IWICStreamImpl_InitializeFromMemory(IWICStream
*iface
,
798 BYTE
*pbBuffer
, DWORD cbBufferSize
)
800 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
801 StreamOnMemory
*pObject
;
802 TRACE("(%p,%p)\n", iface
, pbBuffer
);
804 if (!pbBuffer
) return E_INVALIDARG
;
805 if (This
->pStream
) return WINCODEC_ERR_WRONGSTATE
;
807 pObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnMemory
));
808 if (!pObject
) return E_OUTOFMEMORY
;
810 pObject
->IStream_iface
.lpVtbl
= &StreamOnMemory_Vtbl
;
812 pObject
->pbMemory
= pbBuffer
;
813 pObject
->dwMemsize
= cbBufferSize
;
814 pObject
->dwCurPos
= 0;
815 InitializeCriticalSection(&pObject
->lock
);
816 pObject
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": StreamOnMemory.lock");
818 if (InterlockedCompareExchangePointer((void**)&This
->pStream
, pObject
, NULL
))
820 /* Some other thread set the stream first. */
821 IStream_Release(&pObject
->IStream_iface
);
822 return WINCODEC_ERR_WRONGSTATE
;
828 static HRESULT WINAPI
IWICStreamImpl_InitializeFromIStreamRegion(IWICStream
*iface
,
829 IStream
*pIStream
, ULARGE_INTEGER ulOffset
, ULARGE_INTEGER ulMaxSize
)
831 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
832 StreamOnStreamRange
*pObject
;
833 TRACE("(%p,%p)\n", iface
, pIStream
);
835 if (!pIStream
) return E_INVALIDARG
;
836 if (This
->pStream
) return WINCODEC_ERR_WRONGSTATE
;
838 pObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnStreamRange
));
839 if (!pObject
) return E_OUTOFMEMORY
;
841 pObject
->IStream_iface
.lpVtbl
= &StreamOnStreamRange_Vtbl
;
843 IStream_AddRef(pIStream
);
844 pObject
->stream
= pIStream
;
845 pObject
->pos
.QuadPart
= 0;
846 pObject
->offset
= ulOffset
;
847 pObject
->max_size
= ulMaxSize
;
848 InitializeCriticalSection(&pObject
->lock
);
849 pObject
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": StreamOnStreamRange.lock");
851 if (InterlockedCompareExchangePointer((void**)&This
->pStream
, pObject
, NULL
))
853 /* Some other thread set the stream first. */
854 IStream_Release(&pObject
->IStream_iface
);
855 return WINCODEC_ERR_WRONGSTATE
;
862 static const IWICStreamVtbl WICStream_Vtbl
=
864 /*** IUnknown methods ***/
865 IWICStreamImpl_QueryInterface
,
866 IWICStreamImpl_AddRef
,
867 IWICStreamImpl_Release
,
868 /*** ISequentialStream methods ***/
870 IWICStreamImpl_Write
,
871 /*** IStream methods ***/
873 IWICStreamImpl_SetSize
,
874 IWICStreamImpl_CopyTo
,
875 IWICStreamImpl_Commit
,
876 IWICStreamImpl_Revert
,
877 IWICStreamImpl_LockRegion
,
878 IWICStreamImpl_UnlockRegion
,
880 IWICStreamImpl_Clone
,
881 /*** IWICStream methods ***/
882 IWICStreamImpl_InitializeFromIStream
,
883 IWICStreamImpl_InitializeFromFilename
,
884 IWICStreamImpl_InitializeFromMemory
,
885 IWICStreamImpl_InitializeFromIStreamRegion
,
888 HRESULT
StreamImpl_Create(IWICStream
**stream
)
890 IWICStreamImpl
*pObject
;
892 if( !stream
) return E_INVALIDARG
;
894 pObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(IWICStreamImpl
));
897 return E_OUTOFMEMORY
;
900 pObject
->IWICStream_iface
.lpVtbl
= &WICStream_Vtbl
;
902 pObject
->pStream
= NULL
;
904 *stream
= &pObject
->IWICStream_iface
;