Module: wine Branch: master Commit: fd3ea78702e3c5ae7e1f66edf8b96254df5ae425 URL: http://source.winehq.org/git/wine.git/?a=commit;h=fd3ea78702e3c5ae7e1f66edf8...
Author: Vincent Povirk vincent@codeweavers.com Date: Fri Apr 9 15:27:37 2010 -0500
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; i<lineCount; i++) row_pointers[i] = pbPixels + cbStride * i; @@ -985,6 +1030,8 @@ static HRESULT WINAPI PngFrameEncode_WritePixels(IWICBitmapFrameEncode *iface, ppng_write_rows(This->png_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",