diff --git a/dlls/windowscodecs/stream.c b/dlls/windowscodecs/stream.c index c59a9d2786..f3be0c319e 100644 --- a/dlls/windowscodecs/stream.c +++ b/dlls/windowscodecs/stream.c @@ -41,6 +41,8 @@ typedef struct StreamOnMemory { BYTE *pbMemory; DWORD dwMemsize; DWORD dwCurPos; + + CRITICAL_SECTION lock; /* must be held when pbMemory or dwCurPos is accessed */ } StreamOnMemory; static HRESULT WINAPI StreamOnMemory_QueryInterface(IStream *iface, @@ -82,6 +84,8 @@ static ULONG WINAPI StreamOnMemory_Release(IStream *iface) TRACE("(%p) refcount=%u\n", iface, ref); if (ref == 0) { + This->lock.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->lock); HeapFree(GetProcessHeap(), 0, This); } return ref; @@ -96,9 +100,12 @@ static HRESULT WINAPI StreamOnMemory_Read(IStream *iface, if (!pv) return E_INVALIDARG; + EnterCriticalSection(&This->lock); uBytesRead = min(cb, This->dwMemsize - This->dwCurPos); memcpy(pv, This->pbMemory + This->dwCurPos, uBytesRead); This->dwCurPos += uBytesRead; + LeaveCriticalSection(&This->lock); + if (pcbRead) *pcbRead = uBytesRead; return S_OK; @@ -108,18 +115,26 @@ static HRESULT WINAPI StreamOnMemory_Write(IStream *iface, void const *pv, ULONG cb, ULONG *pcbWritten) { StreamOnMemory *This = (StreamOnMemory*)iface; + HRESULT hr; TRACE("(%p)\n", This); if (!pv) return E_INVALIDARG; - if (cb > This->dwMemsize - This->dwCurPos) return STG_E_MEDIUMFULL; - if (cb) { - memcpy(This->pbMemory + This->dwCurPos, pv, cb); - This->dwCurPos += cb; + EnterCriticalSection(&This->lock); + if (cb > This->dwMemsize - This->dwCurPos) { + hr = STG_E_MEDIUMFULL; } - if (pcbWritten) *pcbWritten = cb; + else { + if (cb) { + memcpy(This->pbMemory + This->dwCurPos, pv, cb); + This->dwCurPos += cb; + hr = S_OK; + } + if (pcbWritten) *pcbWritten = cb; + } + LeaveCriticalSection(&This->lock); - return S_OK; + return hr; } static HRESULT WINAPI StreamOnMemory_Seek(IStream *iface, @@ -127,20 +142,29 @@ static HRESULT WINAPI StreamOnMemory_Seek(IStream *iface, { StreamOnMemory *This = (StreamOnMemory*)iface; LARGE_INTEGER NewPosition; + HRESULT hr=S_OK; TRACE("(%p)\n", This); + EnterCriticalSection(&This->lock); if (dwOrigin == STREAM_SEEK_SET) NewPosition.QuadPart = dlibMove.QuadPart; else if (dwOrigin == STREAM_SEEK_CUR) NewPosition.QuadPart = This->dwCurPos + dlibMove.QuadPart; else if (dwOrigin == STREAM_SEEK_END) NewPosition.QuadPart = This->dwMemsize + dlibMove.QuadPart; - else return E_INVALIDARG; + else hr = E_INVALIDARG; - if (NewPosition.u.HighPart) return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW); - if (NewPosition.QuadPart > This->dwMemsize) return E_INVALIDARG; - if (NewPosition.QuadPart < 0) return E_INVALIDARG; - This->dwCurPos = NewPosition.u.LowPart; + if (SUCCEEDED(hr)) { + if (NewPosition.u.HighPart) hr = HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW); + else if (NewPosition.QuadPart > This->dwMemsize) hr = E_INVALIDARG; + else if (NewPosition.QuadPart < 0) hr = E_INVALIDARG; + } - if(plibNewPosition) plibNewPosition->QuadPart = This->dwCurPos; - return S_OK; + if (SUCCEEDED(hr)) { + This->dwCurPos = NewPosition.u.LowPart; + + if(plibNewPosition) plibNewPosition->QuadPart = This->dwCurPos; + } + LeaveCriticalSection(&This->lock); + + return hr; } /* SetSize isn't implemented in the native windowscodecs DLL either */ @@ -450,6 +474,8 @@ static HRESULT WINAPI IWICStreamImpl_InitializeFromMemory(IWICStream *iface, pObject->pbMemory = pbBuffer; pObject->dwMemsize = cbBufferSize; pObject->dwCurPos = 0; + InitializeCriticalSection(&pObject->lock); + pObject->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": StreamOnMemory.lock"); This->pStream = (IStream*)pObject; return S_OK;