Dmitry Timoshkov : windowscodecs: Implement partial loading of IFD metadata .

Alexandre Julliard julliard at winehq.org
Thu Jun 14 15:31:31 CDT 2012


Module: wine
Branch: master
Commit: ec43788803648ad689274cb44be5c9434d5f7322
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=ec43788803648ad689274cb44be5c9434d5f7322

Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date:   Wed Jun 13 18:30:54 2012 +0900

windowscodecs: Implement partial loading of IFD metadata.

---

 dlls/windowscodecs/metadatahandler.c |  127 +++++++++++++++++++++++++++++++++-
 dlls/windowscodecs/tests/metadata.c  |    1 -
 2 files changed, 124 insertions(+), 4 deletions(-)

diff --git a/dlls/windowscodecs/metadatahandler.c b/dlls/windowscodecs/metadatahandler.c
index a4dc174..20785b4 100644
--- a/dlls/windowscodecs/metadatahandler.c
+++ b/dlls/windowscodecs/metadatahandler.c
@@ -19,6 +19,7 @@
 #include "config.h"
 
 #include <stdarg.h>
+#include <stdio.h>
 
 #define COBJMACROS
 #define NONAMELESSUNION
@@ -598,13 +599,133 @@ HRESULT UnknownMetadataReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, vo
     return MetadataReader_Create(&UnknownMetadataReader_Vtbl, pUnkOuter, iid, ppv);
 }
 
+#include "pshpack2.h"
+struct IFD_entry
+{
+    SHORT id;
+    SHORT type;
+    ULONG length;
+    LONG  value;
+};
+
+struct IFD_rational
+{
+    LONG numerator;
+    LONG denominator;
+};
+#include "poppack.h"
+
+#define IFD_BYTE 1
+#define IFD_ASCII 2
+#define IFD_SHORT 3
+#define IFD_LONG 4
+#define IFD_RATIONAL 5
+#define IFD_SBYTE 6
+#define IFD_UNDEFINED 7
+#define IFD_SSHORT 8
+#define IFD_SLONG 9
+#define IFD_SRATIONAL 10
+#define IFD_FLOAT 11
+#define IFD_DOUBLE 12
+#define IFD_IFD 13
+
+static HRESULT load_IFD_entry(IStream *input, struct IFD_entry *entry, MetadataItem *item)
+{
+    item->schema.vt = VT_EMPTY;
+    item->id.vt = VT_UI2;
+    item->id.u.uiVal = entry->id;
+
+    switch (entry->type)
+    {
+    case IFD_SHORT:
+        if (entry->length == 1)
+        {
+            item->value.vt = VT_UI2;
+            item->value.u.uiVal = entry->value;
+            break;
+        }
+        FIXME("loading multiple short fields is not implemented\n");
+        break;
+    case IFD_LONG:
+        if (entry->length == 1)
+        {
+            item->value.vt = VT_UI4;
+            item->value.u.ulVal = entry->value;
+            break;
+        }
+        FIXME("loading multiple long fields is not implemented\n");
+        break;
+    case IFD_RATIONAL:
+        if (entry->length == 1)
+        {
+            HRESULT hr;
+            LARGE_INTEGER pos;
+            struct IFD_rational rational;
+
+            pos.QuadPart = entry->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);
+            if (FAILED(hr)) return hr;
+            item->value.u.uhVal.QuadPart = ((LONGLONG)rational.denominator << 32) | rational.numerator;
+            break;
+        }
+        FIXME("loading multiple rational fields is not implemented\n");
+        break;
+    default:
+        FIXME("loading field of type %d is not implemented\n", entry->type);
+        break;
+    }
+    return S_OK;
+}
+
 static HRESULT LoadIfdMetadata(IStream *input, const GUID *preferred_vendor,
     DWORD persist_options, MetadataItem **items, DWORD *item_count)
 {
-    FIXME("stub\n");
+    HRESULT hr;
+    MetadataItem *result;
+    USHORT count, i;
+    struct IFD_entry *entry;
+
+    TRACE("\n");
+
+    hr = IStream_Read(input, &count, sizeof(count), NULL);
+    if (FAILED(hr)) return hr;
+
+    entry = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*entry));
+    if (!entry) return E_OUTOFMEMORY;
 
-    *items = NULL;
-    *item_count = 0;
+    hr = IStream_Read(input, entry, count * sizeof(*entry), NULL);
+    if (FAILED(hr))
+    {
+        HeapFree(GetProcessHeap(), 0, entry);
+        return hr;
+    }
+
+    result = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*result));
+    if (!result)
+    {
+        HeapFree(GetProcessHeap(), 0, entry);
+        return E_OUTOFMEMORY;
+    }
+
+    for (i = 0; i < count; i++)
+    {
+        hr = load_IFD_entry(input, &entry[i], &result[i]);
+        if (FAILED(hr))
+        {
+            HeapFree(GetProcessHeap(), 0, entry);
+            HeapFree(GetProcessHeap(), 0, result);
+            return hr;
+        }
+    }
+
+    HeapFree(GetProcessHeap(), 0, entry);
+
+    *items = result;
+    *item_count = count;
 
     return S_OK;
 }
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c
index 6b25963..cf00f1f 100644
--- a/dlls/windowscodecs/tests/metadata.c
+++ b/dlls/windowscodecs/tests/metadata.c
@@ -386,7 +386,6 @@ static void test_metadata_IFD(void)
 
     hr = IWICMetadataReader_GetCount(reader, &count);
     ok(hr == S_OK, "GetCount error %#x\n", hr);
-todo_wine
     ok(count == 6, "unexpected count %u\n", count);
 
     hr = IWICMetadataReader_GetEnumerator(reader, NULL);




More information about the wine-cvs mailing list