windowscodecs: Implement GIF Application Extension metadata reader.

This commit is contained in:
Dmitry Timoshkov 2012-09-17 10:03:15 +09:00 committed by Alexandre Julliard
parent 66a817f067
commit be28f266ff
6 changed files with 143 additions and 1 deletions

View File

@ -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 {

View File

@ -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;

View File

@ -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 */
};

View File

@ -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);

View File

@ -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 */

View File

@ -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; }