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 StreamOnMemory
*This
= (StreamOnMemory
*)iface
;
129 LARGE_INTEGER NewPosition
;
130 TRACE("(%p)\n", This
);
132 if (dwOrigin
== STREAM_SEEK_SET
) NewPosition
.QuadPart
= dlibMove
.QuadPart
;
133 else if (dwOrigin
== STREAM_SEEK_CUR
) NewPosition
.QuadPart
= This
->dwCurPos
+ dlibMove
.QuadPart
;
134 else if (dwOrigin
== STREAM_SEEK_END
) NewPosition
.QuadPart
= This
->dwMemsize
+ dlibMove
.QuadPart
;
135 else return E_INVALIDARG
;
137 if (NewPosition
.u
.HighPart
) return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW
);
138 if (NewPosition
.QuadPart
> This
->dwMemsize
) return E_INVALIDARG
;
139 if (NewPosition
.QuadPart
< 0) return E_INVALIDARG
;
140 This
->dwCurPos
= NewPosition
.u
.LowPart
;
142 if(plibNewPosition
) plibNewPosition
->QuadPart
= This
->dwCurPos
;
146 /* SetSize isn't implemented in the native windowscodecs DLL either */
147 static HRESULT WINAPI
StreamOnMemory_SetSize(IStream
*iface
,
148 ULARGE_INTEGER libNewSize
)
150 TRACE("(%p)\n", iface
);
154 /* CopyTo isn't implemented in the native windowscodecs DLL either */
155 static HRESULT WINAPI
StreamOnMemory_CopyTo(IStream
*iface
,
156 IStream
*pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
158 TRACE("(%p)\n", iface
);
162 /* Commit isn't implemented in the native windowscodecs DLL either */
163 static HRESULT WINAPI
StreamOnMemory_Commit(IStream
*iface
,
164 DWORD grfCommitFlags
)
166 TRACE("(%p)\n", iface
);
170 /* Revert isn't implemented in the native windowscodecs DLL either */
171 static HRESULT WINAPI
StreamOnMemory_Revert(IStream
*iface
)
173 TRACE("(%p)\n", iface
);
177 /* LockRegion isn't implemented in the native windowscodecs DLL either */
178 static HRESULT WINAPI
StreamOnMemory_LockRegion(IStream
*iface
,
179 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
181 TRACE("(%p)\n", iface
);
185 /* UnlockRegion isn't implemented in the native windowscodecs DLL either */
186 static HRESULT WINAPI
StreamOnMemory_UnlockRegion(IStream
*iface
,
187 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
189 TRACE("(%p)\n", iface
);
193 static HRESULT WINAPI
StreamOnMemory_Stat(IStream
*iface
,
194 STATSTG
*pstatstg
, DWORD grfStatFlag
)
196 StreamOnMemory
*This
= (StreamOnMemory
*)iface
;
197 TRACE("(%p)\n", This
);
199 if (!pstatstg
) return E_INVALIDARG
;
201 ZeroMemory(pstatstg
, sizeof(STATSTG
));
202 pstatstg
->type
= STGTY_STREAM
;
203 pstatstg
->cbSize
.QuadPart
= This
->dwMemsize
;
208 /* Clone isn't implemented in the native windowscodecs DLL either */
209 static HRESULT WINAPI
StreamOnMemory_Clone(IStream
*iface
,
212 TRACE("(%p)\n", iface
);
217 const IStreamVtbl StreamOnMemory_Vtbl
=
219 /*** IUnknown methods ***/
220 StreamOnMemory_QueryInterface
,
221 StreamOnMemory_AddRef
,
222 StreamOnMemory_Release
,
223 /*** ISequentialStream methods ***/
225 StreamOnMemory_Write
,
226 /*** IStream methods ***/
228 StreamOnMemory_SetSize
,
229 StreamOnMemory_CopyTo
,
230 StreamOnMemory_Commit
,
231 StreamOnMemory_Revert
,
232 StreamOnMemory_LockRegion
,
233 StreamOnMemory_UnlockRegion
,
235 StreamOnMemory_Clone
,
238 /******************************************
239 * IWICStream implementation
242 typedef struct IWICStreamImpl
244 const IWICStreamVtbl
*lpVtbl
;
250 static HRESULT WINAPI
IWICStreamImpl_QueryInterface(IWICStream
*iface
,
251 REFIID iid
, void **ppv
)
253 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
254 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
256 if (!ppv
) return E_INVALIDARG
;
258 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IStream
, iid
) ||
259 IsEqualIID(&IID_ISequentialStream
, iid
) || IsEqualIID(&IID_IWICStream
, iid
))
262 IUnknown_AddRef((IUnknown
*)*ppv
);
268 return E_NOINTERFACE
;
272 static ULONG WINAPI
IWICStreamImpl_AddRef(IWICStream
*iface
)
274 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
275 ULONG ref
= InterlockedIncrement(&This
->ref
);
277 TRACE("(%p) refcount=%u\n", iface
, ref
);
282 static ULONG WINAPI
IWICStreamImpl_Release(IWICStream
*iface
)
284 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
285 ULONG ref
= InterlockedDecrement(&This
->ref
);
287 TRACE("(%p) refcount=%u\n", iface
, ref
);
290 if (This
->pStream
) IStream_Release(This
->pStream
);
291 HeapFree(GetProcessHeap(), 0, This
);
296 static HRESULT WINAPI
IWICStreamImpl_Read(IWICStream
*iface
,
297 void *pv
, ULONG cb
, ULONG
*pcbRead
)
299 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
300 TRACE("(%p): relay\n", This
);
302 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
303 return IStream_Read(This
->pStream
, pv
, cb
, pcbRead
);
306 static HRESULT WINAPI
IWICStreamImpl_Write(IWICStream
*iface
,
307 void const *pv
, ULONG cb
, ULONG
*pcbWritten
)
309 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
310 TRACE("(%p): relay\n", This
);
312 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
313 return IStream_Write(This
->pStream
, pv
, cb
, pcbWritten
);
316 static HRESULT WINAPI
IWICStreamImpl_Seek(IWICStream
*iface
,
317 LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
319 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
320 TRACE("(%p): relay\n", This
);
322 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
323 return IStream_Seek(This
->pStream
, dlibMove
, dwOrigin
, plibNewPosition
);
326 static HRESULT WINAPI
IWICStreamImpl_SetSize(IWICStream
*iface
,
327 ULARGE_INTEGER libNewSize
)
329 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
330 TRACE("(%p): relay\n", This
);
332 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
333 return IStream_SetSize(This
->pStream
, libNewSize
);
336 static HRESULT WINAPI
IWICStreamImpl_CopyTo(IWICStream
*iface
,
337 IStream
*pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
339 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
340 TRACE("(%p): relay\n", This
);
342 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
343 return IStream_CopyTo(This
->pStream
, pstm
, cb
, pcbRead
, pcbWritten
);
346 static HRESULT WINAPI
IWICStreamImpl_Commit(IWICStream
*iface
,
347 DWORD grfCommitFlags
)
349 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
350 TRACE("(%p): relay\n", This
);
352 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
353 return IStream_Commit(This
->pStream
, grfCommitFlags
);
356 static HRESULT WINAPI
IWICStreamImpl_Revert(IWICStream
*iface
)
358 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
359 TRACE("(%p): relay\n", This
);
361 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
362 return IStream_Revert(This
->pStream
);
365 static HRESULT WINAPI
IWICStreamImpl_LockRegion(IWICStream
*iface
,
366 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
368 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
369 TRACE("(%p): relay\n", This
);
371 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
372 return IStream_LockRegion(This
->pStream
, libOffset
, cb
, dwLockType
);
375 static HRESULT WINAPI
IWICStreamImpl_UnlockRegion(IWICStream
*iface
,
376 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
378 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
379 TRACE("(%p): relay\n", This
);
381 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
382 return IStream_UnlockRegion(This
->pStream
, libOffset
, cb
, dwLockType
);
385 static HRESULT WINAPI
IWICStreamImpl_Stat(IWICStream
*iface
,
386 STATSTG
*pstatstg
, DWORD grfStatFlag
)
388 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
389 TRACE("(%p): relay\n", This
);
391 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
392 return IStream_Stat(This
->pStream
, pstatstg
, grfStatFlag
);
395 static HRESULT WINAPI
IWICStreamImpl_Clone(IWICStream
*iface
,
398 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
399 TRACE("(%p): relay\n", This
);
401 if (!This
->pStream
) return WINCODEC_ERR_NOTINITIALIZED
;
402 return IStream_Clone(This
->pStream
, ppstm
);
405 static HRESULT WINAPI
IWICStreamImpl_InitializeFromIStream(IWICStream
*iface
,
408 FIXME("(%p): stub\n", iface
);
412 static HRESULT WINAPI
IWICStreamImpl_InitializeFromFilename(IWICStream
*iface
,
413 LPCWSTR wzFileName
, DWORD dwDesiredAccess
)
415 FIXME("(%p): stub\n", iface
);
419 /******************************************
420 * IWICStream_InitializeFromMemory
422 * Initializes the internal IStream object to retrieve its data from a memory chunk.
425 * pbBuffer [I] pointer to the memory chunk
426 * cbBufferSize [I] number of bytes to use from the memory chunk
430 * FAILURE: E_INVALIDARG, if pbBuffer is NULL
431 * E_OUTOFMEMORY, if we run out of memory
432 * WINCODEC_ERR_WRONGSTATE, if the IStream object has already been initialized before
435 static HRESULT WINAPI
IWICStreamImpl_InitializeFromMemory(IWICStream
*iface
,
436 BYTE
*pbBuffer
, DWORD cbBufferSize
)
438 IWICStreamImpl
*This
= (IWICStreamImpl
*)iface
;
439 StreamOnMemory
*pObject
;
440 TRACE("(%p,%p)\n", iface
, pbBuffer
);
442 if (!pbBuffer
) return E_INVALIDARG
;
443 if (This
->pStream
) return WINCODEC_ERR_WRONGSTATE
;
445 pObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnMemory
));
446 if (!pObject
) return E_OUTOFMEMORY
;
448 pObject
->lpVtbl
= &StreamOnMemory_Vtbl
;
450 pObject
->pbMemory
= pbBuffer
;
451 pObject
->dwMemsize
= cbBufferSize
;
452 pObject
->dwCurPos
= 0;
454 This
->pStream
= (IStream
*)pObject
;
458 static HRESULT WINAPI
IWICStreamImpl_InitializeFromIStreamRegion(IWICStream
*iface
,
459 IStream
*pIStream
, ULARGE_INTEGER ulOffset
, ULARGE_INTEGER ulMaxSize
)
461 FIXME("(%p): stub\n", iface
);
466 const IWICStreamVtbl WICStream_Vtbl
=
468 /*** IUnknown methods ***/
469 IWICStreamImpl_QueryInterface
,
470 IWICStreamImpl_AddRef
,
471 IWICStreamImpl_Release
,
472 /*** ISequentialStream methods ***/
474 IWICStreamImpl_Write
,
475 /*** IStream methods ***/
477 IWICStreamImpl_SetSize
,
478 IWICStreamImpl_CopyTo
,
479 IWICStreamImpl_Commit
,
480 IWICStreamImpl_Revert
,
481 IWICStreamImpl_LockRegion
,
482 IWICStreamImpl_UnlockRegion
,
484 IWICStreamImpl_Clone
,
485 /*** IWICStream methods ***/
486 IWICStreamImpl_InitializeFromIStream
,
487 IWICStreamImpl_InitializeFromFilename
,
488 IWICStreamImpl_InitializeFromMemory
,
489 IWICStreamImpl_InitializeFromIStreamRegion
,
492 HRESULT
StreamImpl_Create(IWICStream
**stream
)
494 IWICStreamImpl
*pObject
;
496 if( !stream
) return E_INVALIDARG
;
498 pObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(IWICStreamImpl
));
501 return E_OUTOFMEMORY
;
504 pObject
->lpVtbl
= &WICStream_Vtbl
;
506 pObject
->pStream
= NULL
;
508 *stream
= (IWICStream
*)pObject
;