From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/metadataquery.c | 686 ++++++++++++++++------------ dlls/windowscodecs/tests/metadata.c | 78 ++-- 2 files changed, 417 insertions(+), 347 deletions(-)
diff --git a/dlls/windowscodecs/metadataquery.c b/dlls/windowscodecs/metadataquery.c index b1235dbda6f..25c7e553e62 100644 --- a/dlls/windowscodecs/metadataquery.c +++ b/dlls/windowscodecs/metadataquery.c @@ -194,421 +194,509 @@ static VARTYPE map_type(struct string_t *str) return VT_ILLEGAL; }
-static HRESULT get_token(struct string_t *elem, PROPVARIANT *id, PROPVARIANT *schema, int *idx) +struct query_component { - const WCHAR *start, *end, *p; - WCHAR *bstr; - struct string_t next_elem; + unsigned int index; + PROPVARIANT schema; + PROPVARIANT id; + IWICMetadataReader *handler; +}; + +struct query_parser +{ + const WCHAR *ptr; + + WCHAR *scratch; + WCHAR *query; + + struct query_component *components; + size_t count; + size_t capacity; + + struct query_component *last; + struct query_component *prev; + HRESULT hr; +};
- TRACE("%s, len %d\n", wine_dbgstr_wn(elem->str, elem->len), elem->len); +static bool wincodecs_array_reserve(void **elements, size_t *capacity, size_t count, size_t size) +{ + size_t new_capacity, max_capacity; + void *new_elements;
- PropVariantInit(id); - PropVariantInit(schema); + if (count <= *capacity) + return true;
- if (!elem->len) return S_OK; + max_capacity = ~(SIZE_T)0 / size; + if (count > max_capacity) + return false;
- start = elem->str; + new_capacity = max(4, *capacity); + while (new_capacity < count && new_capacity <= max_capacity / 2) + new_capacity *= 2; + if (new_capacity < count) + new_capacity = max_capacity;
- if (*start == '[') - { - WCHAR *idx_end; + new_elements = realloc(*elements, new_capacity * size); + if (!new_elements) + return false;
- if (start[1] < '0' || start[1] > '9') return DISP_E_TYPEMISMATCH; + *elements = new_elements; + *capacity = new_capacity;
- *idx = wcstol(start + 1, &idx_end, 10); - if (idx_end > elem->str + elem->len) return WINCODEC_ERR_INVALIDQUERYREQUEST; - if (*idx_end != ']') return WINCODEC_ERR_INVALIDQUERYREQUEST; - if (*idx < 0) return WINCODEC_ERR_INVALIDQUERYREQUEST; - end = idx_end + 1; + return true; +}
- next_elem.str = end; - next_elem.len = elem->len - (end - start); - hr = get_token(&next_elem, id, schema, idx); - if (hr != S_OK) - { - TRACE("get_token error %#lx\n", hr); - return hr; - } - elem->len = (end - start) + next_elem.len; +static bool parser_skip_char(struct query_parser *parser, WCHAR ch) +{ + if (FAILED(parser->hr)) return true;
- TRACE("indexed %s [%d]\n", wine_dbgstr_wn(elem->str, elem->len), *idx); - return S_OK; - } - else if (*start == '{') + if (*parser->ptr != ch) { - VARTYPE vt; - PROPVARIANT next_token; + parser->hr = WINCODEC_ERR_INVALIDQUERYREQUEST; + return true; + } + parser->ptr++; + return false; +}
- end = wmemchr(start + 1, '=', elem->len - 1); - if (!end) return WINCODEC_ERR_INVALIDQUERYREQUEST; - if (end > elem->str + elem->len) return WINCODEC_ERR_INVALIDQUERYREQUEST; +static bool parser_unescape(struct query_parser *parser) +{ + if (*parser->ptr == '\') + { + parser->ptr++; + if (!*parser->ptr) return true; + }
- next_elem.str = start + 1; - next_elem.len = end - start - 1; - vt = map_type(&next_elem); - TRACE("type %s => %d\n", wine_dbgstr_wn(next_elem.str, next_elem.len), vt); - if (vt == VT_ILLEGAL) return WINCODEC_ERR_WRONGSTATE; + return false; +}
- next_token.vt = VT_BSTR; - next_token.bstrVal = SysAllocStringLen(NULL, elem->len - (end - start) + 1); - if (!next_token.bstrVal) return E_OUTOFMEMORY; +static void parse_query_index(struct query_parser *parser, unsigned int *ret) +{ + unsigned int index = 0, d;
- bstr = next_token.bstrVal; + if (parser_skip_char(parser, '[')) return;
- end++; - while (*end && *end != '}' && end - start < elem->len) - { - if (*end == '\') end++; - *bstr++ = *end++; - } - if (*end != '}') - { - PropVariantClear(&next_token); - return WINCODEC_ERR_INVALIDQUERYREQUEST; - } - *bstr = 0; - TRACE("schema/id %s\n", wine_dbgstr_w(next_token.bstrVal)); + if (*parser->ptr == '*' && *(parser->ptr + 1) == ']') + { + FIXME("[*] index value is not supported.\n"); + parser->ptr += 2; + parser->hr = E_UNEXPECTED; + return; + }
- if (vt == VT_CLSID) - { - id->vt = VT_CLSID; - id->puuid = CoTaskMemAlloc(sizeof(GUID)); - if (!id->puuid) - { - PropVariantClear(&next_token); - return E_OUTOFMEMORY; - } + /* Sign prefix is not allowed */
- hr = UuidFromStringW(next_token.bstrVal, id->puuid); - } + while (*parser->ptr) + { + if (*parser->ptr >= '0' && *parser->ptr <= '9') + d = *parser->ptr - '0'; + else if (*parser->ptr == ']') + break; else - hr = PropVariantChangeType(id, &next_token, 0, vt); - PropVariantClear(&next_token); - if (hr != S_OK) { - PropVariantClear(id); - PropVariantClear(schema); - return hr; + parser->hr = WINCODEC_ERR_INVALIDQUERYCHARACTER; + return; }
- end++; - if (*end == ':') - { - PROPVARIANT next_id, next_schema; - int next_idx = 0; + index = index * 10 + d; + parser->ptr++; + }
- next_elem.str = end + 1; - next_elem.len = elem->len - (end - start + 1); - hr = get_token(&next_elem, &next_id, &next_schema, &next_idx); - if (hr != S_OK) - { - TRACE("get_token error %#lx\n", hr); - return hr; - } - elem->len = (end - start + 1) + next_elem.len; + if (*parser->ptr != ']') + { + parser->hr = WINCODEC_ERR_INVALIDQUERYCHARACTER; + return; + } + parser_skip_char(parser, ']');
- TRACE("id %s [%d]\n", wine_dbgstr_wn(elem->str, elem->len), *idx); + *ret = index; +}
- if (next_schema.vt != VT_EMPTY) - { - PropVariantClear(&next_id); - PropVariantClear(&next_schema); - return WINCODEC_ERR_WRONGSTATE; - } +static void parse_query_data_item(struct query_parser *parser, PROPVARIANT *item) +{ + struct string_t span; + PROPVARIANT v; + GUID guid; + VARTYPE vt;
- *schema = *id; - *id = next_id; + if (parser_skip_char(parser, '{')) return;
- return S_OK; + /* Type */ + span.str = parser->ptr; + span.len = 0; + while (*parser->ptr && *parser->ptr != '=') + { + span.len++; + parser->ptr++; + } + + if (parser_skip_char(parser, '=')) return; + + vt = map_type(&span); + if (vt == VT_ILLEGAL) + { + parser->hr = WINCODEC_ERR_WRONGSTATE; + return; + } + + /* Value */ + span.str = parser->ptr; + span.len = 0; + while (*parser->ptr && *parser->ptr != '}') + { + if (parser_unescape(parser)) break; + parser->scratch[span.len++] = *parser->ptr; + parser->ptr++; + } + + if (parser_skip_char(parser, '}')) return; + + parser->scratch[span.len] = 0; + + if (vt == VT_CLSID) + { + if (UuidFromStringW(parser->scratch, &guid)) + { + parser->hr = WINCODEC_ERR_INVALIDQUERYREQUEST; + return; }
- elem->len = end - start; - return S_OK; + parser->hr = InitPropVariantFromCLSID(&guid, item); } + else + { + v.vt = VT_LPWSTR; + v.pwszVal = parser->scratch; + parser->hr = PropVariantChangeType(item, &v, 0, vt); + } +}
- end = wmemchr(start, '/', elem->len); - if (!end) end = start + elem->len; +static HRESULT init_propvar_from_string(const WCHAR *str, PROPVARIANT *var) +{ + size_t size = (wcslen(str) + 1) * sizeof(*str); + WCHAR *s;
- p = wmemchr(start, ':', end - start); - if (p) + if (!(s = CoTaskMemAlloc(size))) + return E_OUTOFMEMORY; + memcpy(s, str, size); + + var->pwszVal = s; + var->vt = VT_LPWSTR; + return S_OK; +} + +static void parse_query_name(struct query_parser *parser, PROPVARIANT *item) +{ + size_t len = 0; + + while (*parser->ptr && (*parser->ptr != '/' && *parser->ptr != ':')) { - next_elem.str = p + 1; - next_elem.len = end - p - 1; + if (parser_unescape(parser)) break; + parser->scratch[len++] = *parser->ptr; + parser->ptr++; + }
- elem->len = p - start; + if (!len) + { + parser->hr = WINCODEC_ERR_INVALIDQUERYREQUEST; + return; } + + parser->scratch[len] = 0; + + parser->hr = init_propvar_from_string(parser->scratch, item); +} + +static void parse_query_item(struct query_parser *parser, PROPVARIANT *item) +{ + if (FAILED(parser->hr)) + return; + + if (*parser->ptr == '{') + parse_query_data_item(parser, item); else - elem->len = end - start; + parse_query_name(parser, item); +}
- id->vt = VT_BSTR; - id->bstrVal = SysAllocStringLen(NULL, elem->len + 1); - if (!id->bstrVal) return E_OUTOFMEMORY; +static void parse_query_component(struct query_parser *parser) +{ + struct query_component comp = { 0 }; + GUID guid;
- bstr = id->bstrVal; - p = elem->str; - while (p - elem->str < elem->len) + if (*parser->ptr != '/') { - if (*p == '\') p++; - *bstr++ = *p++; + parser->hr = WINCODEC_ERR_PROPERTYNOTSUPPORTED; + return; } - *bstr = 0; - TRACE("%s [%d]\n", wine_dbgstr_variant((VARIANT *)id), *idx); + parser->ptr++; + + /* Optional index */ + if (*parser->ptr == '[') + parse_query_index(parser, &comp.index);
- if (*p == ':') + parse_query_item(parser, &comp.id); + if (*parser->ptr == ':') { - PROPVARIANT next_id, next_schema; - int next_idx = 0; + parser_skip_char(parser, ':');
- hr = get_token(&next_elem, &next_id, &next_schema, &next_idx); - if (hr != S_OK) + comp.schema = comp.id; + PropVariantInit(&comp.id); + parse_query_item(parser, &comp.id); + } + + /* Resolve known names. */ + if (comp.id.vt == VT_LPWSTR) + { + if (SUCCEEDED(WICMapShortNameToGuid(comp.id.pwszVal, &guid))) { - TRACE("get_token error %#lx\n", hr); - PropVariantClear(id); - PropVariantClear(schema); - return hr; + PropVariantClear(&comp.id); + parser->hr = InitPropVariantFromCLSID(&guid, &comp.id); } - elem->len += next_elem.len + 1; - - TRACE("id %s [%d]\n", wine_dbgstr_wn(elem->str, elem->len), *idx); + }
- if (next_schema.vt != VT_EMPTY) + if (SUCCEEDED(parser->hr)) + { + if (comp.id.vt == VT_CLSID) { - PropVariantClear(&next_id); - PropVariantClear(&next_schema); - PropVariantClear(id); - PropVariantClear(schema); - return WINCODEC_ERR_WRONGSTATE; + PropVariantClear(&comp.schema); + if (comp.index) + { + comp.schema.vt = VT_UI2; + comp.schema.uiVal = comp.index; + } }
- *schema = *id; - *id = next_id; + if (!wincodecs_array_reserve((void **)&parser->components, &parser->capacity, + parser->count + 1, sizeof(*parser->components))) + { + parser->hr = E_OUTOFMEMORY; + PropVariantClear(&comp.schema); + PropVariantClear(&comp.id); + } + else + { + parser->components[parser->count++] = comp; + } } - - return S_OK; }
-static HRESULT find_reader_from_block(IWICMetadataBlockReader *block_reader, UINT index, - GUID *guid, IWICMetadataReader **reader) +static HRESULT parser_set_top_level_metadata_handler(struct query_handler *query_handler, + struct query_parser *parser) { + struct query_component *comp; + IWICMetadataReader *handler; HRESULT hr; GUID format; - IWICMetadataReader *new_reader; UINT count, i, matched_index;
- *reader = NULL; + comp = &parser->components[0]; + if (comp->id.vt != VT_CLSID) + return E_UNEXPECTED;
- hr = IWICMetadataBlockReader_GetCount(block_reader, &count); + hr = IWICMetadataBlockReader_GetCount(query_handler->object.block_reader, &count); if (hr != S_OK) return hr;
matched_index = 0;
- for (i = 0; i < count; i++) + for (i = 0; i < count; ++i) { - hr = IWICMetadataBlockReader_GetReaderByIndex(block_reader, i, &new_reader); - if (hr != S_OK) return hr; + if (is_writer_handler(query_handler)) + hr = IWICMetadataBlockWriter_GetWriterByIndex(query_handler->object.block_writer, i, (IWICMetadataWriter **)&handler); + else + hr = IWICMetadataBlockReader_GetReaderByIndex(query_handler->object.block_reader, i, &handler); + + if (FAILED(hr)) + break;
- hr = IWICMetadataReader_GetMetadataFormat(new_reader, &format); + hr = IWICMetadataReader_GetMetadataFormat(handler, &format); if (hr == S_OK) { - if (IsEqualGUID(&format, guid)) + if (IsEqualGUID(&format, comp->id.puuid)) { - if (matched_index == index) - { - *reader = new_reader; - return S_OK; - } + if (matched_index == comp->index) + break;
matched_index++; } }
- IWICMetadataReader_Release(new_reader); - if (hr != S_OK) return hr; + IWICMetadataReader_Release(handler); + handler = NULL; + + if (hr != S_OK) break; }
- return WINCODEC_ERR_PROPERTYNOTFOUND; + if (FAILED(hr)) return hr; + + comp->handler = handler; + return comp->handler ? S_OK : WINCODEC_ERR_PROPERTYNOTFOUND; }
-static HRESULT get_next_reader(IWICMetadataReader *reader, UINT index, - GUID *guid, IWICMetadataReader **new_reader) +static void parser_resolve_component_handlers(struct query_handler *query_handler, struct query_parser *parser) { - HRESULT hr; - PROPVARIANT schema, id, value; + PROPVARIANT value; + const WCHAR *url; + GUID guid; + size_t i;
- *new_reader = NULL; + if (FAILED(parser->hr = parser_set_top_level_metadata_handler(query_handler, parser))) + return;
- PropVariantInit(&schema); - PropVariantInit(&id); - PropVariantInit(&value); - - if (index) + /* First component is handled via block reader/writer. */ + for (i = 1; i < parser->count; ++i) { - schema.vt = VT_UI2; - schema.uiVal = index; - } + struct query_component *prev_comp = &parser->components[i - 1]; + struct query_component *comp = &parser->components[i];
- id.vt = VT_CLSID; - id.puuid = guid; - hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value); - if (hr != S_OK) return hr; + if (!prev_comp->handler) + continue;
- if (value.vt == VT_UNKNOWN) - hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataReader, (void **)new_reader); - else - hr = WINCODEC_ERR_UNEXPECTEDMETADATATYPE; + /* Expand schema urls for "known" formats. */ + if (comp->schema.vt == VT_LPWSTR) + { + if (SUCCEEDED(IWICMetadataReader_GetMetadataFormat(prev_comp->handler, &guid))) + { + url = map_shortname_to_schema(&guid, comp->schema.pwszVal); + if (url) + { + PropVariantClear(&comp->schema); + init_propvar_from_string(url, &comp->schema); + } + } + }
- PropVariantClear(&value); - return hr; + PropVariantInit(&value); + if (FAILED(parser->hr = IWICMetadataReader_GetValue(prev_comp->handler, &comp->schema, &comp->id, &value))) + break; + + if (value.vt == VT_UNKNOWN) + { + parser->hr = IUnknown_QueryInterface(value.punkVal, is_writer_handler(query_handler) ? + &IID_IWICMetadataWriter : &IID_IWICMetadataReader, (void **)&comp->handler); + } + PropVariantClear(&value); + + if (FAILED(parser->hr)) + break; + } }
-static HRESULT WINAPI query_handler_GetMetadataByName(IWICMetadataQueryWriter *iface, LPCWSTR query, PROPVARIANT *value) +static HRESULT parse_query(struct query_handler *query_handler, const WCHAR *user_query, + struct query_parser *parser) { - struct query_handler *This = impl_from_IWICMetadataQueryWriter(iface); - struct string_t elem; - WCHAR *full_query; - const WCHAR *p; - int index, len; - PROPVARIANT tk_id, tk_schema, new_value; - GUID guid; - IWICMetadataReader *reader; - HRESULT hr = S_OK; + WCHAR *query; + size_t len;
- TRACE("(%p,%s,%p)\n", This, wine_dbgstr_w(query), value); + memset(parser, 0, sizeof(*parser));
- len = lstrlenW(query) + 1; - if (This->root) len += lstrlenW(This->root); - full_query = malloc(len * sizeof(WCHAR)); - full_query[0] = 0; - if (This->root) - lstrcpyW(full_query, This->root); - lstrcatW(full_query, query); + len = wcslen(user_query) + 1; + if (query_handler->root) len += wcslen(query_handler->root);
- PropVariantInit(&tk_id); - PropVariantInit(&tk_schema); - PropVariantInit(&new_value); + if (!(query = malloc(len * sizeof(WCHAR)))) + return parser->hr = E_OUTOFMEMORY;
- reader = NULL; - p = full_query; + query[0] = 0; + if (query_handler->root) + wcscpy(query, query_handler->root); + wcscat(query, user_query);
- while (*p) + if (!(parser->scratch = malloc(len * sizeof(WCHAR)))) { - if (*p != '/') - { - WARN("query should start with '/'\n"); - hr = WINCODEC_ERR_PROPERTYNOTSUPPORTED; - break; - } + parser->hr = E_OUTOFMEMORY; + free(query); + return parser->hr; + }
- p++; + parser->query = query; + parser->ptr = query;
- index = 0; - elem.str = p; - elem.len = lstrlenW(p); - hr = get_token(&elem, &tk_id, &tk_schema, &index); - if (hr != S_OK) - { - WARN("get_token error %#lx\n", hr); - break; - } - TRACE("parsed %d characters: %s, index %d\n", elem.len, wine_dbgstr_wn(elem.str, elem.len), index); - TRACE("id %s, schema %s\n", wine_dbgstr_variant((VARIANT *)&tk_id), wine_dbgstr_variant((VARIANT *)&tk_schema)); + while (*parser->ptr && parser->hr == S_OK) + parse_query_component(parser);
- if (!elem.len) break; + if (FAILED(parser->hr)) return parser->hr;
- if (tk_id.vt == VT_CLSID || (tk_id.vt == VT_BSTR && WICMapShortNameToGuid(tk_id.bstrVal, &guid) == S_OK)) - { - WCHAR *root; + if (!parser->count) + return parser->hr = WINCODEC_ERR_INVALIDQUERYREQUEST;
- if (tk_schema.vt != VT_EMPTY) - { - FIXME("unsupported schema vt %u\n", tk_schema.vt); - PropVariantClear(&tk_schema); - } + parser_resolve_component_handlers(query_handler, parser);
- if (tk_id.vt == VT_CLSID) guid = *tk_id.puuid; + /* Validate that query is usable - it should produce an object or + an object followed by a value id. */ + if (SUCCEEDED(parser->hr)) + { + parser->last = &parser->components[parser->count - 1]; + if (parser->last->handler) + return S_OK;
- if (reader) - { - IWICMetadataReader *new_reader; + if (parser->count < 2) + return parser->hr = WINCODEC_ERR_INVALIDQUERYREQUEST;
- hr = get_next_reader(reader, index, &guid, &new_reader); - IWICMetadataReader_Release(reader); - reader = new_reader; - } - else - hr = find_reader_from_block(This->object.block_reader, index, &guid, &reader); + parser->prev = &parser->components[parser->count - 2]; + if (!parser->prev->handler) + return parser->hr = WINCODEC_ERR_INVALIDQUERYREQUEST; + }
- if (hr != S_OK) break; + return parser->hr; +}
- root = SysAllocStringLen(NULL, elem.str + elem.len - full_query + 2); - if (!root) - { - hr = E_OUTOFMEMORY; - break; - } - lstrcpynW(root, full_query, p - full_query + elem.len + 1); +static void parser_cleanup(struct query_parser *parser) +{ + size_t i;
- PropVariantClear(&new_value); - new_value.vt = VT_UNKNOWN; - hr = MetadataQueryReader_CreateInstance(This->object.block_reader, root, (IWICMetadataQueryReader **)&new_value.punkVal); - SysFreeString(root); - if (hr != S_OK) break; - } - else - { - PROPVARIANT schema, id; + for (i = 0; i < parser->count; ++i) + { + if (parser->components[i].handler) + IWICMetadataReader_Release(parser->components[i].handler); + PropVariantClear(&parser->components[i].schema); + PropVariantClear(&parser->components[i].id); + } + free(parser->components); + free(parser->scratch); + free(parser->query); +}
- if (!reader) - { - hr = WINCODEC_ERR_INVALIDQUERYREQUEST; - break; - } +static HRESULT WINAPI query_handler_GetMetadataByName(IWICMetadataQueryWriter *iface, LPCWSTR query, PROPVARIANT *ret) +{ + struct query_handler *handler = impl_from_IWICMetadataQueryWriter(iface); + struct query_component *comp; + struct query_parser parser; + PROPVARIANT value; + HRESULT hr;
- if (tk_schema.vt == VT_BSTR) - { - hr = IWICMetadataReader_GetMetadataFormat(reader, &guid); - if (hr != S_OK) break; + TRACE("(%p,%s,%p)\n", iface, wine_dbgstr_w(query), ret);
- schema.vt = VT_LPWSTR; - schema.pwszVal = (LPWSTR)map_shortname_to_schema(&guid, tk_schema.bstrVal); - if (!schema.pwszVal) - schema.pwszVal = tk_schema.bstrVal; - } - else - schema = tk_schema; + PropVariantInit(&value); + if (SUCCEEDED(hr = parse_query(handler, query, &parser))) + { + comp = parser.last;
- if (tk_id.vt == VT_BSTR) + if (comp->handler) + { + value.vt = VT_UNKNOWN; + if (is_writer_handler(handler)) { - id.vt = VT_LPWSTR; - id.pwszVal = tk_id.bstrVal; + hr = MetadataQueryWriter_CreateInstance(handler->object.block_writer, parser.query, + (IWICMetadataQueryWriter **)&value.punkVal); } else - id = tk_id; - - PropVariantClear(&new_value); - hr = IWICMetadataReader_GetValue(reader, &schema, &id, &new_value); - if (hr != S_OK) break; + { + hr = MetadataQueryReader_CreateInstance(handler->object.block_reader, parser.query, + (IWICMetadataQueryReader **)&value.punkVal); + } + } + else + { + hr = IWICMetadataReader_GetValue(parser.prev->handler, &comp->schema, &comp->id, &value); } - - p += elem.len; - - PropVariantClear(&tk_id); - PropVariantClear(&tk_schema); }
- if (reader) - IWICMetadataReader_Release(reader); - - PropVariantClear(&tk_id); - PropVariantClear(&tk_schema); - - if (hr == S_OK && value) - *value = new_value; + if (ret) + *ret = value; else - PropVariantClear(&new_value); + PropVariantClear(&value);
- free(full_query); + parser_cleanup(&parser);
return hr; } diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index ec236928d74..b680448f25c 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -4338,8 +4338,8 @@ static void test_queryreader(void) { FALSE, &data3, L"/[1]ifd/{str=R\}ATING}", S_OK, VT_LPSTR, 0, the_best },
{ FALSE, &data1, L"[0]/ifd/Rating", WINCODEC_ERR_PROPERTYNOTSUPPORTED }, - { TRUE, &data1, L"/[+1]ifd/Rating", WINCODEC_ERR_INVALIDQUERYCHARACTER }, - { TRUE, &data1, L"/[-1]ifd/Rating", WINCODEC_ERR_INVALIDQUERYCHARACTER }, + { FALSE, &data1, L"/[+1]ifd/Rating", WINCODEC_ERR_INVALIDQUERYCHARACTER }, + { FALSE, &data1, L"/[-1]ifd/Rating", WINCODEC_ERR_INVALIDQUERYCHARACTER }, { FALSE, &data1, L"/ifd/{\str=Rating}", WINCODEC_ERR_WRONGSTATE }, { FALSE, &data1, L"/ifd/{badtype=0}", WINCODEC_ERR_WRONGSTATE }, { TRUE, &data1, L"/ifd/{uint=0x1234}", DISP_E_TYPEMISMATCH }, @@ -5117,7 +5117,6 @@ static void test_metadata_App1(void) hr = IWICMetadataQueryReader_GetMetadataByName(query_reader, L"/app1/ifd/{ushort=34665}", &value); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(value.vt == VT_UNKNOWN, "Unexpected value type: %u.\n", value.vt); - todo_wine check_interface(value.punkVal, &IID_IWICMetadataQueryReader, TRUE); PropVariantClear(&value);
@@ -5125,7 +5124,6 @@ static void test_metadata_App1(void) hr = IWICMetadataQueryReader_GetMetadataByName(query_reader, L"/app1/ifd/{ushort=34853}", &value); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(value.vt == VT_UNKNOWN, "Unexpected value type: %u.\n", value.vt); - todo_wine check_interface(value.punkVal, &IID_IWICMetadataQueryReader, TRUE); PropVariantClear(&value);
@@ -5141,19 +5139,14 @@ static void test_metadata_App1(void) ok(value.vt == VT_UNKNOWN, "Unexpected value type: %u.\n", value.vt);
check_interface(value.punkVal, &IID_IWICMetadataQueryReader, TRUE); - todo_wine check_interface(value.punkVal, &IID_IWICMetadataQueryWriter, TRUE);
hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataQueryWriter, (void **)&query_writer2); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - { - hr = IWICMetadataQueryWriter_GetLocation(query_writer2, ARRAY_SIZE(path), path, &length); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(!lstrcmpW(path, L"/app1"), "Unexpected path %s.\n", wine_dbgstr_w(path)); - IWICMetadataQueryWriter_Release(query_writer2); - } + hr = IWICMetadataQueryWriter_GetLocation(query_writer2, ARRAY_SIZE(path), path, &length); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!lstrcmpW(path, L"/app1"), "Unexpected path %s.\n", wine_dbgstr_w(path)); + IWICMetadataQueryWriter_Release(query_writer2); PropVariantClear(&value);
PropVariantInit(&value); @@ -5161,18 +5154,15 @@ static void test_metadata_App1(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(value.vt == VT_UNKNOWN, "Unexpected value type: %u.\n", value.vt); hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataQueryWriter, (void **)&query_writer2); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - { - hr = IWICMetadataQueryWriter_GetLocation(query_writer2, ARRAY_SIZE(path), path, &length); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(!lstrcmpW(path, L"/app1/ifd"), "Unexpected path %s.\n", wine_dbgstr_w(path)); - hr = IWICMetadataQueryWriter_GetContainerFormat(query_writer2, &format); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); - IWICMetadataQueryWriter_Release(query_writer2); - } + hr = IWICMetadataQueryWriter_GetLocation(query_writer2, ARRAY_SIZE(path), path, &length); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!lstrcmpW(path, L"/app1/ifd"), "Unexpected path %s.\n", wine_dbgstr_w(path)); + hr = IWICMetadataQueryWriter_GetContainerFormat(query_writer2, &format); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine + ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); + IWICMetadataQueryWriter_Release(query_writer2); PropVariantClear(&value);
PropVariantInit(&value); @@ -5180,18 +5170,15 @@ static void test_metadata_App1(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(value.vt == VT_UNKNOWN, "Unexpected value type: %u.\n", value.vt); hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataQueryWriter, (void **)&query_writer2); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - { - hr = IWICMetadataQueryWriter_GetLocation(query_writer2, ARRAY_SIZE(path), path, &length); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(!lstrcmpW(path, L"/app1/ifd/gps"), "Unexpected path %s.\n", wine_dbgstr_w(path)); - hr = IWICMetadataQueryWriter_GetContainerFormat(query_writer2, &format); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(IsEqualGUID(&format, &GUID_MetadataFormatGps), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); - IWICMetadataQueryWriter_Release(query_writer2); - } + hr = IWICMetadataQueryWriter_GetLocation(query_writer2, ARRAY_SIZE(path), path, &length); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!lstrcmpW(path, L"/app1/ifd/gps"), "Unexpected path %s.\n", wine_dbgstr_w(path)); + hr = IWICMetadataQueryWriter_GetContainerFormat(query_writer2, &format); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine + ok(IsEqualGUID(&format, &GUID_MetadataFormatGps), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); + IWICMetadataQueryWriter_Release(query_writer2); PropVariantClear(&value);
PropVariantInit(&value); @@ -5199,18 +5186,15 @@ static void test_metadata_App1(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(value.vt == VT_UNKNOWN, "Unexpected value type: %u.\n", value.vt); hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataQueryWriter, (void **)&query_writer2); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - { - hr = IWICMetadataQueryWriter_GetLocation(query_writer2, ARRAY_SIZE(path), path, &length); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(!lstrcmpW(path, L"/app1/ifd/exif"), "Unexpected path %s.\n", wine_dbgstr_w(path)); - hr = IWICMetadataQueryWriter_GetContainerFormat(query_writer2, &format); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(IsEqualGUID(&format, &GUID_MetadataFormatExif), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); - IWICMetadataQueryWriter_Release(query_writer2); - } + hr = IWICMetadataQueryWriter_GetLocation(query_writer2, ARRAY_SIZE(path), path, &length); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!lstrcmpW(path, L"/app1/ifd/exif"), "Unexpected path %s.\n", wine_dbgstr_w(path)); + hr = IWICMetadataQueryWriter_GetContainerFormat(query_writer2, &format); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine + ok(IsEqualGUID(&format, &GUID_MetadataFormatExif), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); + IWICMetadataQueryWriter_Release(query_writer2); PropVariantClear(&value);
PropVariantInit(&value); @@ -5235,9 +5219,7 @@ static void test_metadata_App1(void) hr = IWICMetadataQueryWriter_GetMetadataByName(query_writer, L"/app1/ifd/{ushort=34665}", &value); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(value.vt == VT_UNKNOWN, "Unexpected value type: %u.\n", value.vt); - todo_wine check_interface(value.punkVal, &IID_IWICMetadataQueryReader, TRUE); - todo_wine check_interface(value.punkVal, &IID_IWICMetadataQueryWriter, TRUE); PropVariantClear(&value);