-- v4: windowscodecs: Handle PNG histogram (hIST) chunk type.
From: Jeff Smith whydoubt@gmail.com
--- dlls/windowscodecs/gifformat.c | 87 +++++++++++++--------------- dlls/windowscodecs/metadatahandler.c | 46 +++++++-------- dlls/windowscodecs/pngformat.c | 20 +++---- 3 files changed, 72 insertions(+), 81 deletions(-)
diff --git a/dlls/windowscodecs/gifformat.c b/dlls/windowscodecs/gifformat.c index 152c51eac76..0b05d47e5e2 100644 --- a/dlls/windowscodecs/gifformat.c +++ b/dlls/windowscodecs/gifformat.c @@ -25,6 +25,7 @@ #include "windef.h" #include "winbase.h" #include "objbase.h" +#include "shlwapi.h"
#include "ungif.h"
@@ -68,14 +69,6 @@ struct image_descriptor
#include "poppack.h"
-static LPWSTR strdupAtoW(const char *src) -{ - int len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0); - LPWSTR dst = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - if (dst) MultiByteToWideChar(CP_ACP, 0, src, -1, dst, len); - return dst; -} - static HRESULT load_LSD_metadata(IStream *stream, const GUID *vendor, DWORD options, MetadataItem **items, DWORD *count) { @@ -101,49 +94,49 @@ static HRESULT load_LSD_metadata(IStream *stream, const GUID *vendor, DWORD opti }
result[0].id.vt = VT_LPWSTR; - result[0].id.pwszVal = strdupAtoW("Signature"); + SHStrDupW(L"Signature", &result[0].id.pwszVal); result[0].value.vt = VT_UI1|VT_VECTOR; result[0].value.caub.cElems = sizeof(lsd_data.signature); - result[0].value.caub.pElems = HeapAlloc(GetProcessHeap(), 0, sizeof(lsd_data.signature)); + result[0].value.caub.pElems = CoTaskMemAlloc(sizeof(lsd_data.signature)); memcpy(result[0].value.caub.pElems, lsd_data.signature, sizeof(lsd_data.signature));
result[1].id.vt = VT_LPWSTR; - result[1].id.pwszVal = strdupAtoW("Width"); + SHStrDupW(L"Width", &result[1].id.pwszVal); result[1].value.vt = VT_UI2; result[1].value.uiVal = lsd_data.width;
result[2].id.vt = VT_LPWSTR; - result[2].id.pwszVal = strdupAtoW("Height"); + SHStrDupW(L"Height", &result[2].id.pwszVal); result[2].value.vt = VT_UI2; result[2].value.uiVal = lsd_data.height;
result[3].id.vt = VT_LPWSTR; - result[3].id.pwszVal = strdupAtoW("GlobalColorTableFlag"); + SHStrDupW(L"GlobalColorTableFlag", &result[3].id.pwszVal); result[3].value.vt = VT_BOOL; result[3].value.boolVal = (lsd_data.packed >> 7) & 1;
result[4].id.vt = VT_LPWSTR; - result[4].id.pwszVal = strdupAtoW("ColorResolution"); + SHStrDupW(L"ColorResolution", &result[4].id.pwszVal); result[4].value.vt = VT_UI1; result[4].value.bVal = (lsd_data.packed >> 4) & 7;
result[5].id.vt = VT_LPWSTR; - result[5].id.pwszVal = strdupAtoW("SortFlag"); + SHStrDupW(L"SortFlag", &result[5].id.pwszVal); result[5].value.vt = VT_BOOL; result[5].value.boolVal = (lsd_data.packed >> 3) & 1;
result[6].id.vt = VT_LPWSTR; - result[6].id.pwszVal = strdupAtoW("GlobalColorTableSize"); + SHStrDupW(L"GlobalColorTableSize", &result[6].id.pwszVal); result[6].value.vt = VT_UI1; result[6].value.bVal = lsd_data.packed & 7;
result[7].id.vt = VT_LPWSTR; - result[7].id.pwszVal = strdupAtoW("BackgroundColorIndex"); + SHStrDupW(L"BackgroundColorIndex", &result[7].id.pwszVal); result[7].value.vt = VT_UI1; result[7].value.bVal = lsd_data.background_color_index;
result[8].id.vt = VT_LPWSTR; - result[8].id.pwszVal = strdupAtoW("PixelAspectRatio"); + SHStrDupW(L"PixelAspectRatio", &result[8].id.pwszVal); result[8].value.vt = VT_UI1; result[8].value.bVal = lsd_data.pixel_aspect_ratio;
@@ -189,42 +182,42 @@ static HRESULT load_IMD_metadata(IStream *stream, const GUID *vendor, DWORD opti }
result[0].id.vt = VT_LPWSTR; - result[0].id.pwszVal = strdupAtoW("Left"); + SHStrDupW(L"Left", &result[0].id.pwszVal); result[0].value.vt = VT_UI2; result[0].value.uiVal = imd_data.left;
result[1].id.vt = VT_LPWSTR; - result[1].id.pwszVal = strdupAtoW("Top"); + SHStrDupW(L"Top", &result[1].id.pwszVal); result[1].value.vt = VT_UI2; result[1].value.uiVal = imd_data.top;
result[2].id.vt = VT_LPWSTR; - result[2].id.pwszVal = strdupAtoW("Width"); + SHStrDupW(L"Width", &result[2].id.pwszVal); result[2].value.vt = VT_UI2; result[2].value.uiVal = imd_data.width;
result[3].id.vt = VT_LPWSTR; - result[3].id.pwszVal = strdupAtoW("Height"); + SHStrDupW(L"Height", &result[3].id.pwszVal); result[3].value.vt = VT_UI2; result[3].value.uiVal = imd_data.height;
result[4].id.vt = VT_LPWSTR; - result[4].id.pwszVal = strdupAtoW("LocalColorTableFlag"); + SHStrDupW(L"LocalColorTableFlag", &result[4].id.pwszVal); result[4].value.vt = VT_BOOL; result[4].value.boolVal = (imd_data.packed >> 7) & 1;
result[5].id.vt = VT_LPWSTR; - result[5].id.pwszVal = strdupAtoW("InterlaceFlag"); + SHStrDupW(L"InterlaceFlag", &result[5].id.pwszVal); result[5].value.vt = VT_BOOL; result[5].value.boolVal = (imd_data.packed >> 6) & 1;
result[6].id.vt = VT_LPWSTR; - result[6].id.pwszVal = strdupAtoW("SortFlag"); + SHStrDupW(L"SortFlag", &result[6].id.pwszVal); result[6].value.vt = VT_BOOL; result[6].value.boolVal = (imd_data.packed >> 5) & 1;
result[7].id.vt = VT_LPWSTR; - result[7].id.pwszVal = strdupAtoW("LocalColorTableSize"); + SHStrDupW(L"LocalColorTableSize", &result[7].id.pwszVal); result[7].value.vt = VT_UI1; result[7].value.bVal = imd_data.packed & 7;
@@ -282,27 +275,27 @@ static HRESULT load_GCE_metadata(IStream *stream, const GUID *vendor, DWORD opti }
result[0].id.vt = VT_LPWSTR; - result[0].id.pwszVal = strdupAtoW("Disposal"); + SHStrDupW(L"Disposal", &result[0].id.pwszVal); result[0].value.vt = VT_UI1; result[0].value.bVal = (gce_data.packed >> 2) & 7;
result[1].id.vt = VT_LPWSTR; - result[1].id.pwszVal = strdupAtoW("UserInputFlag"); + SHStrDupW(L"UserInputFlag", &result[1].id.pwszVal); result[1].value.vt = VT_BOOL; result[1].value.boolVal = (gce_data.packed >> 1) & 1;
result[2].id.vt = VT_LPWSTR; - result[2].id.pwszVal = strdupAtoW("TransparencyFlag"); + SHStrDupW(L"TransparencyFlag", &result[2].id.pwszVal); result[2].value.vt = VT_BOOL; result[2].value.boolVal = gce_data.packed & 1;
result[3].id.vt = VT_LPWSTR; - result[3].id.pwszVal = strdupAtoW("Delay"); + SHStrDupW(L"Delay", &result[3].id.pwszVal); result[3].value.vt = VT_UI2; result[3].value.uiVal = gce_data.delay;
result[4].id.vt = VT_LPWSTR; - result[4].id.pwszVal = strdupAtoW("TransparentColorIndex"); + SHStrDupW(L"TransparentColorIndex", &result[4].id.pwszVal); result[4].value.vt = VT_UI1; result[4].value.bVal = gce_data.transparent_color_index;
@@ -359,19 +352,19 @@ static HRESULT load_APE_metadata(IStream *stream, const GUID *vendor, DWORD opti hr = IStream_Read(stream, &subblock_size, sizeof(subblock_size), &bytesread); if (FAILED(hr) || bytesread != sizeof(subblock_size)) { - HeapFree(GetProcessHeap(), 0, data); + CoTaskMemFree(data); return S_OK; } if (!subblock_size) break;
if (!data) - data = HeapAlloc(GetProcessHeap(), 0, subblock_size + 1); + data = CoTaskMemAlloc(subblock_size + 1); else { - BYTE *new_data = HeapReAlloc(GetProcessHeap(), 0, data, data_size + subblock_size + 1); + BYTE *new_data = CoTaskMemRealloc(data, data_size + subblock_size + 1); if (!new_data) { - HeapFree(GetProcessHeap(), 0, data); + CoTaskMemFree(data); return S_OK; } data = new_data; @@ -380,7 +373,7 @@ static HRESULT load_APE_metadata(IStream *stream, const GUID *vendor, DWORD opti hr = IStream_Read(stream, data + data_size + 1, subblock_size, &bytesread); if (FAILED(hr) || bytesread != subblock_size) { - HeapFree(GetProcessHeap(), 0, data); + CoTaskMemFree(data); return S_OK; } data_size += subblock_size + 1; @@ -389,7 +382,7 @@ static HRESULT load_APE_metadata(IStream *stream, const GUID *vendor, DWORD opti result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem) * 2); if (!result) { - HeapFree(GetProcessHeap(), 0, data); + CoTaskMemFree(data); return E_OUTOFMEMORY; }
@@ -401,14 +394,14 @@ static HRESULT load_APE_metadata(IStream *stream, const GUID *vendor, DWORD opti }
result[0].id.vt = VT_LPWSTR; - result[0].id.pwszVal = strdupAtoW("Application"); + SHStrDupW(L"Application", &result[0].id.pwszVal); result[0].value.vt = VT_UI1|VT_VECTOR; result[0].value.caub.cElems = sizeof(ape_data.application); - result[0].value.caub.pElems = HeapAlloc(GetProcessHeap(), 0, sizeof(ape_data.application)); + result[0].value.caub.pElems = CoTaskMemAlloc(sizeof(ape_data.application)); memcpy(result[0].value.caub.pElems, ape_data.application, sizeof(ape_data.application));
result[1].id.vt = VT_LPWSTR; - result[1].id.pwszVal = strdupAtoW("Data"); + SHStrDupW(L"Data", &result[1].id.pwszVal); result[1].value.vt = VT_UI1|VT_VECTOR; result[1].value.caub.cElems = data_size; result[1].value.caub.pElems = data; @@ -463,19 +456,19 @@ static HRESULT load_GifComment_metadata(IStream *stream, const GUID *vendor, DWO hr = IStream_Read(stream, &subblock_size, sizeof(subblock_size), &bytesread); if (FAILED(hr) || bytesread != sizeof(subblock_size)) { - HeapFree(GetProcessHeap(), 0, data); + CoTaskMemFree(data); return S_OK; } if (!subblock_size) break;
if (!data) - data = HeapAlloc(GetProcessHeap(), 0, subblock_size + 1); + data = CoTaskMemAlloc(subblock_size + 1); else { - char *new_data = HeapReAlloc(GetProcessHeap(), 0, data, data_size + subblock_size + 1); + char *new_data = CoTaskMemRealloc(data, data_size + subblock_size + 1); if (!new_data) { - HeapFree(GetProcessHeap(), 0, data); + CoTaskMemFree(data); return S_OK; } data = new_data; @@ -483,7 +476,7 @@ static HRESULT load_GifComment_metadata(IStream *stream, const GUID *vendor, DWO hr = IStream_Read(stream, data + data_size, subblock_size, &bytesread); if (FAILED(hr) || bytesread != subblock_size) { - HeapFree(GetProcessHeap(), 0, data); + CoTaskMemFree(data); return S_OK; } data_size += subblock_size; @@ -494,7 +487,7 @@ static HRESULT load_GifComment_metadata(IStream *stream, const GUID *vendor, DWO result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem)); if (!result) { - HeapFree(GetProcessHeap(), 0, data); + CoTaskMemFree(data); return E_OUTOFMEMORY; }
@@ -503,7 +496,7 @@ static HRESULT load_GifComment_metadata(IStream *stream, const GUID *vendor, DWO PropVariantInit(&result->value);
result->id.vt = VT_LPWSTR; - result->id.pwszVal = strdupAtoW("TextEntry"); + SHStrDupW(L"TextEntry", &result->id.pwszVal); result->value.vt = VT_LPSTR; result->value.pszVal = data;
diff --git a/dlls/windowscodecs/metadatahandler.c b/dlls/windowscodecs/metadatahandler.c index 5bcca0f58c6..6d519c0f3cd 100644 --- a/dlls/windowscodecs/metadatahandler.c +++ b/dlls/windowscodecs/metadatahandler.c @@ -626,21 +626,21 @@ static HRESULT LoadUnknownMetadata(IStream *input, const GUID *preferred_vendor, if (FAILED(hr)) return hr;
- data = HeapAlloc(GetProcessHeap(), 0, stat.cbSize.QuadPart); + data = CoTaskMemAlloc(stat.cbSize.QuadPart); if (!data) return E_OUTOFMEMORY;
hr = IStream_Read(input, data, stat.cbSize.QuadPart, &bytesread); if (bytesread != stat.cbSize.QuadPart) hr = E_FAIL; if (hr != S_OK) { - HeapFree(GetProcessHeap(), 0, data); + CoTaskMemFree(data); return hr; }
result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem)); if (!result) { - HeapFree(GetProcessHeap(), 0, data); + CoTaskMemFree(data); return E_OUTOFMEMORY; }
@@ -754,7 +754,7 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, { item->value.vt |= VT_VECTOR; item->value.caub.cElems = count; - item->value.caub.pElems = HeapAlloc(GetProcessHeap(), 0, count); + item->value.caub.pElems = CoTaskMemAlloc(count); memcpy(item->value.caub.pElems, data, count); } break; @@ -762,21 +762,21 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry,
item->value.vt |= VT_VECTOR; item->value.caub.cElems = count; - item->value.caub.pElems = HeapAlloc(GetProcessHeap(), 0, count); + item->value.caub.pElems = CoTaskMemAlloc(count); if (!item->value.caub.pElems) return E_OUTOFMEMORY;
pos.QuadPart = value; hr = IStream_Seek(input, pos, SEEK_SET, NULL); if (FAILED(hr)) { - HeapFree(GetProcessHeap(), 0, item->value.caub.pElems); + CoTaskMemFree(item->value.caub.pElems); return hr; } hr = IStream_Read(input, item->value.caub.pElems, count, &bytesread); if (bytesread != count) hr = E_FAIL; if (hr != S_OK) { - HeapFree(GetProcessHeap(), 0, item->value.caub.pElems); + CoTaskMemFree(item->value.caub.pElems); return hr; } break; @@ -797,7 +797,7 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, { item->value.vt |= VT_VECTOR; item->value.caui.cElems = count; - item->value.caui.pElems = HeapAlloc(GetProcessHeap(), 0, count * 2); + item->value.caui.pElems = CoTaskMemAlloc(count * 2); memcpy(item->value.caui.pElems, data, count * 2); for (i = 0; i < count; i++) SWAP_USHORT(item->value.caui.pElems[i]); @@ -807,21 +807,21 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry,
item->value.vt |= VT_VECTOR; item->value.caui.cElems = count; - item->value.caui.pElems = HeapAlloc(GetProcessHeap(), 0, count * 2); + item->value.caui.pElems = CoTaskMemAlloc(count * 2); if (!item->value.caui.pElems) return E_OUTOFMEMORY;
pos.QuadPart = value; hr = IStream_Seek(input, pos, SEEK_SET, NULL); if (FAILED(hr)) { - HeapFree(GetProcessHeap(), 0, item->value.caui.pElems); + CoTaskMemFree(item->value.caui.pElems); return hr; } hr = IStream_Read(input, item->value.caui.pElems, count * 2, &bytesread); if (bytesread != count * 2) hr = E_FAIL; if (hr != S_OK) { - HeapFree(GetProcessHeap(), 0, item->value.caui.pElems); + CoTaskMemFree(item->value.caui.pElems); return hr; } for (i = 0; i < count; i++) @@ -840,21 +840,21 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry,
item->value.vt |= VT_VECTOR; item->value.caul.cElems = count; - item->value.caul.pElems = HeapAlloc(GetProcessHeap(), 0, count * 4); + item->value.caul.pElems = CoTaskMemAlloc(count * 4); if (!item->value.caul.pElems) return E_OUTOFMEMORY;
pos.QuadPart = value; hr = IStream_Seek(input, pos, SEEK_SET, NULL); if (FAILED(hr)) { - HeapFree(GetProcessHeap(), 0, item->value.caul.pElems); + CoTaskMemFree(item->value.caul.pElems); return hr; } hr = IStream_Read(input, item->value.caul.pElems, count * 4, &bytesread); if (bytesread != count * 4) hr = E_FAIL; if (hr != S_OK) { - HeapFree(GetProcessHeap(), 0, item->value.caul.pElems); + CoTaskMemFree(item->value.caul.pElems); return hr; } for (i = 0; i < count; i++) @@ -897,21 +897,21 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, { item->value.vt |= VT_VECTOR; item->value.cauh.cElems = count; - item->value.cauh.pElems = HeapAlloc(GetProcessHeap(), 0, count * 8); + item->value.cauh.pElems = CoTaskMemAlloc(count * 8); if (!item->value.cauh.pElems) return E_OUTOFMEMORY;
pos.QuadPart = value; hr = IStream_Seek(input, pos, SEEK_SET, NULL); if (FAILED(hr)) { - HeapFree(GetProcessHeap(), 0, item->value.cauh.pElems); + CoTaskMemFree(item->value.cauh.pElems); return hr; } hr = IStream_Read(input, item->value.cauh.pElems, count * 8, &bytesread); if (bytesread != count * 8) hr = E_FAIL; if (hr != S_OK) { - HeapFree(GetProcessHeap(), 0, item->value.cauh.pElems); + CoTaskMemFree(item->value.cauh.pElems); return hr; } for (i = 0; i < count; i++) @@ -927,7 +927,7 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, } break; case IFD_ASCII: - item->value.pszVal = HeapAlloc(GetProcessHeap(), 0, count + 1); + item->value.pszVal = CoTaskMemAlloc(count + 1); if (!item->value.pszVal) return E_OUTOFMEMORY;
if (count <= 4) @@ -942,14 +942,14 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, hr = IStream_Seek(input, pos, SEEK_SET, NULL); if (FAILED(hr)) { - HeapFree(GetProcessHeap(), 0, item->value.pszVal); + CoTaskMemFree(item->value.pszVal); return hr; } hr = IStream_Read(input, item->value.pszVal, count, &bytesread); if (bytesread != count) hr = E_FAIL; if (hr != S_OK) { - HeapFree(GetProcessHeap(), 0, item->value.pszVal); + CoTaskMemFree(item->value.pszVal); return hr; } item->value.pszVal[count] = 0; @@ -962,7 +962,7 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, break; }
- item->value.blob.pBlobData = HeapAlloc(GetProcessHeap(), 0, count); + item->value.blob.pBlobData = CoTaskMemAlloc(count); if (!item->value.blob.pBlobData) return E_OUTOFMEMORY;
item->value.blob.cbSize = count; @@ -978,14 +978,14 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, hr = IStream_Seek(input, pos, SEEK_SET, NULL); if (FAILED(hr)) { - HeapFree(GetProcessHeap(), 0, item->value.blob.pBlobData); + CoTaskMemFree(item->value.blob.pBlobData); return hr; } hr = IStream_Read(input, item->value.blob.pBlobData, count, &bytesread); if (bytesread != count) hr = E_FAIL; if (hr != S_OK) { - HeapFree(GetProcessHeap(), 0, item->value.blob.pBlobData); + CoTaskMemFree(item->value.blob.pBlobData); return hr; } break; diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c index b9bdcf1c56e..0141f5033ee 100644 --- a/dlls/windowscodecs/pngformat.c +++ b/dlls/windowscodecs/pngformat.c @@ -25,6 +25,7 @@ #include "windef.h" #include "winbase.h" #include "objbase.h" +#include "shlwapi.h"
#include "wincodecs_private.h"
@@ -63,14 +64,14 @@ static HRESULT LoadTextMetadata(IStream *stream, const GUID *preferred_vendor, value_len = data_size - name_len - 1;
result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem)); - name = HeapAlloc(GetProcessHeap(), 0, name_len + 1); - value = HeapAlloc(GetProcessHeap(), 0, value_len + 1); + name = CoTaskMemAlloc(name_len + 1); + value = CoTaskMemAlloc(value_len + 1); if (!result || !name || !value) { HeapFree(GetProcessHeap(), 0, data); HeapFree(GetProcessHeap(), 0, result); - HeapFree(GetProcessHeap(), 0, name); - HeapFree(GetProcessHeap(), 0, value); + CoTaskMemFree(name); + CoTaskMemFree(value); return E_OUTOFMEMORY; }
@@ -131,11 +132,11 @@ static HRESULT LoadGamaMetadata(IStream *stream, const GUID *preferred_vendor, HeapFree(GetProcessHeap(), 0, data);
result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem)); - name = HeapAlloc(GetProcessHeap(), 0, sizeof(L"ImageGamma")); + SHStrDupW(L"ImageGamma", &name); if (!result || !name) { HeapFree(GetProcessHeap(), 0, result); - HeapFree(GetProcessHeap(), 0, name); + CoTaskMemFree(name); return E_OUTOFMEMORY; }
@@ -143,8 +144,6 @@ static HRESULT LoadGamaMetadata(IStream *stream, const GUID *preferred_vendor, PropVariantInit(&result[0].id); PropVariantInit(&result[0].value);
- memcpy(name, L"ImageGamma", sizeof(L"ImageGamma")); - result[0].id.vt = VT_LPWSTR; result[0].id.pwszVal = name; result[0].value.vt = VT_UI4; @@ -200,14 +199,14 @@ static HRESULT LoadChrmMetadata(IStream *stream, const GUID *preferred_vendor, result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem)*8); for (i=0; i<8; i++) { - dyn_names[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(lstrlenW(names[i])+1)); + SHStrDupW(names[i], &dyn_names[i]); if (!dyn_names[i]) break; } if (!result || i < 8) { HeapFree(GetProcessHeap(), 0, result); for (i=0; i<8; i++) - HeapFree(GetProcessHeap(), 0, dyn_names[i]); + CoTaskMemFree(dyn_names[i]); HeapFree(GetProcessHeap(), 0, data); return E_OUTOFMEMORY; } @@ -219,7 +218,6 @@ static HRESULT LoadChrmMetadata(IStream *stream, const GUID *preferred_vendor, PropVariantInit(&result[i].id); result[i].id.vt = VT_LPWSTR; result[i].id.pwszVal = dyn_names[i]; - lstrcpyW(dyn_names[i], names[i]);
PropVariantInit(&result[i].value); result[i].value.vt = VT_UI4;
From: Jeff Smith whydoubt@gmail.com
--- dlls/windowscodecs/clsfactory.c | 1 + dlls/windowscodecs/pngformat.c | 68 +++++++++++++++++++ dlls/windowscodecs/regsvr.c | 25 +++++++ dlls/windowscodecs/tests/metadata.c | 59 ++++++++++++++++ dlls/windowscodecs/wincodecs_private.h | 1 + dlls/windowscodecs/windowscodecs_wincodec.idl | 8 +++ 6 files changed, 162 insertions(+)
diff --git a/dlls/windowscodecs/clsfactory.c b/dlls/windowscodecs/clsfactory.c index d69e5dc4a6d..5065c8f2ca4 100644 --- a/dlls/windowscodecs/clsfactory.c +++ b/dlls/windowscodecs/clsfactory.c @@ -65,6 +65,7 @@ static const classinfo wic_classes[] = { {&CLSID_WICIfdMetadataReader, IfdMetadataReader_CreateInstance}, {&CLSID_WICPngChrmMetadataReader, PngChrmReader_CreateInstance}, {&CLSID_WICPngGamaMetadataReader, PngGamaReader_CreateInstance}, + {&CLSID_WICPngHistMetadataReader, PngHistReader_CreateInstance}, {&CLSID_WICPngTextMetadataReader, PngTextReader_CreateInstance}, {&CLSID_WICLSDMetadataReader, LSDReader_CreateInstance}, {&CLSID_WICIMDMetadataReader, IMDReader_CreateInstance}, diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c index 0141f5033ee..4c1e1f8463c 100644 --- a/dlls/windowscodecs/pngformat.c +++ b/dlls/windowscodecs/pngformat.c @@ -31,6 +31,11 @@
#include "wine/debug.h"
+static inline USHORT read_ushort_be(BYTE* data) +{ + return data[0] << 8 | data[1]; +} + static inline ULONG read_ulong_be(BYTE* data) { return data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; @@ -243,6 +248,69 @@ HRESULT PngChrmReader_CreateInstance(REFIID iid, void** ppv) return MetadataReader_Create(&ChrmReader_Vtbl, iid, ppv); }
+static HRESULT LoadHistMetadata(IStream *stream, const GUID *preferred_vendor, + DWORD persist_options, MetadataItem **items, DWORD *item_count) +{ + HRESULT hr; + BYTE type[4]; + BYTE *data; + ULONG data_size, element_count, i; + LPWSTR name; + MetadataItem *result; + USHORT *elements; + + hr = read_png_chunk(stream, type, &data, &data_size); + if (FAILED(hr)) return hr; + + element_count = data_size / 2; + elements = CoTaskMemAlloc(element_count * sizeof(USHORT)); + if (!elements) + { + HeapFree(GetProcessHeap(), 0, data); + return E_OUTOFMEMORY; + } + for (i = 0; i < element_count; i++) + elements[i] = read_ushort_be(data + i * 2); + + HeapFree(GetProcessHeap(), 0, data); + + result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem)); + SHStrDupW(L"Frequencies", &name); + if (!result || !name) { + HeapFree(GetProcessHeap(), 0, result); + CoTaskMemFree(name); + CoTaskMemFree(elements); + return E_OUTOFMEMORY; + } + + PropVariantInit(&result[0].schema); + PropVariantInit(&result[0].id); + PropVariantInit(&result[0].value); + + result[0].id.vt = VT_LPWSTR; + result[0].id.pwszVal = name; + + result[0].value.vt = VT_UI2|VT_VECTOR; + result[0].value.caui.cElems = element_count; + result[0].value.caui.pElems = elements; + + *items = result; + *item_count = 1; + + return S_OK; +} + +static const MetadataHandlerVtbl HistReader_Vtbl = { + 0, + &CLSID_WICPngHistMetadataReader, + LoadHistMetadata +}; + +HRESULT PngHistReader_CreateInstance(REFIID iid, void** ppv) +{ + return MetadataReader_Create(&HistReader_Vtbl, iid, ppv); +} + HRESULT PngDecoder_CreateInstance(REFIID iid, void** ppv) { HRESULT hr; diff --git a/dlls/windowscodecs/regsvr.c b/dlls/windowscodecs/regsvr.c index 5aa8b618afa..113fac21603 100644 --- a/dlls/windowscodecs/regsvr.c +++ b/dlls/windowscodecs/regsvr.c @@ -1620,6 +1620,21 @@ static const struct reader_containers pngchrm_containers[] = { { NULL } /* list terminator */ };
+static const BYTE hIST[] = "hIST"; + +static const struct metadata_pattern pnghist_metadata_pattern[] = { + { 4, 4, hIST, mask_all, 4 }, + { 0 } +}; + +static const struct reader_containers pnghist_containers[] = { + { + &GUID_ContainerFormatPng, + pnghist_metadata_pattern + }, + { NULL } /* list terminator */ +}; + static const struct metadata_pattern lsd_metadata_patterns[] = { { 0, 6, gif87a_magic, mask_all, 0 }, { 0, 6, gif89a_magic, mask_all, 0 }, @@ -1735,6 +1750,16 @@ static struct regsvr_metadatareader const metadatareader_list[] = { 0, 0, 0, pnggama_containers }, + { &CLSID_WICPngHistMetadataReader, + "The Wine Project", + "Chunk hIST Reader", + "1.0.0.0", + "1.0.0.0", + &GUID_VendorMicrosoft, + &GUID_MetadataFormatChunkhIST, + 0, 0, 0, + pnghist_containers + }, { &CLSID_WICPngTextMetadataReader, "The Wine Project", "Chunk tEXt Reader", diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 1d3f909350c..a50edbb2412 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -158,6 +158,17 @@ static const char metadata_cHRM[] = { 0xff,0xff,0xff,0xff /* chunk CRC */ };
+static const char metadata_hIST[] = { + 0,0,0,40, /* chunk length */ + 'h','I','S','T', /* chunk type */ + 0,1, 0,2, 0,3, 0,4, + 0,5, 0,6, 0,7, 0,8, + 0,9, 0,10, 0,11, 0,12, + 0,13, 0,14, 0,15, 0,16, + 0,17, 0,18, 0,19, 0,20, + 0xff,0xff,0xff,0xff +}; + static const char pngimage[285] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53, @@ -555,6 +566,53 @@ static void test_metadata_cHRM(void) IWICMetadataReader_Release(reader); }
+static void test_metadata_hIST(void) +{ + HRESULT hr; + IWICMetadataReader *reader; + PROPVARIANT schema, id, value; + UINT count, i; + GUID format; + static const WCHAR Frequencies[] = L"Frequencies"; + + PropVariantInit(&schema); + PropVariantInit(&id); + PropVariantInit(&value); + + hr = CoCreateInstance(&CLSID_WICPngHistMetadataReader, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICMetadataReader, (void**)&reader); + ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG) /*winxp*/, "CoCreateInstance failed, hr=%lx\n", hr); + if (FAILED(hr)) return; + + load_stream((IUnknown*)reader, metadata_hIST, sizeof(metadata_hIST), WICPersistOptionDefault); + + hr = IWICMetadataReader_GetMetadataFormat(reader, &format); + ok(hr == S_OK, "GetMetadataFormat failed, hr=%lx\n", hr); + ok(IsEqualGUID(&format, &GUID_MetadataFormatChunkhIST), "unexpected format %s\n", wine_dbgstr_guid(&format)); + + hr = IWICMetadataReader_GetCount(reader, &count); + ok(hr == S_OK, "GetCount failed, hr=%lx\n", hr); + ok(count == 1, "unexpected count %i\n", count); + + hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, &id, &value); + ok(hr == S_OK, "GetValue failed, hr=%lx\n", hr); + + ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt); + PropVariantClear(&schema); + + ok(id.vt == VT_LPWSTR, "unexpected vt: %i\n", id.vt); + ok(!lstrcmpW(U(id).pwszVal, Frequencies), "unexpected value: %s\n", wine_dbgstr_w(U(id).pwszVal)); + PropVariantClear(&id); + + ok(value.vt == (VT_UI2|VT_VECTOR), "unexpected vt: %i\n", value.vt); + ok(20 == U(value).caui.cElems, "expected cElems %d, got %ld\n", 20, U(value).caub.cElems); + for (i = 0; i < U(value).caui.cElems; i++) + ok(i+1 == U(value).caui.pElems[i], "%u: expected value %u, got %u\n", i, i+1, U(value).caui.pElems[i]); + PropVariantClear(&value); + + IWICMetadataReader_Release(reader); +} + static inline USHORT ushort_bswap(USHORT s) { return (s >> 8) | (s << 8); @@ -3213,6 +3271,7 @@ START_TEST(metadata) test_metadata_tEXt(); test_metadata_gAMA(); test_metadata_cHRM(); + test_metadata_hIST(); test_metadata_IFD(); test_metadata_Exif(); test_create_reader(); diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index 9530325358c..3dcb20786f2 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -219,6 +219,7 @@ extern HRESULT UnknownMetadataReader_CreateInstance(REFIID iid, void** ppv); extern HRESULT IfdMetadataReader_CreateInstance(REFIID iid, void **ppv); extern HRESULT PngChrmReader_CreateInstance(REFIID iid, void** ppv); extern HRESULT PngGamaReader_CreateInstance(REFIID iid, void** ppv); +extern HRESULT PngHistReader_CreateInstance(REFIID iid, void** ppv); extern HRESULT PngTextReader_CreateInstance(REFIID iid, void** ppv); extern HRESULT LSDReader_CreateInstance(REFIID iid, void **ppv); extern HRESULT IMDReader_CreateInstance(REFIID iid, void **ppv); diff --git a/dlls/windowscodecs/windowscodecs_wincodec.idl b/dlls/windowscodecs/windowscodecs_wincodec.idl index ca467226dff..e60111ed19c 100644 --- a/dlls/windowscodecs/windowscodecs_wincodec.idl +++ b/dlls/windowscodecs/windowscodecs_wincodec.idl @@ -174,10 +174,18 @@ coclass WICPngChrmMetadataReader { interface IWICMetadataReader; } ] coclass WICPngGamaMetadataReader { interface IWICMetadataReader; }
+[ + helpstring("WIC Png hIST Metadata Reader"), + threading(both), + uuid(877a0bb7-a313-4491-87b5-2e6d0594f520) +] +coclass WICPngHistMetadataReader { interface IWICMetadataReader; } + [ helpstring("WIC Png tEXt Metadata Reader"), threading(both), uuid(4b59afcc-b8c3-408a-b670-89e5fab6fda7) + ] coclass WICPngTextMetadataReader { interface IWICMetadataReader; }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=135173
Your paranoid android.
=== debian11b (64 bit WoW report) ===
win32u: win32u.c:1057: Test failed: buf = win32u:win32u:0770 done (0) in 0s 1374B
On Mon Jul 24 20:47:35 2023 +0000, Jeffrey Smith wrote:
changed this line in [version 4 of the diff](/wine/wine/-/merge_requests/3363/diffs?diff_id=59093&start_sha=e22586c8109b5f1575285eb0a3d75af693b495cb#82ee617a723da9b24c7492c072078baace71a8d9_283_295)
I moved the allocation earlier in the function and added/adjusted NULL checks and cleanup as needed.