-- v4: rometadata/tests: Add tests for IMetaDataImport::{EnumProperties, GetPropertyProps}. rometadata/tests: Add tests for IMetaDataImport::GetCustomAttributeByName. rometadata/tests: Add tests for IMetaDataImport::{EnumFields, GetFieldProps}. rometadata/tests: Add tests for IMetaDataImport::{EnumMethods, GetMethodProps, GetNativeCallConvFromSig}. rometadata/tests: Add tests for IMetaDataTables::{EnumTypeDefs, GetTypeDefProps, FindTypeDefByName}.
From: Vibhav Pant vibhavp@gmail.com
--- dlls/rometadata/mdtables.c | 548 ++++++++++++++++++++++++++++++++++++- include/rometadataapi.idl | 267 ++++++++++++++++++ 2 files changed, 814 insertions(+), 1 deletion(-)
diff --git a/dlls/rometadata/mdtables.c b/dlls/rometadata/mdtables.c index b5804bd987b..8c9f4825584 100644 --- a/dlls/rometadata/mdtables.c +++ b/dlls/rometadata/mdtables.c @@ -1,5 +1,5 @@ /* - * IMetaDataTables implementation + * IMetaDataTables, IMetaDataImport implementation * * Copyright 2025 Vibhav Pant * @@ -33,6 +33,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(rometadata); struct metadata_tables { IMetaDataTables IMetaDataTables_iface; + IMetaDataImport IMetaDataImport_iface; LONG ref;
assembly_t *assembly; @@ -45,6 +46,8 @@ static inline struct metadata_tables *impl_from_IMetaDataTables(IMetaDataTables
static HRESULT WINAPI tables_QueryInterface(IMetaDataTables *iface, REFIID iid, void **out) { + struct metadata_tables *impl = impl_from_IMetaDataTables(iface); + TRACE("(%p, %s, %p)\n", iface, debugstr_guid(iid), out);
if (IsEqualGUID(&IID_IUnknown, iid) || IsEqualGUID(&IID_IMetaDataTables, iid)) @@ -52,6 +55,11 @@ static HRESULT WINAPI tables_QueryInterface(IMetaDataTables *iface, REFIID iid, IMetaDataTables_AddRef((*out = iface)); return S_OK; } + if (IsEqualGUID(&IID_IMetaDataImport, iid)) + { + IMetaDataImport_AddRef((*out = &impl->IMetaDataImport_iface)); + return S_OK; + }
FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); return E_NOINTERFACE; @@ -286,6 +294,543 @@ static const struct IMetaDataTablesVtbl tables_vtbl = tables_GetNextUserString, };
+static inline struct metadata_tables *impl_from_IMetaDataImport(IMetaDataImport *iface) +{ + return CONTAINING_RECORD(iface, struct metadata_tables, IMetaDataImport_iface); +} + +static HRESULT WINAPI import_QueryInterface(IMetaDataImport *iface, REFIID iid, void **out) +{ + struct metadata_tables *impl = impl_from_IMetaDataImport(iface); + return IMetaDataTables_QueryInterface(&impl->IMetaDataTables_iface, iid, out); +} + +static ULONG WINAPI import_AddRef(IMetaDataImport *iface) +{ + struct metadata_tables *impl = impl_from_IMetaDataImport(iface); + return IMetaDataTables_AddRef(&impl->IMetaDataTables_iface); +} + +static ULONG WINAPI import_Release(IMetaDataImport *iface) +{ + struct metadata_tables *impl = impl_from_IMetaDataImport(iface); + return IMetaDataTables_Release(&impl->IMetaDataTables_iface); +} + +static void WINAPI import_CloseEnum(IMetaDataImport *iface, HCORENUM henum) +{ + FIXME("(%p, %p): stub!\n", iface, henum); +} + +static HRESULT WINAPI import_CountEnum(IMetaDataImport *iface, HCORENUM henum, ULONG *count) +{ + FIXME("(%p, %p, %p): stub!\n", iface, henum, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_ResetEnum(IMetaDataImport *iface, HCORENUM henum, ULONG idx) +{ + FIXME("(%p, %p, %lu): stub\n", iface, henum, idx); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumTypeDefs(IMetaDataImport *iface, HCORENUM *henum, mdTypeDef *typedefs, ULONG len, ULONG *count) +{ + FIXME("(%p, %p, %p, %lu, %p): stub!\n", iface, henum, typedefs, len, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumInterfaceImpls(IMetaDataImport *iface, HCORENUM *henum, mdTypeDef type_def, + mdInterfaceImpl *impls, ULONG len, ULONG *count) +{ + FIXME("(%p, %p, %#x, %p, %lu, %p): stub!\n", iface, henum, type_def, impls, len, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumTypeRefs(IMetaDataImport *iface, HCORENUM *henum, mdTypeRef *typerefs, ULONG len, ULONG *count) +{ + FIXME("(%p, %p, %p, %lu, %p): stub!\n", iface, henum, typerefs, len, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_FindTypeDefByName(IMetaDataImport *iface, const WCHAR *name, mdToken enclosing_class, mdTypeDef *type_def) +{ + FIXME("(%p, %p, %#x, %p): stub!\n", iface, debugstr_w(name), enclosing_class, type_def); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetScopeProps(IMetaDataImport *iface, WCHAR *name, ULONG len, ULONG *written, GUID *mvid) +{ + FIXME("(%p, %p, %lu, %p, %p): stub!\n", iface, name, len, written, mvid); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetModuleFromScope(IMetaDataImport *iface, mdModule *module) +{ + FIXME("(%p, %p): stub!\n", iface, module); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetTypeDefProps(IMetaDataImport *iface, mdTypeDef type_def, WCHAR *name, ULONG len, + ULONG *written, ULONG *flags, mdToken *base) +{ + FIXME("(%p, %#x, %p, %lu, %p, %p, %p): stub!\n", iface, type_def, name, len, written, flags, base); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetInterfaceImplProps(IMetaDataImport *iface, mdInterfaceImpl iface_impl, + mdTypeDef *class_token, mdToken *iface_token) +{ + FIXME("(%p, %#x, %p, %p): stub!\n", iface, iface_impl, class_token, iface_token); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetTypeRefProps(IMetaDataImport *iface, mdTypeRef typeref, mdToken *resolution_scope, + WCHAR *name, ULONG len, ULONG *written) +{ + FIXME("(%p, %#x, %p, %p, %lu, %p): stub!\n", iface, typeref, resolution_scope, name, len, written); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_ResolveTypeRef(IMetaDataImport *iface, mdTypeRef typeref, const GUID *iid, + IUnknown **scope, mdTypeDef *type_def) +{ + FIXME("(%p, %#x, %s, %p, %p): stub!\n", iface, typeref, debugstr_guid(iid), scope, type_def); + return E_NOTIMPL; +} + +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; +} + +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; +} + +static HRESULT WINAPI import_EnumMethods(IMetaDataImport *iface, HCORENUM *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; +} + +static HRESULT WINAPI import_EnumMethodsWithName(IMetaDataImport *iface, HCORENUM *henum, mdTypeDef type_def, + const WCHAR *name, mdMethodDef *method_defs, ULONG len, ULONG *count) +{ + FIXME("(%p, %p, %#x, %s, %p, %lu, %p): stub!\n", iface, henum, type_def, debugstr_w(name), method_defs, len, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumFields(IMetaDataImport *iface, HCORENUM *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; +} + +static HRESULT WINAPI import_EnumFieldsWithName(IMetaDataImport *iface, HCORENUM *henum, mdTypeDef token, + const WCHAR *name, mdFieldDef *field_defs, ULONG len, ULONG *count) +{ + FIXME("(%p, %p, %#x, %s, %p, %lu, %p): stub!\n", iface, henum, token, debugstr_w(name), field_defs, len, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumParams(IMetaDataImport *iface, HCORENUM *henum, mdMethodDef method_def, + mdParamDef *params, ULONG len, ULONG *count) +{ + FIXME("(%p, %p, %#x, %p, %lu, %p): stub!\n", iface, henum, method_def, params, len, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumMemberRefs(IMetaDataImport *iface, HCORENUM *henum, mdToken parent, + mdMemberRef *members, ULONG len, ULONG *count) +{ + FIXME("(%p, %p, %#x, %p, %lu, %p): stub!\n", iface, henum, parent, members, len, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumMethodImpls(IMetaDataImport *iface, HCORENUM *henum, mdTypeDef token, + mdToken *body_tokens, mdToken *decl_tokens, ULONG len, ULONG *count) +{ + FIXME("(%p, %p, %#x, %p, %p, %lu, %p): stub!\n", iface, henum, token, body_tokens, decl_tokens, len, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumPermissionSets(IMetaDataImport *iface, HCORENUM *henum, mdToken token, ULONG actions, + mdPermission *perms, ULONG len, ULONG *count) +{ + FIXME("(%p, %p, %#x, %#lx, %p, %lu, %p): stub!\n", iface, henum, token, actions, perms, len, count); + return E_NOTIMPL; +} + +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; +} + +static HRESULT WINAPI import_FindMethod(IMetaDataImport *iface, mdTypeDef type_def, const WCHAR *name, + const COR_SIGNATURE *sig_blob, ULONG len, mdMethodDef *method_def) +{ + FIXME("(%p, %#x, %s, %p, %lu, %p): stub!\n", iface, type_def, debugstr_w(name), sig_blob, len, method_def); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_FindField(IMetaDataImport *iface, mdTypeDef type_def, const WCHAR *name, + const COR_SIGNATURE *sig_blob, ULONG len, mdFieldDef *field_def) +{ + FIXME("(%p, %#x, %s, %p, %lu, %p): stub!\n", iface, type_def, debugstr_w(name), sig_blob, len, field_def); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_FindMemberRef(IMetaDataImport *iface, mdTypeRef typeref, const WCHAR *name, + const COR_SIGNATURE *sig_blob, ULONG len, mdMemberRef *member_ref) +{ + FIXME("(%p, %#x, %s, %p, %lu, %p): stub!\n", iface, typeref, debugstr_w(name), sig_blob, len, member_ref); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetMethodProps(IMetaDataImport *iface, mdMethodDef method_def, mdTypeDef *type_def, + WCHAR *method_name, ULONG name_len, ULONG *written, ULONG *method_flags, + const COR_SIGNATURE **sig_blob, ULONG *sig_len, ULONG *rva, + ULONG *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; +} + +static HRESULT WINAPI import_GetMemberRefProps(IMetaDataImport *iface, mdMemberRef member_ref, mdToken *token, + WCHAR *member_name, ULONG name_len, ULONG *written, + const COR_SIGNATURE **sig_blob, ULONG *sig_len) +{ + FIXME("(%p, %#x, %p, %p, %lu, %p, %p, %p): stub!\n", iface, member_ref, token, member_name, name_len, written, + sig_blob, sig_len); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumProperties(IMetaDataImport *iface, HCORENUM *henum, mdTypeDef type_def, + mdProperty *props, ULONG len, ULONG *count) +{ + FIXME("(%p, %p, %#x, %p, %lu, %p): stub!\n", iface, henum, type_def, props, len, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumEvents(IMetaDataImport *iface, HCORENUM *henum, mdTypeDef type_def, mdEvent *events, + ULONG len, ULONG *count) +{ + FIXME("(%p, %p, %#x, %p, %lu, %p): stub!\n", iface, henum, type_def, events, len, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetEventProps(IMetaDataImport *iface, mdEvent event, mdTypeDef *class_typedef, WCHAR *name, + ULONG name_len, ULONG *written, ULONG *event_flags, mdToken *event_type, + mdMethodDef *add_method, mdMethodDef *remove_method, + mdMethodDef *fire_method, mdMethodDef *other_methods, ULONG other_len, + ULONG *other_count) +{ + FIXME("(%p, %#x, %p, %p, %lu, %p, %p, %p, %p, %p, %p, %p, %lu, %p): stub!\n", iface, event, class_typedef, name, + name_len, written, event_flags, event_type, add_method, remove_method, fire_method, other_methods, other_len, + other_count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumMethodSemantics(IMetaDataImport *iface, HCORENUM *henum, mdMethodDef method_def, + mdToken *event_props, ULONG len, ULONG *written) +{ + FIXME("(%p, %p, %#x, %p, %lu, %p): stub!\n", iface, henum, method_def, event_props, len, written); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetMethodSemantics(IMetaDataImport *iface, mdMethodDef method_def, mdToken event_prop, + ULONG *semantics) +{ + FIXME("(%p, %#x, %#x, %p): stub!\n", iface, method_def, event_prop, semantics); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetClassLayout(IMetaDataImport *iface, mdTypeDef type_def, ULONG *pack_size, + COR_FIELD_OFFSET *offsets, ULONG len, ULONG *count, ULONG *class_size) +{ + FIXME("(%p, %#x, %p, %p, %lu, %p, %p): stub!\n", iface, type_def, pack_size, offsets, len, count, class_size); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetFieldMarshal(IMetaDataImport *iface, mdToken token, + const COR_SIGNATURE **native_type_blob, ULONG *len) +{ + FIXME("(%p, %#x, %p, %p): stub!\n", iface, token, native_type_blob, len); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetRVA(IMetaDataImport *iface, mdToken token, ULONG *rva, ULONG *impl_flags) +{ + FIXME("(%p, %#x, %p, %p): stub!\n", iface, token, rva, impl_flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetPermissionSetProps(IMetaDataImport *iface, mdPermission perm, ULONG *decl_sec, + const BYTE **perm_blob, ULONG *len) +{ + FIXME("(%p, %#x, %p, %p, %p): stub!\n", iface, perm, decl_sec, perm_blob, len); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetSigFromToken(IMetaDataImport *iface, mdSignature signature, + const COR_SIGNATURE **sig_blob, ULONG *len) +{ + FIXME("(%p, %#x, %p, %p): stub!\n", iface, signature, sig_blob, len); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetModuleRefProps(IMetaDataImport *iface, mdModuleRef module_ref, WCHAR *name, ULONG len, + ULONG *written) +{ + FIXME("(%p, %#x, %p, %lu, %p): stub!\n", iface, module_ref, name, len, written); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumModuleRefs(IMetaDataImport *iface, HCORENUM *henum, mdModuleRef *module_refs, ULONG len, + ULONG *count) +{ + FIXME("(%p, %p, %p, %lu, %p): stub!\n", iface, henum, module_refs, len, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetTypeSpecFromToken(IMetaDataImport *iface, mdTypeSpec typespec, + const COR_SIGNATURE **sig_blob, ULONG *len) +{ + FIXME("(%p, %#x, %p, %p): stub!\n", iface, typespec, sig_blob, len); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetNameFromToken(IMetaDataImport *iface, mdToken token, const char **name) +{ + FIXME("(%p, %#x, %p): stub!\n", iface, token, name); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumUnresolvedMethods(IMetaDataImport *iface, HCORENUM *henum, mdToken *method_defs, + ULONG len, ULONG *count) +{ + FIXME("(%p, %p, %p, %lu, %p): stub!\n", iface, henum, method_defs, len, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetUserString(IMetaDataImport *iface, mdString string_token, WCHAR *str, ULONG len, + ULONG *written) +{ + FIXME("(%p, %#x, %p, %lu, %p): stub!\n", iface, string_token, str, len, written); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetPinvokeMap(IMetaDataImport *iface, mdToken field_method_def, ULONG *map_flags, + WCHAR *import_name, ULONG len, ULONG *written, mdModuleRef *target) +{ + FIXME("(%p, %#x, %p, %p, %lu, %p, %p): stub!\n", iface, field_method_def, map_flags, import_name, len, written, target); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumSignatures(IMetaDataImport *iface, HCORENUM *henum, mdSignature *sigs, ULONG len, + ULONG *count) +{ + FIXME("(%p, %p, %p, %lu, %p): stub!\n", iface, henum, sigs, len, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumTypeSpecs(IMetaDataImport *iface, HCORENUM *henum, mdTypeSpec *typespecs, ULONG len, + ULONG *count) +{ + FIXME("(%p, %p, %p, %lu, %p): stub!\n", iface, henum, typespecs, len, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumUserStrings(IMetaDataImport *iface, HCORENUM *henum, mdString *strings, ULONG len, + ULONG *count) +{ + FIXME("(%p, %p, %p, %lu, %p): stub!\n", iface, henum, strings, len, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetParamForMethodIndex(IMetaDataImport *iface, mdMethodDef token, ULONG param_seq, + mdParamDef *param_def) +{ + FIXME("(%p, %#x, %lu, %p): stub!\n", iface, token, param_seq, param_def); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_EnumCustomAttributes(IMetaDataImport *iface, HCORENUM *henum, mdToken token, + mdToken token_type, mdCustomAttribute *attrs, ULONG len, ULONG *count) +{ + FIXME("(%p, %p, %#x, %#x, %p, %lu, %p): stub!\n", iface, henum, token, token_type, attrs, len, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetCustomAttributeProps(IMetaDataImport *iface, mdCustomAttribute custom_attr, mdToken *obj, + mdToken *attr_type, const BYTE **blob, ULONG *len) +{ + FIXME("(%p, %#x, %p, %p, %p, %p): stub!\n", iface, custom_attr, obj, attr_type, blob, len); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_FindTypeRef(IMetaDataImport *iface, mdToken resolution_scope, const WCHAR *name, + mdTypeRef *typeref) +{ + FIXME("(%p, %#x, %s, %p): stub!\n", iface, resolution_scope, debugstr_w(name), typeref); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetMemberProps(IMetaDataImport *iface, mdToken member, mdTypeDef *type_def, WCHAR *name, + ULONG member_len, ULONG *member_written, ULONG *flags, + const COR_SIGNATURE **sig_blob, ULONG *blob_len, ULONG *rva, + ULONG *impl_flags, ULONG *value_type_flag, UVCP_CONSTANT *value, + ULONG *value_len) +{ + FIXME("(%p, %#x, %p, %p, %lu, %p, %p, %p, %p, %p, %p, %p, %p, %p): stub!\n", iface, member, type_def, name, + member_len, member_written, flags, sig_blob, blob_len, rva, impl_flags, value_type_flag, value, value_len); + return E_NOTIMPL; +} + +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, + 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; +} + +static HRESULT WINAPI import_GetPropertyProps(IMetaDataImport *iface, mdProperty prop, mdTypeDef *type_def, WCHAR *name, + ULONG name_len, ULONG *name_written, ULONG *prop_flags, + const COR_SIGNATURE **sig_blob, ULONG *sig_len, ULONG *value_type_flag, + UVCP_CONSTANT *default_value, ULONG *value_len, mdMethodDef *set_method, + mdMethodDef *get_method, mdMethodDef *other_methods, ULONG other_len, + ULONG *other_count) +{ + FIXME("(%p, %#x, %p, %p, %lu, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %lu, %p): stub!\n", iface, prop, type_def, + name, name_len, name_written, prop_flags, sig_blob, sig_len, value_type_flag, default_value, value_len, + set_method, get_method, other_methods, other_len, other_count); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetParamProps(IMetaDataImport *iface, mdParamDef param_def, mdMethodDef *method_def, + ULONG *param_seq, WCHAR *name, ULONG name_len, ULONG *name_written, + ULONG *flags, ULONG *value_type_flag, UVCP_CONSTANT *value, ULONG *value_len) +{ + FIXME("(%p, %#x, %p, %p, %p, %lu, %p, %p, %p, %p, %p): stub!\n", iface, param_def, method_def, param_seq, name, + name_len, name_written, flags, value_type_flag, value, value_len); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetCustomAttributeByName(IMetaDataImport *iface, mdToken obj, const WCHAR *name, + const BYTE **data, ULONG *len) +{ + FIXME("(%p, %#x, %s, %p, %p): stub!\n", iface, obj, debugstr_w(name), data, len); + return E_NOTIMPL; +} + +static BOOL WINAPI import_IsValidToken(IMetaDataImport *iface, mdToken token) +{ + FIXME("(%p, %#x): stub!\n", iface, token); + return FALSE; +} + +static HRESULT WINAPI import_GetNestedClassProps(IMetaDataImport *iface, mdTypeDef nested_class, + mdTypeDef *enclosing_class) +{ + FIXME("(%p, %#x, %p): stub!\n", iface, nested_class, enclosing_class); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_GetNativeCallConvFromSig(IMetaDataImport *iface, const BYTE *sig_blob, ULONG len, + ULONG *call_conv) +{ + FIXME("(%p, %p, %lu, %p): stub!\n", iface, sig_blob, len, call_conv); + return E_NOTIMPL; +} + +static HRESULT WINAPI import_IsGlobal(IMetaDataImport *iface, mdToken token, int *is_global) +{ + FIXME("(%p, %#x, %p): stub!\n", iface, token, is_global); + return E_NOTIMPL; +} + +static const IMetaDataImportVtbl import_vtbl = { + import_QueryInterface, + import_AddRef, + import_Release, + import_CloseEnum, + import_CountEnum, + import_ResetEnum, + import_EnumTypeDefs, + import_EnumInterfaceImpls, + import_EnumTypeRefs, + import_FindTypeDefByName, + import_GetScopeProps, + import_GetModuleFromScope, + import_GetTypeDefProps, + import_GetInterfaceImplProps, + import_GetTypeRefProps, + import_ResolveTypeRef, + import_EnumMembers, + import_EnumMembersWithName, + import_EnumMethods, + import_EnumMethodsWithName, + import_EnumFields, + import_EnumFieldsWithName, + import_EnumParams, + import_EnumMemberRefs, + import_EnumMethodImpls, + import_EnumPermissionSets, + import_FindMember, + import_FindMethod, + import_FindField, + import_FindMemberRef, + import_GetMethodProps, + import_GetMemberRefProps, + import_EnumProperties, + import_EnumEvents, + import_GetEventProps, + import_EnumMethodSemantics, + import_GetMethodSemantics, + import_GetClassLayout, + import_GetFieldMarshal, + import_GetRVA, + import_GetPermissionSetProps, + import_GetSigFromToken, + import_GetModuleRefProps, + import_EnumModuleRefs, + import_GetTypeSpecFromToken, + import_GetNameFromToken, + import_EnumUnresolvedMethods, + import_GetUserString, + import_GetPinvokeMap, + import_EnumSignatures, + import_EnumTypeSpecs, + import_EnumUserStrings, + import_GetParamForMethodIndex, + import_EnumCustomAttributes, + import_GetCustomAttributeProps, + import_FindTypeRef, + import_GetMemberProps, + import_GetFieldProps, + import_GetPropertyProps, + import_GetParamProps, + import_GetCustomAttributeByName, + import_IsValidToken, + import_GetNestedClassProps, + import_GetNativeCallConvFromSig, + import_IsGlobal +}; + HRESULT IMetaDataTables_create(const WCHAR *path, IMetaDataTables **iface) { struct metadata_tables *impl; @@ -299,6 +844,7 @@ HRESULT IMetaDataTables_create(const WCHAR *path, IMetaDataTables **iface) }
impl->IMetaDataTables_iface.lpVtbl = &tables_vtbl; + impl->IMetaDataImport_iface.lpVtbl = &import_vtbl; impl->ref = 1; *iface = &impl->IMetaDataTables_iface; return S_OK; diff --git a/include/rometadataapi.idl b/include/rometadataapi.idl index 22e7a0d2085..ca96aa96c68 100644 --- a/include/rometadataapi.idl +++ b/include/rometadataapi.idl @@ -19,6 +19,31 @@ import "unknwn.idl"; import "cor.idl";
+cpp_quote("#if 0") + +typedef ULONG32 mdToken; + +typedef mdToken mdModule; +typedef mdToken mdTypeRef; +typedef mdToken mdTypeDef; +typedef mdToken mdFieldDef; +typedef mdToken mdMethodDef; +typedef mdToken mdParamDef; +typedef mdToken mdInterfaceImpl; +typedef mdToken mdMemberRef; +typedef mdToken mdCustomAttribute; +typedef mdToken mdPermission; +typedef mdToken mdSignature; +typedef mdToken mdEvent; +typedef mdToken mdProperty; +typedef mdToken mdModuleRef; +typedef mdToken mdAssembly; +typedef mdToken mdAssemblyRef; +typedef mdToken mdTypeSpec; +typedef mdToken mdString; + +cpp_quote("#endif") + [ local, object, @@ -67,3 +92,245 @@ interface IMetaDataTables : IUnknown
HRESULT GetNextUserString([in] ULONG idx, [out] ULONG *next); } + +typedef void *HCORENUM; +typedef BYTE COR_SIGNATURE; +typedef const char *UVCP_CONSTANT; + +typedef struct COR_FIELD_OFFSET +{ + mdFieldDef ridOfField; + UINT32 ulOffset; +} COR_FIELD_OFFSET; + +[ + local, + object, + uuid(7dac8207-d3ae-4c75-9b67-92801a497d44) +] +interface IMetaDataImport : IUnknown +{ + void CloseEnum([in] HCORENUM henum); + + HRESULT CountEnum([in] HCORENUM henum, [out, retval] ULONG *count); + + HRESULT ResetEnum([in] HCORENUM henum, [in] ULONG pos); + + HRESULT EnumTypeDefs([in, out] HCORENUM *henum, [out, size_is(len), length_is(*count)] mdTypeDef *typedefs, + [in] ULONG len, [out, retval] ULONG *count); + + HRESULT EnumInterfaceImpls([in, out] HCORENUM *henum, [in] mdTypeDef type_def, + [out, size_is(len), length_is(*count)] mdInterfaceImpl *impls, [in] ULONG len, + [out, retval] ULONG *count); + + HRESULT EnumTypeRefs([in, out] HCORENUM *henum, + [out, size_is(len), length_is(*count)] mdTypeRef *typerefs, [in] ULONG len, + [out, retval] ULONG *count); + + HRESULT FindTypeDefByName([in, string] const WCHAR *name, [in] mdToken enclosing_class, + [out, retval] mdTypeDef *type_def); + + HRESULT GetScopeProps([out, string, size_is(len), length_is(*written)] WCHAR *name, [in] ULONG len, + [out] ULONG *written, [out, unique] GUID *mvid); + + HRESULT GetModuleFromScope([out] mdModule *module_token); + + HRESULT GetTypeDefProps([in] mdTypeDef type_def, [out, string, size_is(len), length_is(*written)] WCHAR *name, + [in] ULONG len, [out] ULONG *written, [out] ULONG *flags, [out] mdToken *extends); + + HRESULT GetInterfaceImplProps([in] mdInterfaceImpl iface_impl, [out] mdTypeDef *class_token, [out] mdToken *iface); + + HRESULT GetTypeRefProps([in] mdTypeRef typeref, [out] mdToken *resolution_scope, + [out, string, size_is(len), length_is(*written)] WCHAR *name, [in] ULONG len, + [out] ULONG *written); + + HRESULT ResolveTypeRef([in] mdTypeRef typeref, [in] const GUID *iid, [out, iid_is(iid)] IUnknown **scope, + [out, retval] mdTypeDef *type_def); + + HRESULT EnumMembers([in, out] HCORENUM *henum, [in] mdTypeDef type_def, + [out, size_is(len), length_is(*count)] mdToken *member_defs, [in] ULONG len, + [out] ULONG *count); + + HRESULT EnumMembersWithName([in, out] HCORENUM *henum, [in] mdTypeDef token, [in, string] const WCHAR *name, + [out, size_is(len), length_is(*count)] mdToken *member_defs, [in] ULONG len, + [out] ULONG *count); + + HRESULT EnumMethods([in, out] HCORENUM *henum, [in] mdTypeDef type_def, + [out, size_is(len), length_is(*count)] mdMethodDef *method_defs, [in] ULONG len, + [out] ULONG *count); + + HRESULT EnumMethodsWithName([in, out] HCORENUM *henum, [in] mdTypeDef type_def, [in, string] const WCHAR *name, + [out, size_is(len), length_is(*count)] mdMethodDef *method_defs, [in] ULONG len, + [out] ULONG *count); + + HRESULT EnumFields([in, out] HCORENUM *henum, [in] mdTypeDef token, + [out, size_is(len), length_is(*count)] mdFieldDef *field_defs, [in] ULONG len, + [out] ULONG *count); + + HRESULT EnumFieldsWithName([in, out] HCORENUM *henum, [in] mdTypeDef token, [in, string] const WCHAR *name, + [out, size_is(len), length_is(*count)] mdFieldDef *field_defs, [in] ULONG len, + [out] ULONG *count); + + HRESULT EnumParams([in, out] HCORENUM *henum, [in] mdMethodDef method_def, + [out, size_is(len), length_is(*count)] mdParamDef *params, [in] ULONG len, + [out] ULONG *count); + + HRESULT EnumMemberRefs([in, out] HCORENUM *henum, [in] mdToken parent, + [out, size_is(len), length_is(*count)] mdMemberRef *members, [in] ULONG len, + [out] ULONG *count); + + HRESULT EnumMethodImpls([in, out] HCORENUM *henum, [in] mdTypeDef token, + [out, size_is(len), length_is(*count)] mdToken *body_tokens, + [out, size_is(len), length_is(*count)] mdToken *decl_tokens, [in] ULONG len, + [out] ULONG *count); + + HRESULT EnumPermissionSets([in, out] HCORENUM *henum, [in] mdToken token, [in] ULONG actions, + [out, size_is(len), length_is(*count)] mdPermission *permissions, [in] ULONG len, + [out] ULONG *count); + + HRESULT FindMember([in] mdTypeDef type_def, [in, string] const WCHAR *name, + [in, size_is(len)] const COR_SIGNATURE *sig_blob, [in] ULONG len, [out] mdToken *member_ref); + + HRESULT FindMethod([in] mdTypeDef type_def, [in, string] const WCHAR *name, + [in, size_is(len)] const COR_SIGNATURE *sig_blob, [in] ULONG len, + [out] mdMethodDef *method_def); + + HRESULT FindField([in] mdTypeDef type_def, [in, string] const WCHAR *name, + [in, size_is(len)] const COR_SIGNATURE *sig_blob, [in] ULONG len, [out] mdFieldDef *field_def); + + HRESULT FindMemberRef([in] mdTypeRef typeref, [in, string] const WCHAR *name, + [in, size_is(len)] const COR_SIGNATURE *sig_blob, [in] ULONG len, + [out] mdMemberRef *member_ref); + + HRESULT GetMethodProps([in] mdMethodDef method_def, [out] mdTypeDef *type_def, + [out, string, size_is(name_len), length_is(*written)] WCHAR *method_name, [in] ULONG name_len, + [out] ULONG *written, [out] ULONG *method_flags, + [out, size_is(, *sig_len)] const COR_SIGNATURE **sig_blob, [out] ULONG *sig_len, + [out] ULONG *rva, [out] ULONG *impl_flags); + + HRESULT GetMemberRefProps([in] mdMemberRef member_ref, [out] mdToken *token, + [out, string, size_is(name_len), length_is(*written)] WCHAR *member_name, + [in] ULONG name_len, [out] ULONG *written, + [out, size_is(, *sig_len)] const COR_SIGNATURE **sig_blob, [out] ULONG *sig_len); + + HRESULT EnumProperties([in, out] HCORENUM *henum, [in] mdTypeDef type_def, + [out, size_is(len), length_is(*count)] mdProperty *props, + [in] ULONG len, [out] ULONG *count); + + HRESULT EnumEvents([in, out] HCORENUM *henum, [in] mdTypeDef type_def, + [out, size_is(len), length_is(*count)] mdEvent *events, [in] ULONG len, [out] ULONG *count); + + HRESULT GetEventProps([in] mdEvent event, [out] mdTypeDef *class_typedef, + [out, string, size_is(name_len), length_is(*written)] WCHAR *name, [in] ULONG name_len, + [out] ULONG *written, [out] ULONG *event_flags, [out] mdToken *event_type, + [out] mdMethodDef *add_method, [out] mdMethodDef *remove_method, + [out] mdMethodDef *fire_method, + [out, size_is(other_len), length_is(*other_count)] mdMethodDef *other_methods, + [in] ULONG other_len, [out] ULONG *other_count); + + HRESULT EnumMethodSemantics([in, out] HCORENUM *henum, [in] mdMethodDef method_def, + [out, size_is(len), length_is(*written)] mdToken *event_props, [in] ULONG len, + [out] ULONG *written); + + HRESULT GetMethodSemantics([in] mdMethodDef method_def, [in] mdToken event_prop, [out] ULONG *semantics); + + HRESULT GetClassLayout([in] mdTypeDef type_def, [out] ULONG *pack_size, + [out, size_is(len), length_is(*count)] COR_FIELD_OFFSET *offsets, [in] ULONG len, + [out] ULONG *count, [out] ULONG *class_size); + + HRESULT GetFieldMarshal([in] mdToken token, [out, size_is(, *len)] const COR_SIGNATURE **native_type_blob, + [out] ULONG *len); + + HRESULT GetRVA([in] mdToken token, [out] ULONG *rva, [out] ULONG *impl_flags); + + HRESULT GetPermissionSetProps([in] mdPermission permission, [out] ULONG *decl_sec, + [out, size_is(, *len)] BYTE const **perm_blob, [out] ULONG *len); + + HRESULT GetSigFromToken([in] mdSignature signature, [out, size_is(, *len)] const COR_SIGNATURE **sig_blob, + [out] ULONG *len); + + HRESULT GetModuleRefProps([in] mdModuleRef module_ref, [out, string, size_is(len), length_is(*written)] WCHAR *name, + [in] ULONG len, [out] ULONG *written); + + HRESULT EnumModuleRefs([in, out] HCORENUM *henum, + [out, size_is(len), length_is(*count)] mdModuleRef *module_refs, [in] ULONG len, + [out] ULONG *count); + + HRESULT GetTypeSpecFromToken([in] mdTypeSpec typespec, [out, size_is(, *len)] const COR_SIGNATURE **sig_blob, + [out] ULONG *len); + + HRESULT GetNameFromToken([in] mdToken token, [out, string] const char **name); + + HRESULT EnumUnresolvedMethods([in, out] HCORENUM *henum, + [out, size_is(len), length_is(*count)] mdToken *method_defs, [in] ULONG len, + [out] ULONG *count); + + HRESULT GetUserString([in] mdString string_token, [out, string, size_is(len), length_is(*written)] WCHAR *str, + [in] ULONG len, [out] ULONG *written); + + HRESULT GetPinvokeMap([in] mdToken field_method_def, [out] ULONG *map_flags, + [out, string, size_is(len), length_is(*written)] WCHAR *import_name, [in] ULONG len, + [out] ULONG *written, [out] mdModuleRef *target); + + HRESULT EnumSignatures([in, out] HCORENUM *henum, [out, size_is(len), length_is(*count)] mdSignature *sigs, + [in] ULONG len, [out] ULONG *count); + + HRESULT EnumTypeSpecs([in, out] HCORENUM *henum, [out, size_is(len), length_is(*count)] mdTypeSpec *typespecs, + [in] ULONG len, [out] ULONG *count); + + HRESULT EnumUserStrings([in, out] HCORENUM *henum, [out, size_is(len), length_is(*count)] mdString *strings, + [in] ULONG len, [out] ULONG *count); + + HRESULT GetParamForMethodIndex([in] mdMethodDef token, [in] ULONG param_seq, [out] mdParamDef *param_def); + + HRESULT EnumCustomAttributes([in, out] HCORENUM *henum, [in] mdToken token, [in] mdToken token_type, + [out, size_is(len), length_is(*count)] mdCustomAttribute *attrs, [in] ULONG len, + [out] ULONG *count); + + HRESULT GetCustomAttributeProps([in] mdCustomAttribute custom_attr, [out, unique] mdToken *obj, + [out, unique] mdToken *attr_type, [out, size_is(, *len), unique] BYTE const **blob, + [out] ULONG *len); + + HRESULT FindTypeRef([in] mdToken resolution_scope, [in, string] const WCHAR *name, [out] mdTypeRef *typeref); + + HRESULT GetMemberProps([in] mdToken member, [out] mdTypeDef *type_def, + [out, string, size_is(member_len), length_is(*member_written)] WCHAR *name, + [in] ULONG member_len,[out] ULONG *member_written, [out] ULONG *flags, + [out, size_is(, *blob_len)] const COR_SIGNATURE **sig_blob, [out] ULONG *blob_len, + [out] ULONG *rva, [out] ULONG *impl_flags, [out] ULONG *value_type_flag, + [out, size_is(, *value_len)] UVCP_CONSTANT *value, [out] ULONG *value_len); + + HRESULT GetFieldProps([in] mdFieldDef fielddef, [out] mdTypeDef *type_def, + [out, string, size_is(name_len), length_is(*name_written)] WCHAR *field_name, + [in] ULONG name_len, [out] ULONG *name_written, [out] ULONG *flags, + [out, size_is(, *sig_len)] const COR_SIGNATURE **sig_blob, [out] ULONG *sig_len, + [out] ULONG *value_type_flag, + [out, size_is(, *value_len)] UVCP_CONSTANT *value, [out] ULONG *value_len); + + HRESULT GetPropertyProps([in] mdProperty prop, [out] mdTypeDef *type_def, + [out, string, size_is(name_len), length_is(*name_written)] WCHAR *name, + [in] ULONG name_len, [out] ULONG *name_written, [out] ULONG *prop_flags, + [out, size_is(, *sig_len)] const COR_SIGNATURE **sig_blob, [out] ULONG *sig_len, + [out] ULONG *value_type_flag, [out, size_is(, *value_len)] UVCP_CONSTANT *default_value, + [out] ULONG *value_len, [out] mdMethodDef *set_method, [out] mdMethodDef *get_method, + [out, size_is(other_len), length_is(*other_count)] mdMethodDef *other_methods, + [in] ULONG other_len, [out] ULONG *other_count); + + HRESULT GetParamProps([in] mdParamDef param_def, [out] mdMethodDef *method_def, + [out] ULONG *param_seq, + [out, string, size_is(name_len), length_is(*name_written)] WCHAR *name, [in] ULONG name_len, + [out] ULONG *name_written, [out] ULONG *flags, [out] ULONG *value_type_flag, + [out, size_is(, *value_len)] UVCP_CONSTANT *value, [out] ULONG *value_len); + + HRESULT GetCustomAttributeByName([in] mdToken obj, [in, string] const WCHAR *name, + [out, size_is(, *len)] BYTE const **data, [out] ULONG *len); + + BOOL IsValidToken([in] mdToken token); + + HRESULT GetNestedClassProps([in] mdTypeDef nested_class, [out] mdTypeDef *enclosing_class); + + HRESULT GetNativeCallConvFromSig([in, size_is(len)] BYTE const *sig_blob, [in] ULONG len, + [out] ULONG *call_conv); + + HRESULT IsGlobal([in] mdToken token, [out] int *is_global); +}
From: Vibhav Pant vibhavp@gmail.com
--- dlls/rometadata/tests/Makefile.in | 1 + dlls/rometadata/tests/rometadata.c | 117 +++++++++++++++++++++++++++- dlls/rometadata/tests/rsrc.rc | 3 + dlls/rometadata/tests/test-enum.idl | 72 +++++++++++++++++ include/corhdr.h | 39 ++++++++++ 5 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 dlls/rometadata/tests/test-enum.idl
diff --git a/dlls/rometadata/tests/Makefile.in b/dlls/rometadata/tests/Makefile.in index 329f6a02473..1623a4904df 100644 --- a/dlls/rometadata/tests/Makefile.in +++ b/dlls/rometadata/tests/Makefile.in @@ -4,4 +4,5 @@ IMPORTS = combase rometadata SOURCES = \ rometadata.c \ rsrc.rc \ + test-enum.idl \ test-simple.idl diff --git a/dlls/rometadata/tests/rometadata.c b/dlls/rometadata/tests/rometadata.c index ad62d6759af..f347a574c11 100644 --- a/dlls/rometadata/tests/rometadata.c +++ b/dlls/rometadata/tests/rometadata.c @@ -1,5 +1,6 @@ /* * Copyright 2024 Zhiyi Zhang for CodeWeavers + * Copyright 2025 Vibhav Pant * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,6 +22,7 @@ #include <windows.h> #include "initguid.h" #include "cor.h" +#include "corhdr.h" #include "roapi.h" #include "rometadata.h" #include "rometadataapi.h" @@ -213,6 +215,7 @@ struct type_info DWORD exp_flags; const char *exp_name; const char *exp_namespace; + mdToken exp_base; };
struct column_info @@ -532,8 +535,8 @@ static void test_MetaDataDispenser_OpenScope(void) static const struct type_info type_defs[3] = { { 0, "<Module>", NULL }, - { TYPE_ATTR_INTERFACE | TYPE_ATTR_ABSTRACT | TYPE_ATTR_UNKNOWN, "ITest1", "Wine.Test" }, - { TYPE_ATTR_PUBLIC | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN, "Test1", "Wine.Test" }, + { tdInterface | tdAbstract | tdWindowsRuntime, "ITest1", "Wine.Test" }, + { tdPublic | tdSealed | tdWindowsRuntime, "Test1", "Wine.Test" }, }; const WCHAR *filename = load_resource(L"test-simple.winmd"); ULONG val = 0, i, guid_ctor_idx = 0, itest1_def_idx = 0; @@ -774,6 +777,115 @@ static void test_MetaDataDispenser_OpenScope(void) IMetaDataTables_Release(md_tables); }
+static void test_IMetaDataImport(void) +{ + static const struct type_info type_defs[] = + { + { tdPublic | tdSealed | tdWindowsRuntime, "TestEnum1", "Wine.Test", 0x1000001 }, + { tdPublic | tdSealed | tdSequentialLayout | tdWindowsRuntime, "TestStruct1", "Wine.Test", 0x1000005 }, + { tdInterface | tdAbstract | tdWindowsRuntime, "ITest2", "Wine.Test", 0x1000000 }, + { tdPublic | tdSealed | tdWindowsRuntime, "Test2", "Wine.Test", 0x100000b }, + }; + const WCHAR *filename = load_resource(L"test-enum.winmd"); + ULONG buf_len, buf_count, str_len, str_reqd, i; + IMetaDataDispenser *dispenser; + IMetaDataImport *md_import; + mdTypeDef *typedef_tokens; + HCORENUM henum = 0; + WCHAR *strW; + HRESULT hr; + ULONG val; + + hr = MetaDataGetDispenser(&CLSID_CorMetaDataDispenser, &IID_IMetaDataDispenser, (void **)&dispenser); + ok(hr == S_OK, "got hr %#lx\n", hr); + + hr = IMetaDataDispenser_OpenScope(dispenser, filename, 0, &IID_IMetaDataImport, (IUnknown **)&md_import); + ok(hr == S_OK, "got hr %#lx\n", hr); + IMetaDataDispenser_Release(dispenser); + + 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); + + buf_len = 0; + hr = IMetaDataImport_CountEnum(md_import, henum, &buf_len); + todo_wine 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); + + 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); + for (i = 0; i < buf_len; i++) + { + const struct type_info *info = &type_defs[i]; + mdTypeDef token = 0; + ULONG exp_len, len; + WCHAR bufW[80]; + char bufA[80]; + mdToken base; + + winetest_push_context("i=%lu", i); + + bufW[0] = L'\0'; + bufA[0] = '\0'; + 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); + 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); + len = wcslen(strW); + todo_wine 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)); + 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); + 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 %#x != %#x\n", base, 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 %#x != %#x\n", token, typedef_tokens[i]); + + 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); + + hr = IMetaDataImport_ResetEnum(md_import, henum, 0); + todo_wine 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); + hr = IMetaDataImport_EnumTypeDefs(md_import, &henum, typedef_tokens, buf_len, &buf_count); + todo_wine ok(hr == S_FALSE, "got hr %#lx\n", hr); + IMetaDataImport_CloseEnum(md_import, henum); + free(typedef_tokens); + + hr = IMetaDataImport_FindTypeDefByName(md_import, NULL, 0, NULL); + todo_wine ok(hr == E_INVALIDARG, "got hr %#lx\n", hr); + + IMetaDataImport_Release(md_import); +} + START_TEST(rometadata) { HRESULT hr; @@ -783,6 +895,7 @@ START_TEST(rometadata)
test_MetaDataGetDispenser(); test_MetaDataDispenser_OpenScope(); + test_IMetaDataImport();
RoUninitialize(); } diff --git a/dlls/rometadata/tests/rsrc.rc b/dlls/rometadata/tests/rsrc.rc index 9b2c6daded3..128971553a3 100644 --- a/dlls/rometadata/tests/rsrc.rc +++ b/dlls/rometadata/tests/rsrc.rc @@ -18,3 +18,6 @@
/* @makedep: test-simple.winmd */ test-simple.winmd RCDATA "test-simple.winmd" + +/* @makedep: test-enum.winmd */ +test-enum.winmd RCDATA "test-enum.winmd" diff --git a/dlls/rometadata/tests/test-enum.idl b/dlls/rometadata/tests/test-enum.idl new file mode 100644 index 00000000000..09c0a08a846 --- /dev/null +++ b/dlls/rometadata/tests/test-enum.idl @@ -0,0 +1,72 @@ +/* + * Copyright 2025 Vibhav Pant + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef __WIDL__ +#pragma makedep header winmd +#pragma winrt ns_prefix +#endif + +import "inspectable.idl"; +import "windowscontracts.idl"; + +namespace Wine.Test { + typedef struct TestStruct1 TestStruct1; + typedef enum TestEnum1 TestEnum1; + + interface ITest2; + + runtimeclass Test2; + + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + enum TestEnum1 + { + Foo = 0, + [contract(Windows.Foundation.UniversalApiContract, 2.0)] + Bar = 1, + [contract(Windows.Foundation.UniversalApiContract, 3.0)] + Baz = 2 + }; + + [contract(Windows.Foundation.UniversalApiContract, 2.0)] + struct TestStruct1 + { + int a; + int b; + int c; + }; + + [ + contract(Windows.Foundation.UniversalApiContract, 3.0), + exclusiveto(Wine.Test.Test2), + uuid(deadbeef-dead-beef-dead-deadbeef0002) + ] + interface ITest2 : IInspectable + { + HRESULT Method1([in] int a, [in] int b, [out, retval] int *out); + HRESULT Method2([in] TestEnum1 a, [out, retval] TestEnum1 *out); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 3.0), + marshaling_behavior(agile) + ] + runtimeclass Test2 + { + [default] interface Wine.Test.ITest2; + } +} diff --git a/include/corhdr.h b/include/corhdr.h index 91f67d25c0f..f3af49abc8d 100644 --- a/include/corhdr.h +++ b/include/corhdr.h @@ -129,4 +129,43 @@ typedef mdToken mdGenericParamConstraint; typedef mdToken mdString; typedef mdToken mdCPToken;
+typedef enum CorTypeAttr +{ + tdNotPublic = 0x000000, + tdPublic = 0x000001, + tdNestedPublic = 0x000002, + tdNestedPrivate = 0x000003, + tdNestedFamily = 0x000004, + tdNestedAssembly = 0x000005, + tdNestedFamANDAssem = 0x000006, + tdNestedFamORAssem = 0x000007, + tdAutoLayout = 0x000000, + tdSequentialLayout = 0x000008, + tdExplicitLayout = 0x000010, + tdExtendedLayout = 0x000018, + tdClass = 0x000000, + tdInterface = 0x000020, + tdAbstract = 0x000080, + tdSealed = 0x000100, + tdSpecialName = 0x000400, + tdImport = 0x001000, + tdSerializable = 0x002000, + tdWindowsRuntime = 0x004000, + tdAnsiClass = 0x000000, + tdUnicodeClass = 0x010000, + tdAutoClass = 0x020000, + tdCustomFormatClass = 0x030000, + tdBeforeFieldInit = 0x100000, + tdForwarder = 0x200000, + tdRTSpecialName = 0x000800, + tdHasSecurity = 0x040000, + + tdVisibilityMask = 0x000007, + tdLayoutMask = 0x000018, + tdClassSemanticsMask = 0x000020, + tdStringFormatMask = 0x030000, + tdCustomFormatMask = 0xc00000, + tdReservedMask = 0x040800 +} CorTypeAttr; + #endif /* __WINE_CORHDR_H */
From: Vibhav Pant vibhavp@gmail.com
--- dlls/rometadata/tests/rometadata.c | 74 ++++++++++++++++++++++++++- include/corhdr.h | 82 ++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 1 deletion(-)
diff --git a/dlls/rometadata/tests/rometadata.c b/dlls/rometadata/tests/rometadata.c index f347a574c11..ccfa15e396e 100644 --- a/dlls/rometadata/tests/rometadata.c +++ b/dlls/rometadata/tests/rometadata.c @@ -777,6 +777,16 @@ static void test_MetaDataDispenser_OpenScope(void) IMetaDataTables_Release(md_tables); }
+struct method_props +{ + const WCHAR *exp_name; + CorMethodAttr exp_method_flags; + CorMethodImpl exp_impl_flags; + BYTE exp_sig_blob[6]; + ULONG exp_sig_len; + CorPinvokeMap exp_call_conv; +}; + static void test_IMetaDataImport(void) { static const struct type_info type_defs[] = @@ -786,11 +796,17 @@ static void test_IMetaDataImport(void) { tdInterface | tdAbstract | tdWindowsRuntime, "ITest2", "Wine.Test", 0x1000000 }, { tdPublic | tdSealed | tdWindowsRuntime, "Test2", "Wine.Test", 0x100000b }, }; + static const struct method_props test2_methods[2] = + { + { L"Method1", mdPublic | mdNewSlot | mdFinal | mdVirtual | mdHideBySig, miManaged | miRuntime, { 0x20, 0x2, 0x8, 0x8, 0x8 }, 5, pmCallConvWinapi }, + { L"Method2", mdPublic | mdNewSlot | mdFinal | mdVirtual | mdHideBySig, miManaged | miRuntime, { 0x20, 0x1, 0x11, 0x9, 0x11, 0x9 }, 6, pmCallConvWinapi }, + }; const WCHAR *filename = load_resource(L"test-enum.winmd"); ULONG buf_len, buf_count, str_len, str_reqd, i; + mdTypeDef *typedef_tokens, typedef1, typedef2; + mdMethodDef *methoddef_tokens; IMetaDataDispenser *dispenser; IMetaDataImport *md_import; - mdTypeDef *typedef_tokens; HCORENUM henum = 0; WCHAR *strW; HRESULT hr; @@ -883,6 +899,62 @@ static void test_IMetaDataImport(void) hr = IMetaDataImport_FindTypeDefByName(md_import, NULL, 0, NULL); todo_wine 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); + hr = IMetaDataImport_FindTypeDefByName(md_import, NULL, 0, &typedef1); + todo_wine 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); + 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); + buf_len = 0; + hr = IMetaDataImport_CountEnum(md_import, henum, &buf_len); + todo_wine 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); + 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); + for (i = 0; i < buf_len; i++) + { + ULONG method_flags = 0, impl_flags = 0, sig_len = 0, call_conv = 0; + const struct method_props *method = &test2_methods[i]; + const BYTE *sig_blob; + WCHAR name[80]; + + winetest_push_context("i=%lu", i); + + name[0] = L'\0'; + 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(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); + 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)); + + hr = IMetaDataImport_GetNativeCallConvFromSig(md_import, sig_blob, sig_len, &call_conv); + todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + todo_wine ok(call_conv == method->exp_call_conv, "got call_conv %#lx != %#x\n", call_conv, method->exp_call_conv); + + winetest_pop_context(); + } + free(methoddef_tokens); + IMetaDataImport_CloseEnum(md_import, henum); + IMetaDataImport_Release(md_import); }
diff --git a/include/corhdr.h b/include/corhdr.h index f3af49abc8d..b825e16df4c 100644 --- a/include/corhdr.h +++ b/include/corhdr.h @@ -168,4 +168,86 @@ typedef enum CorTypeAttr tdReservedMask = 0x040800 } CorTypeAttr;
+typedef enum CorMethodAttr +{ + mdPrivateScope = 0x0000, + mdPrivate = 0x0001, + mdFamANDAssem = 0x0002, + mdAssem = 0x0003, + mdFamily = 0x0004, + mdFamORAssem = 0x0005, + mdPublic = 0x0006, + mdStatic = 0x0010, + mdFinal = 0x0020, + mdVirtual = 0x0040, + mdHideBySig = 0x0080, + mdReuseSlot = 0x0000, + mdNewSlot = 0x0100, + mdCheckAccessOnOverride = 0x0200, + mdAbstract = 0x0400, + mdSpecialName = 0x0800, + mdPinvokeImpl = 0x2000, + mdUnmanagedExport = 0x0008, + mdRTSpecialName = 0x1000, + mdHasSecurity = 0x4000, + mdRequireSecObject = 0x8000, + + mdMemberAccessMask = 0x0007, + mdVtableLayoutMask = 0x0100, + mdReservedMask = 0xd000, +} CorMethodAttr; + +typedef enum CorMethodImpl +{ + miIL = 0x0000, + miNative = 0x0001, + miOPTIL = 0x0002, + miRuntime = 0x0003, + miUnmanaged = 0x0004, + miManaged = 0x0000, + miForwardRef = 0x0010, + miPreserveSig = 0x0080, + miInternalCall = 0x1000, + miSynchronized = 0x0020, + miNoInlining = 0x0008, + miAggressiveInlining = 0x0100, + miNoOptimization = 0x0040, + miAggressiveOptimization = 0x0200, + miAsync = 0x2000, + + miCodeTypeMask = 0x0003, + miManagedMask = 0x0004, + miUserMask = 0x33fc, + + miMaxMethodImplVal = 0xffff, +} CorMethodImpl; + +typedef enum CorPinvokeMap +{ + pmNoMangle = 0x0001, + pmCharSetNotSpec = 0x0000, + pmCharSetAnsi = 0x0002, + pmCharSetUnicode = 0x0004, + pmCharSetAuto = 0x0006, + pmBestFitUseAssem = 0x0000, + pmBestFitEnabled = 0x0010, + pmBestFitDisabled = 0x0020, + pmThrowOnUnmappableCharUseAssem = 0x0000, + pmThrowOnUnmappableCharEnabled = 0x1000, + pmThrowOnUnmappableCharDisabled = 0x2000, + pmSupportsLastError = 0x0040, + pmCallConvWinapi = 0x0100, + pmCallConvCdecl = 0x0200, + pmCallConvStdcall = 0x0300, + pmCallConvThiscall = 0x0400, + pmCallConvFastcall = 0x0500, + + pmCharSetMask = 0x0006, + pmBestFitMask = 0x0030, + pmCallConvMask = 0x0700, + pmThrowOnUnmappableCharMask = 0x3000, + + pmMaxValue = 0xffff, +} CorPinvokeMap; + #endif /* __WINE_CORHDR_H */
From: Vibhav Pant vibhavp@gmail.com
--- dlls/rometadata/tests/rometadata.c | 98 ++++++++++++++++++++++++++++++ include/corhdr.h | 27 ++++++++ 2 files changed, 125 insertions(+)
diff --git a/dlls/rometadata/tests/rometadata.c b/dlls/rometadata/tests/rometadata.c index ccfa15e396e..775dca52118 100644 --- a/dlls/rometadata/tests/rometadata.c +++ b/dlls/rometadata/tests/rometadata.c @@ -787,6 +787,17 @@ struct method_props CorPinvokeMap exp_call_conv; };
+struct field_props +{ + const WCHAR *exp_name; + CorFieldAttr exp_flags; + CorElementType exp_value_type; + BYTE exp_sig_blob[3]; + ULONG exp_sig_len; + BOOL has_value; + const char exp_value[2]; +}; + static void test_IMetaDataImport(void) { static const struct type_info type_defs[] = @@ -801,11 +812,34 @@ static void test_IMetaDataImport(void) { L"Method1", mdPublic | mdNewSlot | mdFinal | mdVirtual | mdHideBySig, miManaged | miRuntime, { 0x20, 0x2, 0x8, 0x8, 0x8 }, 5, pmCallConvWinapi }, { L"Method2", mdPublic | mdNewSlot | mdFinal | mdVirtual | mdHideBySig, miManaged | miRuntime, { 0x20, 0x1, 0x11, 0x9, 0x11, 0x9 }, 6, pmCallConvWinapi }, }; + static const struct field_props testenum1_fields[4] = + { + { COR_ENUM_FIELD_NAME_W, fdPrivate | fdSpecialName | fdRTSpecialName, ELEMENT_TYPE_VOID, { 0x6, 0x8 }, 2 }, + { L"Foo", fdPublic | fdStatic | fdLiteral | fdHasDefault, ELEMENT_TYPE_I4, { 0x6, 0x11, 0x9 }, 3, TRUE, { 0x0 } }, + { L"Bar", fdPublic | fdStatic | fdLiteral | fdHasDefault, ELEMENT_TYPE_I4, { 0x6, 0x11, 0x9 }, 3, TRUE, { 0x1, 0x0 } }, + { L"Baz", fdPublic | fdStatic | fdLiteral | fdHasDefault, ELEMENT_TYPE_I4, { 0x6, 0x11, 0x9 }, 3, TRUE, { 0x2, 0x0 } }, + }; + static const struct field_props teststruct1_fields[3] = + { + { L"a", fdPublic, ELEMENT_TYPE_VOID, { 0x6, ELEMENT_TYPE_I4 }, 2 }, + { L"b", fdPublic, ELEMENT_TYPE_VOID, { 0x6, ELEMENT_TYPE_I4 }, 2 }, + { L"c", fdPublic, ELEMENT_TYPE_VOID, { 0x6, ELEMENT_TYPE_I4 }, 2 }, + }; + const struct field_enum_test_case + { + const WCHAR *type_name; + const struct field_props *field_props; + ULONG fields_len; + } field_enum_test_cases[2] = { + { L"Wine.Test.TestEnum1", testenum1_fields, ARRAY_SIZE(testenum1_fields) }, + { L"Wine.Test.TestStruct1", teststruct1_fields, ARRAY_SIZE(teststruct1_fields) }, + }; const WCHAR *filename = load_resource(L"test-enum.winmd"); ULONG buf_len, buf_count, str_len, str_reqd, i; mdTypeDef *typedef_tokens, typedef1, typedef2; mdMethodDef *methoddef_tokens; IMetaDataDispenser *dispenser; + mdFieldDef *fielddef_tokens; IMetaDataImport *md_import; HCORENUM henum = 0; WCHAR *strW; @@ -955,6 +989,70 @@ static void test_IMetaDataImport(void) free(methoddef_tokens); IMetaDataImport_CloseEnum(md_import, henum);
+ for (i = 0; i < ARRAY_SIZE(field_enum_test_cases); i++) + { + const struct field_props *fields_props = field_enum_test_cases[i].field_props; + const WCHAR *type_name = field_enum_test_cases[i].type_name; + const ULONG fields_len = field_enum_test_cases[i].fields_len; + ULONG field_idx; + + winetest_push_context("%s", debugstr_w(type_name)); + + typedef1 = 0; + hr = IMetaDataImport_FindTypeDefByName(md_import, type_name, 0, &typedef1); + todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + 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); + buf_len = 0; + hr = IMetaDataImport_CountEnum(md_import, henum, &buf_len); + todo_wine 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); + 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); + IMetaDataImport_CloseEnum(md_import, henum); + + for (field_idx = 0; field_idx < buf_len; field_idx++) + { + ULONG flags = 0, sig_len = 0, value_type = 0, value_len = 0; + const struct field_props *props = &fields_props[field_idx]; + const COR_SIGNATURE *sig_blob = NULL; + UVCP_CONSTANT value = NULL; + WCHAR name[80]; + + winetest_push_context("field_idx=%lu", field_idx); + + name[0] = L'\0'; + 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 %#x != %#x\n", typedef2, 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); + 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)); + if (props->has_value) + /* Value blobs are NUL terminated, so we can use strcmp. */ + todo_wine ok(!strcmp(value, props->exp_value), "got value %s != %s\n", debugstr_a(value), + debugstr_a(props->exp_value)); + + winetest_pop_context(); + } + free(fielddef_tokens); + winetest_pop_context(); + } IMetaDataImport_Release(md_import); }
diff --git a/include/corhdr.h b/include/corhdr.h index b825e16df4c..6650e84e23e 100644 --- a/include/corhdr.h +++ b/include/corhdr.h @@ -250,4 +250,31 @@ typedef enum CorPinvokeMap pmMaxValue = 0xffff, } CorPinvokeMap;
+typedef enum CorFieldAttr +{ + fdPrivateScope = 0x0000, + fdPrivate = 0x0001, + fdFamANDAssem = 0x0002, + fdAssembly = 0x0003, + fdFamily = 0x0004, + fdFamORAssem = 0x0005, + fdPublic = 0x0006, + fdStatic = 0x0010, + fdInitOnly = 0x0020, + fdLiteral = 0x0040, + fdNotSerialized = 0x0080, + fdSpecialName = 0x0200, + fdPinvokeImpl = 0x2000, + fdRTSpecialName = 0x0400, + fdHasFieldMarshal = 0x1000, + fdHasDefault = 0x8000, + fdHasFieldRVA = 0x0100, + + fdFieldAccessMask = 0x0007, + fdReservedMask = 0x9500 +} CorFieldAttr; + +#define COR_ENUM_FIELD_NAME ("value__") +#define COR_ENUM_FIELD_NAME_W (L"value__") + #endif /* __WINE_CORHDR_H */
From: Vibhav Pant vibhavp@gmail.com
--- dlls/rometadata/tests/rometadata.c | 64 +++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 5 deletions(-)
diff --git a/dlls/rometadata/tests/rometadata.c b/dlls/rometadata/tests/rometadata.c index 775dca52118..61205a13cd5 100644 --- a/dlls/rometadata/tests/rometadata.c +++ b/dlls/rometadata/tests/rometadata.c @@ -30,6 +30,7 @@
#define WIDL_using_Wine_Test #include "test-simple.h" +#include "test-enum.h"
DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@@ -216,6 +217,8 @@ struct type_info const char *exp_name; const char *exp_namespace; mdToken exp_base; + const char *exp_contract_name; + UINT32 exp_contract_version; };
struct column_info @@ -798,14 +801,36 @@ struct field_props const char exp_value[2]; };
+#define test_contract_value(data, data_len, exp_name, exp_version) test_contract_value_(__LINE__, data, data_len, exp_name, exp_version) +static void test_contract_value_(int line, const BYTE *data, ULONG data_len, const char *exp_name, UINT32 exp_version) +{ + const ULONG name_len = strlen(exp_name); + /* {0x1, 0x2, <len>, <exp_name>, <exp_version>, 0x0, 0x0} */ + const ULONG exp_len = 3 + name_len + sizeof(exp_version) + 2; + + ok_(__FILE__, line)(!!data, "got data %p\n", data); + ok_(__FILE__, line)(data_len == exp_len, "got data_len %lu != %lu\n", data_len, exp_len); + if (data && data_len == exp_len) + { + const char *name = (char *)&data[3]; + const UINT32 version = *(UINT32 *)&data[3 + name_len]; + + ok_(__FILE__, line)(data[0] == 1 && data[1] == 0 && data[2] == name_len, + "unexpected contract value prefix {%#x, %#x, %#x}\n", data[0], data[1], data[2]); + ok_(__FILE__, line)(!memcmp(name, exp_name, name_len), "unexpected contract name: %s != %s\n", + debugstr_an(name, name_len), debugstr_a(exp_name)); + ok_(__FILE__, line)(version == exp_version, "got version %#x != %#x\n", version, exp_version); + } +} + static void test_IMetaDataImport(void) { static const struct type_info type_defs[] = { - { tdPublic | tdSealed | tdWindowsRuntime, "TestEnum1", "Wine.Test", 0x1000001 }, - { tdPublic | tdSealed | tdSequentialLayout | tdWindowsRuntime, "TestStruct1", "Wine.Test", 0x1000005 }, - { tdInterface | tdAbstract | tdWindowsRuntime, "ITest2", "Wine.Test", 0x1000000 }, - { tdPublic | tdSealed | tdWindowsRuntime, "Test2", "Wine.Test", 0x100000b }, + { tdPublic | tdSealed | tdWindowsRuntime, "TestEnum1", "Wine.Test", 0x1000001, "Windows.Foundation.UniversalApiContract", 0x10000 }, + { tdPublic | tdSealed | tdSequentialLayout | tdWindowsRuntime, "TestStruct1", "Wine.Test", 0x1000005, "Windows.Foundation.UniversalApiContract", 0x20000 }, + { tdInterface | tdAbstract | tdWindowsRuntime, "ITest2", "Wine.Test", 0x1000000, "Windows.Foundation.UniversalApiContract", 0x30000 }, + { tdPublic | tdSealed | tdWindowsRuntime, "Test2", "Wine.Test", 0x100000b, "Windows.Foundation.UniversalApiContract", 0x30000 }, }; static const struct method_props test2_methods[2] = { @@ -834,6 +859,9 @@ static void test_IMetaDataImport(void) { L"Wine.Test.TestEnum1", testenum1_fields, ARRAY_SIZE(testenum1_fields) }, { L"Wine.Test.TestStruct1", teststruct1_fields, ARRAY_SIZE(teststruct1_fields) }, }; + static const WCHAR *contract_attribute_name = L"Windows.Foundation.Metadata.ContractVersionAttribute"; + static const WCHAR *guid_attribute_name = L"Windows.Foundation.Metadata.GuidAttribute"; + const WCHAR *filename = load_resource(L"test-enum.winmd"); ULONG buf_len, buf_count, str_len, str_reqd, i; mdTypeDef *typedef_tokens, typedef1, typedef2; @@ -841,7 +869,9 @@ static void test_IMetaDataImport(void) IMetaDataDispenser *dispenser; mdFieldDef *fielddef_tokens; IMetaDataImport *md_import; + const BYTE *data = NULL; HCORENUM henum = 0; + const GUID *guid; WCHAR *strW; HRESULT hr; ULONG val; @@ -874,8 +904,8 @@ static void test_IMetaDataImport(void) for (i = 0; i < buf_len; i++) { const struct type_info *info = &type_defs[i]; + ULONG exp_len, data_len, len; mdTypeDef token = 0; - ULONG exp_len, len; WCHAR bufW[80]; char bufA[80]; mdToken base; @@ -914,6 +944,15 @@ static void test_IMetaDataImport(void) todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); todo_wine ok(token == typedef_tokens[i], "got token %#x != %#x\n", token, typedef_tokens[i]);
+ if (info->exp_contract_name) + { + data_len = 0; + data = NULL; + hr = IMetaDataImport_GetCustomAttributeByName(md_import, typedef_tokens[i], contract_attribute_name, &data, &data_len); + todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + todo_wine test_contract_value(data, data_len, info->exp_contract_name, info->exp_contract_version); + } + winetest_pop_context(); } hr = IMetaDataImport_EnumTypeDefs(md_import, &henum, typedef_tokens, buf_len, &buf_count); @@ -1053,6 +1092,21 @@ static void test_IMetaDataImport(void) free(fielddef_tokens); winetest_pop_context(); } + + 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); + 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); + todo_wine ok(buf_len == sizeof(GUID) + 4, "got buf_len %lu\n", buf_len); + if (data && buf_len == sizeof(GUID) + 4) + { + guid = (GUID *)&data[2]; + ok(IsEqualGUID(guid, &IID_ITest2), "got guid %s\n", debugstr_guid(guid)); + } + IMetaDataImport_Release(md_import); }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/rometadata/tests/rometadata.c | 103 ++++++++++++++++++++++++++++ dlls/rometadata/tests/test-enum.idl | 16 +++++ include/corhdr.h | 26 +++++++ 3 files changed, 145 insertions(+)
diff --git a/dlls/rometadata/tests/rometadata.c b/dlls/rometadata/tests/rometadata.c index 61205a13cd5..b9cce8ca87a 100644 --- a/dlls/rometadata/tests/rometadata.c +++ b/dlls/rometadata/tests/rometadata.c @@ -801,6 +801,15 @@ struct field_props const char exp_value[2]; };
+struct property +{ + const WCHAR *exp_name; + BYTE exp_sig_blob[4]; + ULONG exp_sig_len; + BOOL has_get; + BOOL has_set; +}; + #define test_contract_value(data, data_len, exp_name, exp_version) test_contract_value_(__LINE__, data, data_len, exp_name, exp_version) static void test_contract_value_(int line, const BYTE *data, ULONG data_len, const char *exp_name, UINT32 exp_version) { @@ -823,6 +832,39 @@ static void test_contract_value_(int line, const BYTE *data, ULONG data_len, con } }
+enum prop_method_type +{ + PROP_METHOD_GET, + PROP_METHOD_SET +}; + +#define test_prop_method_token(md, class_token, name, type, token) \ + test_prop_method_token_(__LINE__, md, class_token, name, type, token) +static void test_prop_method_token_(int line, IMetaDataImport *md_import, mdTypeDef class_typedef, + const WCHAR *prop_name, enum prop_method_type type, mdMethodDef token) +{ + static const CorMethodAttr exp_attrs = mdPublic | mdNewSlot | mdVirtual | mdHideBySig | mdAbstract | mdSpecialName; + const WCHAR *prefix = type == PROP_METHOD_GET ? L"get" : L"put"; + WCHAR exp_name[80], name[80]; + ULONG attrs = 0, impl = 0; + mdTypeDef type_def = 0; + HRESULT hr; + BOOL valid; + + ok_(__FILE__, line)(token && token != mdMethodDefNil, "got token %#x\n", token); + valid = IMetaDataImport_IsValidToken(md_import, token); + ok_(__FILE__, line)(valid, "got value %d\n", valid); + name[0] = L'\0'; + hr = IMetaDataImport_GetMethodProps(md_import, token, &type_def, name, ARRAY_SIZE(name), NULL, &attrs, NULL, NULL, + NULL, &impl); + todo_wine ok_(__FILE__, line)(hr == S_OK, "GetMethodProps failed, got hr %#lx\n", hr); + swprintf(exp_name, ARRAY_SIZE(exp_name), L"%s_%s", prefix, prop_name); + todo_wine ok_(__FILE__, line)(!wcscmp(name, exp_name), "got name %s != %s\n", debugstr_w(name), + debugstr_w(exp_name)); + todo_wine ok_(__FILE__, line)(attrs == exp_attrs, "got attrs %#lx != %#x\n", attrs, exp_attrs); + todo_wine ok_(__FILE__, line)(!impl, "got impl %#lx\n", impl); +} + static void test_IMetaDataImport(void) { static const struct type_info type_defs[] = @@ -831,6 +873,7 @@ static void test_IMetaDataImport(void) { tdPublic | tdSealed | tdSequentialLayout | tdWindowsRuntime, "TestStruct1", "Wine.Test", 0x1000005, "Windows.Foundation.UniversalApiContract", 0x20000 }, { tdInterface | tdAbstract | tdWindowsRuntime, "ITest2", "Wine.Test", 0x1000000, "Windows.Foundation.UniversalApiContract", 0x30000 }, { tdPublic | tdSealed | tdWindowsRuntime, "Test2", "Wine.Test", 0x100000b, "Windows.Foundation.UniversalApiContract", 0x30000 }, + { tdPublic | tdInterface | tdAbstract | tdWindowsRuntime, "ITest3", "Wine.Test", 0x1000000, "Windows.Foundation.UniversalApiContract", 0x10000 }, }; static const struct method_props test2_methods[2] = { @@ -850,6 +893,14 @@ static void test_IMetaDataImport(void) { L"b", fdPublic, ELEMENT_TYPE_VOID, { 0x6, ELEMENT_TYPE_I4 }, 2 }, { L"c", fdPublic, ELEMENT_TYPE_VOID, { 0x6, ELEMENT_TYPE_I4 }, 2 }, }; + static const struct property test3_props[5] = + { + { L"Prop1", { 0x28, 0x0, 0x8 }, 3, TRUE, FALSE}, + { L"Prop2", { 0x28, 0x0, 0x11, 0x9 }, 4, TRUE, FALSE }, + { L"Prop3", { 0x28, 0, 0x11, 0x19 }, 4, TRUE, FALSE }, + { L"Prop4", { 0x28, 0, 0x1c }, 3, TRUE, FALSE }, + { L"Prop5", { 0x28, 0x0, 0x8 }, 3, TRUE, TRUE}, + }; const struct field_enum_test_case { const WCHAR *type_name; @@ -868,6 +919,7 @@ static void test_IMetaDataImport(void) mdMethodDef *methoddef_tokens; IMetaDataDispenser *dispenser; mdFieldDef *fielddef_tokens; + mdProperty *property_tokens; IMetaDataImport *md_import; const BYTE *data = NULL; HCORENUM henum = 0; @@ -1107,6 +1159,57 @@ static void test_IMetaDataImport(void) ok(IsEqualGUID(guid, &IID_ITest2), "got guid %s\n", debugstr_guid(guid)); }
+ 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); + henum = NULL; + 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); + 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); + buf_count = 0xdeadbeef; + hr = IMetaDataImport_EnumProperties(md_import, &henum, typedef1, property_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); + IMetaDataImport_CloseEnum(md_import, henum); + for (i = 0; i < buf_len; i++) + { + ULONG sig_len = 0, value_type = 0, value_len = 0; + const struct property *props = &test3_props[i]; + mdMethodDef get_method = 0, set_method = 0; + const COR_SIGNATURE *sig_blob = NULL; + UVCP_CONSTANT value = NULL; + WCHAR name[80]; + + winetest_push_context("i=%lu", i); + + name[0] = L'\0'; + str_reqd = 0; + hr = IMetaDataImport_GetPropertyProps(md_import, property_tokens[i], &typedef2, name, ARRAY_SIZE(name), + &str_reqd, &val, &sig_blob, &sig_len, &value_type, &value, &value_len, + &set_method, &get_method, NULL, 0, NULL); + todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + todo_wine ok(typedef1 == typedef2, "got typedef1 %#x != %#x\n", typedef1, typedef2); + todo_wine ok(!wcscmp(name, props->exp_name), "got name %s != %s\n", debugstr_w(name), debugstr_w(props->exp_name)); + todo_wine ok(!!sig_blob, "got sig_blob %p\n", sig_blob); + todo_wine ok(sig_len == props->exp_sig_len, "got sig_len %lu != %lu\n", sig_len, props->exp_sig_len); + 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, "got value_len %lu\n", value_len); + ok(!value, "got value %p\n", value); + if (props->has_get) + test_prop_method_token(md_import, typedef1, props->exp_name, PROP_METHOD_GET, get_method); + else + todo_wine ok(get_method == mdMethodDefNil, "got get_method %#x\n", get_method); + if (props->has_set) + test_prop_method_token(md_import, typedef1, props->exp_name, PROP_METHOD_SET, set_method); + else + todo_wine ok(set_method == mdMethodDefNil, "got set_method %#x\n", set_method); + winetest_pop_context(); + } IMetaDataImport_Release(md_import); }
diff --git a/dlls/rometadata/tests/test-enum.idl b/dlls/rometadata/tests/test-enum.idl index 09c0a08a846..386ca917105 100644 --- a/dlls/rometadata/tests/test-enum.idl +++ b/dlls/rometadata/tests/test-enum.idl @@ -29,6 +29,7 @@ namespace Wine.Test { typedef enum TestEnum1 TestEnum1;
interface ITest2; + interface ITest3;
runtimeclass Test2;
@@ -69,4 +70,19 @@ namespace Wine.Test { { [default] interface Wine.Test.ITest2; } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + uuid(deadbeef-dead-beef-dead-deadbeef0003) + ] + interface ITest3 : IInspectable + { + HRESULT GetTest2([in] TestEnum1 a, [out, retval] Wine.Test.ITest2 **out); + [propget] HRESULT Prop1([out, retval] int *out); + [propget] HRESULT Prop2([out, retval] TestEnum1 *out); + [propget] HRESULT Prop3([out, retval] TestStruct1 *out); + [propget] HRESULT Prop4([out, retval] Wine.Test.ITest2 **out); + [propget] HRESULT Prop5([out, retval] int *a); + [propput] HRESULT Prop5([in] int a); + } } diff --git a/include/corhdr.h b/include/corhdr.h index 6650e84e23e..afa2d1e14e0 100644 --- a/include/corhdr.h +++ b/include/corhdr.h @@ -129,6 +129,32 @@ typedef mdToken mdGenericParamConstraint; typedef mdToken mdString; typedef mdToken mdCPToken;
+#define mdTokenNil ((mdToken)0) +#define mdModuleNil ((mdModule)mdtModule) +#define mdTypeRefNil ((mdTypeRef)mdtTypeRef) +#define mdTypeDefNil ((mdTypeDef)mdtTypeDef) +#define mdFieldDefNil ((mdFieldDef)mdtFieldDef) +#define mdMethodDefNil ((mdMethodDef)mdtMethodDef) +#define mdParamDefNil ((mdParamDef)mdtParamDef) +#define mdInterfaceImplNil ((mdInterfaceImpl)mdtInterfaceImpl) +#define mdMemberRefNil ((mdMemberRef)mdtMemberRef) +#define mdCustomAttributeNil ((mdCustomAttribute)mdtCustomAttribute) +#define mdPermissionNil ((mdPermission)mdtPermission) +#define mdSignatureNil ((mdSignature)mdtSignature) +#define mdEventNil ((mdEvent)mdtEvent) +#define mdPropertyNil ((mdProperty)mdtProperty) +#define mdModuleRefNil ((mdModuleRef)mdtModuleRef) +#define mdTypeSpecNil ((mdTypeSpec)mdtTypeSpec) +#define mdAssemblyNil ((mdAssembly)mdtAssembly) +#define mdAssemblyRefNil ((mdAssemblyRef)mdtAssemblyRef) +#define mdFileNil ((mdFile)mdtFile) +#define mdExportedTypeNil ((mdExportedType)mdtExportedType) +#define mdManifestResourceNil ((mdManifestResource)mdtManifestResource) +#define mdGenericParamNil ((mdGenericParam)mdtGenericParam) +#define mdGenericParamConstraintNil ((mdGenericParamConstraint)mdtGenericParamConstraint) +#define mdMethodSpecNil ((mdMethodSpec)mdtMethodSpec) +#define mdStringNil ((mdString)mdtString) + typedef enum CorTypeAttr { tdNotPublic = 0x000000,