[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