[PATCH v2 0/3] MR11548: rometadata: IMetaDataImport implementation, part 4
Implement `EnumMembers`, `EnumMembersWithName`, and `FindMember`. Also add some tests for `EnumCustomAttributes` and `GetCustomAttributeProps`. -- v2: rometadata: Add tests for IMetaDataImport::{EnumCustomAttributes, GetCustomAttributeProps}. https://gitlab.winehq.org/wine/wine/-/merge_requests/11548
From: Vibhav Pant <vibhavp@gmail.com> --- MAINTAINERS | 4 +++ dlls/rometadata/mdtables.c | 57 +++++++++++++++++++++++++++--- dlls/rometadata/tests/rometadata.c | 44 +++++++++++------------ 3 files changed, 78 insertions(+), 27 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 9426d3f117c..02eadb08131 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -423,6 +423,10 @@ WinRT Devices P: Vibhav Pant <vibhavp@gmail.com> @vibhavp F: dlls/windows.devices.enumeration/ +WinRT Metadata +P: Vibhav Pant <vibhavp@gmail.com> @vibhavp +F: dlls/rometadata/ + X11 Driver M: Alexandre Julliard <julliard@winehq.org> @julliard P: Rémi Bernon <rbernon@codeweavers.com> @rbernon diff --git a/dlls/rometadata/mdtables.c b/dlls/rometadata/mdtables.c index b8c8475ce20..5559a058880 100644 --- a/dlls/rometadata/mdtables.c +++ b/dlls/rometadata/mdtables.c @@ -1,7 +1,7 @@ /* * IMetaDataTables, IMetaDataImport implementation * - * Copyright 2025 Vibhav Pant + * Copyright 2025-2026 Vibhav Pant * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -789,15 +789,62 @@ static HRESULT WINAPI import_ResolveTypeRef(IMetaDataImport *iface, mdTypeRef ty static HRESULT WINAPI import_EnumMembers(IMetaDataImport *iface, HCORENUM *henum, mdTypeDef type_def, mdToken *member_defs, ULONG len, ULONG *count) { - FIXME("(%p, %p, %#x, %p, %lu, %p): stub!\n", iface, henum, type_def, member_defs, len, count); - return E_NOTIMPL; + TRACE("(%p, %p, %s, %p, %lu, %p)\n", iface, henum, debugstr_mdToken(type_def), member_defs, len, count); + return IMetaDataImport_EnumMembersWithName(iface, henum, type_def, NULL, member_defs, len, count); } static HRESULT WINAPI import_EnumMembersWithName(IMetaDataImport *iface, HCORENUM *henum, mdTypeDef token, const WCHAR *name, mdToken *member_defs, ULONG len, ULONG *count) { - FIXME("(%p, %p, %#x, %s, %p, %lu, %p): stub!\n", iface, henum, token, debugstr_w(name), member_defs, len, count); - return E_NOTIMPL; + TRACE("(%p, %p, %s, %s, %p, %lu, %p)\n", iface, henum, debugstr_mdToken(token), debugstr_w(name), member_defs, len, + count); + + if (!*henum) + { + HCORENUM methods_enum = NULL, fields_enum = NULL; + ULONG methods_len, fields_len; + mdToken *tokens = NULL; + HRESULT hr; + + if (FAILED((hr = IMetaDataImport_EnumMethodsWithName(iface, &methods_enum, token, name, NULL, 0, NULL)))) + return hr; + if (FAILED((hr = IMetaDataImport_CountEnum(iface, methods_enum, &methods_len)))) goto done; + + if (FAILED((hr = IMetaDataImport_EnumFieldsWithName(iface, &fields_enum, token, name, NULL, 0, NULL)))) + goto done; + if (FAILED((hr = IMetaDataImport_CountEnum(iface, fields_enum, &fields_len)))) goto done; + + if (!methods_len && !fields_len) + { + hr = S_FALSE; + goto done; + } + if (!(tokens = calloc(methods_len + fields_len, sizeof(*tokens)))) + { + hr = E_OUTOFMEMORY; + goto done; + } + if (methods_len) + { + hr = IMetaDataImport_EnumMethodsWithName(iface, &methods_enum, token, name, tokens, methods_len, NULL); + if (FAILED(hr)) goto done; + } + if (fields_len) + { + hr = IMetaDataImport_EnumFieldsWithName(iface, &fields_enum, token, name, &tokens[methods_len], fields_len, + NULL); + if (FAILED(hr)) goto done; + } + done: + IMetaDataImport_CloseEnum(iface, methods_enum); + IMetaDataImport_CloseEnum(iface, fields_enum); + if (hr == S_OK) + hr = token_enum_list_create(henum, methods_len + fields_len, tokens); + free(tokens); + if (hr != S_OK) return hr; + } + + return token_enum_get_entries(*henum, member_defs, len, count); } static HRESULT table_create_enum_from_token_list(IMetaDataTables *iface, enum table table, enum table list_table, diff --git a/dlls/rometadata/tests/rometadata.c b/dlls/rometadata/tests/rometadata.c index a426934a399..3dc29f77da4 100644 --- a/dlls/rometadata/tests/rometadata.c +++ b/dlls/rometadata/tests/rometadata.c @@ -1216,14 +1216,14 @@ static void test_IMetaDataImport(void) henum2 = NULL; token = mdTokenNil; hr = IMetaDataImport_EnumMembersWithName(md_import, &henum2, typedef2, name, &token, 1, NULL); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(!!henum2, "got henum2 %p\n", henum2); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(!!henum2, "got henum2 %p\n", henum2); buf_len2 = 0; hr = IMetaDataImport_CountEnum(md_import, henum2, &buf_len2); ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(buf_len2 == 1, "got buf_len2 %lu\n", buf_len2); - todo_wine ok(token == methoddef_tokens[i], "got token %s != %s\n", debugstr_mdToken(token), - debugstr_mdToken(methoddef_tokens[i])); + ok(buf_len2 == 1, "got buf_len2 %lu\n", buf_len2); + ok(token == methoddef_tokens[i], "got token %s != %s\n", debugstr_mdToken(token), + debugstr_mdToken(methoddef_tokens[i])); IMetaDataImport_CloseEnum(md_import, henum2); winetest_pop_context(); @@ -1248,22 +1248,22 @@ static void test_IMetaDataImport(void) henum = NULL; hr = IMetaDataImport_EnumMembers(md_import, &henum, typedef2, NULL, 0, NULL); - todo_wine ok(hr == S_FALSE, "got hr %#lx\n", hr); - todo_wine ok(!!henum, "got henum %p\n", henum); + ok(hr == S_FALSE, "got hr %#lx\n", hr); + ok(!!henum, "got henum %p\n", henum); buf_len2 = 0; hr = IMetaDataImport_CountEnum(md_import, henum, &buf_len2); ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(buf_len2 == buf_len, "got buf_len2 %lu != %lu\n", buf_len2, buf_len); + ok(buf_len2 == buf_len, "got buf_len2 %lu != %lu\n", buf_len2, buf_len); IMetaDataImport_CloseEnum(md_import, henum); henum = NULL; hr = IMetaDataImport_EnumMembersWithName(md_import, &henum, typedef2, NULL, NULL, 0, NULL); - todo_wine ok(hr == S_FALSE, "got hr %#lx\n", hr); - todo_wine ok(!!henum, "got henum %p\n", henum); + ok(hr == S_FALSE, "got hr %#lx\n", hr); + ok(!!henum, "got henum %p\n", henum); buf_len2 = 0; hr = IMetaDataImport_CountEnum(md_import, henum, &buf_len2); ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(buf_len2 == buf_len, "got buf_len2 %lu != %lu\n", buf_len2, buf_len); + ok(buf_len2 == buf_len, "got buf_len2 %lu != %lu\n", buf_len2, buf_len); IMetaDataImport_CloseEnum(md_import, henum); for (i = 0; i < ARRAY_SIZE(field_enum_test_cases); i++) @@ -1309,22 +1309,22 @@ static void test_IMetaDataImport(void) henum = NULL; hr = IMetaDataImport_EnumMembers(md_import, &henum, typedef1, NULL, 0, NULL); - todo_wine ok(hr == S_FALSE, "got hr %#lx\n", hr); - todo_wine ok(!!henum, "got henum %p\n", henum); + ok(hr == S_FALSE, "got hr %#lx\n", hr); + ok(!!henum, "got henum %p\n", henum); buf_len2 = 0; hr = IMetaDataImport_CountEnum(md_import, henum, &buf_len2); ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(buf_len2 == buf_len, "got buf_len2 %lu != %lu\n", buf_len2, buf_len); + ok(buf_len2 == buf_len, "got buf_len2 %lu != %lu\n", buf_len2, buf_len); IMetaDataImport_CloseEnum(md_import, henum); henum = NULL; hr = IMetaDataImport_EnumMembersWithName(md_import, &henum, typedef1, NULL, NULL, 0, NULL); - todo_wine ok(hr == S_FALSE, "got hr %#lx\n", hr); - todo_wine ok(!!henum, "got henum %p\n", henum); + ok(hr == S_FALSE, "got hr %#lx\n", hr); + ok(!!henum, "got henum %p\n", henum); buf_len2 = 0; hr = IMetaDataImport_CountEnum(md_import, henum, &buf_len2); ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(buf_len2 == buf_len, "got buf_len2 %lu != %lu\n", buf_len2, buf_len); + ok(buf_len2 == buf_len, "got buf_len2 %lu != %lu\n", buf_len2, buf_len); IMetaDataImport_CloseEnum(md_import, henum); for (field_idx = 0; field_idx < buf_len; field_idx++) @@ -1374,14 +1374,14 @@ static void test_IMetaDataImport(void) henum = NULL; fielddef = mdFieldDefNil; hr = IMetaDataImport_EnumMembersWithName(md_import, &henum, typedef2, name, &fielddef, 1, NULL); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(!!henum, "got henum %p\n", henum); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(!!henum, "got henum %p\n", henum); buf_len2 = 0; hr = IMetaDataImport_CountEnum(md_import, henum, &buf_len2); ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(buf_len2 == 1, "got buf_len2 %lu\n", buf_len2); - todo_wine ok(fielddef == fielddef_tokens[field_idx], "got fielddef %s != %s\n", debugstr_mdToken(fielddef), - debugstr_mdToken(fielddef_tokens[field_idx])); + ok(buf_len2 == 1, "got buf_len2 %lu\n", buf_len2); + ok(fielddef == fielddef_tokens[field_idx], "got fielddef %s != %s\n", debugstr_mdToken(fielddef), + debugstr_mdToken(fielddef_tokens[field_idx])); IMetaDataImport_CloseEnum(md_import, henum); fielddef = mdFieldDefNil; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11548
From: Vibhav Pant <vibhavp@gmail.com> --- dlls/rometadata/mdtables.c | 15 +++++++++++++-- dlls/rometadata/tests/rometadata.c | 28 ++++++++++++++-------------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/dlls/rometadata/mdtables.c b/dlls/rometadata/mdtables.c index 5559a058880..13e36a84c21 100644 --- a/dlls/rometadata/mdtables.c +++ b/dlls/rometadata/mdtables.c @@ -1115,8 +1115,19 @@ static HRESULT WINAPI import_EnumPermissionSets(IMetaDataImport *iface, HCORENUM static HRESULT WINAPI import_FindMember(IMetaDataImport *iface, mdTypeDef type_def, const WCHAR *name, const COR_SIGNATURE *sig_blob, ULONG len, mdToken *member_ref) { - FIXME("(%p, %#x, %s, %p, %lu, %p): stub!\n", iface, type_def, debugstr_w(name), sig_blob, len, member_ref); - return E_NOTIMPL; + HRESULT hr; + + TRACE("(%p, %s, %s, %p, %lu, %p)\n", iface, debugstr_mdToken(type_def), debugstr_w(name), sig_blob, len, + member_ref); + + if (!name) return E_INVALIDARG; + if (IsNilToken(type_def) || TypeFromToken(type_def) != mdtTypeDef) return S_FALSE; + + /* If a method and a field have the same name, native returns the method. */ + hr = IMetaDataImport_FindMethod(iface, type_def, name, sig_blob, len, member_ref); + if (hr == CLDB_E_RECORD_NOTFOUND) + hr = IMetaDataImport_FindField(iface, type_def, name, sig_blob, len, member_ref); + return hr; } static HRESULT WINAPI import_FindMethod(IMetaDataImport *iface, mdTypeDef type_def, const WCHAR *name, diff --git a/dlls/rometadata/tests/rometadata.c b/dlls/rometadata/tests/rometadata.c index 3dc29f77da4..733ded128b7 100644 --- a/dlls/rometadata/tests/rometadata.c +++ b/dlls/rometadata/tests/rometadata.c @@ -1204,14 +1204,14 @@ static void test_IMetaDataImport(void) token = mdTokenNil; hr = IMetaDataImport_FindMember(md_import, typedef2, name, sig_blob, sig_len, &token); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(token == methoddef_tokens[i], "got token %s != %s\n", debugstr_mdToken(token), - debugstr_mdToken(methoddef_tokens[i])); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(token == methoddef_tokens[i], "got token %s != %s\n", debugstr_mdToken(token), + debugstr_mdToken(methoddef_tokens[i])); token = mdTokenNil; hr = IMetaDataImport_FindMember(md_import, typedef2, name, NULL, 0, &token); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(token == methoddef_tokens[i], "got token %s != %s\n", debugstr_mdToken(token), - debugstr_mdToken(methoddef_tokens[i])); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(token == methoddef_tokens[i], "got token %s != %s\n", debugstr_mdToken(token), + debugstr_mdToken(methoddef_tokens[i])); henum2 = NULL; token = mdTokenNil; @@ -1399,14 +1399,14 @@ static void test_IMetaDataImport(void) token = mdTokenNil; hr = IMetaDataImport_FindMember(md_import, typedef2, name, sig_blob, sig_len, &token); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(token == fielddef_tokens[field_idx], "got token %s != %s\n", debugstr_mdToken(token), - debugstr_mdToken(fielddef_tokens[field_idx])); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(token == fielddef_tokens[field_idx], "got token %s != %s\n", debugstr_mdToken(token), + debugstr_mdToken(fielddef_tokens[field_idx])); token = mdTokenNil; hr = IMetaDataImport_FindMember(md_import, typedef2, name, NULL, 0, &token); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(token == fielddef_tokens[field_idx], "got token %s != %s\n", debugstr_mdToken(token), - debugstr_mdToken(fielddef_tokens[field_idx])); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(token == fielddef_tokens[field_idx], "got token %s != %s\n", debugstr_mdToken(token), + debugstr_mdToken(fielddef_tokens[field_idx])); winetest_pop_context(); } @@ -1420,9 +1420,9 @@ static void test_IMetaDataImport(void) ok(hr == CLDB_E_RECORD_NOTFOUND, "got hr %#lx\n", hr); hr = IMetaDataImport_FindMember(md_import, typedef1, NULL, NULL, 0, &token); - todo_wine ok(hr == E_INVALIDARG, "got hr %#lx\n", hr); + ok(hr == E_INVALIDARG, "got hr %#lx\n", hr); hr = IMetaDataImport_FindMember(md_import, typedef1, L"foo", NULL, 0, &token); - todo_wine ok(hr == CLDB_E_RECORD_NOTFOUND, "got hr %#lx\n", hr); + ok(hr == CLDB_E_RECORD_NOTFOUND, "got hr %#lx\n", hr); typedef1 = buf_len = 0; data = NULL; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11548
From: Vibhav Pant <vibhavp@gmail.com> --- dlls/rometadata/tests/rometadata.c | 46 +++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/dlls/rometadata/tests/rometadata.c b/dlls/rometadata/tests/rometadata.c index 733ded128b7..f05e116a9fd 100644 --- a/dlls/rometadata/tests/rometadata.c +++ b/dlls/rometadata/tests/rometadata.c @@ -1,6 +1,6 @@ /* * Copyright 2024 Zhiyi Zhang for CodeWeavers - * Copyright 2025 Vibhav Pant + * Copyright 2025-2026 Vibhav Pant * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -1499,6 +1499,50 @@ static void test_IMetaDataImport(void) ok(set_method == mdMethodDefNil, "got set_method %#x\n", set_method); winetest_pop_context(); } + + henum = NULL; + buf_count = 0; + hr = IMetaDataImport_EnumTypeDefs(md_import, &henum, &typedef1, 1, &buf_count); + ok(hr == S_OK, "got hr %#lx\n", hr); + i = 0; + while (hr == S_OK && i < buf_count) + { + ULONG j = 0, buf_count2 = 0; + mdCustomAttribute attr; + + henum2 = NULL; + winetest_push_context("i=%lu,typedef1=%s", i, debugstr_mdToken(typedef1)); + hr = IMetaDataImport_EnumCustomAttributes(md_import, &henum2, typedef1, mdTokenNil, &attr, 1, &buf_count2); + todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + while (hr == S_OK && j < buf_count2) + { + mdToken obj = mdTokenNil, type = mdTokenNil; + const BYTE *blob = NULL; + ULONG blob_len = 0; + + winetest_push_context("j=%lu,attr=%s", j, debugstr_mdToken(attr)); + hr = IMetaDataImport_GetCustomAttributeProps(md_import, attr, &obj, &type, &blob, &blob_len); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(obj == typedef1, "got obj %s != %s\n", debugstr_mdToken(obj), debugstr_mdToken(typedef1)); + ok(TypeFromToken(type) == mdtMemberRef || TypeFromToken(type) == mdtMethodDef, "got type %s\n", debugstr_mdToken(type)); + ok(!!blob, "got blob %p\n", blob); + ok(!!blob_len, "got blob_len %lu\n", blob_len); + if (++j < buf_count2) + { + hr = IMetaDataImport_EnumCustomAttributes(md_import, &henum2, typedef1, mdTokenNil, &attr, 1, NULL); + ok(SUCCEEDED(hr), "got hr %#lx\n", hr); + } + winetest_pop_context(); + } + IMetaDataImport_CloseEnum(md_import, henum2); + if (++i < buf_count) + { + hr = IMetaDataImport_EnumTypeDefs(md_import, &henum, &typedef1, 1, NULL); + ok(SUCCEEDED(hr), "got hr %#lx\n", hr); + } + winetest_pop_context(); + } + IMetaDataImport_CloseEnum(md_import, henum); IMetaDataImport_Release(md_import); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11548
The MAINTAINERS change should go in a separate commit. Otherwise this looks good. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11548#note_147632
participants (3)
-
Hans Leidekker (@hans) -
Vibhav Pant -
Vibhav Pant (@vibhavp)