Dmitry Timoshkov : windowscodecs: Implement GIF Application Extension metadata reader.
Alexandre Julliard
julliard at winehq.org
Mon Sep 17 14:06:32 CDT 2012
Module: wine
Branch: master
Commit: be28f266ff2a90df66fd886b35cec3fc015cb034
URL: http://source.winehq.org/git/wine.git/?a=commit;h=be28f266ff2a90df66fd886b35cec3fc015cb034
Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date: Mon Sep 17 10:03:15 2012 +0900
windowscodecs: Implement GIF Application Extension metadata reader.
---
dlls/windowscodecs/clsfactory.c | 1 +
dlls/windowscodecs/gifformat.c | 109 +++++++++++++++++++++++++
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, 143 insertions(+), 1 deletions(-)
diff --git a/dlls/windowscodecs/clsfactory.c b/dlls/windowscodecs/clsfactory.c
index a42aeab..61ddfd9 100644
--- a/dlls/windowscodecs/clsfactory.c
+++ b/dlls/windowscodecs/clsfactory.c
@@ -65,6 +65,7 @@ static const classinfo wic_classes[] = {
{&CLSID_WICLSDMetadataReader, LSDReader_CreateInstance},
{&CLSID_WICIMDMetadataReader, IMDReader_CreateInstance},
{&CLSID_WICGCEMetadataReader, GCEReader_CreateInstance},
+ {&CLSID_WICAPEMetadataReader, APEReader_CreateInstance},
{0}};
typedef struct {
diff --git a/dlls/windowscodecs/gifformat.c b/dlls/windowscodecs/gifformat.c
index a814c1a..14d7d01 100644
--- a/dlls/windowscodecs/gifformat.c
+++ b/dlls/windowscodecs/gifformat.c
@@ -325,6 +325,115 @@ HRESULT GCEReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppv)
return MetadataReader_Create(&GCEReader_Vtbl, pUnkOuter, iid, ppv);
}
+static HRESULT load_APE_metadata(IStream *stream, const GUID *vendor, DWORD options,
+ MetadataItem **items, DWORD *count)
+{
+#include "pshpack1.h"
+ struct application_extenstion
+ {
+ BYTE extension_introducer;
+ BYTE extension_label;
+ BYTE block_size;
+ BYTE application[11];
+ } ape_data;
+#include "poppack.h"
+ HRESULT hr;
+ ULONG bytesread, data_size, i;
+ MetadataItem *result;
+ BYTE subblock_size;
+ BYTE *data;
+
+ *items = NULL;
+ *count = 0;
+
+ hr = IStream_Read(stream, &ape_data, sizeof(ape_data), &bytesread);
+ if (FAILED(hr) || bytesread != sizeof(ape_data)) return S_OK;
+ if (ape_data.extension_introducer != 0x21 || ape_data.extension_label != 0xff ||
+ ape_data.block_size != 11)
+ 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 + 1);
+ else
+ {
+ BYTE *new_data = HeapReAlloc(GetProcessHeap(), 0, data, data_size + subblock_size + 1);
+ if (!new_data)
+ {
+ HeapFree(GetProcessHeap(), 0, data);
+ return S_OK;
+ }
+ data = new_data;
+ }
+ data[data_size] = subblock_size;
+ hr = IStream_Read(stream, data + data_size + 1, subblock_size, &bytesread);
+ if (FAILED(hr) || bytesread != subblock_size)
+ {
+ HeapFree(GetProcessHeap(), 0, data);
+ return S_OK;
+ }
+ data_size += subblock_size + 1;
+ }
+
+ result = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem) * 2);
+ if (!result)
+ {
+ HeapFree(GetProcessHeap(), 0, data);
+ return E_OUTOFMEMORY;
+ }
+
+ for (i = 0; i < 2; i++)
+ {
+ PropVariantInit(&result[i].schema);
+ PropVariantInit(&result[i].id);
+ PropVariantInit(&result[i].value);
+ }
+
+ result[0].id.vt = VT_LPWSTR;
+ result[0].id.u.pwszVal = strdupAtoW("Application");
+ result[0].value.vt = VT_UI1|VT_VECTOR;
+ result[0].value.u.caub.cElems = sizeof(ape_data.application);
+ result[0].value.u.caub.pElems = HeapAlloc(GetProcessHeap(), 0, sizeof(ape_data.application));
+ memcpy(result[0].value.u.caub.pElems, ape_data.application, sizeof(ape_data.application));
+
+ result[1].id.vt = VT_LPWSTR;
+ result[1].id.u.pwszVal = strdupAtoW("Data");
+ result[1].value.vt = VT_UI1|VT_VECTOR;
+ result[1].value.u.caub.cElems = data_size;
+ result[1].value.u.caub.pElems = HeapAlloc(GetProcessHeap(), 0, data_size);
+ memcpy(result[1].value.u.caub.pElems, data, data_size);
+
+ HeapFree(GetProcessHeap(), 0, data);
+
+ *items = result;
+ *count = 2;
+
+ return S_OK;
+}
+
+static const MetadataHandlerVtbl APEReader_Vtbl = {
+ 0,
+ &CLSID_WICAPEMetadataReader,
+ load_APE_metadata
+};
+
+HRESULT APEReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppv)
+{
+ return MetadataReader_Create(&APEReader_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 a7ac4b2..47e522c 100644
--- a/dlls/windowscodecs/regsvr.c
+++ b/dlls/windowscodecs/regsvr.c
@@ -1562,6 +1562,21 @@ static const struct reader_containers gce_containers[] = {
{ NULL } /* list terminator */
};
+static const BYTE ape_magic[] = { 0x21, 0xff, 0x0b };
+
+static const struct metadata_pattern ape_metadata_pattern[] = {
+ { 0, 3, ape_magic, mask_all, 0 },
+ { 0 }
+};
+
+static const struct reader_containers ape_containers[] = {
+ {
+ &GUID_ContainerFormatGif,
+ ape_metadata_pattern
+ },
+ { NULL } /* list terminator */
+};
+
static struct regsvr_metadatareader const metadatareader_list[] = {
{ &CLSID_WICUnknownMetadataReader,
"The Wine Project",
@@ -1623,6 +1638,16 @@ static struct regsvr_metadatareader const metadatareader_list[] = {
0, 0, 0,
gce_containers
},
+ { &CLSID_WICAPEMetadataReader,
+ "The Wine Project",
+ "Application Extension Reader",
+ "1.0.0.0",
+ "1.0.0.0",
+ &GUID_VendorMicrosoft,
+ &GUID_MetadataFormatAPE,
+ 0, 0, 0,
+ ape_containers
+ },
{ NULL } /* list terminator */
};
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c
index b62b96e..27a8dcf 100644
--- a/dlls/windowscodecs/tests/metadata.c
+++ b/dlls/windowscodecs/tests/metadata.c
@@ -1657,7 +1657,6 @@ static void test_metadata_APE(void)
hr = CoCreateInstance(&CLSID_WICAPEMetadataReader, 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 b712b2f..406a3fa 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -98,5 +98,6 @@ extern HRESULT PngTextReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, voi
extern HRESULT LSDReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppv) DECLSPEC_HIDDEN;
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;
#endif /* WINCODECS_PRIVATE_H */
diff --git a/dlls/windowscodecs/windowscodecs_wincodec.idl b/dlls/windowscodecs/windowscodecs_wincodec.idl
index e109bf2..7ca2235 100644
--- a/dlls/windowscodecs/windowscodecs_wincodec.idl
+++ b/dlls/windowscodecs/windowscodecs_wincodec.idl
@@ -163,3 +163,10 @@ coclass WICIMDMetadataReader { interface IWICMetadataReader; }
uuid(b92e345d-f52d-41f3-b562-081bc772e3b9)
]
coclass WICGCEMetadataReader { interface IWICMetadataReader; }
+
+[
+ helpstring("WIC Application Extension Reader"),
+ threading(both),
+ uuid(1767b93a-b021-44ea-920f-863c11f4f768)
+]
+coclass WICAPEMetadataReader { interface IWICMetadataReader; }
More information about the wine-cvs
mailing list