Module: wine Branch: master Commit: 5f22fdb86fc6b79a09a35384fa177eb1209a41e6 URL: http://source.winehq.org/git/wine.git/?a=commit;h=5f22fdb86fc6b79a09a35384fa...
Author: Dmitry Timoshkov dmitry@baikal.ru Date: Wed Jun 13 18:31:02 2012 +0900
windowscodecs: Add support for WICPersistOptionsLittleEndian/WICPersistOptionsBigEndian in the IFD metadata reader.
---
dlls/windowscodecs/metadatahandler.c | 51 ++++++++++++++++++++++++++------- 1 files changed, 40 insertions(+), 11 deletions(-)
diff --git a/dlls/windowscodecs/metadatahandler.c b/dlls/windowscodecs/metadatahandler.c index 20785b4..d2eb8b3 100644 --- a/dlls/windowscodecs/metadatahandler.c +++ b/dlls/windowscodecs/metadatahandler.c @@ -1,5 +1,6 @@ /* * Copyright 2012 Vincent Povirk for CodeWeavers + * Copyright 2012 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,6 +27,7 @@
#include "windef.h" #include "winbase.h" +#include "winternl.h" #include "objbase.h" #include "wincodec.h" #include "wincodecsdk.h" @@ -599,12 +601,16 @@ HRESULT UnknownMetadataReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, vo return MetadataReader_Create(&UnknownMetadataReader_Vtbl, pUnkOuter, iid, ppv); }
+#define SWAP_USHORT(x) do { if (!native_byte_order) (x) = RtlUshortByteSwap(x); } while(0) +#define SWAP_ULONG(x) do { if (!native_byte_order) (x) = RtlUlongByteSwap(x); } while(0) +#define SWAP_ULONGLONG(x) do { if (!native_byte_order) (x) = RtlUlonglongByteSwap(x); } while(0) + #include "pshpack2.h" struct IFD_entry { SHORT id; SHORT type; - ULONG length; + ULONG count; LONG value; };
@@ -629,47 +635,60 @@ struct IFD_rational #define IFD_DOUBLE 12 #define IFD_IFD 13
-static HRESULT load_IFD_entry(IStream *input, struct IFD_entry *entry, MetadataItem *item) +static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, + MetadataItem *item, BOOL native_byte_order) { + ULONG count, value; + SHORT type; + item->schema.vt = VT_EMPTY; item->id.vt = VT_UI2; item->id.u.uiVal = entry->id; + SWAP_USHORT(item->id.u.uiVal);
- switch (entry->type) + count = entry->count; + SWAP_ULONG(count); + type = entry->type; + SWAP_USHORT(type); + value = entry->value; + SWAP_ULONG(value); + + switch (type) { case IFD_SHORT: - if (entry->length == 1) + if (count == 1) { item->value.vt = VT_UI2; - item->value.u.uiVal = entry->value; + item->value.u.uiVal = value; break; } FIXME("loading multiple short fields is not implemented\n"); break; case IFD_LONG: - if (entry->length == 1) + if (count == 1) { item->value.vt = VT_UI4; - item->value.u.ulVal = entry->value; + item->value.u.ulVal = value; break; } FIXME("loading multiple long fields is not implemented\n"); break; case IFD_RATIONAL: - if (entry->length == 1) + if (count == 1) { HRESULT hr; LARGE_INTEGER pos; struct IFD_rational rational;
- pos.QuadPart = entry->value; + pos.QuadPart = value; hr = IStream_Seek(input, pos, SEEK_SET, NULL); if (FAILED(hr)) return hr;
item->value.vt = VT_UI8; - hr = IStream_Read(input, &rational , sizeof(rational), NULL); + hr = IStream_Read(input, &rational, sizeof(rational), NULL); if (FAILED(hr)) return hr; item->value.u.uhVal.QuadPart = ((LONGLONG)rational.denominator << 32) | rational.numerator; + SWAP_ULONGLONG(item->value.u.uhVal.QuadPart); break; } FIXME("loading multiple rational fields is not implemented\n"); @@ -688,12 +707,22 @@ static HRESULT LoadIfdMetadata(IStream *input, const GUID *preferred_vendor, MetadataItem *result; USHORT count, i; struct IFD_entry *entry; + BOOL native_byte_order = TRUE;
TRACE("\n");
+#ifdef WORDS_BIGENDIAN + if (persist_options & WICPersistOptionsLittleEndian) +#else + if (persist_options & WICPersistOptionsBigEndian) +#endif + native_byte_order = FALSE; + hr = IStream_Read(input, &count, sizeof(count), NULL); if (FAILED(hr)) return hr;
+ SWAP_USHORT(count); + entry = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*entry)); if (!entry) return E_OUTOFMEMORY;
@@ -713,7 +742,7 @@ static HRESULT LoadIfdMetadata(IStream *input, const GUID *preferred_vendor,
for (i = 0; i < count; i++) { - hr = load_IFD_entry(input, &entry[i], &result[i]); + hr = load_IFD_entry(input, &entry[i], &result[i], native_byte_order); if (FAILED(hr)) { HeapFree(GetProcessHeap(), 0, entry);