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;
46 static HRESULT WINAPI StreamOnMemory_QueryInterface(IStream *iface,
47 REFIID iid, void **ppv)
49 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
51 if (!ppv) return E_INVALIDARG;
53 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) ||
54 IsEqualIID(&IID_ISequentialStream, iid))
57 IUnknown_AddRef((IUnknown*)*ppv);
67 static ULONG WINAPI StreamOnMemory_AddRef(IStream *iface)
69 StreamOnMemory *This = (StreamOnMemory*)iface;
70 ULONG ref = InterlockedIncrement(&This->ref);
72 TRACE("(%p) refcount=%u\n", iface, ref);
77 static ULONG WINAPI StreamOnMemory_Release(IStream *iface)
79 StreamOnMemory *This = (StreamOnMemory*)iface;
80 ULONG ref = InterlockedDecrement(&This->ref);
82 TRACE("(%p) refcount=%u\n", iface, ref);
85 HeapFree(GetProcessHeap(), 0, This);
90 static HRESULT WINAPI StreamOnMemory_Read(IStream *iface,
91 void *pv, ULONG cb, ULONG *pcbRead)
93 StreamOnMemory *This = (StreamOnMemory*)iface;
95 TRACE("(%p)\n", This);
97 if (!pv) return E_INVALIDARG;
99 uBytesRead = min(cb, This->dwMemsize - This->dwCurPos);
100 memcpy(pv, This->pbMemory + This->dwCurPos, uBytesRead);
101 This->dwCurPos += uBytesRead;
102 if (pcbRead) *pcbRead = uBytesRead;
107 static HRESULT WINAPI StreamOnMemory_Write(IStream *iface,
108 void const *pv, ULONG cb, ULONG *pcbWritten)
110 StreamOnMemory *This = (StreamOnMemory*)iface;
111 TRACE("(%p)\n", This);
113 if (!pv) return E_INVALIDARG;
115 if (cb > This->dwMemsize - This->dwCurPos) return STG_E_MEDIUMFULL;
117 memcpy(This->pbMemory + This->dwCurPos, pv, cb);
118 This->dwCurPos += cb;
120 if (pcbWritten) *pcbWritten = cb;
125 static HRESULT WINAPI StreamOnMemory_Seek(IStream *iface,
126 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
128 FIXME("(%p): stub\n", iface);
132 /* SetSize isn't implemented in the native windowscodecs DLL either */
133 static HRESULT WINAPI StreamOnMemory_SetSize(IStream *iface,
134 ULARGE_INTEGER libNewSize)
136 TRACE("(%p)\n", iface);
140 /* CopyTo isn't implemented in the native windowscodecs DLL either */
141 static HRESULT WINAPI StreamOnMemory_CopyTo(IStream *iface,
142 IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
144 TRACE("(%p)\n", iface);
148 /* Commit isn't implemented in the native windowscodecs DLL either */
149 static HRESULT WINAPI StreamOnMemory_Commit(IStream *iface,
150 DWORD grfCommitFlags)
152 TRACE("(%p)\n", iface);
156 /* Revert isn't implemented in the native windowscodecs DLL either */
157 static HRESULT WINAPI StreamOnMemory_Revert(IStream *iface)
159 TRACE("(%p)\n", iface);
163 /* LockRegion isn't implemented in the native windowscodecs DLL either */
164 static HRESULT WINAPI StreamOnMemory_LockRegion(IStream *iface,
165 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
167 TRACE("(%p)\n", iface);
171 /* UnlockRegion isn't implemented in the native windowscodecs DLL either */
172 static HRESULT WINAPI StreamOnMemory_UnlockRegion(IStream *iface,
173 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
175 TRACE("(%p)\n", iface);
179 static HRESULT WINAPI StreamOnMemory_Stat(IStream *iface,
180 STATSTG *pstatstg, DWORD grfStatFlag)
182 FIXME("(%p): stub\n", iface);
186 /* Clone isn't implemented in the native windowscodecs DLL either */
187 static HRESULT WINAPI StreamOnMemory_Clone(IStream *iface,
190 TRACE("(%p)\n", iface);
195 const IStreamVtbl StreamOnMemory_Vtbl =
197 /*** IUnknown methods ***/
198 StreamOnMemory_QueryInterface,
199 StreamOnMemory_AddRef,
200 StreamOnMemory_Release,
201 /*** ISequentialStream methods ***/
203 StreamOnMemory_Write,
204 /*** IStream methods ***/
206 StreamOnMemory_SetSize,
207 StreamOnMemory_CopyTo,
208 StreamOnMemory_Commit,
209 StreamOnMemory_Revert,
210 StreamOnMemory_LockRegion,
211 StreamOnMemory_UnlockRegion,
213 StreamOnMemory_Clone,
216 /******************************************
217 * IWICStream implementation
220 typedef struct IWICStreamImpl
222 const IWICStreamVtbl *lpVtbl;
228 static HRESULT WINAPI IWICStreamImpl_QueryInterface(IWICStream *iface,
229 REFIID iid, void **ppv)
231 IWICStreamImpl *This = (IWICStreamImpl*)iface;
232 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
234 if (!ppv) return E_INVALIDARG;
236 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) ||
237 IsEqualIID(&IID_ISequentialStream, iid) || IsEqualIID(&IID_IWICStream, iid))
240 IUnknown_AddRef((IUnknown*)*ppv);
246 return E_NOINTERFACE;
250 static ULONG WINAPI IWICStreamImpl_AddRef(IWICStream *iface)
252 IWICStreamImpl *This = (IWICStreamImpl*)iface;
253 ULONG ref = InterlockedIncrement(&This->ref);
255 TRACE("(%p) refcount=%u\n", iface, ref);
260 static ULONG WINAPI IWICStreamImpl_Release(IWICStream *iface)
262 IWICStreamImpl *This = (IWICStreamImpl*)iface;
263 ULONG ref = InterlockedDecrement(&This->ref);
265 TRACE("(%p) refcount=%u\n", iface, ref);
268 if (This->pStream) IStream_Release(This->pStream);
269 HeapFree(GetProcessHeap(), 0, This);
274 static HRESULT WINAPI IWICStreamImpl_Read(IWICStream *iface,
275 void *pv, ULONG cb, ULONG *pcbRead)
277 IWICStreamImpl *This = (IWICStreamImpl*)iface;
278 TRACE("(%p): relay\n", This);
280 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
281 return IStream_Read(This->pStream, pv, cb, pcbRead);
284 static HRESULT WINAPI IWICStreamImpl_Write(IWICStream *iface,
285 void const *pv, ULONG cb, ULONG *pcbWritten)
287 IWICStreamImpl *This = (IWICStreamImpl*)iface;
288 TRACE("(%p): relay\n", This);
290 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
291 return IStream_Write(This->pStream, pv, cb, pcbWritten);
294 static HRESULT WINAPI IWICStreamImpl_Seek(IWICStream *iface,
295 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
297 IWICStreamImpl *This = (IWICStreamImpl*)iface;
298 TRACE("(%p): relay\n", This);
300 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
301 return IStream_Seek(This->pStream, dlibMove, dwOrigin, plibNewPosition);
304 static HRESULT WINAPI IWICStreamImpl_SetSize(IWICStream *iface,
305 ULARGE_INTEGER libNewSize)
307 IWICStreamImpl *This = (IWICStreamImpl*)iface;
308 TRACE("(%p): relay\n", This);
310 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
311 return IStream_SetSize(This->pStream, libNewSize);
314 static HRESULT WINAPI IWICStreamImpl_CopyTo(IWICStream *iface,
315 IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
317 IWICStreamImpl *This = (IWICStreamImpl*)iface;
318 TRACE("(%p): relay\n", This);
320 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
321 return IStream_CopyTo(This->pStream, pstm, cb, pcbRead, pcbWritten);
324 static HRESULT WINAPI IWICStreamImpl_Commit(IWICStream *iface,
325 DWORD grfCommitFlags)
327 IWICStreamImpl *This = (IWICStreamImpl*)iface;
328 TRACE("(%p): relay\n", This);
330 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
331 return IStream_Commit(This->pStream, grfCommitFlags);
334 static HRESULT WINAPI IWICStreamImpl_Revert(IWICStream *iface)
336 IWICStreamImpl *This = (IWICStreamImpl*)iface;
337 TRACE("(%p): relay\n", This);
339 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
340 return IStream_Revert(This->pStream);
343 static HRESULT WINAPI IWICStreamImpl_LockRegion(IWICStream *iface,
344 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
346 IWICStreamImpl *This = (IWICStreamImpl*)iface;
347 TRACE("(%p): relay\n", This);
349 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
350 return IStream_LockRegion(This->pStream, libOffset, cb, dwLockType);
353 static HRESULT WINAPI IWICStreamImpl_UnlockRegion(IWICStream *iface,
354 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
356 IWICStreamImpl *This = (IWICStreamImpl*)iface;
357 TRACE("(%p): relay\n", This);
359 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
360 return IStream_UnlockRegion(This->pStream, libOffset, cb, dwLockType);
363 static HRESULT WINAPI IWICStreamImpl_Stat(IWICStream *iface,
364 STATSTG *pstatstg, DWORD grfStatFlag)
366 IWICStreamImpl *This = (IWICStreamImpl*)iface;
367 TRACE("(%p): relay\n", This);
369 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
370 return IStream_Stat(This->pStream, pstatstg, grfStatFlag);
373 static HRESULT WINAPI IWICStreamImpl_Clone(IWICStream *iface,
376 IWICStreamImpl *This = (IWICStreamImpl*)iface;
377 TRACE("(%p): relay\n", This);
379 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
380 return IStream_Clone(This->pStream, ppstm);
383 static HRESULT WINAPI IWICStreamImpl_InitializeFromIStream(IWICStream *iface,
386 FIXME("(%p): stub\n", iface);
390 static HRESULT WINAPI IWICStreamImpl_InitializeFromFilename(IWICStream *iface,
391 LPCWSTR wzFileName, DWORD dwDesiredAccess)
393 FIXME("(%p): stub\n", iface);
397 /******************************************
398 * IWICStream_InitializeFromMemory
400 * Initializes the internal IStream object to retrieve its data from a memory chunk.
403 * pbBuffer [I] pointer to the memory chunk
404 * cbBufferSize [I] number of bytes to use from the memory chunk
408 * FAILURE: E_INVALIDARG, if pbBuffer is NULL
409 * E_OUTOFMEMORY, if we run out of memory
410 * WINCODEC_ERR_WRONGSTATE, if the IStream object has already been initialized before
413 static HRESULT WINAPI IWICStreamImpl_InitializeFromMemory(IWICStream *iface,
414 BYTE *pbBuffer, DWORD cbBufferSize)
416 IWICStreamImpl *This = (IWICStreamImpl*)iface;
417 StreamOnMemory *pObject;
418 TRACE("(%p,%p)\n", iface, pbBuffer);
420 if (!pbBuffer) return E_INVALIDARG;
421 if (This->pStream) return WINCODEC_ERR_WRONGSTATE;
423 pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnMemory));
424 if (!pObject) return E_OUTOFMEMORY;
426 pObject->lpVtbl = &StreamOnMemory_Vtbl;
428 pObject->pbMemory = pbBuffer;
429 pObject->dwMemsize = cbBufferSize;
430 pObject->dwCurPos = 0;
432 This->pStream = (IStream*)pObject;
436 static HRESULT WINAPI IWICStreamImpl_InitializeFromIStreamRegion(IWICStream *iface,
437 IStream *pIStream, ULARGE_INTEGER ulOffset, ULARGE_INTEGER ulMaxSize)
439 FIXME("(%p): stub\n", iface);
444 const IWICStreamVtbl WICStream_Vtbl =
446 /*** IUnknown methods ***/
447 IWICStreamImpl_QueryInterface,
448 IWICStreamImpl_AddRef,
449 IWICStreamImpl_Release,
450 /*** ISequentialStream methods ***/
452 IWICStreamImpl_Write,
453 /*** IStream methods ***/
455 IWICStreamImpl_SetSize,
456 IWICStreamImpl_CopyTo,
457 IWICStreamImpl_Commit,
458 IWICStreamImpl_Revert,
459 IWICStreamImpl_LockRegion,
460 IWICStreamImpl_UnlockRegion,
462 IWICStreamImpl_Clone,
463 /*** IWICStream methods ***/
464 IWICStreamImpl_InitializeFromIStream,
465 IWICStreamImpl_InitializeFromFilename,
466 IWICStreamImpl_InitializeFromMemory,
467 IWICStreamImpl_InitializeFromIStreamRegion,
470 HRESULT StreamImpl_Create(IWICStream **stream)
472 IWICStreamImpl *pObject;
474 if( !stream ) return E_INVALIDARG;
476 pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(IWICStreamImpl));
479 return E_OUTOFMEMORY;
482 pObject->lpVtbl = &WICStream_Vtbl;
484 pObject->pStream = NULL;
486 *stream = (IWICStream*)pObject;