Wine-devel
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
October 2020
- 82 participants
- 799 discussions
This isn't necessary because we do not use libpng to read metadata
or verify checksums. If this happens to be the last thing we do,
it will fail the pngformat tests which do not expect us to return
with the stream seeked to the end of the file.
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
dlls/windowscodecs/libpng.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c
index 36151e94f1b..f101935211c 100644
--- a/dlls/windowscodecs/libpng.c
+++ b/dlls/windowscodecs/libpng.c
@@ -61,7 +61,6 @@ MAKE_FUNCPTR(png_get_io_ptr);
MAKE_FUNCPTR(png_get_pHYs);
MAKE_FUNCPTR(png_get_PLTE);
MAKE_FUNCPTR(png_get_tRNS);
-MAKE_FUNCPTR(png_read_end);
MAKE_FUNCPTR(png_read_image);
MAKE_FUNCPTR(png_read_info);
MAKE_FUNCPTR(png_set_bgr);
@@ -111,7 +110,6 @@ static void *load_libpng(void)
LOAD_FUNCPTR(png_get_pHYs);
LOAD_FUNCPTR(png_get_PLTE);
LOAD_FUNCPTR(png_get_tRNS);
- LOAD_FUNCPTR(png_read_end);
LOAD_FUNCPTR(png_read_image);
LOAD_FUNCPTR(png_read_info);
LOAD_FUNCPTR(png_set_bgr);
@@ -183,7 +181,6 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
struct png_decoder *This = impl_from_decoder(iface);
png_structp png_ptr;
png_infop info_ptr;
- png_infop end_info;
jmp_buf jmpbuf;
HRESULT hr = E_FAIL;
int color_type, bit_depth;
@@ -216,13 +213,6 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
return E_FAIL;
}
- end_info = ppng_create_info_struct(png_ptr);
- if (!end_info)
- {
- ppng_destroy_read_struct(&png_ptr, &info_ptr, NULL);
- return E_FAIL;
- }
-
/* set up setjmp/longjmp error handling */
if (setjmp(jmpbuf))
{
@@ -443,7 +433,7 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
free(row_pointers);
row_pointers = NULL;
- ppng_read_end(png_ptr, end_info);
+ /* png_read_end intentionally not called to not seek to the end of the file */
st->flags = WICBitmapDecoderCapabilityCanDecodeAllImages |
WICBitmapDecoderCapabilityCanDecodeSomeImages |
@@ -455,7 +445,7 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
hr = S_OK;
end:
- ppng_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ ppng_destroy_read_struct(&png_ptr, &info_ptr, NULL);
free(row_pointers);
if (FAILED(hr))
{
--
2.17.1
1
0
09 Oct '20
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
dlls/windowscodecs/libpng.c | 45 ++++++++++++++++++++++++++
dlls/windowscodecs/pngformat.c | 35 +++++++++-----------
dlls/windowscodecs/unix_iface.c | 8 +++++
dlls/windowscodecs/unix_lib.c | 1 +
dlls/windowscodecs/wincodecs_common.h | 6 ++++
dlls/windowscodecs/wincodecs_private.h | 7 ++++
6 files changed, 83 insertions(+), 19 deletions(-)
diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c
index 8a4db91f2a9..36151e94f1b 100644
--- a/dlls/windowscodecs/libpng.c
+++ b/dlls/windowscodecs/libpng.c
@@ -54,6 +54,7 @@ MAKE_FUNCPTR(png_error);
MAKE_FUNCPTR(png_get_bit_depth);
MAKE_FUNCPTR(png_get_color_type);
MAKE_FUNCPTR(png_get_error_ptr);
+MAKE_FUNCPTR(png_get_iCCP);
MAKE_FUNCPTR(png_get_image_height);
MAKE_FUNCPTR(png_get_image_width);
MAKE_FUNCPTR(png_get_io_ptr);
@@ -105,6 +106,7 @@ static void *load_libpng(void)
LOAD_FUNCPTR(png_get_error_ptr);
LOAD_FUNCPTR(png_get_image_height);
LOAD_FUNCPTR(png_get_image_width);
+ LOAD_FUNCPTR(png_get_iCCP);
LOAD_FUNCPTR(png_get_io_ptr);
LOAD_FUNCPTR(png_get_pHYs);
LOAD_FUNCPTR(png_get_PLTE);
@@ -137,6 +139,8 @@ struct png_decoder
struct decoder_frame decoder_frame;
UINT stride;
BYTE *image_bits;
+ BYTE *color_profile;
+ DWORD color_profile_len;
};
static inline struct png_decoder *impl_from_decoder(struct decoder* iface)
@@ -194,6 +198,10 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
int i;
UINT image_size;
png_bytep *row_pointers=NULL;
+ png_charp cp_name;
+ png_bytep cp_profile;
+ png_uint_32 cp_len;
+ int cp_compression;
png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
@@ -351,6 +359,22 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
This->decoder_frame.dpix = This->decoder_frame.dpiy = 96.0;
}
+ ret = ppng_get_iCCP(png_ptr, info_ptr, &cp_name, &cp_compression, &cp_profile, &cp_len);
+ if (ret)
+ {
+ This->decoder_frame.num_color_contexts = 1;
+ This->color_profile_len = cp_len;
+ This->color_profile = malloc(cp_len);
+ if (!This->color_profile)
+ {
+ hr = E_OUTOFMEMORY;
+ goto end;
+ }
+ memcpy(This->color_profile, cp_profile, cp_len);
+ }
+ else
+ This->decoder_frame.num_color_contexts = 0;
+
if (color_type == PNG_COLOR_TYPE_PALETTE)
{
ret = ppng_get_PLTE(png_ptr, info_ptr, &png_palette, &num_palette);
@@ -437,6 +461,8 @@ end:
{
free(This->image_bits);
This->image_bits = NULL;
+ free(This->color_profile);
+ This->color_profile = NULL;
}
return hr;
}
@@ -531,11 +557,28 @@ end:
return hr;
}
+HRESULT CDECL png_decoder_get_color_context(struct decoder* iface, UINT frame, UINT num,
+ BYTE **data, DWORD *datasize)
+{
+ struct png_decoder *This = impl_from_decoder(iface);
+
+ *data = RtlAllocateHeap(GetProcessHeap(), 0, This->color_profile_len);
+ *datasize = This->color_profile_len;
+
+ if (!*data)
+ return E_OUTOFMEMORY;
+
+ memcpy(*data, This->color_profile, This->color_profile_len);
+
+ return S_OK;
+}
+
void CDECL png_decoder_destroy(struct decoder* iface)
{
struct png_decoder *This = impl_from_decoder(iface);
free(This->image_bits);
+ free(This->color_profile);
RtlFreeHeap(GetProcessHeap(), 0, This);
}
@@ -544,6 +587,7 @@ static const struct decoder_funcs png_decoder_vtable = {
png_decoder_get_frame_info,
png_decoder_copy_pixels,
png_decoder_get_metadata_blocks,
+ png_decoder_get_color_context,
png_decoder_destroy
};
@@ -566,6 +610,7 @@ HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **res
This->decoder.vtable = &png_decoder_vtable;
This->image_bits = NULL;
+ This->color_profile = NULL;
*result = &This->decoder;
info->container_format = GUID_ContainerFormatPng;
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index 1d696a4fe01..efd5f6ab2c1 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -976,37 +976,34 @@ static HRESULT WINAPI PngDecoder_Frame_GetColorContexts(IWICBitmapFrameDecode *i
UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
{
PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- png_charp name;
+ HRESULT hr=S_OK;
BYTE *profile;
- png_uint_32 len;
- int compression_type;
- HRESULT hr;
+ DWORD profile_len;
TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
if (!pcActualCount) return E_INVALIDARG;
- EnterCriticalSection(&This->lock);
+ *pcActualCount = This->decoder_frame.num_color_contexts;
- if (ppng_get_iCCP(This->png_ptr, This->info_ptr, &name, &compression_type, (void *)&profile, &len))
+ if (This->decoder_frame.num_color_contexts && cCount && ppIColorContexts)
{
- if (cCount && ppIColorContexts)
+ EnterCriticalSection(&This->lock);
+
+ hr = decoder_get_color_context(This->png_decoder, 0, 0,
+ &profile, &profile_len);
+
+ LeaveCriticalSection(&This->lock);
+
+ if (SUCCEEDED(hr))
{
- hr = IWICColorContext_InitializeFromMemory(*ppIColorContexts, profile, len);
- if (FAILED(hr))
- {
- LeaveCriticalSection(&This->lock);
- return hr;
- }
+ hr = IWICColorContext_InitializeFromMemory(*ppIColorContexts, profile, profile_len);
+
+ HeapFree(GetProcessHeap(), 0, profile);
}
- *pcActualCount = 1;
}
- else
- *pcActualCount = 0;
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
+ return hr;
}
static HRESULT WINAPI PngDecoder_Frame_GetThumbnail(IWICBitmapFrameDecode *iface,
diff --git a/dlls/windowscodecs/unix_iface.c b/dlls/windowscodecs/unix_iface.c
index 8d22b49ba22..cdc92a7d160 100644
--- a/dlls/windowscodecs/unix_iface.c
+++ b/dlls/windowscodecs/unix_iface.c
@@ -92,6 +92,13 @@ HRESULT CDECL decoder_wrapper_get_metadata_blocks(struct decoder* iface,
return unix_funcs->decoder_get_metadata_blocks(This->unix_decoder, frame, count, blocks);
}
+HRESULT CDECL decoder_wrapper_get_color_context(struct decoder* iface,
+ UINT frame, UINT num, BYTE **data, DWORD *datasize)
+{
+ struct decoder_wrapper* This = impl_from_decoder(iface);
+ return unix_funcs->decoder_get_color_context(This->unix_decoder, frame, num, data, datasize);
+}
+
void CDECL decoder_wrapper_destroy(struct decoder* iface)
{
struct decoder_wrapper* This = impl_from_decoder(iface);
@@ -104,6 +111,7 @@ static const struct decoder_funcs decoder_wrapper_vtable = {
decoder_wrapper_get_frame_info,
decoder_wrapper_copy_pixels,
decoder_wrapper_get_metadata_blocks,
+ decoder_wrapper_get_color_context,
decoder_wrapper_destroy
};
diff --git a/dlls/windowscodecs/unix_lib.c b/dlls/windowscodecs/unix_lib.c
index 58c68018430..217a5a2e63a 100644
--- a/dlls/windowscodecs/unix_lib.c
+++ b/dlls/windowscodecs/unix_lib.c
@@ -71,6 +71,7 @@ static const struct unix_funcs unix_funcs = {
decoder_get_frame_info,
decoder_copy_pixels,
decoder_get_metadata_blocks,
+ decoder_get_color_context,
decoder_destroy
};
diff --git a/dlls/windowscodecs/wincodecs_common.h b/dlls/windowscodecs/wincodecs_common.h
index 5489a055a27..b5d7b645638 100644
--- a/dlls/windowscodecs/wincodecs_common.h
+++ b/dlls/windowscodecs/wincodecs_common.h
@@ -37,6 +37,12 @@ HRESULT CDECL decoder_get_metadata_blocks(struct decoder *decoder, UINT frame, U
return decoder->vtable->get_metadata_blocks(decoder, frame, count, blocks);
}
+HRESULT CDECL decoder_get_color_context(struct decoder *decoder, UINT frame,
+ UINT num, BYTE **data, DWORD *datasize)
+{
+ return decoder->vtable->get_color_context(decoder, frame, num, data, datasize);
+}
+
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 3c0b73e893f..e5294b8cf1a 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -275,6 +275,7 @@ struct decoder_frame
UINT width, height;
UINT bpp;
double dpix, dpiy;
+ DWORD num_color_contexts;
DWORD num_colors;
WICColor palette[256];
};
@@ -299,6 +300,8 @@ struct decoder_funcs
UINT stride, UINT buffersize, BYTE *buffer);
HRESULT (CDECL *get_metadata_blocks)(struct decoder* This, UINT frame, UINT *count,
struct decoder_block **blocks);
+ HRESULT (CDECL *get_color_context)(struct decoder* This, UINT frame, UINT num,
+ BYTE **data, DWORD *datasize);
void (CDECL *destroy)(struct decoder* This);
};
@@ -318,6 +321,8 @@ HRESULT CDECL decoder_copy_pixels(struct decoder* This, UINT frame, const WICRec
UINT stride, UINT buffersize, BYTE *buffer);
HRESULT CDECL decoder_get_metadata_blocks(struct decoder* This, UINT frame, UINT *count,
struct decoder_block **blocks);
+HRESULT CDECL decoder_get_color_context(struct decoder* This, UINT frame, UINT num,
+ BYTE **data, DWORD *datasize);
void CDECL decoder_destroy(struct decoder *This);
HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result);
@@ -331,6 +336,8 @@ struct unix_funcs
UINT stride, UINT buffersize, BYTE *buffer);
HRESULT (CDECL *decoder_get_metadata_blocks)(struct decoder* This, UINT frame, UINT *count,
struct decoder_block **blocks);
+ HRESULT (CDECL *decoder_get_color_context)(struct decoder* This, UINT frame, UINT num,
+ BYTE **data, DWORD *datasize);
void (CDECL *decoder_destroy)(struct decoder* This);
};
--
2.17.1
1
0
09 Oct '20
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
dlls/windowscodecs/libpng.c | 77 +++++++++++++
dlls/windowscodecs/main.c | 1 +
dlls/windowscodecs/pngformat.c | 143 ++++---------------------
dlls/windowscodecs/unix_iface.c | 8 ++
dlls/windowscodecs/unix_lib.c | 1 +
dlls/windowscodecs/wincodecs_common.h | 51 +++++++++
dlls/windowscodecs/wincodecs_private.h | 15 +++
7 files changed, 174 insertions(+), 122 deletions(-)
diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c
index 397d2d371ef..8a4db91f2a9 100644
--- a/dlls/windowscodecs/libpng.c
+++ b/dlls/windowscodecs/libpng.c
@@ -133,6 +133,7 @@ static void *load_libpng(void)
struct png_decoder
{
struct decoder decoder;
+ IStream *stream;
struct decoder_frame decoder_frame;
UINT stride;
BYTE *image_bits;
@@ -425,6 +426,8 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
WICBitmapDecoderCapabilityCanEnumerateMetadata;
st->frame_count = 1;
+ This->stream = stream;
+
hr = S_OK;
end:
@@ -455,6 +458,79 @@ HRESULT CDECL png_decoder_copy_pixels(struct decoder *iface, UINT frame,
prc, stride, buffersize, buffer);
}
+HRESULT CDECL png_decoder_get_metadata_blocks(struct decoder* iface,
+ UINT frame, UINT *count, struct decoder_block **blocks)
+{
+ struct png_decoder *This = impl_from_decoder(iface);
+ HRESULT hr;
+ struct decoder_block *result = NULL;
+ ULONGLONG seek;
+ BYTE chunk_type[4];
+ ULONG chunk_size;
+ ULONGLONG chunk_start;
+ ULONG metadata_blocks_size = 0;
+
+ seek = 8;
+ *count = 0;
+
+ do
+ {
+ hr = stream_seek(This->stream, seek, STREAM_SEEK_SET, &chunk_start);
+ if (FAILED(hr)) goto end;
+
+ hr = read_png_chunk(This->stream, chunk_type, NULL, &chunk_size);
+ if (FAILED(hr)) goto end;
+
+ if (chunk_type[0] >= 'a' && chunk_type[0] <= 'z' &&
+ memcmp(chunk_type, "tRNS", 4) && memcmp(chunk_type, "pHYs", 4))
+ {
+ /* This chunk is considered metadata. */
+ if (*count == metadata_blocks_size)
+ {
+ struct decoder_block *new_metadata_blocks;
+ ULONG new_metadata_blocks_size;
+
+ new_metadata_blocks_size = 4 + metadata_blocks_size * 2;
+ new_metadata_blocks = RtlAllocateHeap(GetProcessHeap(), 0,
+ new_metadata_blocks_size * sizeof(*new_metadata_blocks));
+
+ if (!new_metadata_blocks)
+ {
+ hr = E_OUTOFMEMORY;
+ goto end;
+ }
+
+ memcpy(new_metadata_blocks, result,
+ *count * sizeof(*new_metadata_blocks));
+
+ RtlFreeHeap(GetProcessHeap(), 0, result);
+ result = new_metadata_blocks;
+ metadata_blocks_size = new_metadata_blocks_size;
+ }
+
+ result[*count].offset = chunk_start;
+ result[*count].length = chunk_size + 12;
+ result[*count].options = WICMetadataCreationAllowUnknown;
+ (*count)++;
+ }
+
+ seek = chunk_start + chunk_size + 12; /* skip data and CRC */
+ } while (memcmp(chunk_type, "IEND", 4));
+
+end:
+ if (SUCCEEDED(hr))
+ {
+ *blocks = result;
+ }
+ else
+ {
+ *count = 0;
+ *blocks = NULL;
+ RtlFreeHeap(GetProcessHeap(), 0, result);
+ }
+ return hr;
+}
+
void CDECL png_decoder_destroy(struct decoder* iface)
{
struct png_decoder *This = impl_from_decoder(iface);
@@ -467,6 +543,7 @@ static const struct decoder_funcs png_decoder_vtable = {
png_decoder_initialize,
png_decoder_get_frame_info,
png_decoder_copy_pixels,
+ png_decoder_get_metadata_blocks,
png_decoder_destroy
};
diff --git a/dlls/windowscodecs/main.c b/dlls/windowscodecs/main.c
index 982c8ddfada..4dcc146d6c8 100644
--- a/dlls/windowscodecs/main.c
+++ b/dlls/windowscodecs/main.c
@@ -24,6 +24,7 @@
#include "windef.h"
#include "winbase.h"
+#include "winternl.h"
#include "objbase.h"
#include "wincodecs_private.h"
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index 834cc81d306..1d696a4fe01 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -44,47 +44,6 @@ static inline ULONG read_ulong_be(BYTE* data)
return data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
}
-static HRESULT read_png_chunk(IStream *stream, BYTE *type, BYTE **data, ULONG *data_size)
-{
- BYTE header[8];
- HRESULT hr;
- ULONG bytesread;
-
- hr = IStream_Read(stream, header, 8, &bytesread);
- if (FAILED(hr) || bytesread < 8)
- {
- if (SUCCEEDED(hr))
- hr = E_FAIL;
- return hr;
- }
-
- *data_size = read_ulong_be(&header[0]);
-
- memcpy(type, &header[4], 4);
-
- if (data)
- {
- *data = HeapAlloc(GetProcessHeap(), 0, *data_size);
- if (!*data)
- return E_OUTOFMEMORY;
-
- hr = IStream_Read(stream, *data, *data_size, &bytesread);
-
- if (FAILED(hr) || bytesread < *data_size)
- {
- if (SUCCEEDED(hr))
- hr = E_FAIL;
- HeapFree(GetProcessHeap(), 0, *data);
- *data = NULL;
- return hr;
- }
-
- /* Windows ignores CRC of the chunk */
- }
-
- return S_OK;
-}
-
static HRESULT LoadTextMetadata(IStream *stream, const GUID *preferred_vendor,
DWORD persist_options, MetadataItem **items, DWORD *item_count)
{
@@ -459,7 +418,7 @@ typedef struct {
BYTE *image_bits;
CRITICAL_SECTION lock; /* must be held when png structures are accessed or initialized is set */
ULONG metadata_count;
- metadata_block_info* metadata_blocks;
+ struct decoder_block* metadata_blocks;
} PngDecoder;
static inline PngDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
@@ -515,7 +474,6 @@ static ULONG WINAPI PngDecoder_Release(IWICBitmapDecoder *iface)
{
PngDecoder *This = impl_from_IWICBitmapDecoder(iface);
ULONG ref = InterlockedDecrement(&This->ref);
- ULONG i;
TRACE("(%p) refcount=%u\n", iface, ref);
@@ -530,11 +488,6 @@ static ULONG WINAPI PngDecoder_Release(IWICBitmapDecoder *iface)
This->lock.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->lock);
HeapFree(GetProcessHeap(), 0, This->image_bits);
- for (i=0; i<This->metadata_count; i++)
- {
- if (This->metadata_blocks[i].reader)
- IWICMetadataReader_Release(This->metadata_blocks[i].reader);
- }
HeapFree(GetProcessHeap(), 0, This->metadata_blocks);
HeapFree(GetProcessHeap(), 0, This);
}
@@ -587,10 +540,6 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
png_uint_32 transparency;
png_color_16p trans_values;
jmp_buf jmpbuf;
- BYTE chunk_type[4];
- ULONG chunk_size;
- ULARGE_INTEGER chunk_start;
- ULONG metadata_blocks_size = 0;
TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
@@ -783,52 +732,7 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
ppng_read_end(This->png_ptr, This->end_info);
- /* Find the metadata chunks in the file. */
- seek.QuadPart = 8;
-
- do
- {
- hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, &chunk_start);
- if (FAILED(hr)) goto end;
-
- hr = read_png_chunk(pIStream, chunk_type, NULL, &chunk_size);
- if (FAILED(hr)) goto end;
-
- if (chunk_type[0] >= 'a' && chunk_type[0] <= 'z' &&
- memcmp(chunk_type, "tRNS", 4) && memcmp(chunk_type, "pHYs", 4))
- {
- /* This chunk is considered metadata. */
- if (This->metadata_count == metadata_blocks_size)
- {
- metadata_block_info* new_metadata_blocks;
- ULONG new_metadata_blocks_size;
-
- new_metadata_blocks_size = 4 + metadata_blocks_size * 2;
- new_metadata_blocks = HeapAlloc(GetProcessHeap(), 0,
- new_metadata_blocks_size * sizeof(*new_metadata_blocks));
-
- if (!new_metadata_blocks)
- {
- hr = E_OUTOFMEMORY;
- goto end;
- }
-
- memcpy(new_metadata_blocks, This->metadata_blocks,
- This->metadata_count * sizeof(*new_metadata_blocks));
-
- HeapFree(GetProcessHeap(), 0, This->metadata_blocks);
- This->metadata_blocks = new_metadata_blocks;
- metadata_blocks_size = new_metadata_blocks_size;
- }
-
- This->metadata_blocks[This->metadata_count].ofs = chunk_start;
- This->metadata_blocks[This->metadata_count].len.QuadPart = chunk_size + 12;
- This->metadata_blocks[This->metadata_count].reader = NULL;
- This->metadata_count++;
- }
-
- seek.QuadPart = chunk_start.QuadPart + chunk_size + 12; /* skip data and CRC */
- } while (memcmp(chunk_type, "IEND", 4));
+ decoder_get_metadata_blocks(This->png_decoder, 0, &This->metadata_count, &This->metadata_blocks);
This->stream = pIStream;
IStream_AddRef(This->stream);
@@ -1185,39 +1089,34 @@ static HRESULT WINAPI PngDecoder_Block_GetReaderByIndex(IWICMetadataBlockReader
if (nIndex >= This->metadata_count || !ppIMetadataReader)
return E_INVALIDARG;
- if (!This->metadata_blocks[nIndex].reader)
- {
- hr = StreamImpl_Create(&stream);
+ hr = StreamImpl_Create(&stream);
- if (SUCCEEDED(hr))
- {
- hr = IWICStream_InitializeFromIStreamRegion(stream, This->stream,
- This->metadata_blocks[nIndex].ofs, This->metadata_blocks[nIndex].len);
+ if (SUCCEEDED(hr))
+ {
+ ULARGE_INTEGER offset, length;
- if (SUCCEEDED(hr))
- hr = ImagingFactory_CreateInstance(&IID_IWICComponentFactory, (void**)&factory);
+ offset.QuadPart = This->metadata_blocks[nIndex].offset;
+ length.QuadPart = This->metadata_blocks[nIndex].length;
+ hr = IWICStream_InitializeFromIStreamRegion(stream, This->stream,
+ offset, length);
- if (SUCCEEDED(hr))
- {
- hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
- &GUID_ContainerFormatPng, NULL, WICMetadataCreationAllowUnknown,
- (IStream*)stream, &This->metadata_blocks[nIndex].reader);
+ if (SUCCEEDED(hr))
+ hr = ImagingFactory_CreateInstance(&IID_IWICComponentFactory, (void**)&factory);
- IWICComponentFactory_Release(factory);
- }
+ if (SUCCEEDED(hr))
+ {
+ hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
+ &GUID_ContainerFormatPng, NULL, This->metadata_blocks[nIndex].options,
+ (IStream*)stream, ppIMetadataReader);
- IWICStream_Release(stream);
+ IWICComponentFactory_Release(factory);
}
- if (FAILED(hr))
- {
- *ppIMetadataReader = NULL;
- return hr;
- }
+ IWICStream_Release(stream);
}
- *ppIMetadataReader = This->metadata_blocks[nIndex].reader;
- IWICMetadataReader_AddRef(*ppIMetadataReader);
+ if (FAILED(hr))
+ *ppIMetadataReader = NULL;
return S_OK;
}
diff --git a/dlls/windowscodecs/unix_iface.c b/dlls/windowscodecs/unix_iface.c
index 46bcacff941..8d22b49ba22 100644
--- a/dlls/windowscodecs/unix_iface.c
+++ b/dlls/windowscodecs/unix_iface.c
@@ -85,6 +85,13 @@ HRESULT CDECL decoder_wrapper_copy_pixels(struct decoder* iface, UINT frame,
return unix_funcs->decoder_copy_pixels(This->unix_decoder, frame, prc, stride, buffersize, buffer);
}
+HRESULT CDECL decoder_wrapper_get_metadata_blocks(struct decoder* iface,
+ UINT frame, UINT *count, struct decoder_block **blocks)
+{
+ struct decoder_wrapper* This = impl_from_decoder(iface);
+ return unix_funcs->decoder_get_metadata_blocks(This->unix_decoder, frame, count, blocks);
+}
+
void CDECL decoder_wrapper_destroy(struct decoder* iface)
{
struct decoder_wrapper* This = impl_from_decoder(iface);
@@ -96,6 +103,7 @@ static const struct decoder_funcs decoder_wrapper_vtable = {
decoder_wrapper_initialize,
decoder_wrapper_get_frame_info,
decoder_wrapper_copy_pixels,
+ decoder_wrapper_get_metadata_blocks,
decoder_wrapper_destroy
};
diff --git a/dlls/windowscodecs/unix_lib.c b/dlls/windowscodecs/unix_lib.c
index 5ab1cb342e6..58c68018430 100644
--- a/dlls/windowscodecs/unix_lib.c
+++ b/dlls/windowscodecs/unix_lib.c
@@ -70,6 +70,7 @@ static const struct unix_funcs unix_funcs = {
decoder_initialize,
decoder_get_frame_info,
decoder_copy_pixels,
+ decoder_get_metadata_blocks,
decoder_destroy
};
diff --git a/dlls/windowscodecs/wincodecs_common.h b/dlls/windowscodecs/wincodecs_common.h
index f116fb6fd8f..5489a055a27 100644
--- a/dlls/windowscodecs/wincodecs_common.h
+++ b/dlls/windowscodecs/wincodecs_common.h
@@ -32,6 +32,11 @@ HRESULT CDECL decoder_copy_pixels(struct decoder *decoder, UINT frame,
return decoder->vtable->copy_pixels(decoder, frame, prc, stride, buffersize, buffer);
}
+HRESULT CDECL decoder_get_metadata_blocks(struct decoder *decoder, UINT frame, UINT *count, struct decoder_block **blocks)
+{
+ return decoder->vtable->get_metadata_blocks(decoder, frame, count, blocks);
+}
+
void CDECL decoder_destroy(struct decoder *decoder)
{
decoder->vtable->destroy(decoder);
@@ -102,3 +107,49 @@ HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer,
}
}
+static inline ULONG read_ulong_be(BYTE* data)
+{
+ return data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+}
+
+HRESULT read_png_chunk(IStream *stream, BYTE *type, BYTE **data, ULONG *data_size)
+{
+ BYTE header[8];
+ HRESULT hr;
+ ULONG bytesread;
+
+ hr = stream_read(stream, header, 8, &bytesread);
+ if (FAILED(hr) || bytesread < 8)
+ {
+ if (SUCCEEDED(hr))
+ hr = E_FAIL;
+ return hr;
+ }
+
+ *data_size = read_ulong_be(&header[0]);
+
+ memcpy(type, &header[4], 4);
+
+ if (data)
+ {
+ *data = RtlAllocateHeap(GetProcessHeap(), 0, *data_size);
+ if (!*data)
+ return E_OUTOFMEMORY;
+
+ hr = stream_read(stream, *data, *data_size, &bytesread);
+
+ if (FAILED(hr) || bytesread < *data_size)
+ {
+ if (SUCCEEDED(hr))
+ hr = E_FAIL;
+ RtlFreeHeap(GetProcessHeap(), 0, *data);
+ *data = NULL;
+ return hr;
+ }
+
+ /* Windows ignores CRC of the chunk */
+ }
+
+ return S_OK;
+}
+
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index 24cae3652f4..3c0b73e893f 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -249,6 +249,8 @@ static inline const char *debug_wic_rect(const WICRect *rect)
HMODULE windowscodecs_module;
+HRESULT read_png_chunk(IStream *stream, BYTE *type, BYTE **data, ULONG *data_size);
+
/* unixlib iface */
struct decoder_funcs;
@@ -277,6 +279,13 @@ struct decoder_frame
WICColor palette[256];
};
+struct decoder_block
+{
+ ULONGLONG offset;
+ ULONGLONG length;
+ DWORD options;
+};
+
struct decoder
{
const struct decoder_funcs *vtable;
@@ -288,6 +297,8 @@ struct decoder_funcs
HRESULT (CDECL *get_frame_info)(struct decoder* This, UINT frame, struct decoder_frame *info);
HRESULT (CDECL *copy_pixels)(struct decoder* This, UINT frame, const WICRect *prc,
UINT stride, UINT buffersize, BYTE *buffer);
+ HRESULT (CDECL *get_metadata_blocks)(struct decoder* This, UINT frame, UINT *count,
+ struct decoder_block **blocks);
void (CDECL *destroy)(struct decoder* This);
};
@@ -305,6 +316,8 @@ HRESULT CDECL decoder_initialize(struct decoder *This, IStream *stream, struct d
HRESULT CDECL decoder_get_frame_info(struct decoder* This, UINT frame, struct decoder_frame *info);
HRESULT CDECL decoder_copy_pixels(struct decoder* This, UINT frame, const WICRect *prc,
UINT stride, UINT buffersize, BYTE *buffer);
+HRESULT CDECL decoder_get_metadata_blocks(struct decoder* This, UINT frame, UINT *count,
+ struct decoder_block **blocks);
void CDECL decoder_destroy(struct decoder *This);
HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result);
@@ -316,6 +329,8 @@ struct unix_funcs
HRESULT (CDECL *decoder_get_frame_info)(struct decoder* This, UINT frame, struct decoder_frame *info);
HRESULT (CDECL *decoder_copy_pixels)(struct decoder* This, UINT frame, const WICRect *prc,
UINT stride, UINT buffersize, BYTE *buffer);
+ HRESULT (CDECL *decoder_get_metadata_blocks)(struct decoder* This, UINT frame, UINT *count,
+ struct decoder_block **blocks);
void (CDECL *decoder_destroy)(struct decoder* This);
};
--
2.17.1
1
0
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
dlls/windowscodecs/libpng.c | 54 ++++++++++++++++++++
dlls/windowscodecs/main.c | 65 -----------------------
dlls/windowscodecs/pngformat.c | 3 +-
dlls/windowscodecs/unix_iface.c | 8 +++
dlls/windowscodecs/unix_lib.c | 3 ++
dlls/windowscodecs/wincodecs_common.h | 71 ++++++++++++++++++++++++++
dlls/windowscodecs/wincodecs_private.h | 6 +++
7 files changed, 143 insertions(+), 67 deletions(-)
diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c
index bed7ea72d65..397d2d371ef 100644
--- a/dlls/windowscodecs/libpng.c
+++ b/dlls/windowscodecs/libpng.c
@@ -60,6 +60,8 @@ MAKE_FUNCPTR(png_get_io_ptr);
MAKE_FUNCPTR(png_get_pHYs);
MAKE_FUNCPTR(png_get_PLTE);
MAKE_FUNCPTR(png_get_tRNS);
+MAKE_FUNCPTR(png_read_end);
+MAKE_FUNCPTR(png_read_image);
MAKE_FUNCPTR(png_read_info);
MAKE_FUNCPTR(png_set_bgr);
MAKE_FUNCPTR(png_set_crc_action);
@@ -107,6 +109,8 @@ static void *load_libpng(void)
LOAD_FUNCPTR(png_get_pHYs);
LOAD_FUNCPTR(png_get_PLTE);
LOAD_FUNCPTR(png_get_tRNS);
+ LOAD_FUNCPTR(png_read_end);
+ LOAD_FUNCPTR(png_read_image);
LOAD_FUNCPTR(png_read_info);
LOAD_FUNCPTR(png_set_bgr);
LOAD_FUNCPTR(png_set_crc_action);
@@ -130,6 +134,8 @@ struct png_decoder
{
struct decoder decoder;
struct decoder_frame decoder_frame;
+ UINT stride;
+ BYTE *image_bits;
};
static inline struct png_decoder *impl_from_decoder(struct decoder* iface)
@@ -185,6 +191,8 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
png_colorp png_palette;
int num_palette;
int i;
+ UINT image_size;
+ png_bytep *row_pointers=NULL;
png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
@@ -385,6 +393,33 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
This->decoder_frame.num_colors = 0;
}
+ This->stride = (This->decoder_frame.width * This->decoder_frame.bpp + 7) / 8;
+ image_size = This->stride * This->decoder_frame.height;
+
+ This->image_bits = malloc(image_size);
+ if (!This->image_bits)
+ {
+ hr = E_OUTOFMEMORY;
+ goto end;
+ }
+
+ row_pointers = malloc(sizeof(png_bytep)*This->decoder_frame.height);
+ if (!row_pointers)
+ {
+ hr = E_OUTOFMEMORY;
+ goto end;
+ }
+
+ for (i=0; i<This->decoder_frame.height; i++)
+ row_pointers[i] = This->image_bits + i * This->stride;
+
+ ppng_read_image(png_ptr, row_pointers);
+
+ free(row_pointers);
+ row_pointers = NULL;
+
+ ppng_read_end(png_ptr, end_info);
+
st->flags = WICBitmapDecoderCapabilityCanDecodeAllImages |
WICBitmapDecoderCapabilityCanDecodeSomeImages |
WICBitmapDecoderCapabilityCanEnumerateMetadata;
@@ -394,6 +429,12 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
end:
ppng_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ free(row_pointers);
+ if (FAILED(hr))
+ {
+ free(This->image_bits);
+ This->image_bits = NULL;
+ }
return hr;
}
@@ -404,16 +445,28 @@ HRESULT CDECL png_decoder_get_frame_info(struct decoder *iface, UINT frame, stru
return S_OK;
}
+HRESULT CDECL png_decoder_copy_pixels(struct decoder *iface, UINT frame,
+ const WICRect *prc, UINT stride, UINT buffersize, BYTE *buffer)
+{
+ struct png_decoder *This = impl_from_decoder(iface);
+
+ return copy_pixels(This->decoder_frame.bpp, This->image_bits,
+ This->decoder_frame.width, This->decoder_frame.height, This->stride,
+ prc, stride, buffersize, buffer);
+}
+
void CDECL png_decoder_destroy(struct decoder* iface)
{
struct png_decoder *This = impl_from_decoder(iface);
+ free(This->image_bits);
RtlFreeHeap(GetProcessHeap(), 0, This);
}
static const struct decoder_funcs png_decoder_vtable = {
png_decoder_initialize,
png_decoder_get_frame_info,
+ png_decoder_copy_pixels,
png_decoder_destroy
};
@@ -435,6 +488,7 @@ HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **res
}
This->decoder.vtable = &png_decoder_vtable;
+ This->image_bits = NULL;
*result = &This->decoder;
info->container_format = GUID_ContainerFormatPng;
diff --git a/dlls/windowscodecs/main.c b/dlls/windowscodecs/main.c
index 2d8b0336f3f..982c8ddfada 100644
--- a/dlls/windowscodecs/main.c
+++ b/dlls/windowscodecs/main.c
@@ -60,71 +60,6 @@ HRESULT WINAPI DllCanUnloadNow(void)
return S_FALSE;
}
-HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer,
- UINT srcwidth, UINT srcheight, INT srcstride,
- const WICRect *rc, UINT dststride, UINT dstbuffersize, BYTE *dstbuffer)
-{
- UINT bytesperrow;
- UINT row_offset; /* number of bits into the source rows where the data starts */
- WICRect rect;
-
- if (!rc)
- {
- rect.X = 0;
- rect.Y = 0;
- rect.Width = srcwidth;
- rect.Height = srcheight;
- rc = ▭
- }
- else
- {
- if (rc->X < 0 || rc->Y < 0 || rc->X+rc->Width > srcwidth || rc->Y+rc->Height > srcheight)
- return E_INVALIDARG;
- }
-
- bytesperrow = ((bpp * rc->Width)+7)/8;
-
- if (dststride < bytesperrow)
- return E_INVALIDARG;
-
- if ((dststride * (rc->Height-1)) + bytesperrow > dstbuffersize)
- return E_INVALIDARG;
-
- /* if the whole bitmap is copied and the buffer format matches then it's a matter of a single memcpy */
- if (rc->X == 0 && rc->Y == 0 && rc->Width == srcwidth && rc->Height == srcheight &&
- srcstride == dststride && srcstride == bytesperrow)
- {
- memcpy(dstbuffer, srcbuffer, srcstride * srcheight);
- return S_OK;
- }
-
- row_offset = rc->X * bpp;
-
- if (row_offset % 8 == 0)
- {
- /* everything lines up on a byte boundary */
- INT row;
- const BYTE *src;
- BYTE *dst;
-
- src = srcbuffer + (row_offset / 8) + srcstride * rc->Y;
- dst = dstbuffer;
- for (row=0; row < rc->Height; row++)
- {
- memcpy(dst, src, bytesperrow);
- src += srcstride;
- dst += dststride;
- }
- return S_OK;
- }
- else
- {
- /* we have to do a weird bitwise copy. eww. */
- FIXME("cannot reliably copy bitmap data if bpp < 8\n");
- return E_FAIL;
- }
-}
-
HRESULT configure_write_source(IWICBitmapFrameEncode *iface,
IWICBitmapSource *source, const WICRect *prc,
const WICPixelFormatGUID *format,
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index d10afcedbc3..834cc81d306 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -1051,8 +1051,7 @@ static HRESULT WINAPI PngDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface,
PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
- return copy_pixels(This->bpp, This->image_bits,
- This->width, This->height, This->stride,
+ return decoder_copy_pixels(This->png_decoder, 0,
prc, cbStride, cbBufferSize, pbBuffer);
}
diff --git a/dlls/windowscodecs/unix_iface.c b/dlls/windowscodecs/unix_iface.c
index cf66fbd964d..46bcacff941 100644
--- a/dlls/windowscodecs/unix_iface.c
+++ b/dlls/windowscodecs/unix_iface.c
@@ -78,6 +78,13 @@ HRESULT CDECL decoder_wrapper_get_frame_info(struct decoder* iface, UINT frame,
return unix_funcs->decoder_get_frame_info(This->unix_decoder, frame, info);
}
+HRESULT CDECL decoder_wrapper_copy_pixels(struct decoder* iface, UINT frame,
+ const WICRect *prc, UINT stride, UINT buffersize, BYTE *buffer)
+{
+ struct decoder_wrapper* This = impl_from_decoder(iface);
+ return unix_funcs->decoder_copy_pixels(This->unix_decoder, frame, prc, stride, buffersize, buffer);
+}
+
void CDECL decoder_wrapper_destroy(struct decoder* iface)
{
struct decoder_wrapper* This = impl_from_decoder(iface);
@@ -88,6 +95,7 @@ void CDECL decoder_wrapper_destroy(struct decoder* iface)
static const struct decoder_funcs decoder_wrapper_vtable = {
decoder_wrapper_initialize,
decoder_wrapper_get_frame_info,
+ decoder_wrapper_copy_pixels,
decoder_wrapper_destroy
};
diff --git a/dlls/windowscodecs/unix_lib.c b/dlls/windowscodecs/unix_lib.c
index 111a82dc637..5ab1cb342e6 100644
--- a/dlls/windowscodecs/unix_lib.c
+++ b/dlls/windowscodecs/unix_lib.c
@@ -41,6 +41,8 @@
#include "wine/debug.h"
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
#include "wincodecs_common.h"
static const struct win32_funcs *win32_funcs;
@@ -67,6 +69,7 @@ static const struct unix_funcs unix_funcs = {
decoder_create,
decoder_initialize,
decoder_get_frame_info,
+ decoder_copy_pixels,
decoder_destroy
};
diff --git a/dlls/windowscodecs/wincodecs_common.h b/dlls/windowscodecs/wincodecs_common.h
index ac8ae015c76..f116fb6fd8f 100644
--- a/dlls/windowscodecs/wincodecs_common.h
+++ b/dlls/windowscodecs/wincodecs_common.h
@@ -26,8 +26,79 @@ HRESULT CDECL decoder_get_frame_info(struct decoder *decoder, UINT frame, struct
return decoder->vtable->get_frame_info(decoder, frame, info);
}
+HRESULT CDECL decoder_copy_pixels(struct decoder *decoder, UINT frame,
+ const WICRect *prc, UINT stride, UINT buffersize, BYTE *buffer)
+{
+ return decoder->vtable->copy_pixels(decoder, frame, prc, stride, buffersize, buffer);
+}
+
void CDECL decoder_destroy(struct decoder *decoder)
{
decoder->vtable->destroy(decoder);
}
+HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer,
+ UINT srcwidth, UINT srcheight, INT srcstride,
+ const WICRect *rc, UINT dststride, UINT dstbuffersize, BYTE *dstbuffer)
+{
+ UINT bytesperrow;
+ UINT row_offset; /* number of bits into the source rows where the data starts */
+ WICRect rect;
+
+ if (!rc)
+ {
+ rect.X = 0;
+ rect.Y = 0;
+ rect.Width = srcwidth;
+ rect.Height = srcheight;
+ rc = ▭
+ }
+ else
+ {
+ if (rc->X < 0 || rc->Y < 0 || rc->X+rc->Width > srcwidth || rc->Y+rc->Height > srcheight)
+ return E_INVALIDARG;
+ }
+
+ bytesperrow = ((bpp * rc->Width)+7)/8;
+
+ if (dststride < bytesperrow)
+ return E_INVALIDARG;
+
+ if ((dststride * (rc->Height-1)) + bytesperrow > dstbuffersize)
+ return E_INVALIDARG;
+
+ /* if the whole bitmap is copied and the buffer format matches then it's a matter of a single memcpy */
+ if (rc->X == 0 && rc->Y == 0 && rc->Width == srcwidth && rc->Height == srcheight &&
+ srcstride == dststride && srcstride == bytesperrow)
+ {
+ memcpy(dstbuffer, srcbuffer, srcstride * srcheight);
+ return S_OK;
+ }
+
+ row_offset = rc->X * bpp;
+
+ if (row_offset % 8 == 0)
+ {
+ /* everything lines up on a byte boundary */
+ INT row;
+ const BYTE *src;
+ BYTE *dst;
+
+ src = srcbuffer + (row_offset / 8) + srcstride * rc->Y;
+ dst = dstbuffer;
+ for (row=0; row < rc->Height; row++)
+ {
+ memcpy(dst, src, bytesperrow);
+ src += srcstride;
+ dst += dststride;
+ }
+ return S_OK;
+ }
+ else
+ {
+ /* we have to do a weird bitwise copy. eww. */
+ FIXME("cannot reliably copy bitmap data if bpp < 8\n");
+ return E_FAIL;
+ }
+}
+
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index 6d12b98bfc4..24cae3652f4 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -286,6 +286,8 @@ struct decoder_funcs
{
HRESULT (CDECL *initialize)(struct decoder* This, IStream *stream, struct decoder_stat *st);
HRESULT (CDECL *get_frame_info)(struct decoder* This, UINT frame, struct decoder_frame *info);
+ HRESULT (CDECL *copy_pixels)(struct decoder* This, UINT frame, const WICRect *prc,
+ UINT stride, UINT buffersize, BYTE *buffer);
void (CDECL *destroy)(struct decoder* This);
};
@@ -301,6 +303,8 @@ struct win32_funcs
HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
HRESULT CDECL decoder_initialize(struct decoder *This, IStream *stream, struct decoder_stat *st);
HRESULT CDECL decoder_get_frame_info(struct decoder* This, UINT frame, struct decoder_frame *info);
+HRESULT CDECL decoder_copy_pixels(struct decoder* This, UINT frame, const WICRect *prc,
+ UINT stride, UINT buffersize, BYTE *buffer);
void CDECL decoder_destroy(struct decoder *This);
HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result);
@@ -310,6 +314,8 @@ struct unix_funcs
HRESULT (CDECL *decoder_create)(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
HRESULT (CDECL *decoder_initialize)(struct decoder *This, IStream *stream, struct decoder_stat *st);
HRESULT (CDECL *decoder_get_frame_info)(struct decoder* This, UINT frame, struct decoder_frame *info);
+ HRESULT (CDECL *decoder_copy_pixels)(struct decoder* This, UINT frame, const WICRect *prc,
+ UINT stride, UINT buffersize, BYTE *buffer);
void (CDECL *decoder_destroy)(struct decoder* This);
};
--
2.17.1
1
0
09 Oct '20
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
dlls/windowscodecs/libpng.c | 201 +++++++++++++++++++++++++
dlls/windowscodecs/pngformat.c | 96 ++----------
dlls/windowscodecs/unix_iface.c | 7 +
dlls/windowscodecs/unix_lib.c | 1 +
dlls/windowscodecs/wincodecs_common.h | 5 +
dlls/windowscodecs/wincodecs_private.h | 13 ++
6 files changed, 238 insertions(+), 85 deletions(-)
diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c
index f41ef765f9b..bed7ea72d65 100644
--- a/dlls/windowscodecs/libpng.c
+++ b/dlls/windowscodecs/libpng.c
@@ -1,4 +1,5 @@
/*
+ * Copyright 2016 Dmitry Timoshkov
* Copyright 2020 Esme Povirk
*
* This library is free software; you can redistribute it and/or
@@ -50,12 +51,23 @@ MAKE_FUNCPTR(png_create_info_struct);
MAKE_FUNCPTR(png_create_read_struct);
MAKE_FUNCPTR(png_destroy_read_struct);
MAKE_FUNCPTR(png_error);
+MAKE_FUNCPTR(png_get_bit_depth);
+MAKE_FUNCPTR(png_get_color_type);
MAKE_FUNCPTR(png_get_error_ptr);
+MAKE_FUNCPTR(png_get_image_height);
+MAKE_FUNCPTR(png_get_image_width);
MAKE_FUNCPTR(png_get_io_ptr);
+MAKE_FUNCPTR(png_get_pHYs);
+MAKE_FUNCPTR(png_get_PLTE);
+MAKE_FUNCPTR(png_get_tRNS);
MAKE_FUNCPTR(png_read_info);
+MAKE_FUNCPTR(png_set_bgr);
MAKE_FUNCPTR(png_set_crc_action);
MAKE_FUNCPTR(png_set_error_fn);
+MAKE_FUNCPTR(png_set_gray_to_rgb);
MAKE_FUNCPTR(png_set_read_fn);
+MAKE_FUNCPTR(png_set_swap);
+MAKE_FUNCPTR(png_set_tRNS_to_alpha);
#undef MAKE_FUNCPTR
static CRITICAL_SECTION init_png_cs;
@@ -86,12 +98,23 @@ static void *load_libpng(void)
LOAD_FUNCPTR(png_create_read_struct);
LOAD_FUNCPTR(png_destroy_read_struct);
LOAD_FUNCPTR(png_error);
+ LOAD_FUNCPTR(png_get_bit_depth);
+ LOAD_FUNCPTR(png_get_color_type);
LOAD_FUNCPTR(png_get_error_ptr);
+ LOAD_FUNCPTR(png_get_image_height);
+ LOAD_FUNCPTR(png_get_image_width);
LOAD_FUNCPTR(png_get_io_ptr);
+ LOAD_FUNCPTR(png_get_pHYs);
+ LOAD_FUNCPTR(png_get_PLTE);
+ LOAD_FUNCPTR(png_get_tRNS);
LOAD_FUNCPTR(png_read_info);
+ LOAD_FUNCPTR(png_set_bgr);
LOAD_FUNCPTR(png_set_crc_action);
LOAD_FUNCPTR(png_set_error_fn);
+ LOAD_FUNCPTR(png_set_gray_to_rgb);
LOAD_FUNCPTR(png_set_read_fn);
+ LOAD_FUNCPTR(png_set_swap);
+ LOAD_FUNCPTR(png_set_tRNS_to_alpha);
#undef LOAD_FUNCPTR
}
@@ -106,6 +129,7 @@ static void *load_libpng(void)
struct png_decoder
{
struct decoder decoder;
+ struct decoder_frame decoder_frame;
};
static inline struct png_decoder *impl_from_decoder(struct decoder* iface)
@@ -145,11 +169,22 @@ static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t lengt
HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, struct decoder_stat *st)
{
+ struct png_decoder *This = impl_from_decoder(iface);
png_structp png_ptr;
png_infop info_ptr;
png_infop end_info;
jmp_buf jmpbuf;
HRESULT hr = E_FAIL;
+ int color_type, bit_depth;
+ png_bytep trans;
+ int num_trans;
+ png_uint_32 transparency;
+ png_color_16p trans_values;
+ png_uint_32 ret, xres, yres;
+ int unit_type;
+ png_colorp png_palette;
+ int num_palette;
+ int i;
png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
@@ -193,10 +228,168 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
/* read the header */
ppng_read_info(png_ptr, info_ptr);
+ /* choose a pixel format */
+ color_type = ppng_get_color_type(png_ptr, info_ptr);
+ bit_depth = ppng_get_bit_depth(png_ptr, info_ptr);
+
+ /* PNGs with bit-depth greater than 8 are network byte order. Windows does not expect this. */
+ if (bit_depth > 8)
+ ppng_set_swap(png_ptr);
+
+ /* check for color-keyed alpha */
+ transparency = ppng_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values);
+ if (!transparency)
+ num_trans = 0;
+
+ if (transparency && (color_type == PNG_COLOR_TYPE_RGB ||
+ (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 16)))
+ {
+ /* expand to RGBA */
+ if (color_type == PNG_COLOR_TYPE_GRAY)
+ ppng_set_gray_to_rgb(png_ptr);
+ ppng_set_tRNS_to_alpha(png_ptr);
+ color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ }
+
+ switch (color_type)
+ {
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ /* WIC does not support grayscale alpha formats so use RGBA */
+ ppng_set_gray_to_rgb(png_ptr);
+ /* fall through */
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ This->decoder_frame.bpp = bit_depth * 4;
+ switch (bit_depth)
+ {
+ case 8:
+ ppng_set_bgr(png_ptr);
+ This->decoder_frame.pixel_format = GUID_WICPixelFormat32bppBGRA;
+ break;
+ case 16: This->decoder_frame.pixel_format = GUID_WICPixelFormat64bppRGBA; break;
+ default:
+ ERR("invalid RGBA bit depth: %i\n", bit_depth);
+ hr = E_FAIL;
+ goto end;
+ }
+ break;
+ case PNG_COLOR_TYPE_GRAY:
+ This->decoder_frame.bpp = bit_depth;
+ if (!transparency)
+ {
+ switch (bit_depth)
+ {
+ case 1: This->decoder_frame.pixel_format = GUID_WICPixelFormatBlackWhite; break;
+ case 2: This->decoder_frame.pixel_format = GUID_WICPixelFormat2bppGray; break;
+ case 4: This->decoder_frame.pixel_format = GUID_WICPixelFormat4bppGray; break;
+ case 8: This->decoder_frame.pixel_format = GUID_WICPixelFormat8bppGray; break;
+ case 16: This->decoder_frame.pixel_format = GUID_WICPixelFormat16bppGray; break;
+ default:
+ ERR("invalid grayscale bit depth: %i\n", bit_depth);
+ hr = E_FAIL;
+ goto end;
+ }
+ break;
+ }
+ /* else fall through */
+ case PNG_COLOR_TYPE_PALETTE:
+ This->decoder_frame.bpp = bit_depth;
+ switch (bit_depth)
+ {
+ case 1: This->decoder_frame.pixel_format = GUID_WICPixelFormat1bppIndexed; break;
+ case 2: This->decoder_frame.pixel_format = GUID_WICPixelFormat2bppIndexed; break;
+ case 4: This->decoder_frame.pixel_format = GUID_WICPixelFormat4bppIndexed; break;
+ case 8: This->decoder_frame.pixel_format = GUID_WICPixelFormat8bppIndexed; break;
+ default:
+ ERR("invalid indexed color bit depth: %i\n", bit_depth);
+ hr = E_FAIL;
+ goto end;
+ }
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ This->decoder_frame.bpp = bit_depth * 3;
+ switch (bit_depth)
+ {
+ case 8:
+ ppng_set_bgr(png_ptr);
+ This->decoder_frame.pixel_format = GUID_WICPixelFormat24bppBGR;
+ break;
+ case 16: This->decoder_frame.pixel_format = GUID_WICPixelFormat48bppRGB; break;
+ default:
+ ERR("invalid RGB color bit depth: %i\n", bit_depth);
+ hr = E_FAIL;
+ goto end;
+ }
+ break;
+ default:
+ ERR("invalid color type %i\n", color_type);
+ hr = E_FAIL;
+ goto end;
+ }
+
+ This->decoder_frame.width = ppng_get_image_width(png_ptr, info_ptr);
+ This->decoder_frame.height = ppng_get_image_height(png_ptr, info_ptr);
+
+ ret = ppng_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type);
+
+ if (ret && unit_type == PNG_RESOLUTION_METER)
+ {
+ This->decoder_frame.dpix = xres * 0.0254;
+ This->decoder_frame.dpiy = yres * 0.0254;
+ }
+ else
+ {
+ WARN("no pHYs block present\n");
+ This->decoder_frame.dpix = This->decoder_frame.dpiy = 96.0;
+ }
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ ret = ppng_get_PLTE(png_ptr, info_ptr, &png_palette, &num_palette);
+ if (!ret)
+ {
+ ERR("paletted image with no PLTE chunk\n");
+ hr = E_FAIL;
+ goto end;
+ }
+
+ if (num_palette > 256)
+ {
+ ERR("palette has %i colors?!\n", num_palette);
+ hr = E_FAIL;
+ goto end;
+ }
+
+ This->decoder_frame.num_colors = num_palette;
+ for (i=0; i<num_palette; i++)
+ {
+ BYTE alpha = (i < num_trans) ? trans[i] : 0xff;
+ This->decoder_frame.palette[i] = (alpha << 24 |
+ png_palette[i].red << 16|
+ png_palette[i].green << 8|
+ png_palette[i].blue);
+ }
+ }
+ else if (color_type == PNG_COLOR_TYPE_GRAY && transparency && bit_depth <= 8) {
+ num_palette = 1 << bit_depth;
+
+ This->decoder_frame.num_colors = num_palette;
+ for (i=0; i<num_palette; i++)
+ {
+ BYTE alpha = (i == trans_values[0].gray) ? 0 : 0xff;
+ BYTE val = i * 255 / (num_palette - 1);
+ This->decoder_frame.palette[i] = (alpha << 24 | val << 16 | val << 8 | val);
+ }
+ }
+ else
+ {
+ This->decoder_frame.num_colors = 0;
+ }
+
st->flags = WICBitmapDecoderCapabilityCanDecodeAllImages |
WICBitmapDecoderCapabilityCanDecodeSomeImages |
WICBitmapDecoderCapabilityCanEnumerateMetadata;
st->frame_count = 1;
+
hr = S_OK;
end:
@@ -204,6 +397,13 @@ end:
return hr;
}
+HRESULT CDECL png_decoder_get_frame_info(struct decoder *iface, UINT frame, struct decoder_frame *info)
+{
+ struct png_decoder *This = impl_from_decoder(iface);
+ *info = This->decoder_frame;
+ return S_OK;
+}
+
void CDECL png_decoder_destroy(struct decoder* iface)
{
struct png_decoder *This = impl_from_decoder(iface);
@@ -213,6 +413,7 @@ void CDECL png_decoder_destroy(struct decoder* iface)
static const struct decoder_funcs png_decoder_vtable = {
png_decoder_initialize,
+ png_decoder_get_frame_info,
png_decoder_destroy
};
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index 5a4d94ae4f3..d10afcedbc3 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -447,6 +447,7 @@ typedef struct {
struct decoder *png_decoder;
struct decoder_info decoder_info;
struct decoder_stat file_info;
+ struct decoder_frame decoder_frame;
png_structp png_ptr;
png_infop info_ptr;
png_infop end_info;
@@ -605,6 +606,9 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
if (FAILED(hr))
goto end;
+ /* this function cannot fail in PNG decoder */
+ decoder_get_frame_info(This->png_decoder, 0, &This->decoder_frame);
+
/* initialize libpng */
This->png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!This->png_ptr)
@@ -991,8 +995,8 @@ static HRESULT WINAPI PngDecoder_Frame_GetSize(IWICBitmapFrameDecode *iface,
UINT *puiWidth, UINT *puiHeight)
{
PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- *puiWidth = This->width;
- *puiHeight = This->height;
+ *puiWidth = This->decoder_frame.width;
+ *puiHeight = This->decoder_frame.height;
TRACE("(%p)->(%u,%u)\n", iface, *puiWidth, *puiHeight);
return S_OK;
}
@@ -1003,7 +1007,7 @@ static HRESULT WINAPI PngDecoder_Frame_GetPixelFormat(IWICBitmapFrameDecode *ifa
PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
TRACE("(%p,%p)\n", iface, pPixelFormat);
- memcpy(pPixelFormat, This->format, sizeof(GUID));
+ memcpy(pPixelFormat, &This->decoder_frame.pixel_format, sizeof(GUID));
return S_OK;
}
@@ -1012,25 +1016,9 @@ static HRESULT WINAPI PngDecoder_Frame_GetResolution(IWICBitmapFrameDecode *ifac
double *pDpiX, double *pDpiY)
{
PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- png_uint_32 ret, xres, yres;
- int unit_type;
-
- EnterCriticalSection(&This->lock);
-
- ret = ppng_get_pHYs(This->png_ptr, This->info_ptr, &xres, &yres, &unit_type);
-
- if (ret && unit_type == PNG_RESOLUTION_METER)
- {
- *pDpiX = xres * 0.0254;
- *pDpiY = yres * 0.0254;
- }
- else
- {
- WARN("no pHYs block present\n");
- *pDpiX = *pDpiY = 96.0;
- }
- LeaveCriticalSection(&This->lock);
+ *pDpiX = This->decoder_frame.dpix;
+ *pDpiY = This->decoder_frame.dpiy;
TRACE("(%p)->(%0.2f,%0.2f)\n", iface, *pDpiX, *pDpiY);
@@ -1041,81 +1029,19 @@ static HRESULT WINAPI PngDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface,
IWICPalette *pIPalette)
{
PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- png_uint_32 ret, color_type, bit_depth;
- png_colorp png_palette;
- int num_palette;
- WICColor palette[256];
- png_bytep trans_alpha;
- int num_trans;
- png_color_16p trans_values;
- int i;
HRESULT hr=S_OK;
TRACE("(%p,%p)\n", iface, pIPalette);
- EnterCriticalSection(&This->lock);
-
- color_type = ppng_get_color_type(This->png_ptr, This->info_ptr);
- bit_depth = ppng_get_bit_depth(This->png_ptr, This->info_ptr);
-
- if (color_type == PNG_COLOR_TYPE_PALETTE)
+ if (This->decoder_frame.num_colors)
{
- ret = ppng_get_PLTE(This->png_ptr, This->info_ptr, &png_palette, &num_palette);
- if (!ret)
- {
- hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
- goto end;
- }
-
- if (num_palette > 256)
- {
- ERR("palette has %i colors?!\n", num_palette);
- hr = E_FAIL;
- goto end;
- }
-
- ret = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans_alpha, &num_trans, &trans_values);
- if (!ret) num_trans = 0;
-
- for (i=0; i<num_palette; i++)
- {
- BYTE alpha = (i < num_trans) ? trans_alpha[i] : 0xff;
- palette[i] = (alpha << 24 |
- png_palette[i].red << 16|
- png_palette[i].green << 8|
- png_palette[i].blue);
- }
- }
- else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth <= 8) {
- ret = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans_alpha, &num_trans, &trans_values);
-
- if (!ret)
- {
- hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
- goto end;
- }
-
- num_palette = 1 << bit_depth;
-
- for (i=0; i<num_palette; i++)
- {
- BYTE alpha = (i == trans_values[0].gray) ? 0 : 0xff;
- BYTE val = i * 255 / (num_palette - 1);
- palette[i] = (alpha << 24 | val << 16 | val << 8 | val);
- }
+ hr = IWICPalette_InitializeCustom(pIPalette, This->decoder_frame.palette, This->decoder_frame.num_colors);
}
else
{
hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
}
-end:
-
- LeaveCriticalSection(&This->lock);
-
- if (SUCCEEDED(hr))
- hr = IWICPalette_InitializeCustom(pIPalette, palette, num_palette);
-
return hr;
}
diff --git a/dlls/windowscodecs/unix_iface.c b/dlls/windowscodecs/unix_iface.c
index 924ed7f5c0d..cf66fbd964d 100644
--- a/dlls/windowscodecs/unix_iface.c
+++ b/dlls/windowscodecs/unix_iface.c
@@ -72,6 +72,12 @@ HRESULT CDECL decoder_wrapper_initialize(struct decoder* iface, IStream* stream,
return unix_funcs->decoder_initialize(This->unix_decoder, stream, st);
}
+HRESULT CDECL decoder_wrapper_get_frame_info(struct decoder* iface, UINT frame, struct decoder_frame *info)
+{
+ struct decoder_wrapper* This = impl_from_decoder(iface);
+ return unix_funcs->decoder_get_frame_info(This->unix_decoder, frame, info);
+}
+
void CDECL decoder_wrapper_destroy(struct decoder* iface)
{
struct decoder_wrapper* This = impl_from_decoder(iface);
@@ -81,6 +87,7 @@ void CDECL decoder_wrapper_destroy(struct decoder* iface)
static const struct decoder_funcs decoder_wrapper_vtable = {
decoder_wrapper_initialize,
+ decoder_wrapper_get_frame_info,
decoder_wrapper_destroy
};
diff --git a/dlls/windowscodecs/unix_lib.c b/dlls/windowscodecs/unix_lib.c
index fb4400bfe97..111a82dc637 100644
--- a/dlls/windowscodecs/unix_lib.c
+++ b/dlls/windowscodecs/unix_lib.c
@@ -66,6 +66,7 @@ HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *in
static const struct unix_funcs unix_funcs = {
decoder_create,
decoder_initialize,
+ decoder_get_frame_info,
decoder_destroy
};
diff --git a/dlls/windowscodecs/wincodecs_common.h b/dlls/windowscodecs/wincodecs_common.h
index ddc3d486dcd..ac8ae015c76 100644
--- a/dlls/windowscodecs/wincodecs_common.h
+++ b/dlls/windowscodecs/wincodecs_common.h
@@ -21,6 +21,11 @@ HRESULT CDECL decoder_initialize(struct decoder *decoder, IStream *stream, struc
return decoder->vtable->initialize(decoder, stream, st);
}
+HRESULT CDECL decoder_get_frame_info(struct decoder *decoder, UINT frame, struct decoder_frame *info)
+{
+ return decoder->vtable->get_frame_info(decoder, frame, info);
+}
+
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 110a0bd510a..6d12b98bfc4 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -267,6 +267,16 @@ struct decoder_stat
DWORD frame_count;
};
+struct decoder_frame
+{
+ CLSID pixel_format;
+ UINT width, height;
+ UINT bpp;
+ double dpix, dpiy;
+ DWORD num_colors;
+ WICColor palette[256];
+};
+
struct decoder
{
const struct decoder_funcs *vtable;
@@ -275,6 +285,7 @@ struct decoder
struct decoder_funcs
{
HRESULT (CDECL *initialize)(struct decoder* This, IStream *stream, struct decoder_stat *st);
+ HRESULT (CDECL *get_frame_info)(struct decoder* This, UINT frame, struct decoder_frame *info);
void (CDECL *destroy)(struct decoder* This);
};
@@ -289,6 +300,7 @@ struct win32_funcs
HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
HRESULT CDECL decoder_initialize(struct decoder *This, IStream *stream, struct decoder_stat *st);
+HRESULT CDECL decoder_get_frame_info(struct decoder* This, UINT frame, struct decoder_frame *info);
void CDECL decoder_destroy(struct decoder *This);
HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result);
@@ -297,6 +309,7 @@ struct unix_funcs
{
HRESULT (CDECL *decoder_create)(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
HRESULT (CDECL *decoder_initialize)(struct decoder *This, IStream *stream, struct decoder_stat *st);
+ HRESULT (CDECL *decoder_get_frame_info)(struct decoder* This, UINT frame, struct decoder_frame *info);
void (CDECL *decoder_destroy)(struct decoder* This);
};
--
2.17.1
1
0
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
dlls/windowscodecs/libpng.c | 159 ++++++++++++++++++++++++-
dlls/windowscodecs/main.c | 19 +++
dlls/windowscodecs/pngformat.c | 21 +++-
dlls/windowscodecs/unix_iface.c | 14 ++-
dlls/windowscodecs/unix_lib.c | 15 +++
dlls/windowscodecs/wincodecs_common.h | 5 +
dlls/windowscodecs/wincodecs_private.h | 20 ++++
7 files changed, 247 insertions(+), 6 deletions(-)
diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c
index 336fbb389b8..f41ef765f9b 100644
--- a/dlls/windowscodecs/libpng.c
+++ b/dlls/windowscodecs/libpng.c
@@ -42,6 +42,67 @@ WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
#ifdef SONAME_LIBPNG
+#include <png.h>
+
+static void *libpng_handle;
+#define MAKE_FUNCPTR(f) static typeof(f) * p##f
+MAKE_FUNCPTR(png_create_info_struct);
+MAKE_FUNCPTR(png_create_read_struct);
+MAKE_FUNCPTR(png_destroy_read_struct);
+MAKE_FUNCPTR(png_error);
+MAKE_FUNCPTR(png_get_error_ptr);
+MAKE_FUNCPTR(png_get_io_ptr);
+MAKE_FUNCPTR(png_read_info);
+MAKE_FUNCPTR(png_set_crc_action);
+MAKE_FUNCPTR(png_set_error_fn);
+MAKE_FUNCPTR(png_set_read_fn);
+#undef MAKE_FUNCPTR
+
+static CRITICAL_SECTION init_png_cs;
+static CRITICAL_SECTION_DEBUG init_png_cs_debug =
+{
+ 0, 0, &init_png_cs,
+ { &init_png_cs_debug.ProcessLocksList,
+ &init_png_cs_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": init_png_cs") }
+};
+static CRITICAL_SECTION init_png_cs = { &init_png_cs_debug, -1, 0, 0, 0, 0 };
+
+static void *load_libpng(void)
+{
+ void *result;
+
+ RtlEnterCriticalSection(&init_png_cs);
+
+ if(!libpng_handle && (libpng_handle = dlopen(SONAME_LIBPNG, RTLD_NOW)) != NULL) {
+
+#define LOAD_FUNCPTR(f) \
+ if((p##f = dlsym(libpng_handle, #f)) == NULL) { \
+ libpng_handle = NULL; \
+ RtlLeaveCriticalSection(&init_png_cs); \
+ return NULL; \
+ }
+ LOAD_FUNCPTR(png_create_info_struct);
+ LOAD_FUNCPTR(png_create_read_struct);
+ LOAD_FUNCPTR(png_destroy_read_struct);
+ LOAD_FUNCPTR(png_error);
+ LOAD_FUNCPTR(png_get_error_ptr);
+ LOAD_FUNCPTR(png_get_io_ptr);
+ LOAD_FUNCPTR(png_read_info);
+ LOAD_FUNCPTR(png_set_crc_action);
+ LOAD_FUNCPTR(png_set_error_fn);
+ LOAD_FUNCPTR(png_set_read_fn);
+
+#undef LOAD_FUNCPTR
+ }
+
+ result = libpng_handle;
+
+ RtlLeaveCriticalSection(&init_png_cs);
+
+ return result;
+}
+
struct png_decoder
{
struct decoder decoder;
@@ -52,6 +113,97 @@ static inline struct png_decoder *impl_from_decoder(struct decoder* iface)
return CONTAINING_RECORD(iface, struct png_decoder, decoder);
}
+static void user_error_fn(png_structp png_ptr, png_const_charp error_message)
+{
+ jmp_buf *pjmpbuf;
+
+ /* This uses setjmp/longjmp just like the default. We can't use the
+ * default because there's no way to access the jmp buffer in the png_struct
+ * that works in 1.2 and 1.4 and allows us to dynamically load libpng. */
+ WARN("PNG error: %s\n", debugstr_a(error_message));
+ pjmpbuf = ppng_get_error_ptr(png_ptr);
+ longjmp(*pjmpbuf, 1);
+}
+
+static void user_warning_fn(png_structp png_ptr, png_const_charp warning_message)
+{
+ WARN("PNG warning: %s\n", debugstr_a(warning_message));
+}
+
+static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ IStream *stream = ppng_get_io_ptr(png_ptr);
+ HRESULT hr;
+ ULONG bytesread;
+
+ hr = stream_read(stream, data, length, &bytesread);
+ if (FAILED(hr) || bytesread != length)
+ {
+ ppng_error(png_ptr, "failed reading data");
+ }
+}
+
+HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, struct decoder_stat *st)
+{
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_infop end_info;
+ jmp_buf jmpbuf;
+ HRESULT hr = E_FAIL;
+
+ png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr)
+ {
+ return E_FAIL;
+ }
+
+ info_ptr = ppng_create_info_struct(png_ptr);
+ if (!info_ptr)
+ {
+ ppng_destroy_read_struct(&png_ptr, NULL, NULL);
+ return E_FAIL;
+ }
+
+ end_info = ppng_create_info_struct(png_ptr);
+ if (!end_info)
+ {
+ ppng_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ return E_FAIL;
+ }
+
+ /* set up setjmp/longjmp error handling */
+ if (setjmp(jmpbuf))
+ {
+ hr = WINCODEC_ERR_UNKNOWNIMAGEFORMAT;
+ goto end;
+ }
+ ppng_set_error_fn(png_ptr, jmpbuf, user_error_fn, user_warning_fn);
+ ppng_set_crc_action(png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
+
+ /* seek to the start of the stream */
+ hr = stream_seek(stream, 0, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr))
+ {
+ goto end;
+ }
+
+ /* set up custom i/o handling */
+ ppng_set_read_fn(png_ptr, stream, user_read_data);
+
+ /* read the header */
+ ppng_read_info(png_ptr, info_ptr);
+
+ st->flags = WICBitmapDecoderCapabilityCanDecodeAllImages |
+ WICBitmapDecoderCapabilityCanDecodeSomeImages |
+ WICBitmapDecoderCapabilityCanEnumerateMetadata;
+ st->frame_count = 1;
+ hr = S_OK;
+
+end:
+ ppng_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ return hr;
+}
+
void CDECL png_decoder_destroy(struct decoder* iface)
{
struct png_decoder *This = impl_from_decoder(iface);
@@ -60,6 +212,7 @@ void CDECL png_decoder_destroy(struct decoder* iface)
}
static const struct decoder_funcs png_decoder_vtable = {
+ png_decoder_initialize,
png_decoder_destroy
};
@@ -67,7 +220,11 @@ HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **res
{
struct png_decoder *This;
- TRACE("\n");
+ if (!load_libpng())
+ {
+ ERR("Failed reading PNG because unable to find %s\n",SONAME_LIBPNG);
+ return E_FAIL;
+ }
This = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*This));
diff --git a/dlls/windowscodecs/main.c b/dlls/windowscodecs/main.c
index 3849e24c2a1..2d8b0336f3f 100644
--- a/dlls/windowscodecs/main.c
+++ b/dlls/windowscodecs/main.c
@@ -255,6 +255,25 @@ HRESULT write_source(IWICBitmapFrameEncode *iface,
return hr;
}
+HRESULT CDECL stream_read(IStream *stream, void *buffer, ULONG read, ULONG *bytes_read)
+{
+ return IStream_Read(stream, buffer, read, bytes_read);
+}
+
+HRESULT CDECL stream_seek(IStream *stream, LONGLONG ofs, DWORD origin, ULONGLONG *new_position)
+{
+ HRESULT hr;
+ LARGE_INTEGER ofs_large;
+ ULARGE_INTEGER pos_large;
+
+ ofs_large.QuadPart = ofs;
+ hr = IStream_Seek(stream, ofs_large, origin, &pos_large);
+ if (new_position)
+ *new_position = pos_large.QuadPart;
+
+ return hr;
+}
+
void reverse_bgr8(UINT bytesperpixel, LPBYTE bits, UINT width, UINT height, INT stride)
{
UINT x, y;
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index 3b326c1266f..5a4d94ae4f3 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -446,6 +446,7 @@ typedef struct {
IStream *stream;
struct decoder *png_decoder;
struct decoder_info decoder_info;
+ struct decoder_stat file_info;
png_structp png_ptr;
png_infop info_ptr;
png_infop end_info;
@@ -543,6 +544,7 @@ static ULONG WINAPI PngDecoder_Release(IWICBitmapDecoder *iface)
static HRESULT WINAPI PngDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *stream,
DWORD *capability)
{
+ PngDecoder *This = impl_from_IWICBitmapDecoder(iface);
HRESULT hr;
TRACE("(%p,%p,%p)\n", iface, stream, capability);
@@ -552,9 +554,7 @@ static HRESULT WINAPI PngDecoder_QueryCapability(IWICBitmapDecoder *iface, IStre
hr = IWICBitmapDecoder_Initialize(iface, stream, WICDecodeMetadataCacheOnDemand);
if (hr != S_OK) return hr;
- *capability = WICBitmapDecoderCapabilityCanDecodeAllImages |
- WICBitmapDecoderCapabilityCanDecodeSomeImages;
- /* FIXME: WICBitmapDecoderCapabilityCanEnumerateMetadata */
+ *capability = (This->file_info.flags & DECODER_FLAGS_CAPABILITY_MASK);
return S_OK;
}
@@ -595,6 +595,16 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
EnterCriticalSection(&This->lock);
+ if (This->initialized)
+ {
+ hr = WINCODEC_ERR_WRONGSTATE;
+ goto end;
+ }
+
+ hr = decoder_initialize(This->png_decoder, pIStream, &This->file_info);
+ if (FAILED(hr))
+ goto end;
+
/* initialize libpng */
This->png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!This->png_ptr)
@@ -896,9 +906,12 @@ static HRESULT WINAPI PngDecoder_GetThumbnail(IWICBitmapDecoder *iface,
static HRESULT WINAPI PngDecoder_GetFrameCount(IWICBitmapDecoder *iface,
UINT *pCount)
{
+ PngDecoder *This = impl_from_IWICBitmapDecoder(iface);
if (!pCount) return E_INVALIDARG;
- *pCount = 1;
+ if (!This->initialized) return WINCODEC_ERR_WRONGSTATE;
+
+ *pCount = This->file_info.frame_count;
return S_OK;
}
diff --git a/dlls/windowscodecs/unix_iface.c b/dlls/windowscodecs/unix_iface.c
index cae64a6774c..924ed7f5c0d 100644
--- a/dlls/windowscodecs/unix_iface.c
+++ b/dlls/windowscodecs/unix_iface.c
@@ -39,9 +39,14 @@ static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
static const struct unix_funcs *unix_funcs;
+static const struct win32_funcs win32_funcs = {
+ stream_read,
+ stream_seek
+};
+
static BOOL WINAPI load_unixlib( INIT_ONCE *once, void *param, void **context )
{
- __wine_init_unix_lib( windowscodecs_module, DLL_PROCESS_ATTACH, NULL, &unix_funcs );
+ __wine_init_unix_lib( windowscodecs_module, DLL_PROCESS_ATTACH, &win32_funcs, &unix_funcs );
return TRUE;
}
@@ -61,6 +66,12 @@ static inline struct decoder_wrapper *impl_from_decoder(struct decoder* iface)
return CONTAINING_RECORD(iface, struct decoder_wrapper, win32_decoder);
}
+HRESULT CDECL decoder_wrapper_initialize(struct decoder* iface, IStream* stream, struct decoder_stat *st)
+{
+ struct decoder_wrapper* This = impl_from_decoder(iface);
+ return unix_funcs->decoder_initialize(This->unix_decoder, stream, st);
+}
+
void CDECL decoder_wrapper_destroy(struct decoder* iface)
{
struct decoder_wrapper* This = impl_from_decoder(iface);
@@ -69,6 +80,7 @@ void CDECL decoder_wrapper_destroy(struct decoder* iface)
}
static const struct decoder_funcs decoder_wrapper_vtable = {
+ decoder_wrapper_initialize,
decoder_wrapper_destroy
};
diff --git a/dlls/windowscodecs/unix_lib.c b/dlls/windowscodecs/unix_lib.c
index 80321d5b745..fb4400bfe97 100644
--- a/dlls/windowscodecs/unix_lib.c
+++ b/dlls/windowscodecs/unix_lib.c
@@ -43,6 +43,18 @@
#include "wincodecs_common.h"
+static const struct win32_funcs *win32_funcs;
+
+HRESULT CDECL stream_read(IStream *stream, void *buffer, ULONG read, ULONG *bytes_read)
+{
+ return win32_funcs->stream_read(stream, buffer, read, bytes_read);
+}
+
+HRESULT CDECL stream_seek(IStream *stream, LONGLONG ofs, DWORD origin, ULONGLONG *new_position)
+{
+ return win32_funcs->stream_seek(stream, ofs, origin, new_position);
+}
+
HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result)
{
if (IsEqualGUID(decoder_clsid, &CLSID_WICPngDecoder))
@@ -53,6 +65,7 @@ HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *in
static const struct unix_funcs unix_funcs = {
decoder_create,
+ decoder_initialize,
decoder_destroy
};
@@ -60,6 +73,8 @@ NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *p
{
if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS;
+ win32_funcs = ptr_in;
+
*(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
index 4592a7ee15b..ddc3d486dcd 100644
--- a/dlls/windowscodecs/wincodecs_common.h
+++ b/dlls/windowscodecs/wincodecs_common.h
@@ -16,6 +16,11 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+HRESULT CDECL decoder_initialize(struct decoder *decoder, IStream *stream, struct decoder_stat *st)
+{
+ return decoder->vtable->initialize(decoder, stream, st);
+}
+
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 0085639b2e1..110a0bd510a 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -259,6 +259,14 @@ struct decoder_info
CLSID clsid;
};
+#define DECODER_FLAGS_CAPABILITY_MASK 0x1f
+
+struct decoder_stat
+{
+ DWORD flags;
+ DWORD frame_count;
+};
+
struct decoder
{
const struct decoder_funcs *vtable;
@@ -266,10 +274,21 @@ struct decoder
struct decoder_funcs
{
+ HRESULT (CDECL *initialize)(struct decoder* This, IStream *stream, struct decoder_stat *st);
void (CDECL *destroy)(struct decoder* This);
};
+HRESULT CDECL stream_read(IStream *stream, void *buffer, ULONG read, ULONG *bytes_read);
+HRESULT CDECL stream_seek(IStream *stream, LONGLONG ofs, DWORD origin, ULONGLONG *new_position);
+
+struct win32_funcs
+{
+ HRESULT (CDECL *stream_read)(IStream *stream, void *buffer, ULONG read, ULONG *bytes_read);
+ HRESULT (CDECL *stream_seek)(IStream *stream, LONGLONG ofs, DWORD origin, ULONGLONG *new_position);
+};
+
HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
+HRESULT CDECL decoder_initialize(struct decoder *This, IStream *stream, struct decoder_stat *st);
void CDECL decoder_destroy(struct decoder *This);
HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result);
@@ -277,6 +296,7 @@ HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **res
struct unix_funcs
{
HRESULT (CDECL *decoder_create)(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
+ HRESULT (CDECL *decoder_initialize)(struct decoder *This, IStream *stream, struct decoder_stat *st);
void (CDECL *decoder_destroy)(struct decoder* This);
};
--
2.17.1
1
0
[PATCH 1/8] windowscodecs: Add a unix library and start to use it for PNG.
by Esme Povirk 09 Oct '20
by Esme Povirk 09 Oct '20
09 Oct '20
Signed-off-by: Esme Povirk <esme(a)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 */
--
2.17.1
1
0
09 Oct '20
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/localui/tests/localui.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/dlls/localui/tests/localui.c b/dlls/localui/tests/localui.c
index d323dc067b3..23be8c779d1 100644
--- a/dlls/localui/tests/localui.c
+++ b/dlls/localui/tests/localui.c
@@ -43,8 +43,6 @@ static PMONITORUI pui;
static BOOL (WINAPI *pAddPortUI)(PCWSTR, HWND, PCWSTR, PWSTR *);
static BOOL (WINAPI *pConfigurePortUI)(PCWSTR, HWND, PCWSTR);
static BOOL (WINAPI *pDeletePortUI)(PCWSTR, HWND, PCWSTR);
-static const CHAR fmt_comA[] = {'C','O','M','%','u',':',0};
-static const CHAR fmt_lptA[] = {'L','P','T','%','u',':',0};
static LPBYTE pi_buffer;
static DWORD pi_numports;
@@ -304,7 +302,7 @@ START_TEST(localui)
/* "LPT1:" - "LPT9:" */
while (((lpt_present == NULL) || (lpt_absent == NULL)) && id < 9) {
id++;
- sprintf(bufferA, fmt_lptA, id);
+ sprintf(bufferA, "LPT%u:", id);
MultiByteToWideChar( CP_ACP, 0, bufferA, -1, bufferW, ARRAY_SIZE(bufferW));
pi2 = find_portinfo2(bufferW);
if (pi2 && (lpt_present == NULL)) lpt_present = pi2;
@@ -315,7 +313,7 @@ START_TEST(localui)
/* "COM1:" - "COM9:" */
while (((com_present == NULL) || (com_absent == NULL)) && id < 9) {
id++;
- sprintf(bufferA, fmt_comA, id);
+ sprintf(bufferA, "COM%u:", id);
MultiByteToWideChar( CP_ACP, 0, bufferA, -1, bufferW, ARRAY_SIZE(bufferW));
pi2 = find_portinfo2(bufferW);
if (pi2 && (com_present == NULL)) com_present = pi2;
--
2.25.4
1
0
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/wer/main.c | 6 +-----
dlls/wer/tests/main.c | 30 +++++++++++++-----------------
2 files changed, 14 insertions(+), 22 deletions(-)
diff --git a/dlls/wer/main.c b/dlls/wer/main.c
index b40aa1b7625..ad57cbdf40e 100644
--- a/dlls/wer/main.c
+++ b/dlls/wer/main.c
@@ -48,11 +48,7 @@ static CRITICAL_SECTION report_table_cs = { &report_table_cs_debug, -1, 0, 0, 0,
static struct list report_table = LIST_INIT(report_table);
-static const WCHAR regpath_exclude[] =
- {'S','o','f','t','w','a','r','e','\\',
- 'M','i','c','r','o','s','o','f','t','\\',
- 'W','i','n','d','o','w','s',' ','E','r','r','o','r',' ','R','e','p','o','r','t','i','n','g','\\',
- 'E','x','c','l','u','d','e','d','A','p','p','l','i','c','a','t','i','o','n','s',0};
+static const WCHAR regpath_exclude[] = L"Software\\Microsoft\\Windows Error Reporting\\ExcludedApplications";
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
diff --git a/dlls/wer/tests/main.c b/dlls/wer/tests/main.c
index 7fa9a8c67f5..038b29c25a9 100644
--- a/dlls/wer/tests/main.c
+++ b/dlls/wer/tests/main.c
@@ -29,11 +29,7 @@
#include "werapi.h"
#include "wine/test.h"
-
-static const WCHAR appcrash[] = {'A','P','P','C','R','A','S','H',0};
-static const WCHAR backslash[] = {'\\',0};
-static const WCHAR empty[] = {0};
-static const WCHAR winetest_wer[] = {'w','i','n','e','t','e','s','t','_','w','e','r','.','e','x','e',0};
+static const WCHAR winetest_wer[] = L"winetest_wer.exe";
/* ###### */
@@ -51,7 +47,7 @@ static void test_WerAddExcludedApplication(void)
hr = WerAddExcludedApplication(NULL, FALSE);
ok(hr == E_INVALIDARG, "got 0x%x (expected E_INVALIDARG)\n", hr);
- hr = WerAddExcludedApplication(empty, FALSE);
+ hr = WerAddExcludedApplication(L"", FALSE);
ok(hr == E_INVALIDARG, "got 0x%x (expected E_INVALIDARG)\n", hr);
hr = WerAddExcludedApplication(winetest_wer, FALSE);
@@ -74,7 +70,7 @@ static void test_WerAddExcludedApplication(void)
hr = WerRemoveExcludedApplication(buffer, FALSE);
ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
- lstrcatW(buffer, backslash);
+ lstrcatW(buffer, L"\\");
hr = WerAddExcludedApplication(buffer, FALSE);
ok(hr == E_INVALIDARG, "got 0x%x (expected E_INVALIDARG)\n", hr);
@@ -106,7 +102,7 @@ static void test_WerRemoveExcludedApplication(void)
hr = WerRemoveExcludedApplication(NULL, FALSE);
ok(hr == E_INVALIDARG, "got 0x%x (expected E_INVALIDARG)\n", hr);
- hr = WerRemoveExcludedApplication(empty, FALSE);
+ hr = WerRemoveExcludedApplication(L"", FALSE);
ok(hr == E_INVALIDARG, "got 0x%x (expected E_INVALIDARG)\n", hr);
hr = WerRemoveExcludedApplication(winetest_wer, FALSE);
@@ -130,7 +126,7 @@ static void test_WerRemoveExcludedApplication(void)
hr = WerRemoveExcludedApplication(buffer, FALSE);
ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
- lstrcatW(buffer, backslash);
+ lstrcatW(buffer, L"\\");
hr = WerAddExcludedApplication(buffer, FALSE);
ok(hr == E_INVALIDARG, "got 0x%x (expected E_INVALIDARG)\n", hr);
hr = WerRemoveExcludedApplication(buffer, FALSE);
@@ -152,7 +148,7 @@ static void test_WerReportCloseHandle(void)
HREPORT report;
report = (void *) 0xdeadbeef;
- hr = WerReportCreate(appcrash, WerReportCritical, NULL, &report);
+ hr = WerReportCreate(L"APPCRASH", WerReportCritical, NULL, &report);
ok(hr == S_OK, "got 0x%x and %p (expected S_OK)\n", hr, report);
if (!report) {
@@ -183,7 +179,7 @@ static void test_WerReportCreate(void)
report = (void *) 0xdeadbeef;
/* test a simple valid case */
- hr = WerReportCreate(appcrash, WerReportCritical, NULL, &report);
+ hr = WerReportCreate(L"APPCRASH", WerReportCritical, NULL, &report);
ok(hr == S_OK, "got 0x%x and %p (expected S_OK)\n", hr, report);
if (!report) {
@@ -195,7 +191,7 @@ static void test_WerReportCreate(void)
ok(hr == S_OK, "got 0x%x for %p (expected S_OK)\n", hr, report);
/* the ptr to store the created handle is always needed */
- hr = WerReportCreate(appcrash, WerReportCritical, NULL, NULL);
+ hr = WerReportCreate(L"APPCRASH", WerReportCritical, NULL, NULL);
ok(hr == E_INVALIDARG, "got 0x%x (expected E_INVALIDARG)\n", hr);
/* the event type must be a valid string */
@@ -204,13 +200,13 @@ static void test_WerReportCreate(void)
ok(hr == E_INVALIDARG, "got 0x%x and %p(expected E_INVALIDARG)\n", hr, report);
report = (void *) 0xdeadbeef;
- hr = WerReportCreate(empty, WerReportCritical, NULL, &report);
+ hr = WerReportCreate(L"", WerReportCritical, NULL, &report);
ok(hr == E_INVALIDARG, "got 0x%x and %p(expected E_INVALIDARG)\n", hr, report);
/* a valid WER_REPORT_TYPE works */
for (i = 0; i < WerReportInvalid; i++) {
report = (void *) 0xdeadbeef;
- hr = WerReportCreate(appcrash, i, NULL, &report);
+ hr = WerReportCreate(L"APPCRASH", i, NULL, &report);
ok(hr == S_OK, "%d: got 0x%x and %p (expected S_OK)\n", i, hr, report);
hr = WerReportCloseHandle(report);
@@ -222,7 +218,7 @@ static void test_WerReportCreate(void)
but older windows versions did not check the report type and WerReportCreate always succeeded */
report = (void *) 0xdeadbeef;
- hr = WerReportCreate(appcrash, WerReportInvalid, NULL, &report);
+ hr = WerReportCreate(L"APPCRASH", WerReportInvalid, NULL, &report);
ok((hr == E_INVALIDARG) | broken(hr == S_OK),
"%d: got 0x%x and %p (expected E_INVALIDARG or a broken S_OK)\n", i, hr, report);
if (hr == S_OK) {
@@ -231,7 +227,7 @@ static void test_WerReportCreate(void)
}
report = (void *) 0xdeadbeef;
- hr = WerReportCreate(appcrash, 42, NULL, &report);
+ hr = WerReportCreate(L"APPCRASH", 42, NULL, &report);
ok((hr == E_INVALIDARG) | broken(hr == S_OK),
"%d: got 0x%x and %p (expected E_INVALIDARG or a broken S_OK)\n", i, hr, report);
if (hr == S_OK) {
@@ -243,7 +239,7 @@ static void test_WerReportCreate(void)
memset(table, 0, sizeof(table));
for (i = 0; i < (ARRAY_SIZE(table) - 1); i++) {
report = (void *) 0xdeadbeef;
- hr = WerReportCreate(appcrash, WerReportCritical, NULL, &table[i]);
+ hr = WerReportCreate(L"APPCRASH", WerReportCritical, NULL, &table[i]);
ok(hr == S_OK, "%02d: got 0x%x and %p (expected S_OK)\n", i, hr, table[i]);
}
--
2.25.4
1
0
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/localui/localui.c | 58 ++++++++++--------------------------
dlls/localui/tests/localui.c | 19 +++++-------
2 files changed, 23 insertions(+), 54 deletions(-)
diff --git a/dlls/localui/localui.c b/dlls/localui/localui.c
index ab8f5c95d52..87522494a1d 100644
--- a/dlls/localui/localui.c
+++ b/dlls/localui/localui.c
@@ -38,32 +38,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(localui);
static HINSTANCE LOCALUI_hInstance;
-static const WCHAR cmd_AddPortW[] = {'A','d','d','P','o','r','t',0};
-static const WCHAR cmd_ConfigureLPTPortCommandOKW[] = {'C','o','n','f','i','g','u','r','e',
- 'L','P','T','P','o','r','t',
- 'C','o','m','m','a','n','d','O','K',0};
-static const WCHAR cmd_DeletePortW[] = {'D','e','l','e','t','e','P','o','r','t',0};
-static const WCHAR cmd_GetDefaultCommConfigW[] = {'G','e','t',
- 'D','e','f','a','u','l','t',
- 'C','o','m','m','C','o','n','f','i','g',0};
-static const WCHAR cmd_GetTransmissionRetryTimeoutW[] = {'G','e','t',
- 'T','r','a','n','s','m','i','s','s','i','o','n',
- 'R','e','t','r','y','T','i','m','e','o','u','t',0};
-static const WCHAR cmd_PortIsValidW[] = {'P','o','r','t','I','s','V','a','l','i','d',0};
-static const WCHAR cmd_SetDefaultCommConfigW[] = {'S','e','t',
- 'D','e','f','a','u','l','t',
- 'C','o','m','m','C','o','n','f','i','g',0};
-
-static const WCHAR fmt_uW[] = {'%','u',0};
-static const WCHAR portname_LPT[] = {'L','P','T',0};
-static const WCHAR portname_COM[] = {'C','O','M',0};
-static const WCHAR portname_FILE[] = {'F','I','L','E',':',0};
-static const WCHAR portname_CUPS[] = {'C','U','P','S',':',0};
-static const WCHAR portname_LPR[] = {'L','P','R',':',0};
-
-static const WCHAR XcvMonitorW[] = {',','X','c','v','M','o','n','i','t','o','r',' ',0};
-static const WCHAR XcvPortW[] = {',','X','c','v','P','o','r','t',' ',0};
-
/*****************************************************/
typedef struct tag_addportui_t {
@@ -121,7 +95,7 @@ static BOOL dlg_configure_com(HANDLE hXcv, HWND hWnd, PCWSTR pPortName)
/* get current settings */
len = FIELD_OFFSET(COMMCONFIG, wcProviderData[1]);
status = ERROR_SUCCESS;
- res = XcvDataW( hXcv, cmd_GetDefaultCommConfigW,
+ res = XcvDataW( hXcv, L"GetDefaultCommConfig",
(PBYTE) shortname,
(lstrlenW(shortname) +1) * sizeof(WCHAR),
(PBYTE) &cfg, len, &len, &status);
@@ -132,7 +106,7 @@ static BOOL dlg_configure_com(HANDLE hXcv, HWND hWnd, PCWSTR pPortName)
if (res) {
status = ERROR_SUCCESS;
/* set new settings */
- res = XcvDataW(hXcv, cmd_SetDefaultCommConfigW,
+ res = XcvDataW(hXcv, L"SetDefaultCommConfig",
(PBYTE) &cfg, len,
(PBYTE) &dummy, 0, &len, &status);
}
@@ -292,7 +266,7 @@ static INT_PTR CALLBACK dlgproc_addport(HWND hwnd, UINT msg, WPARAM wparam, LPAR
/* length is in WCHAR, including the '\0' */
GetDlgItemTextW(hwnd, ADDPORT_EDIT, data->portname, len + 1);
status = ERROR_SUCCESS;
- res = XcvDataW( data->hXcv, cmd_PortIsValidW, (PBYTE) data->portname,
+ res = XcvDataW( data->hXcv, L"PortIsValid", (BYTE *) data->portname,
(lstrlenW(data->portname) + 1) * sizeof(WCHAR),
(PBYTE) &dummy, 0, &len, &status);
@@ -356,7 +330,7 @@ static INT_PTR CALLBACK dlgproc_lptconfig(HWND hwnd, UINT msg, WPARAM wparam, LP
/* Get current setting */
data->value = 45;
status = ERROR_SUCCESS;
- res = XcvDataW( data->hXcv, cmd_GetTransmissionRetryTimeoutW,
+ res = XcvDataW( data->hXcv, L"GetTransmissionRetryTimeout",
(PBYTE) &dummy, 0,
(PBYTE) &data->value, sizeof(data->value), &len, &status);
@@ -379,8 +353,8 @@ static INT_PTR CALLBACK dlgproc_lptconfig(HWND hwnd, UINT msg, WPARAM wparam, LP
/* native localui.dll use the same limits */
if ((res > 0) && (res < 1000000) && status) {
- swprintf(bufferW, ARRAY_SIZE(bufferW), fmt_uW, res);
- res = XcvDataW( data->hXcv, cmd_ConfigureLPTPortCommandOKW,
+ swprintf(bufferW, ARRAY_SIZE(bufferW), L"%u", res);
+ res = XcvDataW( data->hXcv, L"ConfigureLPTPortCommandOK",
(PBYTE) bufferW,
(lstrlenW(bufferW) +1) * sizeof(WCHAR),
(PBYTE) &dummy, 0, &len, &status);
@@ -415,13 +389,13 @@ static DWORD get_type_from_name(LPCWSTR name)
{
HANDLE hfile;
- if (!wcsnicmp(name, portname_LPT, ARRAY_SIZE(portname_LPT) -1))
+ if (!wcsnicmp(name, L"LPT", ARRAY_SIZE(L"LPT") -1))
return PORT_IS_LPT;
- if (!wcsnicmp(name, portname_COM, ARRAY_SIZE(portname_COM) -1))
+ if (!wcsnicmp(name, L"COM", ARRAY_SIZE(L"COM") -1))
return PORT_IS_COM;
- if (!wcsicmp(name, portname_FILE))
+ if (!wcsicmp(name, L"FILE:"))
return PORT_IS_FILE;
if (name[0] == '/')
@@ -430,10 +404,10 @@ static DWORD get_type_from_name(LPCWSTR name)
if (name[0] == '|')
return PORT_IS_PIPE;
- if (!wcsncmp(name, portname_CUPS, ARRAY_SIZE(portname_CUPS) -1))
+ if (!wcsncmp(name, L"CUPS:", ARRAY_SIZE(L"CUPS:") -1))
return PORT_IS_CUPS;
- if (!wcsncmp(name, portname_LPR, ARRAY_SIZE(portname_LPR) -1))
+ if (!wcsncmp(name, L"LPR:", ARRAY_SIZE(L"LPR:") -1))
return PORT_IS_LPR;
/* Must be a file or a directory. Does the file exist ? */
@@ -508,7 +482,7 @@ static BOOL WINAPI localui_AddPortUI(PCWSTR pName, HWND hWnd, PCWSTR pMonitorNam
TRACE( "(%s, %p, %s, %p) (*ppPortName: %p)\n", debugstr_w(pName), hWnd,
debugstr_w(pMonitorName), ppPortName, ppPortName ? *ppPortName : NULL);
- if (open_monitor_by_name(XcvMonitorW, pMonitorName, &hXcv)) {
+ if (open_monitor_by_name(L",XcvMonitor ", pMonitorName, &hXcv)) {
ZeroMemory(&data, sizeof(addportui_t));
data.hXcv = hXcv;
@@ -520,7 +494,7 @@ static BOOL WINAPI localui_AddPortUI(PCWSTR pName, HWND hWnd, PCWSTR pMonitorNam
if (ppPortName) *ppPortName = NULL;
if (res) {
- res = XcvDataW(hXcv, cmd_AddPortW, (PBYTE) data.portname,
+ res = XcvDataW(hXcv, L"AddPort", (BYTE *) data.portname,
(lstrlenW(data.portname)+1) * sizeof(WCHAR),
(PBYTE) &dummy, 0, &needed, &status);
@@ -572,7 +546,7 @@ static BOOL WINAPI localui_ConfigurePortUI(PCWSTR pName, HWND hWnd, PCWSTR pPort
DWORD res;
TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName));
- if (open_monitor_by_name(XcvPortW, pPortName, &hXcv)) {
+ if (open_monitor_by_name(L",XcvPort ", pPortName, &hXcv)) {
res = get_type_from_name(pPortName);
switch(res)
@@ -631,10 +605,10 @@ static BOOL WINAPI localui_DeletePortUI(PCWSTR pName, HWND hWnd, PCWSTR pPortNam
return FALSE;
}
- if (open_monitor_by_name(XcvPortW, pPortName, &hXcv)) {
+ if (open_monitor_by_name(L",XcvPort ", pPortName, &hXcv)) {
/* native localui tests here for LPT / COM - Ports and failed with
ERROR_NOT_SUPPORTED. */
- if (XcvDataW(hXcv, cmd_DeletePortW, (LPBYTE) pPortName,
+ if (XcvDataW(hXcv, L"DeletePort", (BYTE *) pPortName,
(lstrlenW(pPortName)+1) * sizeof(WCHAR), (LPBYTE) &dummy, 0, &needed, &status)) {
ClosePrinter(hXcv);
diff --git a/dlls/localui/tests/localui.c b/dlls/localui/tests/localui.c
index f051880fd1c..d323dc067b3 100644
--- a/dlls/localui/tests/localui.c
+++ b/dlls/localui/tests/localui.c
@@ -43,13 +43,8 @@ static PMONITORUI pui;
static BOOL (WINAPI *pAddPortUI)(PCWSTR, HWND, PCWSTR, PWSTR *);
static BOOL (WINAPI *pConfigurePortUI)(PCWSTR, HWND, PCWSTR);
static BOOL (WINAPI *pDeletePortUI)(PCWSTR, HWND, PCWSTR);
-
-static const WCHAR does_not_existW[] = {'d','o','e','s','_','n','o','t','_','e','x','i','s','t',0};
-static const WCHAR emptyW[] = {0};
static const CHAR fmt_comA[] = {'C','O','M','%','u',':',0};
static const CHAR fmt_lptA[] = {'L','P','T','%','u',':',0};
-static const WCHAR localportW[] = {'L','o','c','a','l',' ','P','o','r','t',0};
-static const WCHAR portname_fileW[] = {'F','I','L','E',':',0};
static LPBYTE pi_buffer;
static DWORD pi_numports;
@@ -148,14 +143,14 @@ static void test_AddPortUI(void)
"ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
SetLastError(0xdeadbeef);
- res = pAddPortUI(NULL, NULL, emptyW, NULL);
+ res = pAddPortUI(NULL, NULL, L"", NULL);
ok( !res &&
((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
"got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
"ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
SetLastError(0xdeadbeef);
- res = pAddPortUI(NULL, NULL, does_not_existW, NULL);
+ res = pAddPortUI(NULL, NULL, L"does_not_exist", NULL);
ok( !res &&
((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
"got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
@@ -172,7 +167,7 @@ static void test_AddPortUI(void)
* - When the new port starts with "COM" or "LPT",
* FALSE is returned with ERROR_NOT_SUPPORTED on windows
*/
- res = pAddPortUI(NULL, NULL, localportW, &new_portname);
+ res = pAddPortUI(NULL, NULL, L"Local Port", &new_portname);
ok( res ||
(GetLastError() == ERROR_CANCELLED) ||
(GetLastError() == ERROR_ACCESS_DENIED) ||
@@ -205,7 +200,7 @@ static void test_ConfigurePortUI(void)
"ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
SetLastError(0xdeadbeef);
- res = pConfigurePortUI(NULL, NULL, emptyW);
+ res = pConfigurePortUI(NULL, NULL, L"");
ok( !res &&
((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
"got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
@@ -213,7 +208,7 @@ static void test_ConfigurePortUI(void)
SetLastError(0xdeadbeef);
- res = pConfigurePortUI(NULL, NULL, does_not_existW);
+ res = pConfigurePortUI(NULL, NULL, L"does_not_exist");
ok( !res &&
((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
"got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
@@ -258,7 +253,7 @@ static void test_ConfigurePortUI(void)
if (winetest_interactive && file_present) {
SetLastError(0xdeadbeef);
- res = pConfigurePortUI(NULL, NULL, portname_fileW);
+ res = pConfigurePortUI(NULL, NULL, L"FILE:");
ok( !res &&
((GetLastError() == ERROR_CANCELLED) || (GetLastError() == ERROR_ACCESS_DENIED)),
"got %d with %u (expected '0' with: ERROR_CANCELLED or "
@@ -300,7 +295,7 @@ START_TEST(localui)
/* find installed ports */
/* "FILE:" */
- file_present = find_portinfo2(portname_fileW);
+ file_present = find_portinfo2(L"FILE:");
if (!pi_numports) /* Nothing to test without a port */
return;
--
2.25.4
1
0