[1/5] windowscodecs: Implement IWICStream::InitializeFromIStream.
Józef Kucia
joseph.kucia at gmail.com
Mon May 28 00:07:21 CDT 2012
---
dlls/windowscodecs/stream.c | 231 ++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 229 insertions(+), 2 deletions(-)
diff --git a/dlls/windowscodecs/stream.c b/dlls/windowscodecs/stream.c
index cd235a3..ce6f34c 100644
--- a/dlls/windowscodecs/stream.c
+++ b/dlls/windowscodecs/stream.c
@@ -559,6 +559,210 @@ static const IStreamVtbl StreamOnStreamRange_Vtbl =
StreamOnStreamRange_Clone,
};
+/* *****************************************
+ * StreamOnStream implementation
+ *
+ * Used by IWICStream_InitializeFromIStream
+ *
+ */
+typedef struct StreamOnStream {
+ IStream IStream_iface;
+ LONG ref;
+
+ IStream *stream;
+ CRITICAL_SECTION lock;
+} StreamOnStream;
+
+static inline StreamOnStream *StreamOnStream_from_IStream(IStream *iface)
+{
+ return CONTAINING_RECORD(iface, StreamOnStream, IStream_iface);
+}
+
+static HRESULT WINAPI StreamOnStream_QueryInterface(IStream *iface,
+ REFIID iid, void **ppv)
+{
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) ||
+ IsEqualIID(&IID_ISequentialStream, iid))
+ {
+ *ppv = iface;
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+static ULONG WINAPI StreamOnStream_AddRef(IStream *iface)
+{
+ StreamOnStream *This = StreamOnStream_from_IStream(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI StreamOnStream_Release(IStream *iface)
+{
+ StreamOnStream *This = StreamOnStream_from_IStream(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0) {
+ This->lock.DebugInfo->Spare[0] = 0;
+ DeleteCriticalSection(&This->lock);
+ IStream_Release(This->stream);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+ return ref;
+}
+
+static HRESULT WINAPI StreamOnStream_Read(IStream *iface,
+ void *pv, ULONG cb, ULONG *pcbRead)
+{
+ StreamOnStream *This = StreamOnStream_from_IStream(iface);
+ HRESULT hr;
+ TRACE("(%p)\n", This);
+
+ if (!pv) return E_INVALIDARG;
+
+ EnterCriticalSection(&This->lock);
+ hr = IStream_Read(This->stream, pv, cb, pcbRead);
+ LeaveCriticalSection(&This->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI StreamOnStream_Write(IStream *iface,
+ void const *pv, ULONG cb, ULONG *pcbWritten)
+{
+ StreamOnStream *This = StreamOnStream_from_IStream(iface);
+ HRESULT hr;
+ TRACE("(%p)\n", This);
+
+ if (!pv) return E_INVALIDARG;
+
+ EnterCriticalSection(&This->lock);
+ hr = IStream_Write(This->stream, pv, cb, pcbWritten);
+ LeaveCriticalSection(&This->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI StreamOnStream_Seek(IStream *iface,
+ LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
+{
+ StreamOnStream *This = StreamOnStream_from_IStream(iface);
+ HRESULT hr=S_OK;
+ TRACE("(%p)\n", This);
+
+ EnterCriticalSection(&This->lock);
+ hr = IStream_Seek(This->stream, dlibMove, dwOrigin, plibNewPosition);
+ LeaveCriticalSection(&This->lock);
+
+ return hr;
+}
+
+/* SetSize isn't implemented in the native windowscodecs DLL either */
+static HRESULT WINAPI StreamOnStream_SetSize(IStream *iface,
+ ULARGE_INTEGER libNewSize)
+{
+ TRACE("(%p)\n", iface);
+ return E_NOTIMPL;
+}
+
+/* CopyTo isn't implemented in the native windowscodecs DLL either */
+static HRESULT WINAPI StreamOnStream_CopyTo(IStream *iface,
+ IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
+{
+ TRACE("(%p)\n", iface);
+ return E_NOTIMPL;
+}
+
+/* Commit isn't implemented in the native windowscodecs DLL either */
+static HRESULT WINAPI StreamOnStream_Commit(IStream *iface,
+ DWORD grfCommitFlags)
+{
+ TRACE("(%p)\n", iface);
+ return E_NOTIMPL;
+}
+
+/* Revert isn't implemented in the native windowscodecs DLL either */
+static HRESULT WINAPI StreamOnStream_Revert(IStream *iface)
+{
+ TRACE("(%p)\n", iface);
+ return E_NOTIMPL;
+}
+
+/* LockRegion isn't implemented in the native windowscodecs DLL either */
+static HRESULT WINAPI StreamOnStream_LockRegion(IStream *iface,
+ ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
+{
+ TRACE("(%p)\n", iface);
+ return E_NOTIMPL;
+}
+
+/* UnlockRegion isn't implemented in the native windowscodecs DLL either */
+static HRESULT WINAPI StreamOnStream_UnlockRegion(IStream *iface,
+ ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
+{
+ TRACE("(%p)\n", iface);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI StreamOnStream_Stat(IStream *iface,
+ STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ StreamOnStream *This = StreamOnStream_from_IStream(iface);
+ HRESULT hr;
+ TRACE("(%p)\n", This);
+
+ if (!pstatstg) return E_INVALIDARG;
+
+ EnterCriticalSection(&This->lock);
+ hr = IStream_Stat(This->stream, pstatstg, grfStatFlag);
+ LeaveCriticalSection(&This->lock);
+
+ return hr;
+}
+
+/* Clone isn't implemented in the native windowscodecs DLL either */
+static HRESULT WINAPI StreamOnStream_Clone(IStream *iface,
+ IStream **ppstm)
+{
+ TRACE("(%p)\n", iface);
+ return E_NOTIMPL;
+}
+
+
+static const IStreamVtbl StreamOnStream_Vtbl =
+{
+ /*** IUnknown methods ***/
+ StreamOnStream_QueryInterface,
+ StreamOnStream_AddRef,
+ StreamOnStream_Release,
+ /*** ISequentialStream methods ***/
+ StreamOnStream_Read,
+ StreamOnStream_Write,
+ /*** IStream methods ***/
+ StreamOnStream_Seek,
+ StreamOnStream_SetSize,
+ StreamOnStream_CopyTo,
+ StreamOnStream_Commit,
+ StreamOnStream_Revert,
+ StreamOnStream_LockRegion,
+ StreamOnStream_UnlockRegion,
+ StreamOnStream_Stat,
+ StreamOnStream_Clone
+};
/******************************************
* IWICStream implementation
@@ -735,8 +939,31 @@ static HRESULT WINAPI IWICStreamImpl_Clone(IWICStream *iface,
static HRESULT WINAPI IWICStreamImpl_InitializeFromIStream(IWICStream *iface,
IStream *pIStream)
{
- FIXME("(%p): stub\n", iface);
- return E_NOTIMPL;
+ IWICStreamImpl *This = impl_from_IWICStream(iface);
+ StreamOnStream *pObject;
+ TRACE("(%p,%p)\n", iface, pIStream);
+
+ if (!pIStream) return E_INVALIDARG;
+ if (This->pStream) return WINCODEC_ERR_WRONGSTATE;
+
+ pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnStreamRange));
+ if (!pObject) return E_OUTOFMEMORY;
+
+ pObject->IStream_iface.lpVtbl = &StreamOnStream_Vtbl;
+ pObject->ref = 1;
+ IStream_AddRef(pIStream);
+ pObject->stream = pIStream;
+ InitializeCriticalSection(&pObject->lock);
+ pObject->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": StreamOnStream.lock");
+
+ if (InterlockedCompareExchangePointer((void**)&This->pStream, pObject, NULL))
+ {
+ /* Some other thread set the stream first. */
+ IStream_Release(&pObject->IStream_iface);
+ return WINCODEC_ERR_WRONGSTATE;
+ }
+
+ return S_OK;
}
static HRESULT WINAPI IWICStreamImpl_InitializeFromFilename(IWICStream *iface,
--
1.7.8.6
More information about the wine-patches
mailing list