Signed-off-by: Esme Povirk esme@codeweavers.com --- dlls/windowscodecs/Makefile.in | 3 + dlls/windowscodecs/libpng.c | 98 ++++++++++++++++++++++++ dlls/windowscodecs/main.c | 5 ++ dlls/windowscodecs/pngformat.c | 20 ++++- dlls/windowscodecs/unix_iface.c | 102 +++++++++++++++++++++++++ dlls/windowscodecs/unix_lib.c | 66 ++++++++++++++++ dlls/windowscodecs/wincodecs_common.h | 23 ++++++ dlls/windowscodecs/wincodecs_private.h | 35 +++++++++ 8 files changed, 349 insertions(+), 3 deletions(-) create mode 100644 dlls/windowscodecs/libpng.c create mode 100644 dlls/windowscodecs/unix_iface.c create mode 100644 dlls/windowscodecs/unix_lib.c create mode 100644 dlls/windowscodecs/wincodecs_common.h
diff --git a/dlls/windowscodecs/Makefile.in b/dlls/windowscodecs/Makefile.in index fac90344fa3..fde28aea778 100644 --- a/dlls/windowscodecs/Makefile.in +++ b/dlls/windowscodecs/Makefile.in @@ -21,6 +21,7 @@ C_SRCS = \ imgfactory.c \ info.c \ jpegformat.c \ + libpng.c \ main.c \ metadatahandler.c \ metadataquery.c \ @@ -34,6 +35,8 @@ C_SRCS = \ tgaformat.c \ tiffformat.c \ ungif.c \ + unix_iface.c \ + unix_lib.c \ uuid.c
RC_SRCS = version.rc diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c new file mode 100644 index 00000000000..336fbb389b8 --- /dev/null +++ b/dlls/windowscodecs/libpng.c @@ -0,0 +1,98 @@ +/* + * Copyright 2020 Esme Povirk + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep unix +#endif + +#include "config.h" +#include "wine/port.h" + +#include <stdarg.h> + +#define NONAMELESSUNION + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winternl.h" +#include "winbase.h" +#include "objbase.h" + +#include "wincodecs_private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); + +#ifdef SONAME_LIBPNG + +struct png_decoder +{ + struct decoder decoder; +}; + +static inline struct png_decoder *impl_from_decoder(struct decoder* iface) +{ + return CONTAINING_RECORD(iface, struct png_decoder, decoder); +} + +void CDECL png_decoder_destroy(struct decoder* iface) +{ + struct png_decoder *This = impl_from_decoder(iface); + + RtlFreeHeap(GetProcessHeap(), 0, This); +} + +static const struct decoder_funcs png_decoder_vtable = { + png_decoder_destroy +}; + +HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result) +{ + struct png_decoder *This; + + TRACE("\n"); + + This = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*This)); + + if (!This) + { + return E_OUTOFMEMORY; + } + + This->decoder.vtable = &png_decoder_vtable; + *result = &This->decoder; + + info->container_format = GUID_ContainerFormatPng; + info->block_format = GUID_ContainerFormatPng; + info->clsid = CLSID_WICPngDecoder; + + return S_OK; +} + +#else + +HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result) +{ + ERR("Trying to load PNG picture, but PNG support is not compiled in.\n"); + return E_FAIL; +} + +#endif + diff --git a/dlls/windowscodecs/main.c b/dlls/windowscodecs/main.c index 7e03112a63c..3849e24c2a1 100644 --- a/dlls/windowscodecs/main.c +++ b/dlls/windowscodecs/main.c @@ -32,8 +32,12 @@
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+#include "wincodecs_common.h" + extern BOOL WINAPI WIC_DllMain(HINSTANCE, DWORD, LPVOID) DECLSPEC_HIDDEN;
+extern HMODULE windowscodecs_module; + BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
@@ -41,6 +45,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hinstDLL); + windowscodecs_module = hinstDLL; break; case DLL_PROCESS_DETACH: ReleaseComponentInfos(); diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c index 3cf47b4211f..3b326c1266f 100644 --- a/dlls/windowscodecs/pngformat.c +++ b/dlls/windowscodecs/pngformat.c @@ -444,6 +444,8 @@ typedef struct { IWICMetadataBlockReader IWICMetadataBlockReader_iface; LONG ref; IStream *stream; + struct decoder *png_decoder; + struct decoder_info decoder_info; png_structp png_ptr; png_infop info_ptr; png_infop end_info; @@ -521,6 +523,8 @@ static ULONG WINAPI PngDecoder_Release(IWICBitmapDecoder *iface) IStream_Release(This->stream); if (This->png_ptr) ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, &This->end_info); + if (This->png_decoder) + decoder_destroy(This->png_decoder); This->lock.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->lock); HeapFree(GetProcessHeap(), 0, This->image_bits); @@ -828,16 +832,18 @@ end: static HRESULT WINAPI PngDecoder_GetContainerFormat(IWICBitmapDecoder *iface, GUID *pguidContainerFormat) { - memcpy(pguidContainerFormat, &GUID_ContainerFormatPng, sizeof(GUID)); + PngDecoder *This = impl_from_IWICBitmapDecoder(iface); + memcpy(pguidContainerFormat, &This->decoder_info.container_format, sizeof(GUID)); return S_OK; }
static HRESULT WINAPI PngDecoder_GetDecoderInfo(IWICBitmapDecoder *iface, IWICBitmapDecoderInfo **ppIDecoderInfo) { + PngDecoder *This = impl_from_IWICBitmapDecoder(iface); TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
- return get_decoder_info(&CLSID_WICPngDecoder, ppIDecoderInfo); + return get_decoder_info(&This->decoder_info.clsid, ppIDecoderInfo); }
static HRESULT WINAPI PngDecoder_CopyPalette(IWICBitmapDecoder *iface, @@ -1208,8 +1214,9 @@ static ULONG WINAPI PngDecoder_Block_Release(IWICMetadataBlockReader *iface) static HRESULT WINAPI PngDecoder_Block_GetContainerFormat(IWICMetadataBlockReader *iface, GUID *pguidContainerFormat) { + PngDecoder *This = impl_from_IWICMetadataBlockReader(iface); if (!pguidContainerFormat) return E_INVALIDARG; - memcpy(pguidContainerFormat, &GUID_ContainerFormatPng, sizeof(GUID)); + memcpy(pguidContainerFormat, &This->decoder_info.block_format, sizeof(GUID)); return S_OK; }
@@ -1312,6 +1319,13 @@ HRESULT PngDecoder_CreateInstance(REFIID iid, void** ppv) This = HeapAlloc(GetProcessHeap(), 0, sizeof(PngDecoder)); if (!This) return E_OUTOFMEMORY;
+ ret = get_unix_decoder(&CLSID_WICPngDecoder, &This->decoder_info, &This->png_decoder); + if (FAILED(ret)) + { + HeapFree(GetProcessHeap(), 0, This); + return ret; + } + This->IWICBitmapDecoder_iface.lpVtbl = &PngDecoder_Vtbl; This->IWICBitmapFrameDecode_iface.lpVtbl = &PngDecoder_FrameVtbl; This->IWICMetadataBlockReader_iface.lpVtbl = &PngDecoder_BlockVtbl; diff --git a/dlls/windowscodecs/unix_iface.c b/dlls/windowscodecs/unix_iface.c new file mode 100644 index 00000000000..cae64a6774c --- /dev/null +++ b/dlls/windowscodecs/unix_iface.c @@ -0,0 +1,102 @@ +/* + * unix_iface.c - This is the Win32 side of the Unix interface. + * + * Copyright 2020 Esme Povirk + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "wine/port.h" + +#include <stdarg.h> + +#define NONAMELESSUNION +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "objbase.h" +#include "winternl.h" + +#include "wincodecs_private.h" + +#include "wine/debug.h" + +static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT; + +static const struct unix_funcs *unix_funcs; + +static BOOL WINAPI load_unixlib( INIT_ONCE *once, void *param, void **context ) +{ + __wine_init_unix_lib( windowscodecs_module, DLL_PROCESS_ATTACH, NULL, &unix_funcs ); + return TRUE; +} + +static void init_unixlib(void) +{ + InitOnceExecuteOnce( &init_once, load_unixlib, NULL, NULL ); +} + +struct decoder_wrapper +{ + struct decoder win32_decoder; + struct decoder *unix_decoder; +}; + +static inline struct decoder_wrapper *impl_from_decoder(struct decoder* iface) +{ + return CONTAINING_RECORD(iface, struct decoder_wrapper, win32_decoder); +} + +void CDECL decoder_wrapper_destroy(struct decoder* iface) +{ + struct decoder_wrapper* This = impl_from_decoder(iface); + unix_funcs->decoder_destroy(This->unix_decoder); + HeapFree(GetProcessHeap(), 0, This); +} + +static const struct decoder_funcs decoder_wrapper_vtable = { + decoder_wrapper_destroy +}; + +HRESULT get_unix_decoder(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result) +{ + HRESULT hr; + struct decoder_wrapper *wrapper; + struct decoder *unix_decoder; + + init_unixlib(); + + hr = unix_funcs->decoder_create(decoder_clsid, info, &unix_decoder); + + if (SUCCEEDED(hr)) + { + wrapper = HeapAlloc(GetProcessHeap(), 0, sizeof(*wrapper)); + + if (!wrapper) + { + unix_funcs->decoder_destroy(unix_decoder); + return E_OUTOFMEMORY; + } + + wrapper->win32_decoder.vtable = &decoder_wrapper_vtable; + wrapper->unix_decoder = unix_decoder; + *result = &wrapper->win32_decoder; + } + + return hr; +} + diff --git a/dlls/windowscodecs/unix_lib.c b/dlls/windowscodecs/unix_lib.c new file mode 100644 index 00000000000..80321d5b745 --- /dev/null +++ b/dlls/windowscodecs/unix_lib.c @@ -0,0 +1,66 @@ +/* + * unix_lib.c - This is the Unix side of the Unix interface. + * + * Copyright 2020 Esme Povirk + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep unix +#endif + +#include "config.h" +#include "wine/port.h" + +#include <stdarg.h> + +#define NONAMELESSUNION + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winternl.h" +#include "winbase.h" +#include "objbase.h" + +#include "initguid.h" +#include "wincodecs_private.h" + +#include "wine/debug.h" + +#include "wincodecs_common.h" + +HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result) +{ + if (IsEqualGUID(decoder_clsid, &CLSID_WICPngDecoder)) + return png_decoder_create(info, result); + + return E_NOTIMPL; +} + +static const struct unix_funcs unix_funcs = { + decoder_create, + decoder_destroy +}; + +NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out ) +{ + if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS; + + *(const struct unix_funcs **)ptr_out = &unix_funcs; + return STATUS_SUCCESS; +} + diff --git a/dlls/windowscodecs/wincodecs_common.h b/dlls/windowscodecs/wincodecs_common.h new file mode 100644 index 00000000000..4592a7ee15b --- /dev/null +++ b/dlls/windowscodecs/wincodecs_common.h @@ -0,0 +1,23 @@ +/* + * Copyright 2020 Esme Povirk + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +void CDECL decoder_destroy(struct decoder *decoder) +{ + decoder->vtable->destroy(decoder); +} + diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index f7665d11732..0085639b2e1 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -247,4 +247,39 @@ static inline const char *debug_wic_rect(const WICRect *rect) return wine_dbg_sprintf("(%u,%u)-(%u,%u)", rect->X, rect->Y, rect->Width, rect->Height); }
+HMODULE windowscodecs_module; + +/* unixlib iface */ +struct decoder_funcs; + +struct decoder_info +{ + GUID container_format; + GUID block_format; + CLSID clsid; +}; + +struct decoder +{ + const struct decoder_funcs *vtable; +}; + +struct decoder_funcs +{ + void (CDECL *destroy)(struct decoder* This); +}; + +HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result); +void CDECL decoder_destroy(struct decoder *This); + +HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result); + +struct unix_funcs +{ + HRESULT (CDECL *decoder_create)(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result); + void (CDECL *decoder_destroy)(struct decoder* This); +}; + +HRESULT get_unix_decoder(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result); + #endif /* WINCODECS_PRIVATE_H */