[PATCH 0/6] MR9525: rometadata: IMetaDataImport implementation, part 1
From: Vibhav Pant <vibhavp(a)gmail.com> --- dlls/rometadata/assembly.c | 50 -------------------- dlls/rometadata/mdtables.c | 74 ++++++++++++++++++++++++++---- dlls/rometadata/rometadatapriv.h | 50 ++++++++++++++++++++ dlls/rometadata/tests/rometadata.c | 30 ++++++------ 4 files changed, 131 insertions(+), 73 deletions(-) diff --git a/dlls/rometadata/assembly.c b/dlls/rometadata/assembly.c index a76cf6099ec..83b8e7338bb 100644 --- a/dlls/rometadata/assembly.c +++ b/dlls/rometadata/assembly.c @@ -70,56 +70,6 @@ struct metadata_stream const BYTE *start; }; -enum table -{ - TABLE_MODULE = 0x00, - TABLE_TYPEREF = 0x01, - TABLE_TYPEDEF = 0x02, - TABLE_FIELDPTR = 0x03, - TABLE_FIELD = 0x04, - TABLE_METHODPTR = 0x05, - TABLE_METHODDEF = 0x06, - TABLE_PARAMPTR = 0x07, - TABLE_PARAM = 0x08, - TABLE_INTERFACEIMPL = 0x09, - TABLE_MEMBERREF = 0x0a, - TABLE_CONSTANT = 0x0b, - TABLE_CUSTOMATTRIBUTE = 0x0c, - TABLE_FIELDMARSHAL = 0x0d, - TABLE_DECLSECURITY = 0x0e, - TABLE_CLASSLAYOUT = 0x0f, - TABLE_FIELDLAYOUT = 0x10, - TABLE_STANDALONESIG = 0x11, - TABLE_EVENTMAP = 0x12, - TABLE_EVENTPTR = 0x13, - TABLE_EVENT = 0x14, - TABLE_PROPERTYMAP = 0x15, - TABLE_PROPERTYPTR = 0x16, - TABLE_PROPERTY = 0x17, - TABLE_METHODSEMANTICS = 0x18, - TABLE_METHODIMPL = 0x19, - TABLE_MODULEREF = 0x1a, - TABLE_TYPESPEC = 0x1b, - TABLE_IMPLMAP = 0x1c, - TABLE_FIELDRVA = 0x1d, - TABLE_ENCLOG = 0x1e, - TABLE_ENCMAP = 0x1f, - TABLE_ASSEMBLY = 0x20, - TABLE_ASSEMBLYPROCESSOR = 0x21, - TABLE_ASSEMBLYOS = 0x22, - TABLE_ASSEMBLYREF = 0x23, - TABLE_ASSEMBLYREFPROCESSOR = 0x24, - TABLE_ASSEMBLYREFOS = 0x25, - TABLE_FILE = 0x26, - TABLE_EXPORTEDTYPE = 0x27, - TABLE_MANIFESTRESOURCE = 0x28, - TABLE_NESTEDCLASS = 0x29, - TABLE_GENERICPARAM = 0x2a, - TABLE_METHODSPEC = 0x2b, - TABLE_GENERICPARAMCONSTRAINT = 0x2c, - TABLE_MAX = 0x2d -}; - enum coded_idx_type { CT_TypeDefOrRef = 64, diff --git a/dlls/rometadata/mdtables.c b/dlls/rometadata/mdtables.c index 8c9f4825584..8c073a3f165 100644 --- a/dlls/rometadata/mdtables.c +++ b/dlls/rometadata/mdtables.c @@ -317,27 +317,85 @@ static ULONG WINAPI import_Release(IMetaDataImport *iface) return IMetaDataTables_Release(&impl->IMetaDataTables_iface); } +struct token_enum +{ + ULONG count; + ULONG row_start; + ULONG row_cur; + ULONG row_end; +}; + +HRESULT token_enum_create(HCORENUM *out) +{ + struct token_enum *md_enum; + + if (!(md_enum = calloc(1, sizeof(*md_enum)))) return E_OUTOFMEMORY; + *out = md_enum; + return S_OK; +} + static void WINAPI import_CloseEnum(IMetaDataImport *iface, HCORENUM henum) { - FIXME("(%p, %p): stub!\n", iface, henum); + TRACE("(%p, %p)\n", iface, henum); + free(henum); } static HRESULT WINAPI import_CountEnum(IMetaDataImport *iface, HCORENUM henum, ULONG *count) { - FIXME("(%p, %p, %p): stub!\n", iface, henum, count); - return E_NOTIMPL; + const struct token_enum *md_enum = henum; + + TRACE("(%p, %p, %p)\n", iface, henum, count); + + *count = henum ? md_enum->count : 0; + return S_OK; } static HRESULT WINAPI import_ResetEnum(IMetaDataImport *iface, HCORENUM henum, ULONG idx) { - FIXME("(%p, %p, %lu): stub\n", iface, henum, idx); - return E_NOTIMPL; + struct token_enum *md_enum = henum; + + TRACE("(%p, %p, %lu)\n", iface, henum, idx); + + if (henum) + md_enum->row_cur = md_enum->row_start + idx; + return S_OK; } -static HRESULT WINAPI import_EnumTypeDefs(IMetaDataImport *iface, HCORENUM *henum, mdTypeDef *typedefs, ULONG len, ULONG *count) +static HRESULT WINAPI import_EnumTypeDefs(IMetaDataImport *iface, HCORENUM *ret_henum, mdTypeDef *typedefs, ULONG len, ULONG *count) { - FIXME("(%p, %p, %p, %lu, %p): stub!\n", iface, henum, typedefs, len, count); - return E_NOTIMPL; + struct metadata_tables *impl = impl_from_IMetaDataImport(iface); + ULONG row_size, rows, cols, key_idx, i = 0; + struct token_enum *henum = *ret_henum; + const char *name; + HRESULT hr; + + TRACE("(%p, %p, %p, %lu, %p)\n", iface, ret_henum, typedefs, len, count); + + if (count) + *count = 0; + + if (!henum) + { + hr = IMetaDataTables_GetTableInfo(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, &row_size, &rows, &cols, + &key_idx, &name); + if (FAILED(hr)) return hr; + /* Skip the <Module> row. */ + if (rows < 2) return S_FALSE; + if (FAILED((hr = token_enum_create((HCORENUM *)&henum)))) return hr; + + henum->count = rows - 1; + henum->row_start = henum->row_cur = 2; + henum->row_end = rows; + *ret_henum = henum; + } + + while (henum->row_cur <= henum->row_end && i < len) + typedefs[i++] = TokenFromRid(henum->row_cur++, mdtTypeDef); + + if (count) + *count = i; + + return i ? S_OK : S_FALSE; } static HRESULT WINAPI import_EnumInterfaceImpls(IMetaDataImport *iface, HCORENUM *henum, mdTypeDef type_def, diff --git a/dlls/rometadata/rometadatapriv.h b/dlls/rometadata/rometadatapriv.h index 3e5ddaf8649..e91a50a133f 100644 --- a/dlls/rometadata/rometadatapriv.h +++ b/dlls/rometadata/rometadatapriv.h @@ -54,6 +54,56 @@ enum heap_type HEAP_USER_STRING = 3 }; +enum table +{ + TABLE_MODULE = 0x00, + TABLE_TYPEREF = 0x01, + TABLE_TYPEDEF = 0x02, + TABLE_FIELDPTR = 0x03, + TABLE_FIELD = 0x04, + TABLE_METHODPTR = 0x05, + TABLE_METHODDEF = 0x06, + TABLE_PARAMPTR = 0x07, + TABLE_PARAM = 0x08, + TABLE_INTERFACEIMPL = 0x09, + TABLE_MEMBERREF = 0x0a, + TABLE_CONSTANT = 0x0b, + TABLE_CUSTOMATTRIBUTE = 0x0c, + TABLE_FIELDMARSHAL = 0x0d, + TABLE_DECLSECURITY = 0x0e, + TABLE_CLASSLAYOUT = 0x0f, + TABLE_FIELDLAYOUT = 0x10, + TABLE_STANDALONESIG = 0x11, + TABLE_EVENTMAP = 0x12, + TABLE_EVENTPTR = 0x13, + TABLE_EVENT = 0x14, + TABLE_PROPERTYMAP = 0x15, + TABLE_PROPERTYPTR = 0x16, + TABLE_PROPERTY = 0x17, + TABLE_METHODSEMANTICS = 0x18, + TABLE_METHODIMPL = 0x19, + TABLE_MODULEREF = 0x1a, + TABLE_TYPESPEC = 0x1b, + TABLE_IMPLMAP = 0x1c, + TABLE_FIELDRVA = 0x1d, + TABLE_ENCLOG = 0x1e, + TABLE_ENCMAP = 0x1f, + TABLE_ASSEMBLY = 0x20, + TABLE_ASSEMBLYPROCESSOR = 0x21, + TABLE_ASSEMBLYOS = 0x22, + TABLE_ASSEMBLYREF = 0x23, + TABLE_ASSEMBLYREFPROCESSOR = 0x24, + TABLE_ASSEMBLYREFOS = 0x25, + TABLE_FILE = 0x26, + TABLE_EXPORTEDTYPE = 0x27, + TABLE_MANIFESTRESOURCE = 0x28, + TABLE_NESTEDCLASS = 0x29, + TABLE_GENERICPARAM = 0x2a, + TABLE_METHODSPEC = 0x2b, + TABLE_GENERICPARAMCONSTRAINT = 0x2c, + TABLE_MAX = 0x2d +}; + extern HRESULT assembly_open_from_file(const WCHAR *path, assembly_t **out); extern void assembly_free(assembly_t *assembly); extern HRESULT assembly_get_table(const assembly_t *assembly, ULONG table_idx, struct metadata_table_info *info); diff --git a/dlls/rometadata/tests/rometadata.c b/dlls/rometadata/tests/rometadata.c index a4fa39c6f5a..c8e33d86a81 100644 --- a/dlls/rometadata/tests/rometadata.c +++ b/dlls/rometadata/tests/rometadata.c @@ -1005,21 +1005,21 @@ static void test_IMetaDataImport(void) buf_count = 0xdeadbeef; henum = NULL; hr = IMetaDataImport_EnumTypeDefs(md_import, &henum, NULL, 0, &buf_count); - todo_wine ok(hr == S_FALSE, "got hr %#lx\n", hr); - todo_wine ok(buf_count == 0, "got buf_reqd %lu\n", buf_count); - todo_wine ok(!!henum, "got henum %p\n", henum); + ok(hr == S_FALSE, "got hr %#lx\n", hr); + ok(buf_count == 0, "got buf_reqd %lu\n", buf_count); + ok(!!henum, "got henum %p\n", henum); buf_len = 0; hr = IMetaDataImport_CountEnum(md_import, henum, &buf_len); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + ok(hr == S_OK, "got hr %#lx\n", hr); /* The <Module> typedef is ommitted. */ - todo_wine ok(buf_len == ARRAY_SIZE(type_defs), "got len %lu\n", buf_len); + ok(buf_len == ARRAY_SIZE(type_defs), "got len %lu\n", buf_len); typedef_tokens = calloc(buf_len, sizeof(*typedef_tokens)); ok(!!typedef_tokens, "got typedef_tokens %p\n", typedef_tokens); hr = IMetaDataImport_EnumTypeDefs(md_import, &henum, typedef_tokens, buf_len, &buf_count); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(buf_len == buf_count, "got len %lu != %lu\n", buf_len, buf_count); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(buf_len == buf_count, "got len %lu != %lu\n", buf_len, buf_count); for (i = 0; i < buf_len; i++) { const struct type_info *info = &type_defs[i]; @@ -1077,16 +1077,16 @@ static void test_IMetaDataImport(void) winetest_pop_context(); } hr = IMetaDataImport_EnumTypeDefs(md_import, &henum, typedef_tokens, buf_len, &buf_count); - todo_wine ok(hr == S_FALSE, "got hr %#lx\n", hr); + ok(hr == S_FALSE, "got hr %#lx\n", hr); hr = IMetaDataImport_ResetEnum(md_import, henum, 0); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + ok(hr == S_OK, "got hr %#lx\n", hr); buf_count = 0xdeadbeef; hr = IMetaDataImport_EnumTypeDefs(md_import, &henum, typedef_tokens, buf_len, &buf_count); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(buf_len == buf_count, "got len %lu != %lu\n", buf_len, buf_count); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(buf_len == buf_count, "got len %lu != %lu\n", buf_len, buf_count); hr = IMetaDataImport_EnumTypeDefs(md_import, &henum, typedef_tokens, buf_len, &buf_count); - todo_wine ok(hr == S_FALSE, "got hr %#lx\n", hr); + ok(hr == S_FALSE, "got hr %#lx\n", hr); IMetaDataImport_CloseEnum(md_import, henum); free(typedef_tokens); @@ -1109,7 +1109,7 @@ static void test_IMetaDataImport(void) todo_wine ok(buf_count == 0, "got buf_reqd %lu\n", buf_count); buf_len = 0; hr = IMetaDataImport_CountEnum(md_import, henum, &buf_len); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + ok(hr == S_OK, "got hr %#lx\n", hr); todo_wine ok(buf_len == ARRAY_SIZE(test2_methods), "got buf_len %#lx\n" , buf_len); methoddef_tokens = calloc(buf_len, sizeof(*methoddef_tokens)); ok(!!methoddef_tokens, "got methoddef_tokens %p\n", methoddef_tokens); @@ -1174,7 +1174,7 @@ static void test_IMetaDataImport(void) todo_wine ok(buf_count == 0, "got buf_count %lu\n", buf_count); buf_len = 0; hr = IMetaDataImport_CountEnum(md_import, henum, &buf_len); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + ok(hr == S_OK, "got hr %#lx\n", hr); todo_wine ok(buf_len == fields_len, "got buf_len %lu\n", buf_len); fielddef_tokens = calloc(buf_len, sizeof(*fielddef_tokens)); ok(!!fielddef_tokens, "got fielddef_tokens %p\n", fielddef_tokens); @@ -1241,7 +1241,7 @@ static void test_IMetaDataImport(void) hr = IMetaDataImport_EnumProperties(md_import, &henum, typedef1, NULL, 0, NULL); todo_wine ok(hr == S_FALSE, "got hr %#lx\n", hr); hr = IMetaDataImport_CountEnum(md_import, henum, &buf_len); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + ok(hr == S_OK, "got hr %#lx\n", hr); todo_wine ok(buf_len == ARRAY_SIZE(test3_props), "got buf_len %lu\n", buf_len); property_tokens = calloc(buf_len, sizeof(*property_tokens)); ok(!!property_tokens, "got property_tokens %p\n", property_tokens); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9525
From: Vibhav Pant <vibhavp(a)gmail.com> --- dlls/rometadata/mdtables.c | 74 ++++++++++++++++++++++++++++-- dlls/rometadata/tests/rometadata.c | 19 ++++---- 2 files changed, 80 insertions(+), 13 deletions(-) diff --git a/dlls/rometadata/mdtables.c b/dlls/rometadata/mdtables.c index 8c073a3f165..e5a5185b899 100644 --- a/dlls/rometadata/mdtables.c +++ b/dlls/rometadata/mdtables.c @@ -19,8 +19,12 @@ */ #include <assert.h> +#include <stdarg.h> #define COBJMACROS +#include "windef.h" +#include "winbase.h" +#include "winnls.h" #include "objbase.h" #include "cor.h" #include "rometadataapi.h" @@ -429,11 +433,75 @@ static HRESULT WINAPI import_GetModuleFromScope(IMetaDataImport *iface, mdModule return E_NOTIMPL; } +static BOOL type_full_name(WCHAR *out, ULONG out_len, ULONG *needed, const char *namespace, const char *name) +{ + ULONG full_name_len; + char *full_name; + + if (namespace[0] && name[0]) + full_name_len = strlen(namespace) + 1 + strlen(name) + 1; + else + full_name_len = strlen(namespace[0] ? namespace : name) + 1; + if (!(full_name = malloc(full_name_len))) return FALSE; + if (namespace[0] && name[0]) + snprintf(full_name, full_name_len, "%s.%s", namespace, name); + else + strcpy(full_name, namespace[0] ? namespace : name); + *needed = MultiByteToWideChar(CP_ACP, 0, full_name, -1, NULL, 0); + if (out && out_len) + { + ULONG n = MultiByteToWideChar(CP_ACP, 0, full_name, min(full_name_len, out_len) - 1, out, out_len - 1); + out[n] = L'\0'; + } + free(full_name); + return TRUE; +} + static HRESULT WINAPI import_GetTypeDefProps(IMetaDataImport *iface, mdTypeDef type_def, WCHAR *name, ULONG len, - ULONG *written, ULONG *flags, mdToken *base) + ULONG *written, ULONG *ret_flags, mdToken *base) { - FIXME("(%p, %#x, %p, %lu, %p, %p, %p): stub!\n", iface, type_def, name, len, written, flags, base); - return E_NOTIMPL; + struct metadata_tables *impl = impl_from_IMetaDataImport(iface); + ULONG needed = 0, flags = 0, extends = 0; + + TRACE("(%p, %#x, %p, %lu, %p, %p, %p)\n", iface, type_def, name, len, written, ret_flags, base); + + if (TypeFromToken(type_def) != mdtTypeDef) return S_FALSE; + + if (name && len) + name[0] = L'\0'; + if (type_def != mdTypeDefNil) + { + const ULONG row = RidFromToken(type_def); + const char *namespace, *nameA; + ULONG name_idx, ns_idx; + HRESULT hr; + + if (FAILED((hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, 0, row, &flags)))) + return hr; + if (FAILED((hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, 1, row, &name_idx)))) + return hr; + if (FAILED((hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, 2, row, &ns_idx)))) + return hr; + if (FAILED((hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, 3, row, &extends)))) + return hr; + if (FAILED(hr = IMetaDataTables_GetString(&impl->IMetaDataTables_iface, name_idx, &nameA))) + return hr; + if (FAILED(hr = IMetaDataTables_GetString(&impl->IMetaDataTables_iface, ns_idx, &namespace))) + return hr; + if (!type_full_name(name, len, &needed, namespace, nameA)) return E_OUTOFMEMORY; + /* Native replaces tokens with rid 0 with mdTypeRefNil. */ + if (IsNilToken(extends)) + extends = mdTypeRefNil; + } + + if (written) + *written = needed; + if (ret_flags) + *ret_flags = flags; + if (base) + *base = extends; + + return (name && needed > len) ? CLDB_S_TRUNCATION : S_OK; } static HRESULT WINAPI import_GetInterfaceImplProps(IMetaDataImport *iface, mdInterfaceImpl iface_impl, diff --git a/dlls/rometadata/tests/rometadata.c b/dlls/rometadata/tests/rometadata.c index c8e33d86a81..f3bbae157d7 100644 --- a/dlls/rometadata/tests/rometadata.c +++ b/dlls/rometadata/tests/rometadata.c @@ -1037,29 +1037,28 @@ static void test_IMetaDataImport(void) exp_len = snprintf(bufA, sizeof(bufA), "%s.%s", info->exp_namespace, info->exp_name) + 1; str_reqd = 0; hr = IMetaDataImport_GetTypeDefProps(md_import, typedef_tokens[i], NULL, 0, &str_reqd, NULL, NULL); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(str_reqd == exp_len, "got str_reqd %lu != %lu\n", str_reqd, exp_len); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(str_reqd == exp_len, "got str_reqd %lu != %lu\n", str_reqd, exp_len); MultiByteToWideChar(CP_ACP, 0, bufA, -1, bufW, ARRAY_SIZE(bufW)); str_len = str_reqd; strW = calloc(str_len, sizeof(WCHAR)); hr = IMetaDataImport_GetTypeDefProps(md_import, typedef_tokens[i], strW, str_len - 1, &str_reqd, &val, &base); - todo_wine ok(hr == CLDB_S_TRUNCATION, "got hr %#lx\n", hr); + ok(hr == CLDB_S_TRUNCATION, "got hr %#lx\n", hr); len = wcslen(strW); - todo_wine ok( len == str_len - 2, "got len %lu != %lu\n", len, str_len - 2); + ok( len == str_len - 2, "got len %lu != %lu\n", len, str_len - 2); if (hr == CLDB_S_TRUNCATION) - todo_wine ok(!wcsncmp(strW, bufW, str_len - 2), "got bufW %s != %s\n", debugstr_w(strW), - debugstr_wn(bufW, str_len - 2)); + ok(!wcsncmp(strW, bufW, str_len - 2), "got bufW %s != %s\n", debugstr_w(strW), + debugstr_wn(bufW, str_len - 2)); val = base = 0; hr = IMetaDataImport_GetTypeDefProps(md_import, typedef_tokens[i], strW, str_len, NULL, &val, &base); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + ok(hr == S_OK, "got hr %#lx\n", hr); if (hr == S_OK) ok(1 || !wcscmp(strW, bufW), "got strW %s != %s\n", debugstr_w(strW), debugstr_w(bufW)); free(strW); - todo_wine ok(val == info->exp_flags, "got val %#lx != %#lx\n", val, info->exp_flags); - todo_wine ok(base == info->exp_base, "got base %s != %s\n", debugstr_mdToken(base), - debugstr_mdToken(info->exp_base)); + ok(val == info->exp_flags, "got val %#lx != %#lx\n", val, info->exp_flags); + ok(base == info->exp_base, "got base %s != %s\n", debugstr_mdToken(base), debugstr_mdToken(info->exp_base)); hr = IMetaDataImport_FindTypeDefByName(md_import, bufW, 0, &token); todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9525
From: Vibhav Pant <vibhavp(a)gmail.com> --- dlls/rometadata/mdtables.c | 136 ++++++++++++++++++++++++++++- dlls/rometadata/tests/rometadata.c | 24 ++--- 2 files changed, 144 insertions(+), 16 deletions(-) diff --git a/dlls/rometadata/mdtables.c b/dlls/rometadata/mdtables.c index e5a5185b899..7794d9ce874 100644 --- a/dlls/rometadata/mdtables.c +++ b/dlls/rometadata/mdtables.c @@ -365,6 +365,56 @@ static HRESULT WINAPI import_ResetEnum(IMetaDataImport *iface, HCORENUM henum, U return S_OK; } +static const char *debugstr_mdToken(mdToken token) +{ +#define TYPE(t) { t, #t } + static const struct type_str + { + CorTokenType type; + const char *str; + } types[] = { + TYPE(mdtModule), + TYPE(mdtTypeRef), + TYPE(mdtTypeDef), + TYPE(mdtFieldDef), + TYPE(mdtMethodDef), + TYPE(mdtParamDef), + TYPE(mdtInterfaceImpl), + TYPE(mdtMemberRef), + TYPE(mdtCustomAttribute), + TYPE(mdtPermission), + TYPE(mdtSignature), + TYPE(mdtEvent), + TYPE(mdtProperty), + TYPE(mdtModuleRef), + TYPE(mdtTypeSpec), + TYPE(mdtAssembly), + TYPE(mdtAssemblyRef), + TYPE(mdtFile), + TYPE(mdtExportedType), + TYPE(mdtManifestResource), + TYPE(mdtGenericParam), + TYPE(mdtMethodSpec), + TYPE(mdtGenericParamConstraint), + TYPE(mdtString), + TYPE(mdtName), + TYPE(mdtBaseType) + }; +#undef TYPE + const CorTokenType type = TypeFromToken(token); + const UINT rid = RidFromToken(token); + int i; + + if (!token) return "(mdTokenNil)"; + for (i = 0; i < ARRAY_SIZE(types); i++) + { + if (type == types[i].type) + return rid ? wine_dbg_sprintf("(%s|%#x)", types[i].str, rid) + : wine_dbg_sprintf("(md%sNil)", &types[i].str[3]); + } + return wine_dbg_sprintf("(%#x|%#x)", type, rid); +} + static HRESULT WINAPI import_EnumTypeDefs(IMetaDataImport *iface, HCORENUM *ret_henum, mdTypeDef *typedefs, ULONG len, ULONG *count) { struct metadata_tables *impl = impl_from_IMetaDataImport(iface); @@ -415,10 +465,88 @@ static HRESULT WINAPI import_EnumTypeRefs(IMetaDataImport *iface, HCORENUM *henu return E_NOTIMPL; } -static HRESULT WINAPI import_FindTypeDefByName(IMetaDataImport *iface, const WCHAR *name, mdToken enclosing_class, mdTypeDef *type_def) +static void type_split_name(const char *nameA, const char **namespace, size_t *ns_len, const char **type_name) { - FIXME("(%p, %p, %#x, %p): stub!\n", iface, debugstr_w(name), enclosing_class, type_def); - return E_NOTIMPL; + const char *sep; + + if ((sep = strrchr(nameA, '.'))) + { + *namespace = nameA; + *ns_len = sep - nameA; + *type_name = &sep[1]; + } + else + { + *namespace = NULL; + *ns_len = 0; + *type_name = nameA; + } +} + +static HRESULT WINAPI import_FindTypeDefByName(IMetaDataImport *iface, const WCHAR *name, mdToken enclosing_class, + mdTypeDef *type_def) +{ + struct metadata_tables *impl = impl_from_IMetaDataImport(iface); + const char *namespace, *type_name; + HCORENUM henum = NULL; + mdTypeDef cur_typedef; + size_t len, ns_len; + BOOL found = FALSE; + char *nameA; + HRESULT hr; + + TRACE("(%p, %s, %s, %p)\n", iface, debugstr_w(name), debugstr_mdToken(enclosing_class), type_def); + + if (!name) return E_INVALIDARG; + if (!IsNilToken(enclosing_class) && enclosing_class != TokenFromRid(1, mdtModule)) + { + CorTokenType type = TypeFromToken(enclosing_class); + + if (type == mdtTypeDef || type == mdtTypeRef) + FIXME("unsupported enclosing_class: %s\n", debugstr_mdToken(enclosing_class)); + return CLDB_E_RECORD_NOTFOUND; + } + + len = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL); + if (!(nameA = malloc(len))) return E_OUTOFMEMORY; + WideCharToMultiByte(CP_ACP, 0, name, -1, nameA, len, NULL, NULL); + type_split_name(nameA, &namespace, &ns_len, &type_name); + + hr = IMetaDataImport_EnumTypeDefs(&impl->IMetaDataImport_iface, &henum, NULL, 0, NULL); + if (FAILED(hr)) + { + free(nameA); + return hr; + } + hr = IMetaDataImport_EnumTypeDefs(&impl->IMetaDataImport_iface, &henum, &cur_typedef, 1, NULL); + while (hr == S_OK) + { + ULONG row = RidFromToken(cur_typedef), idx; + const char *cur_type_name, *cur_ns; + + if (FAILED((hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, 1, row, &idx)))) break; + if (FAILED((hr = IMetaDataTables_GetString(&impl->IMetaDataTables_iface, idx, &cur_type_name)))) break; + if (FAILED((hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, 2, row, &idx)))) break; + if (FAILED((hr = IMetaDataTables_GetString(&impl->IMetaDataTables_iface, idx, &cur_ns)))) break; + + if (!!namespace == !!cur_ns[0] && + (!namespace || !strncmp(namespace, cur_ns, ns_len)) && + !strcmp(type_name, cur_type_name)) + { + found = TRUE; + *type_def = cur_typedef; + break; + } + hr = IMetaDataImport_EnumTypeDefs(&impl->IMetaDataImport_iface, &henum, &cur_typedef, 1, NULL); + } + IMetaDataImport_CloseEnum(&impl->IMetaDataImport_iface, henum); + free(nameA); + + if (found) + hr = S_OK; + else if (SUCCEEDED(hr)) + hr = CLDB_E_RECORD_NOTFOUND; + return hr; } static HRESULT WINAPI import_GetScopeProps(IMetaDataImport *iface, WCHAR *name, ULONG len, ULONG *written, GUID *mvid) @@ -463,7 +591,7 @@ static HRESULT WINAPI import_GetTypeDefProps(IMetaDataImport *iface, mdTypeDef t struct metadata_tables *impl = impl_from_IMetaDataImport(iface); ULONG needed = 0, flags = 0, extends = 0; - TRACE("(%p, %#x, %p, %lu, %p, %p, %p)\n", iface, type_def, name, len, written, ret_flags, base); + TRACE("(%p, %s, %p, %lu, %p, %p, %p)\n", iface, debugstr_mdToken(type_def), name, len, written, ret_flags, base); if (TypeFromToken(type_def) != mdtTypeDef) return S_FALSE; diff --git a/dlls/rometadata/tests/rometadata.c b/dlls/rometadata/tests/rometadata.c index f3bbae157d7..d150caffb04 100644 --- a/dlls/rometadata/tests/rometadata.c +++ b/dlls/rometadata/tests/rometadata.c @@ -1061,8 +1061,8 @@ static void test_IMetaDataImport(void) ok(base == info->exp_base, "got base %s != %s\n", debugstr_mdToken(base), debugstr_mdToken(info->exp_base)); hr = IMetaDataImport_FindTypeDefByName(md_import, bufW, 0, &token); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(token == typedef_tokens[i], "got token %s != %s\n", debugstr_mdToken(token), debugstr_mdToken(typedef_tokens[i])); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(token == typedef_tokens[i], "got token %s != %s\n", debugstr_mdToken(token), debugstr_mdToken(typedef_tokens[i])); if (info->exp_contract_name) { @@ -1090,17 +1090,17 @@ static void test_IMetaDataImport(void) free(typedef_tokens); hr = IMetaDataImport_FindTypeDefByName(md_import, NULL, 0, NULL); - todo_wine ok(hr == E_INVALIDARG, "got hr %#lx\n", hr); + ok(hr == E_INVALIDARG, "got hr %#lx\n", hr); hr = IMetaDataImport_FindTypeDefByName(md_import, L"Test2", 0, &typedef1); - todo_wine ok(hr == CLDB_E_RECORD_NOTFOUND, "got hr %#lx\n", hr); + ok(hr == CLDB_E_RECORD_NOTFOUND, "got hr %#lx\n", hr); hr = IMetaDataImport_FindTypeDefByName(md_import, NULL, 0, &typedef1); - todo_wine ok(hr == E_INVALIDARG, "got hr %#lx\n", hr); + ok(hr == E_INVALIDARG, "got hr %#lx\n", hr); typedef1 = 0; hr = IMetaDataImport_FindTypeDefByName(md_import, L"Wine.Test.Test2", 0, &typedef1); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine test_token(md_import, typedef1, mdtTypeDef, FALSE); + ok(hr == S_OK, "got hr %#lx\n", hr); + test_token(md_import, typedef1, mdtTypeDef, FALSE); buf_count = 0xdeadbeef; henum = NULL; hr = IMetaDataImport_EnumMethods(md_import, &henum, typedef1, NULL, 0, &buf_count); @@ -1163,8 +1163,8 @@ static void test_IMetaDataImport(void) typedef1 = 0; hr = IMetaDataImport_FindTypeDefByName(md_import, type_name, 0, &typedef1); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine test_token(md_import, typedef1, mdtTypeDef, FALSE); + ok(hr == S_OK, "got hr %#lx\n", hr); + test_token(md_import, typedef1, mdtTypeDef, FALSE); henum = NULL; buf_count = 0xdeadbeef; hr = IMetaDataImport_EnumFields(md_import, &henum, typedef1, NULL, 0, &buf_count); @@ -1221,8 +1221,8 @@ static void test_IMetaDataImport(void) typedef1 = buf_len = 0; data = NULL; hr = IMetaDataImport_FindTypeDefByName(md_import, L"Wine.Test.ITest2", 0, &typedef1); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine test_token(md_import, typedef1, mdtTypeDef, FALSE); + ok(hr == S_OK, "got hr %#lx\n", hr); + test_token(md_import, typedef1, mdtTypeDef, FALSE); hr = IMetaDataImport_GetCustomAttributeByName(md_import, typedef1, guid_attribute_name, &data, &buf_len); todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); todo_wine ok(!!data, "got data %p\n", data); @@ -1235,7 +1235,7 @@ static void test_IMetaDataImport(void) typedef1 = buf_len = 0; hr = IMetaDataImport_FindTypeDefByName(md_import, L"Wine.Test.ITest3", 0, &typedef1); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + ok(hr == S_OK, "got hr %#lx\n", hr); henum = NULL; hr = IMetaDataImport_EnumProperties(md_import, &henum, typedef1, NULL, 0, NULL); todo_wine ok(hr == S_FALSE, "got hr %#lx\n", hr); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9525
From: Vibhav Pant <vibhavp(a)gmail.com> --- dlls/rometadata/mdtables.c | 185 +++++++++++++++++++++++++---- dlls/rometadata/tests/rometadata.c | 29 ++--- 2 files changed, 178 insertions(+), 36 deletions(-) diff --git a/dlls/rometadata/mdtables.c b/dlls/rometadata/mdtables.c index 7794d9ce874..496133c7c05 100644 --- a/dlls/rometadata/mdtables.c +++ b/dlls/rometadata/mdtables.c @@ -338,6 +338,18 @@ HRESULT token_enum_create(HCORENUM *out) return S_OK; } +static HRESULT token_enum_get_entries(struct token_enum *henum, CorTokenType type, mdToken *buf, ULONG buf_len, + ULONG *buf_written) +{ + ULONG i = 0; + + while (henum->row_cur <= henum->row_end && i < buf_len) + buf[i++] = TokenFromRid(henum->row_cur++, type); + if (buf_written) + *buf_written = i; + return !!i ? S_OK : S_FALSE; +} + static void WINAPI import_CloseEnum(IMetaDataImport *iface, HCORENUM henum) { TRACE("(%p, %p)\n", iface, henum); @@ -415,12 +427,19 @@ static const char *debugstr_mdToken(mdToken token) return wine_dbg_sprintf("(%#x|%#x)", type, rid); } +static HRESULT table_get_num_rows(IMetaDataTables *iface, enum table table, ULONG *rows) +{ + ULONG row_size, cols, key_idx; + const char *name; + + return IMetaDataTables_GetTableInfo(iface, table, &row_size, rows, &cols, &key_idx, &name); +} + static HRESULT WINAPI import_EnumTypeDefs(IMetaDataImport *iface, HCORENUM *ret_henum, mdTypeDef *typedefs, ULONG len, ULONG *count) { struct metadata_tables *impl = impl_from_IMetaDataImport(iface); - ULONG row_size, rows, cols, key_idx, i = 0; struct token_enum *henum = *ret_henum; - const char *name; + ULONG rows; HRESULT hr; TRACE("(%p, %p, %p, %lu, %p)\n", iface, ret_henum, typedefs, len, count); @@ -430,8 +449,7 @@ static HRESULT WINAPI import_EnumTypeDefs(IMetaDataImport *iface, HCORENUM *ret_ if (!henum) { - hr = IMetaDataTables_GetTableInfo(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, &row_size, &rows, &cols, - &key_idx, &name); + hr = table_get_num_rows(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, &rows); if (FAILED(hr)) return hr; /* Skip the <Module> row. */ if (rows < 2) return S_FALSE; @@ -443,13 +461,7 @@ static HRESULT WINAPI import_EnumTypeDefs(IMetaDataImport *iface, HCORENUM *ret_ *ret_henum = henum; } - while (henum->row_cur <= henum->row_end && i < len) - typedefs[i++] = TokenFromRid(henum->row_cur++, mdtTypeDef); - - if (count) - *count = i; - - return i ? S_OK : S_FALSE; + return token_enum_get_entries(henum, mdtTypeDef, typedefs, len, count); } static HRESULT WINAPI import_EnumInterfaceImpls(IMetaDataImport *iface, HCORENUM *henum, mdTypeDef type_def, @@ -667,11 +679,52 @@ static HRESULT WINAPI import_EnumMembersWithName(IMetaDataImport *iface, HCORENU return E_NOTIMPL; } -static HRESULT WINAPI import_EnumMethods(IMetaDataImport *iface, HCORENUM *henum, mdTypeDef type_def, +static HRESULT WINAPI import_EnumMethods(IMetaDataImport *iface, HCORENUM *ret_henum, mdTypeDef type_def, mdMethodDef *method_defs, ULONG len, ULONG *count) { - FIXME("(%p, %p, %#x, %p, %lu, %p): stub!\n", iface, henum, type_def, method_defs, len, count); - return E_NOTIMPL; + struct metadata_tables *impl = impl_from_IMetaDataImport(iface); + struct token_enum *henum = *ret_henum; + + TRACE("(%p, %p, %s, %p, %lu, %p)\n", iface, ret_henum, debugstr_mdToken(type_def), method_defs, len, count); + + if (count) *count = 0; + if (TypeFromToken(type_def) != mdtTypeDef || IsNilToken(type_def)) return S_FALSE; + if (!henum) + { + ULONG methods_start, methods_end, row = RidFromToken(type_def), num_typedef_rows; + HRESULT hr; + + if (FAILED((hr = table_get_num_rows(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, &num_typedef_rows)))) + return hr; + if (row > num_typedef_rows) return S_FALSE; + hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, 5, row, &methods_start); + if (FAILED(hr)) return hr; + + /* From Partition II.22.37, "TypeDef": + * + * The (MethodList) run continues to the smaller of: + * the last row of the MethodDef table + * the next run of Methods, found by inspecting the MethodList of the next row in this TypeDef table + */ + if (row != num_typedef_rows) /* Get the end MethodDef from the next TypeDef's MethodList. */ + { + hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, 5, RidFromToken(row + 1), + &methods_end); + if (SUCCEEDED(hr)) + methods_end = RidFromToken(methods_end) - 1; + } + else /* The run ends at the last MethodDef row. */ + hr = table_get_num_rows(&impl->IMetaDataTables_iface, TABLE_METHODDEF, &methods_end); + + if (FAILED(hr) || FAILED((hr = token_enum_create((HCORENUM *)&henum)))) return hr; + + henum->count = methods_end - methods_start + 1; + henum->row_start = henum->row_cur = methods_start; + henum->row_end = methods_end; + *ret_henum = henum; + } + + return token_enum_get_entries(*ret_henum, mdtMethodDef, method_defs, len, count); } static HRESULT WINAPI import_EnumMethodsWithName(IMetaDataImport *iface, HCORENUM *henum, mdTypeDef type_def, @@ -751,14 +804,106 @@ static HRESULT WINAPI import_FindMemberRef(IMetaDataImport *iface, mdTypeRef typ return E_NOTIMPL; } -static HRESULT WINAPI import_GetMethodProps(IMetaDataImport *iface, mdMethodDef method_def, mdTypeDef *type_def, +static HRESULT methoddef_get_parent(IMetaDataImport *iface, mdMethodDef method, mdTypeDef *parent) +{ + mdTypeDef cur_typedef = mdTypeDefNil; + HCORENUM typedef_enum = NULL; + HRESULT hr; + + *parent = mdTypeDefNil; + hr = IMetaDataImport_EnumTypeDefs(iface, &typedef_enum, &cur_typedef, 1, NULL); + while (hr == S_OK) + { + HCORENUM methoddef_enum = NULL; + mdMethodDef first, last; + ULONG count; + + hr = IMetaDataImport_EnumMethods(iface, &methoddef_enum, cur_typedef, &first, 1, NULL); + if (FAILED(hr)) break; + hr = IMetaDataImport_CountEnum(iface, methoddef_enum, &count); + IMetaDataImport_CloseEnum(iface, methoddef_enum); + if (FAILED(hr)) break; + if (count) + { + /* MethodDef runs are strictly sequential. */ + last = TokenFromRid(RidFromToken(first) + count - 1, mdtMethodDef); + if (method >= first && method <= last) + { + *parent = cur_typedef; + break; + } + } + hr = IMetaDataImport_EnumTypeDefs(iface, &typedef_enum, &cur_typedef, 1, NULL); + } + IMetaDataImport_CloseEnum(iface, typedef_enum); + return hr; +} + +static HRESULT WINAPI import_GetMethodProps(IMetaDataImport *iface, mdMethodDef method_def, mdTypeDef *ret_parent, WCHAR *method_name, ULONG name_len, ULONG *written, ULONG *method_flags, - const COR_SIGNATURE **sig_blob, ULONG *sig_len, ULONG *rva, - ULONG *impl_flags) + const COR_SIGNATURE **ret_sig_blob, ULONG *ret_sig_len, ULONG *rva, + ULONG *ret_impl_flags) { - FIXME("(%p, %#x, %p, %p, %lu, %p, %p, %p, %p, %p, %p): stub!\n", iface, method_def, type_def, method_name, name_len, - written, method_flags, sig_blob, sig_len, rva, impl_flags); - return E_NOTIMPL; + ULONG attrs = 0, impl_flags = 0, addr = 0, sig_len = 0, name_needed = 0; + struct metadata_tables *impl = impl_from_IMetaDataImport(iface); + mdToken parent = mdTypeDefNil; + const BYTE *sig_blob = NULL; + + TRACE("(%p, %s, %p, %p, %lu, %p, %p, %p, %p, %p, %p)\n", iface, debugstr_mdToken(method_def), ret_parent, + method_name, name_len, written, method_flags, ret_sig_blob, ret_sig_len, rva, ret_impl_flags); + + if (TypeFromToken(method_def) != mdtMethodDef) return S_FALSE; + + if (method_name && name_len) + method_name[0] = L'\0'; + if (method_def != mdMethodDefNil) + { + const ULONG row = RidFromToken(method_def); + ULONG name_idx, sig_idx; + const char *nameA = NULL; + HRESULT hr; + + if (FAILED((hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_METHODDEF, 0, row, &addr)))) + return hr; + if (FAILED((hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_METHODDEF, 1, row, &impl_flags)))) + return hr; + if (FAILED((hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_METHODDEF, 2, row, &attrs)))) + return hr; + if (FAILED((hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_METHODDEF, 3, row, &name_idx)))) + return hr; + if (FAILED((hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_METHODDEF, 4, row, &sig_idx)))) + return hr; + + if (FAILED(hr = IMetaDataTables_GetString(&impl->IMetaDataTables_iface, name_idx, &nameA))) + return hr; + if (FAILED((hr = IMetaDataTables_GetBlob(&impl->IMetaDataTables_iface, sig_idx, &sig_len, &sig_blob)))) + return hr; + if (FAILED((hr = methoddef_get_parent(iface, method_def, &parent)))) + return hr; + + name_needed = MultiByteToWideChar(CP_ACP, 0, nameA, -1, NULL, 0); + if (method_name && name_len) + { + ULONG n = MultiByteToWideChar(CP_ACP, 0, nameA, min(strlen(nameA), name_len - 1), method_name, name_len - 1); + method_name[n] = L'\0'; + } + } + if (ret_parent) + *ret_parent = parent; + if (method_flags) + *method_flags = attrs; + if (ret_sig_blob) + *ret_sig_blob = sig_blob; + if (ret_sig_len) + *ret_sig_len = sig_len; + if (rva) + *rva = addr; + if (ret_impl_flags) + *ret_impl_flags = impl_flags; + if (written) + *written = name_needed; + + return (method_name && name_needed > name_len) ? CLDB_S_TRUNCATION : S_OK; } static HRESULT WINAPI import_GetMemberRefProps(IMetaDataImport *iface, mdMemberRef member_ref, mdToken *token, diff --git a/dlls/rometadata/tests/rometadata.c b/dlls/rometadata/tests/rometadata.c index d150caffb04..f8e9a2399e6 100644 --- a/dlls/rometadata/tests/rometadata.c +++ b/dlls/rometadata/tests/rometadata.c @@ -1104,17 +1104,17 @@ static void test_IMetaDataImport(void) buf_count = 0xdeadbeef; henum = NULL; hr = IMetaDataImport_EnumMethods(md_import, &henum, typedef1, NULL, 0, &buf_count); - todo_wine ok(hr == S_FALSE, "got hr %#lx\n", hr); - todo_wine ok(buf_count == 0, "got buf_reqd %lu\n", buf_count); + ok(hr == S_FALSE, "got hr %#lx\n", hr); + ok(buf_count == 0, "got buf_reqd %lu\n", buf_count); buf_len = 0; hr = IMetaDataImport_CountEnum(md_import, henum, &buf_len); ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(buf_len == ARRAY_SIZE(test2_methods), "got buf_len %#lx\n" , buf_len); + ok(buf_len == ARRAY_SIZE(test2_methods), "got buf_len %#lx\n" , buf_len); methoddef_tokens = calloc(buf_len, sizeof(*methoddef_tokens)); ok(!!methoddef_tokens, "got methoddef_tokens %p\n", methoddef_tokens); hr = IMetaDataImport_EnumMethods(md_import, &henum, typedef1, methoddef_tokens, buf_len, &buf_count); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(buf_count == buf_len, "got buf_reqd %lu != %lu\n", buf_count, buf_len); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(buf_count == buf_len, "got buf_reqd %lu != %lu\n", buf_count, buf_len); for (i = 0; i < buf_len; i++) { ULONG method_flags = 0, impl_flags = 0, sig_len = 0, call_conv = 0; @@ -1129,19 +1129,16 @@ static void test_IMetaDataImport(void) str_len = 0; hr = IMetaDataImport_GetMethodProps(md_import, methoddef_tokens[i], &typedef2, name, ARRAY_SIZE(name), &str_len, &method_flags, &sig_blob, &sig_len, NULL, &impl_flags); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(typedef2 == typedef1, "got typedef2 %s != %s\n", debugstr_mdToken(typedef2), - debugstr_mdToken(typedef1)); - todo_wine ok(method_flags == method->exp_method_flags, "got method_flags %#lx != %#x\n", method_flags, - method->exp_method_flags); - todo_wine ok(impl_flags == method->exp_impl_flags, "got impl_flags %#lx != %#x\n", impl_flags, - method->exp_impl_flags); - todo_wine ok(!!sig_blob, "got sig_blob %p\n", sig_blob); - todo_wine ok(sig_len == method->exp_sig_len, "got sig_len %lu != %lu\n", sig_len, method->exp_sig_len); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(typedef2 == typedef1, "got typedef2 %s != %s\n", debugstr_mdToken(typedef2), debugstr_mdToken(typedef1)); + ok(method_flags == method->exp_method_flags, "got method_flags %#lx != %#x\n", method_flags, + method->exp_method_flags); + ok(impl_flags == method->exp_impl_flags, "got impl_flags %#lx != %#x\n", impl_flags, method->exp_impl_flags); + ok(!!sig_blob, "got sig_blob %p\n", sig_blob); + ok(sig_len == method->exp_sig_len, "got sig_len %lu != %lu\n", sig_len, method->exp_sig_len); if (sig_blob && sig_len == method->exp_sig_len) ok(!memcmp(sig_blob, method->exp_sig_blob, method->exp_sig_len), "got unexpected sig_blob\n"); - todo_wine ok(!wcscmp(name, method->exp_name), "got name %s != %s\n", debugstr_w(name), - debugstr_w(method->exp_name)); + ok(!wcscmp(name, method->exp_name), "got name %s != %s\n", debugstr_w(name), debugstr_w(method->exp_name)); hr = IMetaDataImport_GetNativeCallConvFromSig(md_import, sig_blob, sig_len, &call_conv); todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9525
From: Vibhav Pant <vibhavp(a)gmail.com> --- dlls/rometadata/mdtables.c | 96 ++++++++++++++++++++---------- dlls/rometadata/tests/rometadata.c | 16 ++--- 2 files changed, 71 insertions(+), 41 deletions(-) diff --git a/dlls/rometadata/mdtables.c b/dlls/rometadata/mdtables.c index 496133c7c05..fd0d1576394 100644 --- a/dlls/rometadata/mdtables.c +++ b/dlls/rometadata/mdtables.c @@ -679,11 +679,43 @@ static HRESULT WINAPI import_EnumMembersWithName(IMetaDataImport *iface, HCORENU return E_NOTIMPL; } +static HRESULT table_create_enum_from_token_list(IMetaDataTables *iface, enum table table, enum table list_table, + ULONG row, ULONG col, HCORENUM *ret_henum) +{ + ULONG num_rows, row_start, row_end; + struct token_enum *henum; + HRESULT hr; + + if (FAILED((hr = table_get_num_rows(iface, table, &num_rows)))) return hr; + if (row > num_rows) return S_FALSE; + if (FAILED((hr = IMetaDataTables_GetColumn(iface, table, col, row, &row_start)))) return hr; + row_start = RidFromToken(row_start); + + if (row != num_rows) + { + /* Use the next row to get the last token. */ + if (FAILED((hr = IMetaDataTables_GetColumn(iface, table, col, row + 1, &row_end)))) return hr; + row_end = RidFromToken(row_end) - 1; + } + /* This is the last row, so the final token can be derived from the number of rows in list_table. */ + else if (FAILED((hr = table_get_num_rows(iface, list_table, &row_end)))) + return hr; + + if (FAILED((hr = token_enum_create((HCORENUM *)&henum)))) return hr; + + henum->count = row_end - row_start + 1; + henum->row_start = henum->row_cur = row_start; + henum->row_end = row_end; + *ret_henum = henum; + return S_OK; +} + static HRESULT WINAPI import_EnumMethods(IMetaDataImport *iface, HCORENUM *ret_henum, mdTypeDef type_def, mdMethodDef *method_defs, ULONG len, ULONG *count) { struct metadata_tables *impl = impl_from_IMetaDataImport(iface); struct token_enum *henum = *ret_henum; + HRESULT hr; TRACE("(%p, %p, %s, %p, %lu, %p)\n", iface, ret_henum, debugstr_mdToken(type_def), method_defs, len, count); @@ -691,37 +723,15 @@ static HRESULT WINAPI import_EnumMethods(IMetaDataImport *iface, HCORENUM *ret_h if (TypeFromToken(type_def) != mdtTypeDef || IsNilToken(type_def)) return S_FALSE; if (!henum) { - ULONG methods_start, methods_end, row = RidFromToken(type_def), num_typedef_rows; - HRESULT hr; - - if (FAILED((hr = table_get_num_rows(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, &num_typedef_rows)))) - return hr; - if (row > num_typedef_rows) return S_FALSE; - hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, 5, row, &methods_start); - if (FAILED(hr)) return hr; - /* From Partition II.22.37, "TypeDef": - * - * The (MethodList) run continues to the smaller of: - * the last row of the MethodDef table - * the next run of Methods, found by inspecting the MethodList of the next row in this TypeDef table - */ - if (row != num_typedef_rows) /* Get the end MethodDef from the next TypeDef's MethodList. */ - { - hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, 5, RidFromToken(row + 1), - &methods_end); - if (SUCCEEDED(hr)) - methods_end = RidFromToken(methods_end) - 1; - } - else /* The run ends at the last MethodDef row. */ - hr = table_get_num_rows(&impl->IMetaDataTables_iface, TABLE_METHODDEF, &methods_end); - - if (FAILED(hr) || FAILED((hr = token_enum_create((HCORENUM *)&henum)))) return hr; - - henum->count = methods_end - methods_start + 1; - henum->row_start = henum->row_cur = methods_start; - henum->row_end = methods_end; - *ret_henum = henum; + * + * The (MethodList) run continues to the smaller of: + * the last row of the MethodDef table + * the next run of Methods, found by inspecting the MethodList of the next row in this TypeDef table + */ + hr = table_create_enum_from_token_list(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, TABLE_METHODDEF, + RidFromToken(type_def), 5, ret_henum); + if (hr != S_OK) return hr; } return token_enum_get_entries(*ret_henum, mdtMethodDef, method_defs, len, count); @@ -734,11 +744,31 @@ static HRESULT WINAPI import_EnumMethodsWithName(IMetaDataImport *iface, HCORENU return E_NOTIMPL; } -static HRESULT WINAPI import_EnumFields(IMetaDataImport *iface, HCORENUM *henum, mdTypeDef token, +static HRESULT WINAPI import_EnumFields(IMetaDataImport *iface, HCORENUM *ret_henum, mdTypeDef token, mdFieldDef *field_defs, ULONG len, ULONG *count) { - FIXME("(%p, %p, %#x, %p, %lu, %p): stub!\n", iface, henum, token, field_defs, len, count); - return E_NOTIMPL; + struct metadata_tables *impl = impl_from_IMetaDataImport(iface); + struct token_enum *henum = *ret_henum; + HRESULT hr; + + TRACE("(%p, %p, %s, %p, %lu, %p)\n", iface, ret_henum, debugstr_mdToken(token), field_defs, len, count); + + if (count) *count = 0; + if (TypeFromToken(token) != mdtTypeDef || IsNilToken(token)) return S_FALSE; + if (!henum) + { + /* From Partition II.22.37, "TypeDef": + * + * The (FieldList) run continues to the smaller of: + * the last row of the Field table + * the next run of Fields, found by inspecting the FieldList of the next row in this TypeDef table + */ + hr = table_create_enum_from_token_list(&impl->IMetaDataTables_iface, TABLE_TYPEDEF, TABLE_FIELD, + RidFromToken(token), 4, ret_henum); + if (hr != S_OK) return hr; + } + + return token_enum_get_entries(*ret_henum, mdtFieldDef, field_defs, len, count); } static HRESULT WINAPI import_EnumFieldsWithName(IMetaDataImport *iface, HCORENUM *henum, mdTypeDef token, diff --git a/dlls/rometadata/tests/rometadata.c b/dlls/rometadata/tests/rometadata.c index f8e9a2399e6..54e365e5c98 100644 --- a/dlls/rometadata/tests/rometadata.c +++ b/dlls/rometadata/tests/rometadata.c @@ -1165,18 +1165,18 @@ static void test_IMetaDataImport(void) henum = NULL; buf_count = 0xdeadbeef; hr = IMetaDataImport_EnumFields(md_import, &henum, typedef1, NULL, 0, &buf_count); - todo_wine ok(hr == S_FALSE, "got hr %#lx\n", hr); - todo_wine ok(!!henum, "got henum %p\n", henum); - todo_wine ok(buf_count == 0, "got buf_count %lu\n", buf_count); + ok(hr == S_FALSE, "got hr %#lx\n", hr); + ok(!!henum, "got henum %p\n", henum); + ok(buf_count == 0, "got buf_count %lu\n", buf_count); buf_len = 0; hr = IMetaDataImport_CountEnum(md_import, henum, &buf_len); ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(buf_len == fields_len, "got buf_len %lu\n", buf_len); + ok(buf_len == fields_len, "got buf_len %lu\n", buf_len); fielddef_tokens = calloc(buf_len, sizeof(*fielddef_tokens)); ok(!!fielddef_tokens, "got fielddef_tokens %p\n", fielddef_tokens); hr = IMetaDataImport_EnumFields(md_import, &henum, typedef1, fielddef_tokens, buf_len, &buf_count); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(buf_count == buf_len, "got buf_count %lu != %lu\n", buf_count, buf_len); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(buf_count == buf_len, "got buf_count %lu != %lu\n", buf_count, buf_len); IMetaDataImport_CloseEnum(md_import, henum); for (field_idx = 0; field_idx < buf_len; field_idx++) @@ -1203,8 +1203,8 @@ static void test_IMetaDataImport(void) todo_wine ok(!!sig_blob, "got sig_blob %p\n", sig_blob); if (sig_blob && sig_len == props->exp_sig_len) ok(!memcmp(sig_blob, props->exp_sig_blob, sig_len), "got unexpected sig_blob\n"); - todo_wine ok(value_len == 0, "got value_len %lu\n", value_len); /* Non-zero only for string types. */ - todo_wine ok(props->has_value == !!value, "got value %s\n", debugstr_a(value)); + ok(value_len == 0, "got value_len %lu\n", value_len); /* Non-zero only for string types. */ + todo_wine_if(FAILED(hr) && props->has_value) ok(props->has_value == !!value, "got value %s\n", debugstr_a(value)); if (props->has_value) todo_wine ok(value && !memcmp(value, props->exp_value, props->value_len), "got unexpected value %p\n", value); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9525
From: Vibhav Pant <vibhavp(a)gmail.com> --- dlls/rometadata/mdtables.c | 142 ++++++++++++++++++++++++++--- dlls/rometadata/tests/rometadata.c | 19 ++-- 2 files changed, 138 insertions(+), 23 deletions(-) diff --git a/dlls/rometadata/mdtables.c b/dlls/rometadata/mdtables.c index fd0d1576394..71cacb10f95 100644 --- a/dlls/rometadata/mdtables.c +++ b/dlls/rometadata/mdtables.c @@ -834,30 +834,37 @@ static HRESULT WINAPI import_FindMemberRef(IMetaDataImport *iface, mdTypeRef typ return E_NOTIMPL; } -static HRESULT methoddef_get_parent(IMetaDataImport *iface, mdMethodDef method, mdTypeDef *parent) + +typedef HRESULT (*WINAPI token_enum_func)(IMetaDataImport *, HCORENUM *, mdTypeDef, mdToken *, ULONG, ULONG *); +static HRESULT token_get_parent_typedef(IMetaDataImport *iface, mdToken token, token_enum_func enum_func, mdTypeDef *parent) { + CorTokenType type = TypeFromToken(token); mdTypeDef cur_typedef = mdTypeDefNil; HCORENUM typedef_enum = NULL; HRESULT hr; + TRACE("(%p, %s, %p, %p)\n", iface, debugstr_mdToken(token), enum_func, parent); + + assert(type == mdtMethodDef || type == mdtFieldDef); + *parent = mdTypeDefNil; hr = IMetaDataImport_EnumTypeDefs(iface, &typedef_enum, &cur_typedef, 1, NULL); while (hr == S_OK) { - HCORENUM methoddef_enum = NULL; + HCORENUM token_enum = NULL; mdMethodDef first, last; ULONG count; - hr = IMetaDataImport_EnumMethods(iface, &methoddef_enum, cur_typedef, &first, 1, NULL); + hr = enum_func(iface, &token_enum, cur_typedef, &first, 1, NULL); if (FAILED(hr)) break; - hr = IMetaDataImport_CountEnum(iface, methoddef_enum, &count); - IMetaDataImport_CloseEnum(iface, methoddef_enum); + hr = IMetaDataImport_CountEnum(iface, token_enum, &count); + IMetaDataImport_CloseEnum(iface, token_enum); if (FAILED(hr)) break; if (count) { - /* MethodDef runs are strictly sequential. */ - last = TokenFromRid(RidFromToken(first) + count - 1, mdtMethodDef); - if (method >= first && method <= last) + /* Token lists/runs are strictly sequential */ + last = TokenFromRid(RidFromToken(first) + count - 1, type); + if (token >= first && token <= last) { *parent = cur_typedef; break; @@ -869,6 +876,11 @@ static HRESULT methoddef_get_parent(IMetaDataImport *iface, mdMethodDef method, return hr; } +static HRESULT methoddef_get_parent_typedef(IMetaDataImport *iface, mdMethodDef method, mdTypeDef *parent) +{ + return token_get_parent_typedef(iface, method, iface->lpVtbl->EnumMethods, parent); +} + static HRESULT WINAPI import_GetMethodProps(IMetaDataImport *iface, mdMethodDef method_def, mdTypeDef *ret_parent, WCHAR *method_name, ULONG name_len, ULONG *written, ULONG *method_flags, const COR_SIGNATURE **ret_sig_blob, ULONG *ret_sig_len, ULONG *rva, @@ -908,7 +920,7 @@ static HRESULT WINAPI import_GetMethodProps(IMetaDataImport *iface, mdMethodDef return hr; if (FAILED((hr = IMetaDataTables_GetBlob(&impl->IMetaDataTables_iface, sig_idx, &sig_len, &sig_blob)))) return hr; - if (FAILED((hr = methoddef_get_parent(iface, method_def, &parent)))) + if (FAILED((hr = methoddef_get_parent_typedef(iface, method_def, &parent)))) return hr; name_needed = MultiByteToWideChar(CP_ACP, 0, nameA, -1, NULL, 0); @@ -1127,14 +1139,118 @@ static HRESULT WINAPI import_GetMemberProps(IMetaDataImport *iface, mdToken memb return E_NOTIMPL; } +static HRESULT token_get_constant_value(IMetaDataImport *iface, mdToken token, ULONG *value_type, const BYTE **value, + ULONG *value_len) +{ + struct metadata_tables *impl = impl_from_IMetaDataImport(iface); + ULONG type = TypeFromToken(token), row, num_constant; + HRESULT hr; + + TRACE("(%p, %s, %p, %p, %p)\n", iface, debugstr_mdToken(token), value_type, value, value_len); + assert(type == mdtFieldDef || type == mdtParamDef || type == mdtProperty); + + if (FAILED((hr = table_get_num_rows(&impl->IMetaDataTables_iface, TABLE_CONSTANT, &num_constant)))) return hr; + + *value_type = ELEMENT_TYPE_VOID; + *value = NULL; + *value_len = 0; + if (!num_constant) return S_OK; + + for (row = 1; row <= num_constant; row++) + { + ULONG parent, len; + + if (FAILED((hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_CONSTANT, 1, row, &parent)))) + break; + if (parent == token) + { + ULONG blob_idx; + + hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_CONSTANT, 0, row, value_type); + if (FAILED(hr)) break; + hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_CONSTANT, 2, row, &blob_idx); + if (FAILED(hr)) break; + + if (FAILED((hr = IMetaDataTables_GetBlob(&impl->IMetaDataTables_iface, blob_idx, &len, value)))) + break; + if (*value_type == ELEMENT_TYPE_STRING) + *value_len = len / sizeof(WCHAR); + break; + } + } + return hr; +} + +static HRESULT fielddef_get_parent_typedef(IMetaDataImport *iface, mdFieldDef field, mdTypeDef *parent) +{ + return token_get_parent_typedef(iface, field, iface->lpVtbl->EnumFields, parent); +} + static HRESULT WINAPI import_GetFieldProps(IMetaDataImport *iface, mdFieldDef fielddef, mdTypeDef *type_def, WCHAR *field_name, ULONG name_len, ULONG *name_written, ULONG *flags, - const COR_SIGNATURE **sig_blob, ULONG *sig_len, ULONG *value_type_flag, + const COR_SIGNATURE **ret_sig_blob, ULONG *ret_sig_len, ULONG *value_type_flag, UVCP_CONSTANT *value, ULONG *value_len) { - FIXME("(%p, %#x, %p, %p, %lu, %p, %p, %p, %p, %p, %p, %p): stub!\n", iface, fielddef, type_def, field_name, - name_len, name_written, flags, sig_blob, sig_len, value_type_flag, value, value_len); - return E_NOTIMPL; + ULONG attrs = 0, sig_len = 0, name_needed = 0, val_len = 0, val_type = ELEMENT_TYPE_VOID; + struct metadata_tables *impl = impl_from_IMetaDataImport(iface); + const BYTE *sig_blob = NULL, *val_blob = NULL; + mdToken parent = mdTypeDefNil; + + TRACE("(%p, %s, %p, %p, %lu, %p, %p, %p, %p, %p, %p, %p)\n", iface, debugstr_mdToken(fielddef), type_def, + field_name, name_len, name_written, flags, ret_sig_blob, ret_sig_len, value_type_flag, value, value_len); + + if (TypeFromToken(fielddef) != mdtFieldDef) return S_FALSE; + + if (field_name && name_len) + field_name[0] = L'\0'; + if (!IsNilToken(fielddef)) + { + const ULONG row = RidFromToken(fielddef); + ULONG name_idx, sig_idx; + const char *nameA; + HRESULT hr; + + if (FAILED((hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_FIELD, 0, row, &attrs)))) + return hr; + if (FAILED((hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_FIELD, 1, row, &name_idx)))) + return hr; + if (FAILED((hr = IMetaDataTables_GetColumn(&impl->IMetaDataTables_iface, TABLE_FIELD, 2, row, &sig_idx)))) + return hr; + + if (FAILED((hr = IMetaDataTables_GetString(&impl->IMetaDataTables_iface, name_idx, &nameA)))) + return hr; + if (FAILED((hr = IMetaDataTables_GetBlob(&impl->IMetaDataTables_iface, sig_idx, &sig_len, &sig_blob)))) + return hr; + if (FAILED((hr = fielddef_get_parent_typedef(iface, fielddef, &parent)))) + return hr; + if (FAILED((hr = token_get_constant_value(iface, fielddef, &val_type, &val_blob, &val_len)))) + return hr; + + name_needed = MultiByteToWideChar(CP_ACP, 0, nameA, -1, NULL, 0); + if (field_name && name_len) + { + ULONG n = MultiByteToWideChar(CP_ACP, 0, nameA, min(strlen(nameA), name_len - 1), field_name, name_len - 1); + field_name[n] = L'\0'; + } + } + if (type_def) + *type_def = parent; + if (name_written) + *name_written = name_needed; + if (flags) + *flags = attrs; + if (ret_sig_blob) + *ret_sig_blob = sig_blob; + if (ret_sig_len) + *ret_sig_len = sig_len; + if (value_type_flag) + *value_type_flag = val_type; + if (value) + *value = (UVCP_CONSTANT)val_blob; + if (value_len) + *value_len = val_len; + + return (field_name && name_needed > name_len) ? CLDB_S_TRUNCATION : S_OK; } static HRESULT WINAPI import_GetPropertyProps(IMetaDataImport *iface, mdProperty prop, mdTypeDef *type_def, WCHAR *name, diff --git a/dlls/rometadata/tests/rometadata.c b/dlls/rometadata/tests/rometadata.c index 54e365e5c98..6be43222c6f 100644 --- a/dlls/rometadata/tests/rometadata.c +++ b/dlls/rometadata/tests/rometadata.c @@ -1194,20 +1194,19 @@ static void test_IMetaDataImport(void) typedef2 = 0; hr = IMetaDataImport_GetFieldProps(md_import, fielddef_tokens[field_idx], &typedef2, name, ARRAY_SIZE(name), NULL, &flags, &sig_blob, &sig_len, &value_type, &value, &value_len); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine ok(typedef2 == typedef1, "got typedef2 %s != %s\n", debugstr_mdToken(typedef2), debugstr_mdToken(typedef1)); - todo_wine ok(!wcscmp(name, props->exp_name), "got name %s != %s\n", debugstr_w(name), debugstr_w(props->exp_name)); - todo_wine ok(flags == props->exp_flags, "got flags %#lx != %#x\n", flags, props->exp_flags); - todo_wine ok(value_type == props->exp_value_type, "got value_type %#lx != %#x\n", value_type, props->exp_value_type); - todo_wine ok(sig_len == props->exp_sig_len, "got sig_len %lu != %lu\n", sig_len, props->exp_sig_len); - todo_wine ok(!!sig_blob, "got sig_blob %p\n", sig_blob); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(typedef2 == typedef1, "got typedef2 %s != %s\n", debugstr_mdToken(typedef2), debugstr_mdToken(typedef1)); + ok(!wcscmp(name, props->exp_name), "got name %s != %s\n", debugstr_w(name), debugstr_w(props->exp_name)); + ok(flags == props->exp_flags, "got flags %#lx != %#x\n", flags, props->exp_flags); + ok(value_type == props->exp_value_type, "got value_type %#lx != %#x\n", value_type, props->exp_value_type); + ok(sig_len == props->exp_sig_len, "got sig_len %lu != %lu\n", sig_len, props->exp_sig_len); + ok(!!sig_blob, "got sig_blob %p\n", sig_blob); if (sig_blob && sig_len == props->exp_sig_len) ok(!memcmp(sig_blob, props->exp_sig_blob, sig_len), "got unexpected sig_blob\n"); ok(value_len == 0, "got value_len %lu\n", value_len); /* Non-zero only for string types. */ - todo_wine_if(FAILED(hr) && props->has_value) ok(props->has_value == !!value, "got value %s\n", debugstr_a(value)); + ok(props->has_value == !!value, "got value %s\n", debugstr_a(value)); if (props->has_value) - todo_wine ok(value && !memcmp(value, props->exp_value, props->value_len), "got unexpected value %p\n", - value); + ok(value && !memcmp(value, props->exp_value, props->value_len), "got unexpected value %p\n", value); winetest_pop_context(); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9525
This merge request was approved by Hans Leidekker. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9525
participants (3)
-
Hans Leidekker (@hans) -
Vibhav Pant -
Vibhav Pant (@vibhavp)