From d05bee6a66b07c8ca1942c81a66e8c00541a8c5d Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Fri, 9 Apr 2010 15:27:37 -0500 Subject: [PATCH 1/2] windowscodecs: Add locking to the PNG encoder. --- dlls/windowscodecs/pngformat.c | 102 ++++++++++++++++++++++++++++++++++++++-- dlls/windowscodecs/regsvr.c | 2 +- 2 files changed, 98 insertions(+), 6 deletions(-) diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c index 8f2b74c..3dcbd9a 100644 --- a/dlls/windowscodecs/pngformat.c +++ b/dlls/windowscodecs/pngformat.c @@ -802,6 +802,7 @@ typedef struct PngEncoder { UINT lines_written; BOOL frame_committed; BOOL committed; + CRITICAL_SECTION lock; } PngEncoder; static inline PngEncoder *encoder_from_frame(IWICBitmapFrameEncode *iface) @@ -850,10 +851,18 @@ static HRESULT WINAPI PngFrameEncode_Initialize(IWICBitmapFrameEncode *iface, PngEncoder *This = encoder_from_frame(iface); TRACE("(%p,%p)\n", iface, pIEncoderOptions); - if (This->frame_initialized) return WINCODEC_ERR_WRONGSTATE; + EnterCriticalSection(&This->lock); + + if (This->frame_initialized) + { + LeaveCriticalSection(&This->lock); + return WINCODEC_ERR_WRONGSTATE; + } This->frame_initialized = TRUE; + LeaveCriticalSection(&This->lock); + return S_OK; } @@ -863,11 +872,19 @@ static HRESULT WINAPI PngFrameEncode_SetSize(IWICBitmapFrameEncode *iface, PngEncoder *This = encoder_from_frame(iface); TRACE("(%p,%u,%u)\n", iface, uiWidth, uiHeight); - if (!This->frame_initialized || This->info_written) return WINCODEC_ERR_WRONGSTATE; + EnterCriticalSection(&This->lock); + + if (!This->frame_initialized || This->info_written) + { + LeaveCriticalSection(&This->lock); + return WINCODEC_ERR_WRONGSTATE; + } This->width = uiWidth; This->height = uiHeight; + LeaveCriticalSection(&This->lock); + return S_OK; } @@ -877,11 +894,19 @@ static HRESULT WINAPI PngFrameEncode_SetResolution(IWICBitmapFrameEncode *iface, PngEncoder *This = encoder_from_frame(iface); TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY); - if (!This->frame_initialized || This->info_written) return WINCODEC_ERR_WRONGSTATE; + EnterCriticalSection(&This->lock); + + if (!This->frame_initialized || This->info_written) + { + LeaveCriticalSection(&This->lock); + return WINCODEC_ERR_WRONGSTATE; + } This->xres = dpiX; This->yres = dpiY; + LeaveCriticalSection(&This->lock); + return S_OK; } @@ -892,7 +917,13 @@ static HRESULT WINAPI PngFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface int i; TRACE("(%p,%s)\n", iface, debugstr_guid(pPixelFormat)); - if (!This->frame_initialized || This->info_written) return WINCODEC_ERR_WRONGSTATE; + EnterCriticalSection(&This->lock); + + if (!This->frame_initialized || This->info_written) + { + LeaveCriticalSection(&This->lock); + return WINCODEC_ERR_WRONGSTATE; + } for (i=0; formats[i].guid; i++) { @@ -905,6 +936,8 @@ static HRESULT WINAPI PngFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface This->format = &formats[i]; memcpy(pPixelFormat, This->format->guid, sizeof(GUID)); + LeaveCriticalSection(&This->lock); + return S_OK; } @@ -938,15 +971,24 @@ static HRESULT WINAPI PngFrameEncode_WritePixels(IWICBitmapFrameEncode *iface, jmp_buf jmpbuf; TRACE("(%p,%u,%u,%u,%p)\n", iface, lineCount, cbStride, cbBufferSize, pbPixels); + EnterCriticalSection(&This->lock); + if (!This->frame_initialized || !This->width || !This->height || !This->format) + { + LeaveCriticalSection(&This->lock); return WINCODEC_ERR_WRONGSTATE; + } if (lineCount == 0 || lineCount + This->lines_written > This->height) + { + LeaveCriticalSection(&This->lock); return E_INVALIDARG; + } /* set up setjmp/longjmp error handling */ if (setjmp(jmpbuf)) { + LeaveCriticalSection(&This->lock); HeapFree(GetProcessHeap(), 0, row_pointers); return E_FAIL; } @@ -977,7 +1019,10 @@ static HRESULT WINAPI PngFrameEncode_WritePixels(IWICBitmapFrameEncode *iface, row_pointers = HeapAlloc(GetProcessHeap(), 0, lineCount * sizeof(png_byte*)); if (!row_pointers) + { + LeaveCriticalSection(&This->lock); return E_OUTOFMEMORY; + } for (i=0; ipng_ptr, row_pointers, lineCount); This->lines_written += lineCount; + LeaveCriticalSection(&This->lock); + HeapFree(GetProcessHeap(), 0, row_pointers); return S_OK; @@ -1069,12 +1116,18 @@ static HRESULT WINAPI PngFrameEncode_Commit(IWICBitmapFrameEncode *iface) jmp_buf jmpbuf; TRACE("(%p)\n", iface); + EnterCriticalSection(&This->lock); + if (!This->info_written || This->lines_written != This->height || This->frame_committed) + { + LeaveCriticalSection(&This->lock); return WINCODEC_ERR_WRONGSTATE; + } /* set up setjmp/longjmp error handling */ if (setjmp(jmpbuf)) { + LeaveCriticalSection(&This->lock); return E_FAIL; } ppng_set_error_fn(This->png_ptr, &jmpbuf, user_error_fn, user_warning_fn); @@ -1083,6 +1136,8 @@ static HRESULT WINAPI PngFrameEncode_Commit(IWICBitmapFrameEncode *iface) This->frame_committed = TRUE; + LeaveCriticalSection(&This->lock); + return S_OK; } @@ -1152,6 +1207,8 @@ static ULONG WINAPI PngEncoder_Release(IWICBitmapEncoder *iface) if (ref == 0) { + This->lock.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->lock); if (This->png_ptr) ppng_destroy_write_struct(&This->png_ptr, &This->info_ptr); if (This->stream) @@ -1187,19 +1244,28 @@ static HRESULT WINAPI PngEncoder_Initialize(IWICBitmapEncoder *iface, TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOption); + EnterCriticalSection(&This->lock); + if (This->png_ptr) + { + LeaveCriticalSection(&This->lock); return WINCODEC_ERR_WRONGSTATE; + } /* initialize libpng */ This->png_ptr = ppng_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!This->png_ptr) + { + LeaveCriticalSection(&This->lock); return E_FAIL; + } This->info_ptr = ppng_create_info_struct(This->png_ptr); if (!This->info_ptr) { ppng_destroy_write_struct(&This->png_ptr, NULL); This->png_ptr = NULL; + LeaveCriticalSection(&This->lock); return E_FAIL; } @@ -1213,6 +1279,7 @@ static HRESULT WINAPI PngEncoder_Initialize(IWICBitmapEncoder *iface, This->png_ptr = NULL; IStream_Release(This->stream); This->stream = NULL; + LeaveCriticalSection(&This->lock); return E_FAIL; } ppng_set_error_fn(This->png_ptr, &jmpbuf, user_error_fn, user_warning_fn); @@ -1220,6 +1287,8 @@ static HRESULT WINAPI PngEncoder_Initialize(IWICBitmapEncoder *iface, /* set up custom i/o handling */ ppng_set_write_fn(This->png_ptr, This, user_write_data, user_flush); + LeaveCriticalSection(&This->lock); + return S_OK; } @@ -1269,17 +1338,31 @@ static HRESULT WINAPI PngEncoder_CreateNewFrame(IWICBitmapEncoder *iface, HRESULT hr; TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions); + EnterCriticalSection(&This->lock); + if (This->frame_count != 0) + { + LeaveCriticalSection(&This->lock); return WINCODEC_ERR_UNSUPPORTEDOPERATION; + } if (!This->stream) + { + LeaveCriticalSection(&This->lock); return WINCODEC_ERR_NOTINITIALIZED; + } hr = CreatePropertyBag2(ppIEncoderOptions); - if (FAILED(hr)) return hr; + if (FAILED(hr)) + { + LeaveCriticalSection(&This->lock); + return hr; + } This->frame_count = 1; + LeaveCriticalSection(&This->lock); + IWICBitmapEncoder_AddRef(iface); *ppIFrameEncode = (IWICBitmapFrameEncode*)&This->lpFrameVtbl; @@ -1291,11 +1374,18 @@ static HRESULT WINAPI PngEncoder_Commit(IWICBitmapEncoder *iface) PngEncoder *This = (PngEncoder*)iface; TRACE("(%p)\n", iface); + EnterCriticalSection(&This->lock); + if (!This->frame_committed || This->committed) + { + LeaveCriticalSection(&This->lock); return WINCODEC_ERR_WRONGSTATE; + } This->committed = TRUE; + EnterCriticalSection(&This->lock); + return S_OK; } @@ -1359,6 +1449,8 @@ HRESULT PngEncoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) This->lines_written = 0; This->frame_committed = FALSE; This->committed = FALSE; + InitializeCriticalSection(&This->lock); + This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PngEncoder.lock"); ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv); IUnknown_Release((IUnknown*)This); diff --git a/dlls/windowscodecs/regsvr.c b/dlls/windowscodecs/regsvr.c index a71ef0a..c5828a6 100644 --- a/dlls/windowscodecs/regsvr.c +++ b/dlls/windowscodecs/regsvr.c @@ -745,7 +745,7 @@ static struct regsvr_coclass const coclass_list[] = { "WIC PNG Encoder", NULL, "windowscodecs.dll", - "Apartment" + "Both" }, { &CLSID_WICBmpEncoder, "WIC BMP Encoder", -- 1.6.3.3