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"
27 #include "wincodecs_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
31 /******************************************
32 * StreamOnMemory implementation
34 * Used by IWICStream_InitializeFromMemory
37 typedef struct StreamOnMemory {
38 const IStreamVtbl *lpVtbl;
45 CRITICAL_SECTION lock; /* must be held when pbMemory or dwCurPos is accessed */
48 static HRESULT WINAPI StreamOnMemory_QueryInterface(IStream *iface,
49 REFIID iid, void **ppv)
51 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
53 if (!ppv) return E_INVALIDARG;
55 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) ||
56 IsEqualIID(&IID_ISequentialStream, iid))
59 IUnknown_AddRef((IUnknown*)*ppv);
69 static ULONG WINAPI StreamOnMemory_AddRef(IStream *iface)
71 StreamOnMemory *This = (StreamOnMemory*)iface;
72 ULONG ref = InterlockedIncrement(&This->ref);
74 TRACE("(%p) refcount=%u\n", iface, ref);
79 static ULONG WINAPI StreamOnMemory_Release(IStream *iface)
81 StreamOnMemory *This = (StreamOnMemory*)iface;
82 ULONG ref = InterlockedDecrement(&This->ref);
84 TRACE("(%p) refcount=%u\n", iface, ref);
87 This->lock.DebugInfo->Spare[0] = 0;
88 DeleteCriticalSection(&This->lock);
89 HeapFree(GetProcessHeap(), 0, This);
94 static HRESULT WINAPI StreamOnMemory_Read(IStream *iface,
95 void *pv, ULONG cb, ULONG *pcbRead)
97 StreamOnMemory *This = (StreamOnMemory*)iface;
99 TRACE("(%p)\n", This);
101 if (!pv) return E_INVALIDARG;
103 EnterCriticalSection(&This->lock);
104 uBytesRead = min(cb, This->dwMemsize - This->dwCurPos);
105 memcpy(pv, This->pbMemory + This->dwCurPos, uBytesRead);
106 This->dwCurPos += uBytesRead;
107 LeaveCriticalSection(&This->lock);
109 if (pcbRead) *pcbRead = uBytesRead;
114 static HRESULT WINAPI StreamOnMemory_Write(IStream *iface,
115 void const *pv, ULONG cb, ULONG *pcbWritten)
117 StreamOnMemory *This = (StreamOnMemory*)iface;
119 TRACE("(%p)\n", This);
121 if (!pv) return E_INVALIDARG;
123 EnterCriticalSection(&This->lock);
124 if (cb > This->dwMemsize - This->dwCurPos) {
125 hr = STG_E_MEDIUMFULL;
129 memcpy(This->pbMemory + This->dwCurPos, pv, cb);
130 This->dwCurPos += cb;
133 if (pcbWritten) *pcbWritten = cb;
135 LeaveCriticalSection(&This->lock);
140 static HRESULT WINAPI StreamOnMemory_Seek(IStream *iface,
141 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
143 StreamOnMemory *This = (StreamOnMemory*)iface;
144 LARGE_INTEGER NewPosition;
146 TRACE("(%p)\n", This);
148 EnterCriticalSection(&This->lock);
149 if (dwOrigin == STREAM_SEEK_SET) NewPosition.QuadPart = dlibMove.QuadPart;
150 else if (dwOrigin == STREAM_SEEK_CUR) NewPosition.QuadPart = This->dwCurPos + dlibMove.QuadPart;
151 else if (dwOrigin == STREAM_SEEK_END) NewPosition.QuadPart = This->dwMemsize + dlibMove.QuadPart;
152 else hr = E_INVALIDARG;
155 if (NewPosition.u.HighPart) hr = HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
156 else if (NewPosition.QuadPart > This->dwMemsize) hr = E_INVALIDARG;
157 else if (NewPosition.QuadPart < 0) hr = E_INVALIDARG;
161 This->dwCurPos = NewPosition.u.LowPart;
163 if(plibNewPosition) plibNewPosition->QuadPart = This->dwCurPos;
165 LeaveCriticalSection(&This->lock);
170 /* SetSize isn't implemented in the native windowscodecs DLL either */
171 static HRESULT WINAPI StreamOnMemory_SetSize(IStream *iface,
172 ULARGE_INTEGER libNewSize)
174 TRACE("(%p)\n", iface);
178 /* CopyTo isn't implemented in the native windowscodecs DLL either */
179 static HRESULT WINAPI StreamOnMemory_CopyTo(IStream *iface,
180 IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
182 TRACE("(%p)\n", iface);
186 /* Commit isn't implemented in the native windowscodecs DLL either */
187 static HRESULT WINAPI StreamOnMemory_Commit(IStream *iface,
188 DWORD grfCommitFlags)
190 TRACE("(%p)\n", iface);
194 /* Revert isn't implemented in the native windowscodecs DLL either */
195 static HRESULT WINAPI StreamOnMemory_Revert(IStream *iface)
197 TRACE("(%p)\n", iface);
201 /* LockRegion isn't implemented in the native windowscodecs DLL either */
202 static HRESULT WINAPI StreamOnMemory_LockRegion(IStream *iface,
203 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
205 TRACE("(%p)\n", iface);
209 /* UnlockRegion isn't implemented in the native windowscodecs DLL either */
210 static HRESULT WINAPI StreamOnMemory_UnlockRegion(IStream *iface,
211 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
213 TRACE("(%p)\n", iface);
217 static HRESULT WINAPI StreamOnMemory_Stat(IStream *iface,
218 STATSTG *pstatstg, DWORD grfStatFlag)
220 StreamOnMemory *This = (StreamOnMemory*)iface;
221 TRACE("(%p)\n", This);
223 if (!pstatstg) return E_INVALIDARG;
225 ZeroMemory(pstatstg, sizeof(STATSTG));
226 pstatstg->type = STGTY_STREAM;
227 pstatstg->cbSize.QuadPart = This->dwMemsize;
232 /* Clone isn't implemented in the native windowscodecs DLL either */
233 static HRESULT WINAPI StreamOnMemory_Clone(IStream *iface,
236 TRACE("(%p)\n", iface);
241 const IStreamVtbl StreamOnMemory_Vtbl =
243 /*** IUnknown methods ***/
244 StreamOnMemory_QueryInterface,
245 StreamOnMemory_AddRef,
246 StreamOnMemory_Release,
247 /*** ISequentialStream methods ***/
249 StreamOnMemory_Write,
250 /*** IStream methods ***/
252 StreamOnMemory_SetSize,
253 StreamOnMemory_CopyTo,
254 StreamOnMemory_Commit,
255 StreamOnMemory_Revert,
256 StreamOnMemory_LockRegion,
257 StreamOnMemory_UnlockRegion,
259 StreamOnMemory_Clone,
262 /******************************************
263 * IWICStream implementation
266 typedef struct IWICStreamImpl
268 const IWICStreamVtbl *lpVtbl;
274 static HRESULT WINAPI IWICStreamImpl_QueryInterface(IWICStream *iface,
275 REFIID iid, void **ppv)
277 IWICStreamImpl *This = (IWICStreamImpl*)iface;
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) || IsEqualIID(&IID_IWICStream, iid))
286 IUnknown_AddRef((IUnknown*)*ppv);
292 return E_NOINTERFACE;
296 static ULONG WINAPI IWICStreamImpl_AddRef(IWICStream *iface)
298 IWICStreamImpl *This = (IWICStreamImpl*)iface;
299 ULONG ref = InterlockedIncrement(&This->ref);
301 TRACE("(%p) refcount=%u\n", iface, ref);
306 static ULONG WINAPI IWICStreamImpl_Release(IWICStream *iface)
308 IWICStreamImpl *This = (IWICStreamImpl*)iface;
309 ULONG ref = InterlockedDecrement(&This->ref);
311 TRACE("(%p) refcount=%u\n", iface, ref);
314 if (This->pStream) IStream_Release(This->pStream);
315 HeapFree(GetProcessHeap(), 0, This);
320 static HRESULT WINAPI IWICStreamImpl_Read(IWICStream *iface,
321 void *pv, ULONG cb, ULONG *pcbRead)
323 IWICStreamImpl *This = (IWICStreamImpl*)iface;
324 TRACE("(%p): relay\n", This);
326 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
327 return IStream_Read(This->pStream, pv, cb, pcbRead);
330 static HRESULT WINAPI IWICStreamImpl_Write(IWICStream *iface,
331 void const *pv, ULONG cb, ULONG *pcbWritten)
333 IWICStreamImpl *This = (IWICStreamImpl*)iface;
334 TRACE("(%p): relay\n", This);
336 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
337 return IStream_Write(This->pStream, pv, cb, pcbWritten);
340 static HRESULT WINAPI IWICStreamImpl_Seek(IWICStream *iface,
341 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
343 IWICStreamImpl *This = (IWICStreamImpl*)iface;
344 TRACE("(%p): relay\n", This);
346 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
347 return IStream_Seek(This->pStream, dlibMove, dwOrigin, plibNewPosition);
350 static HRESULT WINAPI IWICStreamImpl_SetSize(IWICStream *iface,
351 ULARGE_INTEGER libNewSize)
353 IWICStreamImpl *This = (IWICStreamImpl*)iface;
354 TRACE("(%p): relay\n", This);
356 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
357 return IStream_SetSize(This->pStream, libNewSize);
360 static HRESULT WINAPI IWICStreamImpl_CopyTo(IWICStream *iface,
361 IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
363 IWICStreamImpl *This = (IWICStreamImpl*)iface;
364 TRACE("(%p): relay\n", This);
366 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
367 return IStream_CopyTo(This->pStream, pstm, cb, pcbRead, pcbWritten);
370 static HRESULT WINAPI IWICStreamImpl_Commit(IWICStream *iface,
371 DWORD grfCommitFlags)
373 IWICStreamImpl *This = (IWICStreamImpl*)iface;
374 TRACE("(%p): relay\n", This);
376 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
377 return IStream_Commit(This->pStream, grfCommitFlags);
380 static HRESULT WINAPI IWICStreamImpl_Revert(IWICStream *iface)
382 IWICStreamImpl *This = (IWICStreamImpl*)iface;
383 TRACE("(%p): relay\n", This);
385 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
386 return IStream_Revert(This->pStream);
389 static HRESULT WINAPI IWICStreamImpl_LockRegion(IWICStream *iface,
390 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
392 IWICStreamImpl *This = (IWICStreamImpl*)iface;
393 TRACE("(%p): relay\n", This);
395 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
396 return IStream_LockRegion(This->pStream, libOffset, cb, dwLockType);
399 static HRESULT WINAPI IWICStreamImpl_UnlockRegion(IWICStream *iface,
400 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
402 IWICStreamImpl *This = (IWICStreamImpl*)iface;
403 TRACE("(%p): relay\n", This);
405 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
406 return IStream_UnlockRegion(This->pStream, libOffset, cb, dwLockType);
409 static HRESULT WINAPI IWICStreamImpl_Stat(IWICStream *iface,
410 STATSTG *pstatstg, DWORD grfStatFlag)
412 IWICStreamImpl *This = (IWICStreamImpl*)iface;
413 TRACE("(%p): relay\n", This);
415 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
416 return IStream_Stat(This->pStream, pstatstg, grfStatFlag);
419 static HRESULT WINAPI IWICStreamImpl_Clone(IWICStream *iface,
422 IWICStreamImpl *This = (IWICStreamImpl*)iface;
423 TRACE("(%p): relay\n", This);
425 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
426 return IStream_Clone(This->pStream, ppstm);
429 static HRESULT WINAPI IWICStreamImpl_InitializeFromIStream(IWICStream *iface,
432 FIXME("(%p): stub\n", iface);
436 static HRESULT WINAPI IWICStreamImpl_InitializeFromFilename(IWICStream *iface,
437 LPCWSTR wzFileName, DWORD dwDesiredAccess)
439 FIXME("(%p): stub\n", iface);
443 /******************************************
444 * IWICStream_InitializeFromMemory
446 * Initializes the internal IStream object to retrieve its data from a memory chunk.
449 * pbBuffer [I] pointer to the memory chunk
450 * cbBufferSize [I] number of bytes to use from the memory chunk
454 * FAILURE: E_INVALIDARG, if pbBuffer is NULL
455 * E_OUTOFMEMORY, if we run out of memory
456 * WINCODEC_ERR_WRONGSTATE, if the IStream object has already been initialized before
459 static HRESULT WINAPI IWICStreamImpl_InitializeFromMemory(IWICStream *iface,
460 BYTE *pbBuffer, DWORD cbBufferSize)
462 IWICStreamImpl *This = (IWICStreamImpl*)iface;
463 StreamOnMemory *pObject;
464 TRACE("(%p,%p)\n", iface, pbBuffer);
466 if (!pbBuffer) return E_INVALIDARG;
467 if (This->pStream) return WINCODEC_ERR_WRONGSTATE;
469 pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnMemory));
470 if (!pObject) return E_OUTOFMEMORY;
472 pObject->lpVtbl = &StreamOnMemory_Vtbl;
474 pObject->pbMemory = pbBuffer;
475 pObject->dwMemsize = cbBufferSize;
476 pObject->dwCurPos = 0;
477 InitializeCriticalSection(&pObject->lock);
478 pObject->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": StreamOnMemory.lock");
480 This->pStream = (IStream*)pObject;
484 static HRESULT WINAPI IWICStreamImpl_InitializeFromIStreamRegion(IWICStream *iface,
485 IStream *pIStream, ULARGE_INTEGER ulOffset, ULARGE_INTEGER ulMaxSize)
487 FIXME("(%p): stub\n", iface);
492 const IWICStreamVtbl WICStream_Vtbl =
494 /*** IUnknown methods ***/
495 IWICStreamImpl_QueryInterface,
496 IWICStreamImpl_AddRef,
497 IWICStreamImpl_Release,
498 /*** ISequentialStream methods ***/
500 IWICStreamImpl_Write,
501 /*** IStream methods ***/
503 IWICStreamImpl_SetSize,
504 IWICStreamImpl_CopyTo,
505 IWICStreamImpl_Commit,
506 IWICStreamImpl_Revert,
507 IWICStreamImpl_LockRegion,
508 IWICStreamImpl_UnlockRegion,
510 IWICStreamImpl_Clone,
511 /*** IWICStream methods ***/
512 IWICStreamImpl_InitializeFromIStream,
513 IWICStreamImpl_InitializeFromFilename,
514 IWICStreamImpl_InitializeFromMemory,
515 IWICStreamImpl_InitializeFromIStreamRegion,
518 HRESULT StreamImpl_Create(IWICStream **stream)
520 IWICStreamImpl *pObject;
522 if( !stream ) return E_INVALIDARG;
524 pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(IWICStreamImpl));
527 return E_OUTOFMEMORY;
530 pObject->lpVtbl = &WICStream_Vtbl;
532 pObject->pStream = NULL;
534 *stream = (IWICStream*)pObject;