d3dcompiler_43: Make asmshader_error() and set_rel_reg() static.
[wine/multimedia.git] / dlls / windowscodecs / stream.c
bloba00f666f10577d92f470860c8098c2500f7a275e
1 /*
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"
21 #define COBJMACROS
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winreg.h"
25 #include "objbase.h"
26 #include "shlwapi.h"
27 #include "wincodec.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;
40 LONG ref;
42 BYTE *pbMemory;
43 DWORD dwMemsize;
44 DWORD dwCurPos;
46 CRITICAL_SECTION lock; /* must be held when pbMemory or dwCurPos is accessed */
47 } StreamOnMemory;
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))
59 *ppv = iface;
60 IUnknown_AddRef((IUnknown*)*ppv);
61 return S_OK;
63 else
65 *ppv = NULL;
66 return E_NOINTERFACE;
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);
77 return 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);
87 if (ref == 0) {
88 This->lock.DebugInfo->Spare[0] = 0;
89 DeleteCriticalSection(&This->lock);
90 HeapFree(GetProcessHeap(), 0, This);
92 return ref;
95 static HRESULT WINAPI StreamOnMemory_Read(IStream *iface,
96 void *pv, ULONG cb, ULONG *pcbRead)
98 StreamOnMemory *This = (StreamOnMemory*)iface;
99 ULONG uBytesRead;
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;
112 return S_OK;
115 static HRESULT WINAPI StreamOnMemory_Write(IStream *iface,
116 void const *pv, ULONG cb, ULONG *pcbWritten)
118 StreamOnMemory *This = (StreamOnMemory*)iface;
119 HRESULT hr;
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;
128 else {
129 memcpy(This->pbMemory + This->dwCurPos, pv, cb);
130 This->dwCurPos += cb;
131 hr = S_OK;
132 if (pcbWritten) *pcbWritten = cb;
134 LeaveCriticalSection(&This->lock);
136 return hr;
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;
144 HRESULT hr=S_OK;
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;
153 if (SUCCEEDED(hr)) {
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;
159 if (SUCCEEDED(hr)) {
160 This->dwCurPos = NewPosition.u.LowPart;
162 if(plibNewPosition) plibNewPosition->QuadPart = This->dwCurPos;
164 LeaveCriticalSection(&This->lock);
166 return hr;
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);
174 return E_NOTIMPL;
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);
182 return E_NOTIMPL;
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);
190 return E_NOTIMPL;
193 /* Revert isn't implemented in the native windowscodecs DLL either */
194 static HRESULT WINAPI StreamOnMemory_Revert(IStream *iface)
196 TRACE("(%p)\n", iface);
197 return E_NOTIMPL;
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);
205 return E_NOTIMPL;
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);
213 return E_NOTIMPL;
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;
228 return S_OK;
231 /* Clone isn't implemented in the native windowscodecs DLL either */
232 static HRESULT WINAPI StreamOnMemory_Clone(IStream *iface,
233 IStream **ppstm)
235 TRACE("(%p)\n", iface);
236 return E_NOTIMPL;
240 const IStreamVtbl StreamOnMemory_Vtbl =
242 /*** IUnknown methods ***/
243 StreamOnMemory_QueryInterface,
244 StreamOnMemory_AddRef,
245 StreamOnMemory_Release,
246 /*** ISequentialStream methods ***/
247 StreamOnMemory_Read,
248 StreamOnMemory_Write,
249 /*** IStream methods ***/
250 StreamOnMemory_Seek,
251 StreamOnMemory_SetSize,
252 StreamOnMemory_CopyTo,
253 StreamOnMemory_Commit,
254 StreamOnMemory_Revert,
255 StreamOnMemory_LockRegion,
256 StreamOnMemory_UnlockRegion,
257 StreamOnMemory_Stat,
258 StreamOnMemory_Clone,
261 /******************************************
262 * StreamOnStreamRange implementation
264 * Used by IWICStream_InitializeFromIStreamRegion
267 typedef struct StreamOnStreamRange {
268 const IStreamVtbl *lpVtbl;
269 LONG ref;
271 IStream *stream;
272 ULARGE_INTEGER pos;
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))
289 *ppv = iface;
290 IUnknown_AddRef((IUnknown*)*ppv);
291 return S_OK;
293 else
295 *ppv = NULL;
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);
307 return 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);
317 if (ref == 0) {
318 This->lock.DebugInfo->Spare[0] = 0;
319 DeleteCriticalSection(&This->lock);
320 IStream_Release(This->stream);
321 HeapFree(GetProcessHeap(), 0, This);
323 return ref;
326 static HRESULT WINAPI StreamOnStreamRange_Read(IStream *iface,
327 void *pv, ULONG cb, ULONG *pcbRead)
329 StreamOnStreamRange *This = (StreamOnStreamRange*)iface;
330 ULONG uBytesRead=0;
331 HRESULT hr;
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);
341 if (SUCCEEDED(hr))
343 SetPosition.QuadPart = This->pos.QuadPart + This->offset.QuadPart;
344 hr = IStream_Seek(This->stream, SetPosition, STREAM_SEEK_CUR, NULL);
346 if (SUCCEEDED(hr))
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)
352 cb = 0;
353 else
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);
360 if (SUCCEEDED(hr))
361 This->pos.QuadPart += uBytesRead;
362 LeaveCriticalSection(&This->lock);
364 if (pcbRead) *pcbRead = uBytesRead;
366 return hr;
369 static HRESULT WINAPI StreamOnStreamRange_Write(IStream *iface,
370 void const *pv, ULONG cb, ULONG *pcbWritten)
372 StreamOnStreamRange *This = (StreamOnStreamRange*)iface;
373 HRESULT hr;
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);
384 if (SUCCEEDED(hr))
386 SetPosition.QuadPart = This->pos.QuadPart + This->offset.QuadPart;
387 hr = IStream_Seek(This->stream, SetPosition, STREAM_SEEK_CUR, NULL);
389 if (SUCCEEDED(hr))
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)
395 cb = 0;
396 else
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);
403 if (SUCCEEDED(hr))
404 This->pos.QuadPart += uBytesWritten;
405 LeaveCriticalSection(&This->lock);
407 if (pcbWritten) *pcbWritten = uBytesWritten;
409 return hr;
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;
417 HRESULT hr=S_OK;
418 STATSTG statstg;
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);
430 if (SUCCEEDED(hr))
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;
442 if (SUCCEEDED(hr)) {
443 This->pos.QuadPart = NewPosition.QuadPart;
445 if(plibNewPosition) plibNewPosition->QuadPart = This->pos.QuadPart;
447 LeaveCriticalSection(&This->lock);
449 return hr;
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);
457 return E_NOTIMPL;
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);
465 return E_NOTIMPL;
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);
473 return E_NOTIMPL;
476 /* Revert isn't implemented in the native windowscodecs DLL either */
477 static HRESULT WINAPI StreamOnStreamRange_Revert(IStream *iface)
479 TRACE("(%p)\n", iface);
480 return E_NOTIMPL;
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);
488 return E_NOTIMPL;
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);
496 return E_NOTIMPL;
499 static HRESULT WINAPI StreamOnStreamRange_Stat(IStream *iface,
500 STATSTG *pstatstg, DWORD grfStatFlag)
502 StreamOnStreamRange *This = (StreamOnStreamRange*)iface;
503 HRESULT hr;
504 TRACE("(%p)\n", This);
506 if (!pstatstg) return E_INVALIDARG;
508 EnterCriticalSection(&This->lock);
509 hr = IStream_Stat(This->stream, pstatstg, grfStatFlag);
510 if (SUCCEEDED(hr))
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);
519 return hr;
522 /* Clone isn't implemented in the native windowscodecs DLL either */
523 static HRESULT WINAPI StreamOnStreamRange_Clone(IStream *iface,
524 IStream **ppstm)
526 TRACE("(%p)\n", iface);
527 return E_NOTIMPL;
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;
560 LONG ref;
562 IStream *pStream;
563 } IWICStreamImpl;
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))
576 *ppv = This;
577 IUnknown_AddRef((IUnknown*)*ppv);
578 return S_OK;
580 else
582 *ppv = NULL;
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);
594 return 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);
604 if (ref == 0) {
605 if (This->pStream) IStream_Release(This->pStream);
606 HeapFree(GetProcessHeap(), 0, This);
608 return ref;
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,
711 IStream **ppstm)
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,
721 IStream *pIStream)
723 FIXME("(%p): stub\n", iface);
724 return E_NOTIMPL;
727 static HRESULT WINAPI IWICStreamImpl_InitializeFromFilename(IWICStream *iface,
728 LPCWSTR wzFileName, DWORD dwDesiredAccess)
730 IWICStreamImpl *This = (IWICStreamImpl*)iface;
731 HRESULT hr;
732 DWORD dwMode;
733 IStream *stream;
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;
743 else
744 return E_INVALIDARG;
746 hr = SHCreateStreamOnFileW(wzFileName, dwMode, &stream);
748 if (SUCCEEDED(hr))
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;
758 return hr;
761 /******************************************
762 * IWICStream_InitializeFromMemory
764 * Initializes the internal IStream object to retrieve its data from a memory chunk.
766 * PARAMS
767 * pbBuffer [I] pointer to the memory chunk
768 * cbBufferSize [I] number of bytes to use from the memory chunk
770 * RETURNS
771 * SUCCESS: S_OK
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;
791 pObject->ref = 1;
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;
805 return S_OK;
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;
822 pObject->ref = 1;
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;
838 return S_OK;
842 const IWICStreamVtbl WICStream_Vtbl =
844 /*** IUnknown methods ***/
845 IWICStreamImpl_QueryInterface,
846 IWICStreamImpl_AddRef,
847 IWICStreamImpl_Release,
848 /*** ISequentialStream methods ***/
849 IWICStreamImpl_Read,
850 IWICStreamImpl_Write,
851 /*** IStream methods ***/
852 IWICStreamImpl_Seek,
853 IWICStreamImpl_SetSize,
854 IWICStreamImpl_CopyTo,
855 IWICStreamImpl_Commit,
856 IWICStreamImpl_Revert,
857 IWICStreamImpl_LockRegion,
858 IWICStreamImpl_UnlockRegion,
859 IWICStreamImpl_Stat,
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));
875 if( !pObject ) {
876 *stream = NULL;
877 return E_OUTOFMEMORY;
880 pObject->lpVtbl = &WICStream_Vtbl;
881 pObject->ref = 1;
882 pObject->pStream = NULL;
884 *stream = (IWICStream*)pObject;
886 return S_OK;