Dmitry Timoshkov : windowscodecs: Implement GIF Comment Extension metadata reader.

Alexandre Julliard julliard at winehq.org
Mon Sep 17 14:06:32 CDT 2012


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

Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date:   Mon Sep 17 10:04:14 2012 +0900

windowscodecs: Implement GIF Comment Extension metadata reader.

---

 dlls/windowscodecs/clsfactory.c               |    1 +
 dlls/windowscodecs/gifformat.c                |   95 +++++++++++++++++++++++++
 dlls/windowscodecs/regsvr.c                   |   25 +++++++
 dlls/windowscodecs/tests/metadata.c           |    1 -
 dlls/windowscodecs/wincodecs_private.h        |    1 +
 dlls/windowscodecs/windowscodecs_wincodec.idl |    7 ++
 6 files changed, 129 insertions(+), 1 deletions(-)

diff --git a/dlls/windowscodecs/clsfactory.c b/dlls/windowscodecs/clsfactory.c
index 61ddfd9..a57d673 100644
--- a/dlls/windowscodecs/clsfactory.c
+++ b/dlls/windowscodecs/clsfactory.c
@@ -66,6 +66,7 @@ static const classinfo wic_classes[] = {
     {&CLSID_WICIMDMetadataReader, IMDReader_CreateInstance},
     {&CLSID_WICGCEMetadataReader, GCEReader_CreateInstance},
     {&CLSID_WICAPEMetadataReader, APEReader_CreateInstance},
+    {&CLSID_WICGifCommentMetadataReader, GifCommentReader_CreateInstance},
     {0}};
 
 typedef struct {
diff --git a/dlls/windowscodecs/gifformat.c b/dlls/windowscodecs/gifformat.c
index 14d7d01..1dba2bb 100644
--- a/dlls/windowscodecs/gifformat.c
+++ b/dlls/windowscodecs/gifformat.c
@@ -434,6 +434,101 @@ HRESULT APEReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppv)
     return MetadataReader_Create(&APEReader_Vtbl, pUnkOuter, iid, ppv);
 }
 
+static HRESULT load_GifComment_metadata(IStream *stream, const GUID *vendor, DWORD options,
+                                        MetadataItem **items, DWORD *count)
+{
+#include "pshpack1.h"
+    struct gif_extenstion
+    {
+        BYTE extension_introducer;
+        BYTE extension_label;
+    } ext_data;
+#include "poppack.h"
+    HRESULT hr;
+    ULONG bytesread, data_size;
+    MetadataItem *result;
+    BYTE subblock_size;
+    BYTE *data;
+
+    *items = NULL;
+    *count = 0;
+
+    hr = IStream_Read(stream, &ext_data, sizeof(ext_data), &bytesread);
+    if (FAILED(hr) || bytesread != sizeof(ext_data)) return S_OK;
+    if (ext_data.extension_introducer != 0x21 || ext_data.extension_label != 0xfe)
+        return S_OK;
+
+    data = NULL;
+    data_size = 0;
+
+    for (;;)
+    {
+        hr = IStream_Read(stream, &subblock_size, sizeof(subblock_size), &bytesread);
+        if (FAILED(hr) || bytesread != sizeof(subblock_size))
+        {
+            HeapFree(GetProcessHeap(), 0, data);
+            return S_OK;
+        }
+        if (!subblock_size) break;
+
+        if (!data)
+            data = HeapAlloc(GetProcessHeap(), 0, subblock_size);
+        else
+        {
+            BYTE *new_data = HeapReAlloc(GetProcessHeap(), 0, data, data_size + subblock_size);
+            if (!new_data)
+            {
+                HeapFree(GetProcessHeap(), 0, data);
+                return S_OK;
+            }
+            data = new_data;
+        }
+        hr = IStream_Read(stream, data + data_size, subblock_size, &bytesread);
+        if (FAILED(hr) || bytesread != subblock_size)
+        {
+            HeapFree(GetProcessHeap(), 0, data);
+            return S_OK;
+        }
+        data_size += subblock_size;
+    }
+
+    result = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem));
+    if (!result)
+    {
+        HeapFree(GetProcessHeap(), 0, data);
+        return E_OUTOFMEMORY;
+    }
+
+    PropVariantInit(&result->schema);
+    PropVariantInit(&result->id);
+    PropVariantInit(&result->value);
+
+    result->id.vt = VT_LPWSTR;
+    result->id.u.pwszVal = strdupAtoW("TextEntry");
+    result->value.vt = VT_LPSTR;
+    result->value.u.pszVal = HeapAlloc(GetProcessHeap(), 0, data_size + 1);
+    memcpy(result->value.u.pszVal, data, data_size);
+    result->value.u.pszVal[data_size] = 0;
+
+    HeapFree(GetProcessHeap(), 0, data);
+
+    *items = result;
+    *count = 1;
+
+    return S_OK;
+}
+
+static const MetadataHandlerVtbl GifCommentReader_Vtbl = {
+    0,
+    &CLSID_WICGifCommentMetadataReader,
+    load_GifComment_metadata
+};
+
+HRESULT GifCommentReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppv)
+{
+    return MetadataReader_Create(&GifCommentReader_Vtbl, pUnkOuter, iid, ppv);
+}
+
 static IStream *create_stream(const void *data, int data_size)
 {
     HRESULT hr;
diff --git a/dlls/windowscodecs/regsvr.c b/dlls/windowscodecs/regsvr.c
index 47e522c..626887f 100644
--- a/dlls/windowscodecs/regsvr.c
+++ b/dlls/windowscodecs/regsvr.c
@@ -1577,6 +1577,21 @@ static const struct reader_containers ape_containers[] = {
     { NULL } /* list terminator */
 };
 
+static const BYTE gif_comment_magic[] = { 0x21, 0xfe };
+
+static const struct metadata_pattern gif_comment_metadata_pattern[] = {
+    { 0, 2, gif_comment_magic, mask_all, 0 },
+    { 0 }
+};
+
+static const struct reader_containers gif_comment_containers[] = {
+    {
+        &GUID_ContainerFormatGif,
+        gif_comment_metadata_pattern
+    },
+    { NULL } /* list terminator */
+};
+
 static struct regsvr_metadatareader const metadatareader_list[] = {
     {   &CLSID_WICUnknownMetadataReader,
         "The Wine Project",
@@ -1648,6 +1663,16 @@ static struct regsvr_metadatareader const metadatareader_list[] = {
         0, 0, 0,
         ape_containers
     },
+    {   &CLSID_WICGifCommentMetadataReader,
+        "The Wine Project",
+        "Comment Extension Reader",
+        "1.0.0.0",
+        "1.0.0.0",
+        &GUID_VendorMicrosoft,
+        &GUID_MetadataFormatGifComment,
+        0, 0, 0,
+        gif_comment_containers
+    },
     { NULL }			/* list terminator */
 };
 
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c
index 27a8dcf..ed02e2f 100644
--- a/dlls/windowscodecs/tests/metadata.c
+++ b/dlls/windowscodecs/tests/metadata.c
@@ -1727,7 +1727,6 @@ static void test_metadata_GIF_comment(void)
 
     hr = CoCreateInstance(&CLSID_WICGifCommentMetadataReader, NULL, CLSCTX_INPROC_SERVER,
                           &IID_IWICMetadataReader, (void **)&reader);
-todo_wine
     ok(hr == S_OK || broken(hr == E_NOINTERFACE || hr == REGDB_E_CLASSNOTREG) /* before Win7 */,
        "CoCreateInstance error %#x\n", hr);
 
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index 406a3fa..41d2d80 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -99,5 +99,6 @@ extern HRESULT LSDReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **
 extern HRESULT IMDReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppv) DECLSPEC_HIDDEN;
 extern HRESULT GCEReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppv) DECLSPEC_HIDDEN;
 extern HRESULT APEReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppv) DECLSPEC_HIDDEN;
+extern HRESULT GifCommentReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppv) DECLSPEC_HIDDEN;
 
 #endif /* WINCODECS_PRIVATE_H */
diff --git a/dlls/windowscodecs/windowscodecs_wincodec.idl b/dlls/windowscodecs/windowscodecs_wincodec.idl
index 7ca2235..658ced0 100644
--- a/dlls/windowscodecs/windowscodecs_wincodec.idl
+++ b/dlls/windowscodecs/windowscodecs_wincodec.idl
@@ -170,3 +170,10 @@ coclass WICGCEMetadataReader { interface IWICMetadataReader; }
     uuid(1767b93a-b021-44ea-920f-863c11f4f768)
 ]
 coclass WICAPEMetadataReader { interface IWICMetadataReader; }
+
+[
+    helpstring("WIC Comment Extension Reader"),
+    threading(both),
+    uuid(32557d3b-69dc-4f95-836e-f5972b2f6159)
+]
+coclass WICGifCommentMetadataReader { interface IWICMetadataReader; }




More information about the wine-cvs mailing list