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 "wincodecs_private.h"
23 /******************************************
24 * StreamOnMemory implementation
26 * Used by IWICStream_InitializeFromMemory
29 typedef struct StreamOnMemory
{
30 IStream IStream_iface
;
37 CRITICAL_SECTION lock
; /* must be held when pbMemory or dwCurPos is accessed */
40 static inline StreamOnMemory
*StreamOnMemory_from_IStream(IStream
*iface
)
42 return CONTAINING_RECORD(iface
, StreamOnMemory
, IStream_iface
);
45 static HRESULT WINAPI
StreamOnMemory_QueryInterface(IStream
*iface
,
46 REFIID iid
, void **ppv
)
48 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
50 if (!ppv
) return E_INVALIDARG
;
52 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IStream
, iid
) ||
53 IsEqualIID(&IID_ISequentialStream
, iid
))
56 IUnknown_AddRef((IUnknown
*)*ppv
);
66 static ULONG WINAPI
StreamOnMemory_AddRef(IStream
*iface
)
68 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
69 ULONG ref
= InterlockedIncrement(&This
->ref
);
71 TRACE("(%p) refcount=%u\n", iface
, ref
);
76 static ULONG WINAPI
StreamOnMemory_Release(IStream
*iface
)
78 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
79 ULONG ref
= InterlockedDecrement(&This
->ref
);
81 TRACE("(%p) refcount=%u\n", iface
, ref
);
84 This
->lock
.DebugInfo
->Spare
[0] = 0;
85 DeleteCriticalSection(&This
->lock
);
86 HeapFree(GetProcessHeap(), 0, This
);
91 static HRESULT WINAPI
StreamOnMemory_Read(IStream
*iface
,
92 void *pv
, ULONG cb
, ULONG
*pcbRead
)
94 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
96 TRACE("(%p)\n", This
);
98 if (!pv
) return E_INVALIDARG
;
100 EnterCriticalSection(&This
->lock
);
101 uBytesRead
= min(cb
, This
->dwMemsize
- This
->dwCurPos
);
102 memmove(pv
, This
->pbMemory
+ This
->dwCurPos
, uBytesRead
);
103 This
->dwCurPos
+= uBytesRead
;
104 LeaveCriticalSection(&This
->lock
);
106 if (pcbRead
) *pcbRead
= uBytesRead
;
111 static HRESULT WINAPI
StreamOnMemory_Write(IStream
*iface
,
112 void const *pv
, ULONG cb
, ULONG
*pcbWritten
)
114 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
116 TRACE("(%p)\n", This
);
118 if (!pv
) return E_INVALIDARG
;
120 EnterCriticalSection(&This
->lock
);
121 if (cb
> This
->dwMemsize
- This
->dwCurPos
) {
122 hr
= STG_E_MEDIUMFULL
;
125 memmove(This
->pbMemory
+ This
->dwCurPos
, pv
, cb
);
126 This
->dwCurPos
+= cb
;
128 if (pcbWritten
) *pcbWritten
= cb
;
130 LeaveCriticalSection(&This
->lock
);
135 static HRESULT WINAPI
StreamOnMemory_Seek(IStream
*iface
,
136 LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
138 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
139 LARGE_INTEGER NewPosition
;
141 TRACE("(%p)\n", This
);
143 EnterCriticalSection(&This
->lock
);
144 if (dwOrigin
== STREAM_SEEK_SET
) NewPosition
.QuadPart
= dlibMove
.QuadPart
;
145 else if (dwOrigin
== STREAM_SEEK_CUR
) NewPosition
.QuadPart
= This
->dwCurPos
+ dlibMove
.QuadPart
;
146 else if (dwOrigin
== STREAM_SEEK_END
) NewPosition
.QuadPart
= This
->dwMemsize
+ dlibMove
.QuadPart
;
147 else hr
= E_INVALIDARG
;
150 if (NewPosition
.u
.HighPart
) hr
= HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW
);
151 else if (NewPosition
.QuadPart
> This
->dwMemsize
) hr
= E_INVALIDARG
;
152 else if (NewPosition
.QuadPart
< 0) hr
= E_INVALIDARG
;
156 This
->dwCurPos
= NewPosition
.u
.LowPart
;
158 if(plibNewPosition
) plibNewPosition
->QuadPart
= This
->dwCurPos
;
160 LeaveCriticalSection(&This
->lock
);
165 /* SetSize isn't implemented in the native windowscodecs DLL either */
166 static HRESULT WINAPI
StreamOnMemory_SetSize(IStream
*iface
,
167 ULARGE_INTEGER libNewSize
)
169 TRACE("(%p)\n", iface
);
173 /* CopyTo isn't implemented in the native windowscodecs DLL either */
174 static HRESULT WINAPI
StreamOnMemory_CopyTo(IStream
*iface
,
175 IStream
*pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
177 TRACE("(%p)\n", iface
);
181 /* Commit isn't implemented in the native windowscodecs DLL either */
182 static HRESULT WINAPI
StreamOnMemory_Commit(IStream
*iface
,
183 DWORD grfCommitFlags
)
185 TRACE("(%p)\n", iface
);
189 /* Revert isn't implemented in the native windowscodecs DLL either */
190 static HRESULT WINAPI
StreamOnMemory_Revert(IStream
*iface
)
192 TRACE("(%p)\n", iface
);
196 /* LockRegion isn't implemented in the native windowscodecs DLL either */
197 static HRESULT WINAPI
StreamOnMemory_LockRegion(IStream
*iface
,
198 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
200 TRACE("(%p)\n", iface
);
204 /* UnlockRegion isn't implemented in the native windowscodecs DLL either */
205 static HRESULT WINAPI
StreamOnMemory_UnlockRegion(IStream
*iface
,
206 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
208 TRACE("(%p)\n", iface
);
212 static HRESULT WINAPI
StreamOnMemory_Stat(IStream
*iface
,
213 STATSTG
*pstatstg
, DWORD grfStatFlag
)
215 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
216 TRACE("(%p)\n", This
);
218 if (!pstatstg
) return E_INVALIDARG
;
220 ZeroMemory(pstatstg
, sizeof(STATSTG
));
221 pstatstg
->type
= STGTY_STREAM
;
222 pstatstg
->cbSize
.QuadPart
= This
->dwMemsize
;
227 /* Clone isn't implemented in the native windowscodecs DLL either */
228 static HRESULT WINAPI
StreamOnMemory_Clone(IStream
*iface
,
231 TRACE("(%p)\n", iface
);
236 static const IStreamVtbl StreamOnMemory_Vtbl
=
238 /*** IUnknown methods ***/
239 StreamOnMemory_QueryInterface
,
240 StreamOnMemory_AddRef
,
241 StreamOnMemory_Release
,
242 /*** ISequentialStream methods ***/
244 StreamOnMemory_Write
,
245 /*** IStream methods ***/
247 StreamOnMemory_SetSize
,
248 StreamOnMemory_CopyTo
,
249 StreamOnMemory_Commit
,
250 StreamOnMemory_Revert
,
251 StreamOnMemory_LockRegion
,
252 StreamOnMemory_UnlockRegion
,
254 StreamOnMemory_Clone
,
257 /******************************************
258 * StreamOnFileHandle implementation (internal)
261 typedef struct StreamOnFileHandle
{
262 IStream IStream_iface
;
268 } StreamOnFileHandle
;
270 static inline StreamOnFileHandle
*StreamOnFileHandle_from_IStream(IStream
*iface
)
272 return CONTAINING_RECORD(iface
, StreamOnFileHandle
, IStream_iface
);
275 static HRESULT WINAPI
StreamOnFileHandle_QueryInterface(IStream
*iface
,
276 REFIID iid
, void **ppv
)
278 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
280 if (!ppv
) return E_INVALIDARG
;
282 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IStream
, iid
) ||
283 IsEqualIID(&IID_ISequentialStream
, iid
))
286 IUnknown_AddRef((IUnknown
*)*ppv
);
292 return E_NOINTERFACE
;
296 static ULONG WINAPI
StreamOnFileHandle_AddRef(IStream
*iface
)
298 StreamOnFileHandle
*This
= StreamOnFileHandle_from_IStream(iface
);
299 ULONG ref
= InterlockedIncrement(&This
->ref
);
301 TRACE("(%p) refcount=%u\n", iface
, ref
);
306 static ULONG WINAPI
StreamOnFileHandle_Release(IStream
*iface
)
308 StreamOnFileHandle
*This
= StreamOnFileHandle_from_IStream(iface
);
309 ULONG ref
= InterlockedDecrement(&This
->ref
);
311 TRACE("(%p) refcount=%u\n", iface
, ref
);
314 IWICStream_Release(This
->stream
);
315 UnmapViewOfFile(This
->mem
);
316 CloseHandle(This
->map
);
317 HeapFree(GetProcessHeap(), 0, This
);
322 static HRESULT WINAPI
StreamOnFileHandle_Read(IStream
*iface
,
323 void *pv
, ULONG cb
, ULONG
*pcbRead
)
325 StreamOnFileHandle
*This
= StreamOnFileHandle_from_IStream(iface
);
326 TRACE("(%p)\n", This
);
328 return IWICStream_Read(This
->stream
, pv
, cb
, pcbRead
);
331 static HRESULT WINAPI
StreamOnFileHandle_Write(IStream
*iface
,
332 void const *pv
, ULONG cb
, ULONG
*pcbWritten
)
334 ERR("(%p)\n", iface
);
335 return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED
);
338 static HRESULT WINAPI
StreamOnFileHandle_Seek(IStream
*iface
,
339 LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
341 StreamOnFileHandle
*This
= StreamOnFileHandle_from_IStream(iface
);
342 TRACE("(%p)\n", This
);
344 return IWICStream_Seek(This
->stream
, dlibMove
, dwOrigin
, plibNewPosition
);
347 static HRESULT WINAPI
StreamOnFileHandle_SetSize(IStream
*iface
,
348 ULARGE_INTEGER libNewSize
)
350 TRACE("(%p)\n", iface
);
354 static HRESULT WINAPI
StreamOnFileHandle_CopyTo(IStream
*iface
,
355 IStream
*pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
357 TRACE("(%p)\n", iface
);
361 static HRESULT WINAPI
StreamOnFileHandle_Commit(IStream
*iface
,
362 DWORD grfCommitFlags
)
364 TRACE("(%p)\n", iface
);
368 static HRESULT WINAPI
StreamOnFileHandle_Revert(IStream
*iface
)
370 TRACE("(%p)\n", iface
);
374 static HRESULT WINAPI
StreamOnFileHandle_LockRegion(IStream
*iface
,
375 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
377 TRACE("(%p)\n", iface
);
381 static HRESULT WINAPI
StreamOnFileHandle_UnlockRegion(IStream
*iface
,
382 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
384 TRACE("(%p)\n", iface
);
388 static HRESULT WINAPI
StreamOnFileHandle_Stat(IStream
*iface
,
389 STATSTG
*pstatstg
, DWORD grfStatFlag
)
391 StreamOnFileHandle
*This
= StreamOnFileHandle_from_IStream(iface
);
392 TRACE("(%p)\n", This
);
394 return IWICStream_Stat(This
->stream
, pstatstg
, grfStatFlag
);
397 static HRESULT WINAPI
StreamOnFileHandle_Clone(IStream
*iface
,
400 TRACE("(%p)\n", iface
);
405 static const IStreamVtbl StreamOnFileHandle_Vtbl
=
407 /*** IUnknown methods ***/
408 StreamOnFileHandle_QueryInterface
,
409 StreamOnFileHandle_AddRef
,
410 StreamOnFileHandle_Release
,
411 /*** ISequentialStream methods ***/
412 StreamOnFileHandle_Read
,
413 StreamOnFileHandle_Write
,
414 /*** IStream methods ***/
415 StreamOnFileHandle_Seek
,
416 StreamOnFileHandle_SetSize
,
417 StreamOnFileHandle_CopyTo
,
418 StreamOnFileHandle_Commit
,
419 StreamOnFileHandle_Revert
,
420 StreamOnFileHandle_LockRegion
,
421 StreamOnFileHandle_UnlockRegion
,
422 StreamOnFileHandle_Stat
,
423 StreamOnFileHandle_Clone
,
426 /******************************************
427 * StreamOnStreamRange implementation
429 * Used by IWICStream_InitializeFromIStreamRegion
432 typedef struct StreamOnStreamRange
{
433 IStream IStream_iface
;
438 ULARGE_INTEGER offset
;
439 ULARGE_INTEGER max_size
;
441 CRITICAL_SECTION lock
;
442 } StreamOnStreamRange
;
444 static inline StreamOnStreamRange
*StreamOnStreamRange_from_IStream(IStream
*iface
)
446 return CONTAINING_RECORD(iface
, StreamOnStreamRange
, IStream_iface
);
449 static HRESULT WINAPI
StreamOnStreamRange_QueryInterface(IStream
*iface
,
450 REFIID iid
, void **ppv
)
452 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
454 if (!ppv
) return E_INVALIDARG
;
456 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IStream
, iid
) ||
457 IsEqualIID(&IID_ISequentialStream
, iid
))
460 IUnknown_AddRef((IUnknown
*)*ppv
);
466 return E_NOINTERFACE
;
470 static ULONG WINAPI
StreamOnStreamRange_AddRef(IStream
*iface
)
472 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
473 ULONG ref
= InterlockedIncrement(&This
->ref
);
475 TRACE("(%p) refcount=%u\n", iface
, ref
);
480 static ULONG WINAPI
StreamOnStreamRange_Release(IStream
*iface
)
482 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
483 ULONG ref
= InterlockedDecrement(&This
->ref
);
485 TRACE("(%p) refcount=%u\n", iface
, ref
);
488 This
->lock
.DebugInfo
->Spare
[0] = 0;
489 DeleteCriticalSection(&This
->lock
);
490 IStream_Release(This
->stream
);
491 HeapFree(GetProcessHeap(), 0, This
);
496 static HRESULT WINAPI
StreamOnStreamRange_Read(IStream
*iface
,
497 void *pv
, ULONG cb
, ULONG
*pcbRead
)
499 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
502 ULARGE_INTEGER OldPosition
;
503 LARGE_INTEGER SetPosition
;
504 TRACE("(%p)\n", This
);
506 if (!pv
) return E_INVALIDARG
;
508 EnterCriticalSection(&This
->lock
);
509 SetPosition
.QuadPart
= 0;
510 hr
= IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_CUR
, &OldPosition
);
513 SetPosition
.QuadPart
= This
->pos
.QuadPart
+ This
->offset
.QuadPart
;
514 hr
= IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_SET
, NULL
);
518 if (This
->pos
.QuadPart
+ cb
> This
->max_size
.QuadPart
)
520 /* This would read past the end of the stream. */
521 if (This
->pos
.QuadPart
> This
->max_size
.QuadPart
)
524 cb
= This
->max_size
.QuadPart
- This
->pos
.QuadPart
;
526 hr
= IStream_Read(This
->stream
, pv
, cb
, &uBytesRead
);
527 SetPosition
.QuadPart
= OldPosition
.QuadPart
;
528 IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_SET
, NULL
);
531 This
->pos
.QuadPart
+= uBytesRead
;
532 LeaveCriticalSection(&This
->lock
);
534 if (SUCCEEDED(hr
) && pcbRead
) *pcbRead
= uBytesRead
;
539 static HRESULT WINAPI
StreamOnStreamRange_Write(IStream
*iface
,
540 void const *pv
, ULONG cb
, ULONG
*pcbWritten
)
542 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
544 ULARGE_INTEGER OldPosition
;
545 LARGE_INTEGER SetPosition
;
546 ULONG uBytesWritten
=0;
547 TRACE("(%p)\n", This
);
549 if (!pv
) return E_INVALIDARG
;
551 EnterCriticalSection(&This
->lock
);
552 SetPosition
.QuadPart
= 0;
553 hr
= IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_CUR
, &OldPosition
);
556 SetPosition
.QuadPart
= This
->pos
.QuadPart
+ This
->offset
.QuadPart
;
557 hr
= IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_SET
, NULL
);
561 if (This
->pos
.QuadPart
+ cb
> This
->max_size
.QuadPart
)
563 /* This would read past the end of the stream. */
564 if (This
->pos
.QuadPart
> This
->max_size
.QuadPart
)
567 cb
= This
->max_size
.QuadPart
- This
->pos
.QuadPart
;
569 hr
= IStream_Write(This
->stream
, pv
, cb
, &uBytesWritten
);
570 SetPosition
.QuadPart
= OldPosition
.QuadPart
;
571 IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_SET
, NULL
);
574 This
->pos
.QuadPart
+= uBytesWritten
;
575 LeaveCriticalSection(&This
->lock
);
577 if (SUCCEEDED(hr
) && pcbWritten
) *pcbWritten
= uBytesWritten
;
582 static HRESULT WINAPI
StreamOnStreamRange_Seek(IStream
*iface
,
583 LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
585 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
586 ULARGE_INTEGER NewPosition
, actual_size
;
589 TRACE("(%p)\n", This
);
591 EnterCriticalSection(&This
->lock
);
592 actual_size
= This
->max_size
;
593 if (dwOrigin
== STREAM_SEEK_SET
)
594 NewPosition
.QuadPart
= dlibMove
.QuadPart
;
595 else if (dwOrigin
== STREAM_SEEK_CUR
)
596 NewPosition
.QuadPart
= This
->pos
.QuadPart
+ dlibMove
.QuadPart
;
597 else if (dwOrigin
== STREAM_SEEK_END
)
599 hr
= IStream_Stat(This
->stream
, &statstg
, STATFLAG_NONAME
);
602 if (This
->max_size
.QuadPart
+ This
->offset
.QuadPart
> statstg
.cbSize
.QuadPart
)
603 actual_size
.QuadPart
= statstg
.cbSize
.QuadPart
- This
->offset
.QuadPart
;
604 NewPosition
.QuadPart
= dlibMove
.QuadPart
+ actual_size
.QuadPart
;
607 else hr
= E_INVALIDARG
;
609 if (SUCCEEDED(hr
) && (NewPosition
.u
.HighPart
!= 0 || NewPosition
.QuadPart
> actual_size
.QuadPart
))
610 hr
= WINCODEC_ERR_VALUEOUTOFRANGE
;
613 This
->pos
.QuadPart
= NewPosition
.QuadPart
;
615 if(plibNewPosition
) plibNewPosition
->QuadPart
= This
->pos
.QuadPart
;
617 LeaveCriticalSection(&This
->lock
);
622 /* SetSize isn't implemented in the native windowscodecs DLL either */
623 static HRESULT WINAPI
StreamOnStreamRange_SetSize(IStream
*iface
,
624 ULARGE_INTEGER libNewSize
)
626 TRACE("(%p)\n", iface
);
630 /* CopyTo isn't implemented in the native windowscodecs DLL either */
631 static HRESULT WINAPI
StreamOnStreamRange_CopyTo(IStream
*iface
,
632 IStream
*pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
634 TRACE("(%p)\n", iface
);
638 /* Commit isn't implemented in the native windowscodecs DLL either */
639 static HRESULT WINAPI
StreamOnStreamRange_Commit(IStream
*iface
,
640 DWORD grfCommitFlags
)
642 TRACE("(%p)\n", iface
);
646 /* Revert isn't implemented in the native windowscodecs DLL either */
647 static HRESULT WINAPI
StreamOnStreamRange_Revert(IStream
*iface
)
649 TRACE("(%p)\n", iface
);
653 /* LockRegion isn't implemented in the native windowscodecs DLL either */
654 static HRESULT WINAPI
StreamOnStreamRange_LockRegion(IStream
*iface
,
655 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
657 TRACE("(%p)\n", iface
);
661 /* UnlockRegion isn't implemented in the native windowscodecs DLL either */
662 static HRESULT WINAPI
StreamOnStreamRange_UnlockRegion(IStream
*iface
,
663 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
665 TRACE("(%p)\n", iface
);
669 static HRESULT WINAPI
StreamOnStreamRange_Stat(IStream
*iface
,
670 STATSTG
*pstatstg
, DWORD grfStatFlag
)
672 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
674 TRACE("(%p)\n", This
);
676 if (!pstatstg
) return E_INVALIDARG
;
678 EnterCriticalSection(&This
->lock
);
679 hr
= IStream_Stat(This
->stream
, pstatstg
, grfStatFlag
);
682 pstatstg
->cbSize
.QuadPart
-= This
->offset
.QuadPart
;
683 if (This
->max_size
.QuadPart
< pstatstg
->cbSize
.QuadPart
)
684 pstatstg
->cbSize
.QuadPart
= This
->max_size
.QuadPart
;
687 LeaveCriticalSection(&This
->lock
);
692 /* Clone isn't implemented in the native windowscodecs DLL either */
693 static HRESULT WINAPI
StreamOnStreamRange_Clone(IStream
*iface
,
696 TRACE("(%p)\n", iface
);
701 static const IStreamVtbl StreamOnStreamRange_Vtbl
=
703 /*** IUnknown methods ***/
704 StreamOnStreamRange_QueryInterface
,
705 StreamOnStreamRange_AddRef
,
706 StreamOnStreamRange_Release
,
707 /*** ISequentialStream methods ***/
708 StreamOnStreamRange_Read
,
709 StreamOnStreamRange_Write
,
710 /*** IStream methods ***/
711 StreamOnStreamRange_Seek
,
712 StreamOnStreamRange_SetSize
,
713 StreamOnStreamRange_CopyTo
,
714 StreamOnStreamRange_Commit
,
715 StreamOnStreamRange_Revert
,
716 StreamOnStreamRange_LockRegion
,
717 StreamOnStreamRange_UnlockRegion
,
718 StreamOnStreamRange_Stat
,
719 StreamOnStreamRange_Clone
,
723 /******************************************
724 * IWICStream implementation
727 typedef struct IWICStreamImpl
729 IWICStream IWICStream_iface
;
735 static inline IWICStreamImpl
*impl_from_IWICStream(IWICStream
*iface
)
737 return CONTAINING_RECORD(iface
, IWICStreamImpl
, IWICStream_iface
);
740 static HRESULT WINAPI
IWICStreamImpl_QueryInterface(IWICStream
*iface
,
741 REFIID iid
, void **ppv
)
743 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
744 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
746 if (!ppv
) return E_INVALIDARG
;
748 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IStream
, iid
) ||
749 IsEqualIID(&IID_ISequentialStream
, iid
) || IsEqualIID(&IID_IWICStream
, iid
))
751 *ppv
= &This
->IWICStream_iface
;
752 IUnknown_AddRef((IUnknown
*)*ppv
);
758 return E_NOINTERFACE
;
762 static ULONG WINAPI
IWICStreamImpl_AddRef(IWICStream
*iface
)
764 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
765 ULONG ref
= InterlockedIncrement(&This
->ref
);
767 TRACE("(%p) refcount=%u\n", iface
, ref
);
772 static ULONG WINAPI
IWICStreamImpl_Release(IWICStream
*iface
)
774 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
775 ULONG ref
= InterlockedDecrement(&This
->ref
);
777 TRACE("(%p) refcount=%u\n", iface
, ref
);
780 if (This
->pStream
) IStream_Release(This
->pStream
);
781 HeapFree(GetProcessHeap(), 0, This
);
786 static HRESULT WINAPI
IWICStreamImpl_Read(IWICStream
*iface
,
787 void *pv
, ULONG cb
, ULONG
*pcbRead
)
789 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
790 TRACE("(%p): relay\n", This
);
792 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
793 return IStream_Read(This
->pStream
, pv
, cb
, pcbRead
);
796 static HRESULT WINAPI
IWICStreamImpl_Write(IWICStream
*iface
,
797 void const *pv
, ULONG cb
, ULONG
*pcbWritten
)
799 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
800 TRACE("(%p): relay\n", This
);
802 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
803 return IStream_Write(This
->pStream
, pv
, cb
, pcbWritten
);
806 static HRESULT WINAPI
IWICStreamImpl_Seek(IWICStream
*iface
,
807 LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
809 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
810 TRACE("(%p): relay\n", This
);
812 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
813 return IStream_Seek(This
->pStream
, dlibMove
, dwOrigin
, plibNewPosition
);
816 static HRESULT WINAPI
IWICStreamImpl_SetSize(IWICStream
*iface
,
817 ULARGE_INTEGER libNewSize
)
819 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
820 TRACE("(%p): relay\n", This
);
822 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
823 return IStream_SetSize(This
->pStream
, libNewSize
);
826 static HRESULT WINAPI
IWICStreamImpl_CopyTo(IWICStream
*iface
,
827 IStream
*pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
829 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
830 TRACE("(%p): relay\n", This
);
832 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
833 return IStream_CopyTo(This
->pStream
, pstm
, cb
, pcbRead
, pcbWritten
);
836 static HRESULT WINAPI
IWICStreamImpl_Commit(IWICStream
*iface
,
837 DWORD grfCommitFlags
)
839 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
840 TRACE("(%p): relay\n", This
);
842 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
843 return IStream_Commit(This
->pStream
, grfCommitFlags
);
846 static HRESULT WINAPI
IWICStreamImpl_Revert(IWICStream
*iface
)
848 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
849 TRACE("(%p): relay\n", This
);
851 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
852 return IStream_Revert(This
->pStream
);
855 static HRESULT WINAPI
IWICStreamImpl_LockRegion(IWICStream
*iface
,
856 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
858 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
859 TRACE("(%p): relay\n", This
);
861 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
862 return IStream_LockRegion(This
->pStream
, libOffset
, cb
, dwLockType
);
865 static HRESULT WINAPI
IWICStreamImpl_UnlockRegion(IWICStream
*iface
,
866 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
868 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
869 TRACE("(%p): relay\n", This
);
871 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
872 return IStream_UnlockRegion(This
->pStream
, libOffset
, cb
, dwLockType
);
875 static HRESULT WINAPI
IWICStreamImpl_Stat(IWICStream
*iface
,
876 STATSTG
*pstatstg
, DWORD grfStatFlag
)
878 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
879 TRACE("(%p): relay\n", This
);
881 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
882 return IStream_Stat(This
->pStream
, pstatstg
, grfStatFlag
);
885 static HRESULT WINAPI
IWICStreamImpl_Clone(IWICStream
*iface
,
888 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
889 TRACE("(%p): relay\n", This
);
891 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
892 return IStream_Clone(This
->pStream
, ppstm
);
895 static HRESULT WINAPI
IWICStreamImpl_InitializeFromIStream(IWICStream
*iface
,
898 ULARGE_INTEGER offset
, size
;
899 TRACE("(%p): relay\n", iface
);
902 size
.u
.LowPart
= 0xffffffff;
903 size
.u
.HighPart
= 0xffffffff;
904 return IWICStream_InitializeFromIStreamRegion(iface
, pIStream
, offset
, size
);
907 static HRESULT WINAPI
IWICStreamImpl_InitializeFromFilename(IWICStream
*iface
,
908 LPCWSTR wzFileName
, DWORD dwDesiredAccess
)
910 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
915 TRACE("(%p, %s, %u)\n", iface
, debugstr_w(wzFileName
), dwDesiredAccess
);
917 if (This
->pStream
) return WINCODEC_ERR_WRONGSTATE
;
919 if(dwDesiredAccess
& GENERIC_WRITE
)
920 dwMode
= STGM_SHARE_DENY_WRITE
| STGM_WRITE
| STGM_CREATE
;
921 else if(dwDesiredAccess
& GENERIC_READ
)
922 dwMode
= STGM_SHARE_DENY_WRITE
| STGM_READ
| STGM_FAILIFTHERE
;
926 hr
= SHCreateStreamOnFileW(wzFileName
, dwMode
, &stream
);
930 if (InterlockedCompareExchangePointer((void**)&This
->pStream
, stream
, NULL
))
932 /* Some other thread set the stream first. */
933 IStream_Release(stream
);
934 hr
= WINCODEC_ERR_WRONGSTATE
;
941 /******************************************
942 * IWICStream_InitializeFromMemory
944 * Initializes the internal IStream object to retrieve its data from a memory chunk.
947 * pbBuffer [I] pointer to the memory chunk
948 * cbBufferSize [I] number of bytes to use from the memory chunk
952 * FAILURE: E_INVALIDARG, if pbBuffer is NULL
953 * E_OUTOFMEMORY, if we run out of memory
954 * WINCODEC_ERR_WRONGSTATE, if the IStream object has already been initialized before
957 static HRESULT WINAPI
IWICStreamImpl_InitializeFromMemory(IWICStream
*iface
,
958 BYTE
*pbBuffer
, DWORD cbBufferSize
)
960 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
961 StreamOnMemory
*pObject
;
962 TRACE("(%p,%p)\n", iface
, pbBuffer
);
964 if (!pbBuffer
) return E_INVALIDARG
;
965 if (This
->pStream
) return WINCODEC_ERR_WRONGSTATE
;
967 pObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnMemory
));
968 if (!pObject
) return E_OUTOFMEMORY
;
970 pObject
->IStream_iface
.lpVtbl
= &StreamOnMemory_Vtbl
;
972 pObject
->pbMemory
= pbBuffer
;
973 pObject
->dwMemsize
= cbBufferSize
;
974 pObject
->dwCurPos
= 0;
975 InitializeCriticalSection(&pObject
->lock
);
976 pObject
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": StreamOnMemory.lock");
978 if (InterlockedCompareExchangePointer((void**)&This
->pStream
, pObject
, NULL
))
980 /* Some other thread set the stream first. */
981 IStream_Release(&pObject
->IStream_iface
);
982 return WINCODEC_ERR_WRONGSTATE
;
988 static HRESULT
map_file(HANDLE file
, HANDLE
*map
, void **mem
, LARGE_INTEGER
*size
)
991 if (!GetFileSizeEx(file
, size
)) return HRESULT_FROM_WIN32(GetLastError());
992 if (size
->u
.HighPart
)
994 WARN("file too large\n");
997 if (!(*map
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, size
->u
.LowPart
, NULL
)))
999 return HRESULT_FROM_WIN32(GetLastError());
1001 if (!(*mem
= MapViewOfFile(*map
, FILE_MAP_READ
, 0, 0, size
->u
.LowPart
)))
1004 return HRESULT_FROM_WIN32(GetLastError());
1009 HRESULT
stream_initialize_from_filehandle(IWICStream
*iface
, HANDLE file
)
1011 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
1012 StreamOnFileHandle
*pObject
;
1013 IWICStream
*stream
= NULL
;
1018 TRACE("(%p,%p)\n", iface
, file
);
1020 if (This
->pStream
) return WINCODEC_ERR_WRONGSTATE
;
1022 hr
= map_file(file
, &map
, &mem
, &size
);
1023 if (FAILED(hr
)) return hr
;
1025 hr
= StreamImpl_Create(&stream
);
1026 if (FAILED(hr
)) goto error
;
1028 hr
= IWICStreamImpl_InitializeFromMemory(stream
, mem
, size
.u
.LowPart
);
1029 if (FAILED(hr
)) goto error
;
1031 pObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnFileHandle
));
1037 pObject
->IStream_iface
.lpVtbl
= &StreamOnFileHandle_Vtbl
;
1041 pObject
->stream
= stream
;
1043 if (InterlockedCompareExchangePointer((void**)&This
->pStream
, pObject
, NULL
))
1045 /* Some other thread set the stream first. */
1046 IStream_Release(&pObject
->IStream_iface
);
1047 return WINCODEC_ERR_WRONGSTATE
;
1052 if (stream
) IWICStream_Release(stream
);
1053 UnmapViewOfFile(mem
);
1058 static HRESULT WINAPI
IWICStreamImpl_InitializeFromIStreamRegion(IWICStream
*iface
,
1059 IStream
*pIStream
, ULARGE_INTEGER ulOffset
, ULARGE_INTEGER ulMaxSize
)
1061 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
1062 StreamOnStreamRange
*pObject
;
1063 TRACE("(%p,%p)\n", iface
, pIStream
);
1065 if (!pIStream
) return E_INVALIDARG
;
1066 if (This
->pStream
) return WINCODEC_ERR_WRONGSTATE
;
1068 pObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnStreamRange
));
1069 if (!pObject
) return E_OUTOFMEMORY
;
1071 pObject
->IStream_iface
.lpVtbl
= &StreamOnStreamRange_Vtbl
;
1073 IStream_AddRef(pIStream
);
1074 pObject
->stream
= pIStream
;
1075 pObject
->pos
.QuadPart
= 0;
1076 pObject
->offset
= ulOffset
;
1077 pObject
->max_size
= ulMaxSize
;
1078 InitializeCriticalSection(&pObject
->lock
);
1079 pObject
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": StreamOnStreamRange.lock");
1081 if (InterlockedCompareExchangePointer((void**)&This
->pStream
, pObject
, NULL
))
1083 /* Some other thread set the stream first. */
1084 IStream_Release(&pObject
->IStream_iface
);
1085 return WINCODEC_ERR_WRONGSTATE
;
1092 static const IWICStreamVtbl WICStream_Vtbl
=
1094 /*** IUnknown methods ***/
1095 IWICStreamImpl_QueryInterface
,
1096 IWICStreamImpl_AddRef
,
1097 IWICStreamImpl_Release
,
1098 /*** ISequentialStream methods ***/
1099 IWICStreamImpl_Read
,
1100 IWICStreamImpl_Write
,
1101 /*** IStream methods ***/
1102 IWICStreamImpl_Seek
,
1103 IWICStreamImpl_SetSize
,
1104 IWICStreamImpl_CopyTo
,
1105 IWICStreamImpl_Commit
,
1106 IWICStreamImpl_Revert
,
1107 IWICStreamImpl_LockRegion
,
1108 IWICStreamImpl_UnlockRegion
,
1109 IWICStreamImpl_Stat
,
1110 IWICStreamImpl_Clone
,
1111 /*** IWICStream methods ***/
1112 IWICStreamImpl_InitializeFromIStream
,
1113 IWICStreamImpl_InitializeFromFilename
,
1114 IWICStreamImpl_InitializeFromMemory
,
1115 IWICStreamImpl_InitializeFromIStreamRegion
,
1118 HRESULT
StreamImpl_Create(IWICStream
**stream
)
1120 IWICStreamImpl
*pObject
;
1122 if( !stream
) return E_INVALIDARG
;
1124 pObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(IWICStreamImpl
));
1127 return E_OUTOFMEMORY
;
1130 pObject
->IWICStream_iface
.lpVtbl
= &WICStream_Vtbl
;
1132 pObject
->pStream
= NULL
;
1134 *stream
= &pObject
->IWICStream_iface
;