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 #define WIN32_NO_STATUS
21 #define COM_NO_WINDOWS_H
23 #include <wine/debug.h>
32 #include "wincodecs_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
36 /******************************************
37 * StreamOnMemory implementation
39 * Used by IWICStream_InitializeFromMemory
42 typedef struct StreamOnMemory
{
43 IStream IStream_iface
;
50 CRITICAL_SECTION lock
; /* must be held when pbMemory or dwCurPos is accessed */
53 static inline StreamOnMemory
*StreamOnMemory_from_IStream(IStream
*iface
)
55 return CONTAINING_RECORD(iface
, StreamOnMemory
, IStream_iface
);
58 static HRESULT WINAPI
StreamOnMemory_QueryInterface(IStream
*iface
,
59 REFIID iid
, void **ppv
)
61 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
63 if (!ppv
) return E_INVALIDARG
;
65 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IStream
, iid
) ||
66 IsEqualIID(&IID_ISequentialStream
, iid
))
69 IUnknown_AddRef((IUnknown
*)*ppv
);
79 static ULONG WINAPI
StreamOnMemory_AddRef(IStream
*iface
)
81 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
82 ULONG ref
= InterlockedIncrement(&This
->ref
);
84 TRACE("(%p) refcount=%u\n", iface
, ref
);
89 static ULONG WINAPI
StreamOnMemory_Release(IStream
*iface
)
91 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
92 ULONG ref
= InterlockedDecrement(&This
->ref
);
94 TRACE("(%p) refcount=%u\n", iface
, ref
);
97 This
->lock
.DebugInfo
->Spare
[0] = 0;
98 DeleteCriticalSection(&This
->lock
);
99 HeapFree(GetProcessHeap(), 0, This
);
104 static HRESULT WINAPI
StreamOnMemory_Read(IStream
*iface
,
105 void *pv
, ULONG cb
, ULONG
*pcbRead
)
107 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
109 TRACE("(%p)\n", This
);
111 if (!pv
) return E_INVALIDARG
;
113 EnterCriticalSection(&This
->lock
);
114 uBytesRead
= min(cb
, This
->dwMemsize
- This
->dwCurPos
);
115 memmove(pv
, This
->pbMemory
+ This
->dwCurPos
, uBytesRead
);
116 This
->dwCurPos
+= uBytesRead
;
117 LeaveCriticalSection(&This
->lock
);
119 if (pcbRead
) *pcbRead
= uBytesRead
;
124 static HRESULT WINAPI
StreamOnMemory_Write(IStream
*iface
,
125 void const *pv
, ULONG cb
, ULONG
*pcbWritten
)
127 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
129 TRACE("(%p)\n", This
);
131 if (!pv
) return E_INVALIDARG
;
133 EnterCriticalSection(&This
->lock
);
134 if (cb
> This
->dwMemsize
- This
->dwCurPos
) {
135 hr
= STG_E_MEDIUMFULL
;
138 memmove(This
->pbMemory
+ This
->dwCurPos
, pv
, cb
);
139 This
->dwCurPos
+= cb
;
141 if (pcbWritten
) *pcbWritten
= cb
;
143 LeaveCriticalSection(&This
->lock
);
148 static HRESULT WINAPI
StreamOnMemory_Seek(IStream
*iface
,
149 LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
151 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
152 LARGE_INTEGER NewPosition
;
154 TRACE("(%p)\n", This
);
156 EnterCriticalSection(&This
->lock
);
157 if (dwOrigin
== STREAM_SEEK_SET
) NewPosition
.QuadPart
= dlibMove
.QuadPart
;
158 else if (dwOrigin
== STREAM_SEEK_CUR
) NewPosition
.QuadPart
= This
->dwCurPos
+ dlibMove
.QuadPart
;
159 else if (dwOrigin
== STREAM_SEEK_END
) NewPosition
.QuadPart
= This
->dwMemsize
+ dlibMove
.QuadPart
;
160 else hr
= E_INVALIDARG
;
163 if (NewPosition
.u
.HighPart
) hr
= HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW
);
164 else if (NewPosition
.QuadPart
> This
->dwMemsize
) hr
= E_INVALIDARG
;
165 else if (NewPosition
.QuadPart
< 0) hr
= E_INVALIDARG
;
169 This
->dwCurPos
= NewPosition
.u
.LowPart
;
171 if(plibNewPosition
) plibNewPosition
->QuadPart
= This
->dwCurPos
;
173 LeaveCriticalSection(&This
->lock
);
178 /* SetSize isn't implemented in the native windowscodecs DLL either */
179 static HRESULT WINAPI
StreamOnMemory_SetSize(IStream
*iface
,
180 ULARGE_INTEGER libNewSize
)
182 TRACE("(%p)\n", iface
);
186 /* CopyTo isn't implemented in the native windowscodecs DLL either */
187 static HRESULT WINAPI
StreamOnMemory_CopyTo(IStream
*iface
,
188 IStream
*pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
190 TRACE("(%p)\n", iface
);
194 /* Commit isn't implemented in the native windowscodecs DLL either */
195 static HRESULT WINAPI
StreamOnMemory_Commit(IStream
*iface
,
196 DWORD grfCommitFlags
)
198 TRACE("(%p)\n", iface
);
202 /* Revert isn't implemented in the native windowscodecs DLL either */
203 static HRESULT WINAPI
StreamOnMemory_Revert(IStream
*iface
)
205 TRACE("(%p)\n", iface
);
209 /* LockRegion isn't implemented in the native windowscodecs DLL either */
210 static HRESULT WINAPI
StreamOnMemory_LockRegion(IStream
*iface
,
211 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
213 TRACE("(%p)\n", iface
);
217 /* UnlockRegion isn't implemented in the native windowscodecs DLL either */
218 static HRESULT WINAPI
StreamOnMemory_UnlockRegion(IStream
*iface
,
219 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
221 TRACE("(%p)\n", iface
);
225 static HRESULT WINAPI
StreamOnMemory_Stat(IStream
*iface
,
226 STATSTG
*pstatstg
, DWORD grfStatFlag
)
228 StreamOnMemory
*This
= StreamOnMemory_from_IStream(iface
);
229 TRACE("(%p)\n", This
);
231 if (!pstatstg
) return E_INVALIDARG
;
233 ZeroMemory(pstatstg
, sizeof(STATSTG
));
234 pstatstg
->type
= STGTY_STREAM
;
235 pstatstg
->cbSize
.QuadPart
= This
->dwMemsize
;
240 /* Clone isn't implemented in the native windowscodecs DLL either */
241 static HRESULT WINAPI
StreamOnMemory_Clone(IStream
*iface
,
244 TRACE("(%p)\n", iface
);
249 static const IStreamVtbl StreamOnMemory_Vtbl
=
251 /*** IUnknown methods ***/
252 StreamOnMemory_QueryInterface
,
253 StreamOnMemory_AddRef
,
254 StreamOnMemory_Release
,
255 /*** ISequentialStream methods ***/
257 StreamOnMemory_Write
,
258 /*** IStream methods ***/
260 StreamOnMemory_SetSize
,
261 StreamOnMemory_CopyTo
,
262 StreamOnMemory_Commit
,
263 StreamOnMemory_Revert
,
264 StreamOnMemory_LockRegion
,
265 StreamOnMemory_UnlockRegion
,
267 StreamOnMemory_Clone
,
270 /******************************************
271 * StreamOnFileHandle implementation (internal)
274 typedef struct StreamOnFileHandle
{
275 IStream IStream_iface
;
281 } StreamOnFileHandle
;
283 static inline StreamOnFileHandle
*StreamOnFileHandle_from_IStream(IStream
*iface
)
285 return CONTAINING_RECORD(iface
, StreamOnFileHandle
, IStream_iface
);
288 static HRESULT WINAPI
StreamOnFileHandle_QueryInterface(IStream
*iface
,
289 REFIID iid
, void **ppv
)
291 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
293 if (!ppv
) return E_INVALIDARG
;
295 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IStream
, iid
) ||
296 IsEqualIID(&IID_ISequentialStream
, iid
))
299 IUnknown_AddRef((IUnknown
*)*ppv
);
305 return E_NOINTERFACE
;
309 static ULONG WINAPI
StreamOnFileHandle_AddRef(IStream
*iface
)
311 StreamOnFileHandle
*This
= StreamOnFileHandle_from_IStream(iface
);
312 ULONG ref
= InterlockedIncrement(&This
->ref
);
314 TRACE("(%p) refcount=%u\n", iface
, ref
);
319 static ULONG WINAPI
StreamOnFileHandle_Release(IStream
*iface
)
321 StreamOnFileHandle
*This
= StreamOnFileHandle_from_IStream(iface
);
322 ULONG ref
= InterlockedDecrement(&This
->ref
);
324 TRACE("(%p) refcount=%u\n", iface
, ref
);
327 IWICStream_Release(This
->stream
);
328 UnmapViewOfFile(This
->mem
);
329 CloseHandle(This
->map
);
330 HeapFree(GetProcessHeap(), 0, This
);
335 static HRESULT WINAPI
StreamOnFileHandle_Read(IStream
*iface
,
336 void *pv
, ULONG cb
, ULONG
*pcbRead
)
338 StreamOnFileHandle
*This
= StreamOnFileHandle_from_IStream(iface
);
339 TRACE("(%p)\n", This
);
341 return IWICStream_Read(This
->stream
, pv
, cb
, pcbRead
);
344 static HRESULT WINAPI
StreamOnFileHandle_Write(IStream
*iface
,
345 void const *pv
, ULONG cb
, ULONG
*pcbWritten
)
347 ERR("(%p)\n", iface
);
348 return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED
);
351 static HRESULT WINAPI
StreamOnFileHandle_Seek(IStream
*iface
,
352 LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
354 StreamOnFileHandle
*This
= StreamOnFileHandle_from_IStream(iface
);
355 TRACE("(%p)\n", This
);
357 return IWICStream_Seek(This
->stream
, dlibMove
, dwOrigin
, plibNewPosition
);
360 static HRESULT WINAPI
StreamOnFileHandle_SetSize(IStream
*iface
,
361 ULARGE_INTEGER libNewSize
)
363 TRACE("(%p)\n", iface
);
367 static HRESULT WINAPI
StreamOnFileHandle_CopyTo(IStream
*iface
,
368 IStream
*pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
370 TRACE("(%p)\n", iface
);
374 static HRESULT WINAPI
StreamOnFileHandle_Commit(IStream
*iface
,
375 DWORD grfCommitFlags
)
377 TRACE("(%p)\n", iface
);
381 static HRESULT WINAPI
StreamOnFileHandle_Revert(IStream
*iface
)
383 TRACE("(%p)\n", iface
);
387 static HRESULT WINAPI
StreamOnFileHandle_LockRegion(IStream
*iface
,
388 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
390 TRACE("(%p)\n", iface
);
394 static HRESULT WINAPI
StreamOnFileHandle_UnlockRegion(IStream
*iface
,
395 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
397 TRACE("(%p)\n", iface
);
401 static HRESULT WINAPI
StreamOnFileHandle_Stat(IStream
*iface
,
402 STATSTG
*pstatstg
, DWORD grfStatFlag
)
404 StreamOnFileHandle
*This
= StreamOnFileHandle_from_IStream(iface
);
405 TRACE("(%p)\n", This
);
407 return IWICStream_Stat(This
->stream
, pstatstg
, grfStatFlag
);
410 static HRESULT WINAPI
StreamOnFileHandle_Clone(IStream
*iface
,
413 TRACE("(%p)\n", iface
);
418 static const IStreamVtbl StreamOnFileHandle_Vtbl
=
420 /*** IUnknown methods ***/
421 StreamOnFileHandle_QueryInterface
,
422 StreamOnFileHandle_AddRef
,
423 StreamOnFileHandle_Release
,
424 /*** ISequentialStream methods ***/
425 StreamOnFileHandle_Read
,
426 StreamOnFileHandle_Write
,
427 /*** IStream methods ***/
428 StreamOnFileHandle_Seek
,
429 StreamOnFileHandle_SetSize
,
430 StreamOnFileHandle_CopyTo
,
431 StreamOnFileHandle_Commit
,
432 StreamOnFileHandle_Revert
,
433 StreamOnFileHandle_LockRegion
,
434 StreamOnFileHandle_UnlockRegion
,
435 StreamOnFileHandle_Stat
,
436 StreamOnFileHandle_Clone
,
439 /******************************************
440 * StreamOnStreamRange implementation
442 * Used by IWICStream_InitializeFromIStreamRegion
445 typedef struct StreamOnStreamRange
{
446 IStream IStream_iface
;
451 ULARGE_INTEGER offset
;
452 ULARGE_INTEGER max_size
;
454 CRITICAL_SECTION lock
;
455 } StreamOnStreamRange
;
457 static inline StreamOnStreamRange
*StreamOnStreamRange_from_IStream(IStream
*iface
)
459 return CONTAINING_RECORD(iface
, StreamOnStreamRange
, IStream_iface
);
462 static HRESULT WINAPI
StreamOnStreamRange_QueryInterface(IStream
*iface
,
463 REFIID iid
, void **ppv
)
465 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
467 if (!ppv
) return E_INVALIDARG
;
469 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IStream
, iid
) ||
470 IsEqualIID(&IID_ISequentialStream
, iid
))
473 IUnknown_AddRef((IUnknown
*)*ppv
);
479 return E_NOINTERFACE
;
483 static ULONG WINAPI
StreamOnStreamRange_AddRef(IStream
*iface
)
485 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
486 ULONG ref
= InterlockedIncrement(&This
->ref
);
488 TRACE("(%p) refcount=%u\n", iface
, ref
);
493 static ULONG WINAPI
StreamOnStreamRange_Release(IStream
*iface
)
495 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
496 ULONG ref
= InterlockedDecrement(&This
->ref
);
498 TRACE("(%p) refcount=%u\n", iface
, ref
);
501 This
->lock
.DebugInfo
->Spare
[0] = 0;
502 DeleteCriticalSection(&This
->lock
);
503 IStream_Release(This
->stream
);
504 HeapFree(GetProcessHeap(), 0, This
);
509 static HRESULT WINAPI
StreamOnStreamRange_Read(IStream
*iface
,
510 void *pv
, ULONG cb
, ULONG
*pcbRead
)
512 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
515 ULARGE_INTEGER OldPosition
;
516 LARGE_INTEGER SetPosition
;
517 TRACE("(%p)\n", This
);
519 if (!pv
) return E_INVALIDARG
;
521 EnterCriticalSection(&This
->lock
);
522 SetPosition
.QuadPart
= 0;
523 hr
= IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_CUR
, &OldPosition
);
526 SetPosition
.QuadPart
= This
->pos
.QuadPart
+ This
->offset
.QuadPart
;
527 hr
= IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_SET
, NULL
);
531 if (This
->pos
.QuadPart
+ cb
> This
->max_size
.QuadPart
)
533 /* This would read past the end of the stream. */
534 if (This
->pos
.QuadPart
> This
->max_size
.QuadPart
)
537 cb
= This
->max_size
.QuadPart
- This
->pos
.QuadPart
;
539 hr
= IStream_Read(This
->stream
, pv
, cb
, &uBytesRead
);
540 SetPosition
.QuadPart
= OldPosition
.QuadPart
;
541 IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_SET
, NULL
);
544 This
->pos
.QuadPart
+= uBytesRead
;
545 LeaveCriticalSection(&This
->lock
);
547 if (SUCCEEDED(hr
) && pcbRead
) *pcbRead
= uBytesRead
;
552 static HRESULT WINAPI
StreamOnStreamRange_Write(IStream
*iface
,
553 void const *pv
, ULONG cb
, ULONG
*pcbWritten
)
555 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
557 ULARGE_INTEGER OldPosition
;
558 LARGE_INTEGER SetPosition
;
559 ULONG uBytesWritten
=0;
560 TRACE("(%p)\n", This
);
562 if (!pv
) return E_INVALIDARG
;
564 EnterCriticalSection(&This
->lock
);
565 SetPosition
.QuadPart
= 0;
566 hr
= IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_CUR
, &OldPosition
);
569 SetPosition
.QuadPart
= This
->pos
.QuadPart
+ This
->offset
.QuadPart
;
570 hr
= IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_SET
, NULL
);
574 if (This
->pos
.QuadPart
+ cb
> This
->max_size
.QuadPart
)
576 /* This would read past the end of the stream. */
577 if (This
->pos
.QuadPart
> This
->max_size
.QuadPart
)
580 cb
= This
->max_size
.QuadPart
- This
->pos
.QuadPart
;
582 hr
= IStream_Write(This
->stream
, pv
, cb
, &uBytesWritten
);
583 SetPosition
.QuadPart
= OldPosition
.QuadPart
;
584 IStream_Seek(This
->stream
, SetPosition
, STREAM_SEEK_SET
, NULL
);
587 This
->pos
.QuadPart
+= uBytesWritten
;
588 LeaveCriticalSection(&This
->lock
);
590 if (SUCCEEDED(hr
) && pcbWritten
) *pcbWritten
= uBytesWritten
;
595 static HRESULT WINAPI
StreamOnStreamRange_Seek(IStream
*iface
,
596 LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
598 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
599 ULARGE_INTEGER NewPosition
, actual_size
;
602 TRACE("(%p)\n", This
);
604 EnterCriticalSection(&This
->lock
);
605 actual_size
= This
->max_size
;
606 if (dwOrigin
== STREAM_SEEK_SET
)
607 NewPosition
.QuadPart
= dlibMove
.QuadPart
;
608 else if (dwOrigin
== STREAM_SEEK_CUR
)
609 NewPosition
.QuadPart
= This
->pos
.QuadPart
+ dlibMove
.QuadPart
;
610 else if (dwOrigin
== STREAM_SEEK_END
)
612 hr
= IStream_Stat(This
->stream
, &statstg
, STATFLAG_NONAME
);
615 if (This
->max_size
.QuadPart
+ This
->offset
.QuadPart
> statstg
.cbSize
.QuadPart
)
616 actual_size
.QuadPart
= statstg
.cbSize
.QuadPart
- This
->offset
.QuadPart
;
617 NewPosition
.QuadPart
= dlibMove
.QuadPart
+ actual_size
.QuadPart
;
620 else hr
= E_INVALIDARG
;
622 if (SUCCEEDED(hr
) && (NewPosition
.u
.HighPart
!= 0 || NewPosition
.QuadPart
> actual_size
.QuadPart
))
623 hr
= WINCODEC_ERR_VALUEOUTOFRANGE
;
626 This
->pos
.QuadPart
= NewPosition
.QuadPart
;
628 if(plibNewPosition
) plibNewPosition
->QuadPart
= This
->pos
.QuadPart
;
630 LeaveCriticalSection(&This
->lock
);
635 /* SetSize isn't implemented in the native windowscodecs DLL either */
636 static HRESULT WINAPI
StreamOnStreamRange_SetSize(IStream
*iface
,
637 ULARGE_INTEGER libNewSize
)
639 TRACE("(%p)\n", iface
);
643 /* CopyTo isn't implemented in the native windowscodecs DLL either */
644 static HRESULT WINAPI
StreamOnStreamRange_CopyTo(IStream
*iface
,
645 IStream
*pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
647 TRACE("(%p)\n", iface
);
651 /* Commit isn't implemented in the native windowscodecs DLL either */
652 static HRESULT WINAPI
StreamOnStreamRange_Commit(IStream
*iface
,
653 DWORD grfCommitFlags
)
655 TRACE("(%p)\n", iface
);
659 /* Revert isn't implemented in the native windowscodecs DLL either */
660 static HRESULT WINAPI
StreamOnStreamRange_Revert(IStream
*iface
)
662 TRACE("(%p)\n", iface
);
666 /* LockRegion isn't implemented in the native windowscodecs DLL either */
667 static HRESULT WINAPI
StreamOnStreamRange_LockRegion(IStream
*iface
,
668 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
670 TRACE("(%p)\n", iface
);
674 /* UnlockRegion isn't implemented in the native windowscodecs DLL either */
675 static HRESULT WINAPI
StreamOnStreamRange_UnlockRegion(IStream
*iface
,
676 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
678 TRACE("(%p)\n", iface
);
682 static HRESULT WINAPI
StreamOnStreamRange_Stat(IStream
*iface
,
683 STATSTG
*pstatstg
, DWORD grfStatFlag
)
685 StreamOnStreamRange
*This
= StreamOnStreamRange_from_IStream(iface
);
687 TRACE("(%p)\n", This
);
689 if (!pstatstg
) return E_INVALIDARG
;
691 EnterCriticalSection(&This
->lock
);
692 hr
= IStream_Stat(This
->stream
, pstatstg
, grfStatFlag
);
695 pstatstg
->cbSize
.QuadPart
-= This
->offset
.QuadPart
;
696 if (This
->max_size
.QuadPart
< pstatstg
->cbSize
.QuadPart
)
697 pstatstg
->cbSize
.QuadPart
= This
->max_size
.QuadPart
;
700 LeaveCriticalSection(&This
->lock
);
705 /* Clone isn't implemented in the native windowscodecs DLL either */
706 static HRESULT WINAPI
StreamOnStreamRange_Clone(IStream
*iface
,
709 TRACE("(%p)\n", iface
);
714 static const IStreamVtbl StreamOnStreamRange_Vtbl
=
716 /*** IUnknown methods ***/
717 StreamOnStreamRange_QueryInterface
,
718 StreamOnStreamRange_AddRef
,
719 StreamOnStreamRange_Release
,
720 /*** ISequentialStream methods ***/
721 StreamOnStreamRange_Read
,
722 StreamOnStreamRange_Write
,
723 /*** IStream methods ***/
724 StreamOnStreamRange_Seek
,
725 StreamOnStreamRange_SetSize
,
726 StreamOnStreamRange_CopyTo
,
727 StreamOnStreamRange_Commit
,
728 StreamOnStreamRange_Revert
,
729 StreamOnStreamRange_LockRegion
,
730 StreamOnStreamRange_UnlockRegion
,
731 StreamOnStreamRange_Stat
,
732 StreamOnStreamRange_Clone
,
736 /******************************************
737 * IWICStream implementation
740 typedef struct IWICStreamImpl
742 IWICStream IWICStream_iface
;
748 static inline IWICStreamImpl
*impl_from_IWICStream(IWICStream
*iface
)
750 return CONTAINING_RECORD(iface
, IWICStreamImpl
, IWICStream_iface
);
753 static HRESULT WINAPI
IWICStreamImpl_QueryInterface(IWICStream
*iface
,
754 REFIID iid
, void **ppv
)
756 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
757 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
759 if (!ppv
) return E_INVALIDARG
;
761 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IStream
, iid
) ||
762 IsEqualIID(&IID_ISequentialStream
, iid
) || IsEqualIID(&IID_IWICStream
, iid
))
765 IUnknown_AddRef((IUnknown
*)*ppv
);
771 return E_NOINTERFACE
;
775 static ULONG WINAPI
IWICStreamImpl_AddRef(IWICStream
*iface
)
777 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
778 ULONG ref
= InterlockedIncrement(&This
->ref
);
780 TRACE("(%p) refcount=%u\n", iface
, ref
);
785 static ULONG WINAPI
IWICStreamImpl_Release(IWICStream
*iface
)
787 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
788 ULONG ref
= InterlockedDecrement(&This
->ref
);
790 TRACE("(%p) refcount=%u\n", iface
, ref
);
793 if (This
->pStream
) IStream_Release(This
->pStream
);
794 HeapFree(GetProcessHeap(), 0, This
);
799 static HRESULT WINAPI
IWICStreamImpl_Read(IWICStream
*iface
,
800 void *pv
, ULONG cb
, ULONG
*pcbRead
)
802 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
803 TRACE("(%p): relay\n", This
);
805 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
806 return IStream_Read(This
->pStream
, pv
, cb
, pcbRead
);
809 static HRESULT WINAPI
IWICStreamImpl_Write(IWICStream
*iface
,
810 void const *pv
, ULONG cb
, ULONG
*pcbWritten
)
812 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
813 TRACE("(%p): relay\n", This
);
815 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
816 return IStream_Write(This
->pStream
, pv
, cb
, pcbWritten
);
819 static HRESULT WINAPI
IWICStreamImpl_Seek(IWICStream
*iface
,
820 LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
822 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
823 TRACE("(%p): relay\n", This
);
825 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
826 return IStream_Seek(This
->pStream
, dlibMove
, dwOrigin
, plibNewPosition
);
829 static HRESULT WINAPI
IWICStreamImpl_SetSize(IWICStream
*iface
,
830 ULARGE_INTEGER libNewSize
)
832 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
833 TRACE("(%p): relay\n", This
);
835 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
836 return IStream_SetSize(This
->pStream
, libNewSize
);
839 static HRESULT WINAPI
IWICStreamImpl_CopyTo(IWICStream
*iface
,
840 IStream
*pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
842 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
843 TRACE("(%p): relay\n", This
);
845 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
846 return IStream_CopyTo(This
->pStream
, pstm
, cb
, pcbRead
, pcbWritten
);
849 static HRESULT WINAPI
IWICStreamImpl_Commit(IWICStream
*iface
,
850 DWORD grfCommitFlags
)
852 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
853 TRACE("(%p): relay\n", This
);
855 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
856 return IStream_Commit(This
->pStream
, grfCommitFlags
);
859 static HRESULT WINAPI
IWICStreamImpl_Revert(IWICStream
*iface
)
861 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
862 TRACE("(%p): relay\n", This
);
864 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
865 return IStream_Revert(This
->pStream
);
868 static HRESULT WINAPI
IWICStreamImpl_LockRegion(IWICStream
*iface
,
869 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
871 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
872 TRACE("(%p): relay\n", This
);
874 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
875 return IStream_LockRegion(This
->pStream
, libOffset
, cb
, dwLockType
);
878 static HRESULT WINAPI
IWICStreamImpl_UnlockRegion(IWICStream
*iface
,
879 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
881 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
882 TRACE("(%p): relay\n", This
);
884 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
885 return IStream_UnlockRegion(This
->pStream
, libOffset
, cb
, dwLockType
);
888 static HRESULT WINAPI
IWICStreamImpl_Stat(IWICStream
*iface
,
889 STATSTG
*pstatstg
, DWORD grfStatFlag
)
891 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
892 TRACE("(%p): relay\n", This
);
894 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
895 return IStream_Stat(This
->pStream
, pstatstg
, grfStatFlag
);
898 static HRESULT WINAPI
IWICStreamImpl_Clone(IWICStream
*iface
,
901 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
902 TRACE("(%p): relay\n", This
);
904 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
905 return IStream_Clone(This
->pStream
, ppstm
);
908 static HRESULT WINAPI
IWICStreamImpl_InitializeFromIStream(IWICStream
*iface
,
911 ULARGE_INTEGER offset
, size
;
912 TRACE("(%p): relay\n", iface
);
915 size
.u
.LowPart
= 0xffffffff;
916 size
.u
.HighPart
= 0xffffffff;
917 return IWICStream_InitializeFromIStreamRegion(iface
, pIStream
, offset
, size
);
920 static HRESULT WINAPI
IWICStreamImpl_InitializeFromFilename(IWICStream
*iface
,
921 LPCWSTR wzFileName
, DWORD dwDesiredAccess
)
923 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
928 TRACE("(%p, %s, %u)\n", iface
, debugstr_w(wzFileName
), dwDesiredAccess
);
930 if (This
->pStream
) return WINCODEC_ERR_WRONGSTATE
;
932 if(dwDesiredAccess
& GENERIC_WRITE
)
933 dwMode
= STGM_SHARE_DENY_WRITE
| STGM_WRITE
| STGM_CREATE
;
934 else if(dwDesiredAccess
& GENERIC_READ
)
935 dwMode
= STGM_SHARE_DENY_WRITE
| STGM_READ
| STGM_FAILIFTHERE
;
939 hr
= SHCreateStreamOnFileW(wzFileName
, dwMode
, &stream
);
943 if (InterlockedCompareExchangePointer((void**)&This
->pStream
, stream
, NULL
))
945 /* Some other thread set the stream first. */
946 IStream_Release(stream
);
947 hr
= WINCODEC_ERR_WRONGSTATE
;
954 /******************************************
955 * IWICStream_InitializeFromMemory
957 * Initializes the internal IStream object to retrieve its data from a memory chunk.
960 * pbBuffer [I] pointer to the memory chunk
961 * cbBufferSize [I] number of bytes to use from the memory chunk
965 * FAILURE: E_INVALIDARG, if pbBuffer is NULL
966 * E_OUTOFMEMORY, if we run out of memory
967 * WINCODEC_ERR_WRONGSTATE, if the IStream object has already been initialized before
970 static HRESULT WINAPI
IWICStreamImpl_InitializeFromMemory(IWICStream
*iface
,
971 BYTE
*pbBuffer
, DWORD cbBufferSize
)
973 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
974 StreamOnMemory
*pObject
;
975 TRACE("(%p,%p)\n", iface
, pbBuffer
);
977 if (!pbBuffer
) return E_INVALIDARG
;
978 if (This
->pStream
) return WINCODEC_ERR_WRONGSTATE
;
980 pObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnMemory
));
981 if (!pObject
) return E_OUTOFMEMORY
;
983 pObject
->IStream_iface
.lpVtbl
= &StreamOnMemory_Vtbl
;
985 pObject
->pbMemory
= pbBuffer
;
986 pObject
->dwMemsize
= cbBufferSize
;
987 pObject
->dwCurPos
= 0;
988 InitializeCriticalSection(&pObject
->lock
);
989 pObject
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": StreamOnMemory.lock");
991 if (InterlockedCompareExchangePointer((void**)&This
->pStream
, pObject
, NULL
))
993 /* Some other thread set the stream first. */
994 IStream_Release(&pObject
->IStream_iface
);
995 return WINCODEC_ERR_WRONGSTATE
;
1001 static HRESULT
map_file(HANDLE file
, HANDLE
*map
, void **mem
, LARGE_INTEGER
*size
)
1004 if (!GetFileSizeEx(file
, size
)) return HRESULT_FROM_WIN32(GetLastError());
1005 if (size
->u
.HighPart
)
1007 WARN("file too large\n");
1010 if (!(*map
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, size
->u
.LowPart
, NULL
)))
1012 return HRESULT_FROM_WIN32(GetLastError());
1014 if (!(*mem
= MapViewOfFile(*map
, FILE_MAP_READ
, 0, 0, size
->u
.LowPart
)))
1017 return HRESULT_FROM_WIN32(GetLastError());
1022 HRESULT
stream_initialize_from_filehandle(IWICStream
*iface
, HANDLE file
)
1024 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
1025 StreamOnFileHandle
*pObject
;
1026 IWICStream
*stream
= NULL
;
1031 TRACE("(%p,%p)\n", iface
, file
);
1033 if (This
->pStream
) return WINCODEC_ERR_WRONGSTATE
;
1035 hr
= map_file(file
, &map
, &mem
, &size
);
1036 if (FAILED(hr
)) return hr
;
1038 hr
= StreamImpl_Create(&stream
);
1039 if (FAILED(hr
)) goto error
;
1041 hr
= IWICStreamImpl_InitializeFromMemory(stream
, mem
, size
.u
.LowPart
);
1042 if (FAILED(hr
)) goto error
;
1044 pObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnFileHandle
));
1050 pObject
->IStream_iface
.lpVtbl
= &StreamOnFileHandle_Vtbl
;
1054 pObject
->stream
= stream
;
1056 if (InterlockedCompareExchangePointer((void**)&This
->pStream
, pObject
, NULL
))
1058 /* Some other thread set the stream first. */
1059 IStream_Release(&pObject
->IStream_iface
);
1060 return WINCODEC_ERR_WRONGSTATE
;
1065 if (stream
) IWICStream_Release(stream
);
1066 UnmapViewOfFile(mem
);
1071 static HRESULT WINAPI
IWICStreamImpl_InitializeFromIStreamRegion(IWICStream
*iface
,
1072 IStream
*pIStream
, ULARGE_INTEGER ulOffset
, ULARGE_INTEGER ulMaxSize
)
1074 IWICStreamImpl
*This
= impl_from_IWICStream(iface
);
1075 StreamOnStreamRange
*pObject
;
1076 TRACE("(%p,%p)\n", iface
, pIStream
);
1078 if (!pIStream
) return E_INVALIDARG
;
1079 if (This
->pStream
) return WINCODEC_ERR_WRONGSTATE
;
1081 pObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnStreamRange
));
1082 if (!pObject
) return E_OUTOFMEMORY
;
1084 pObject
->IStream_iface
.lpVtbl
= &StreamOnStreamRange_Vtbl
;
1086 IStream_AddRef(pIStream
);
1087 pObject
->stream
= pIStream
;
1088 pObject
->pos
.QuadPart
= 0;
1089 pObject
->offset
= ulOffset
;
1090 pObject
->max_size
= ulMaxSize
;
1091 InitializeCriticalSection(&pObject
->lock
);
1092 pObject
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": StreamOnStreamRange.lock");
1094 if (InterlockedCompareExchangePointer((void**)&This
->pStream
, pObject
, NULL
))
1096 /* Some other thread set the stream first. */
1097 IStream_Release(&pObject
->IStream_iface
);
1098 return WINCODEC_ERR_WRONGSTATE
;
1105 static const IWICStreamVtbl WICStream_Vtbl
=
1107 /*** IUnknown methods ***/
1108 IWICStreamImpl_QueryInterface
,
1109 IWICStreamImpl_AddRef
,
1110 IWICStreamImpl_Release
,
1111 /*** ISequentialStream methods ***/
1112 IWICStreamImpl_Read
,
1113 IWICStreamImpl_Write
,
1114 /*** IStream methods ***/
1115 IWICStreamImpl_Seek
,
1116 IWICStreamImpl_SetSize
,
1117 IWICStreamImpl_CopyTo
,
1118 IWICStreamImpl_Commit
,
1119 IWICStreamImpl_Revert
,
1120 IWICStreamImpl_LockRegion
,
1121 IWICStreamImpl_UnlockRegion
,
1122 IWICStreamImpl_Stat
,
1123 IWICStreamImpl_Clone
,
1124 /*** IWICStream methods ***/
1125 IWICStreamImpl_InitializeFromIStream
,
1126 IWICStreamImpl_InitializeFromFilename
,
1127 IWICStreamImpl_InitializeFromMemory
,
1128 IWICStreamImpl_InitializeFromIStreamRegion
,
1131 HRESULT
StreamImpl_Create(IWICStream
**stream
)
1133 IWICStreamImpl
*pObject
;
1135 if( !stream
) return E_INVALIDARG
;
1137 pObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(IWICStreamImpl
));
1140 return E_OUTOFMEMORY
;
1143 pObject
->IWICStream_iface
.lpVtbl
= &WICStream_Vtbl
;
1145 pObject
->pStream
= NULL
;
1147 *stream
= &pObject
->IWICStream_iface
;