From: Hans Leidekker hans@codeweavers.com
--- tools/widl/metadata.c | 155 +++++++++++++++++++++++++++++++++++++++++ tools/widl/widltypes.h | 1 + 2 files changed, 156 insertions(+)
diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index 0e3d7f18e75..4e10bce8898 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -601,6 +601,16 @@ static enum table customattribute_type_to_table( UINT token ) } }
+static enum table has_semantics_to_table( UINT token ) +{ + switch (token & 0x1) + { + case 0: return TABLE_EVENT; + case 1: return TABLE_PROPERTY; + default: assert( 0 ); + } +} + struct module_row { USHORT generation; @@ -998,6 +1008,97 @@ static void serialize_assemblyref_table( void ) } }
+struct propertymap_row +{ + UINT parent; + UINT proplist; +}; + +static UINT add_propertymap_row( UINT parent, UINT proplist ) +{ + struct propertymap_row row = { parent, proplist }; + return add_row( TABLE_PROPERTYMAP, (const BYTE *)&row, sizeof(row) ); +} + +static void serialize_propertymap_table( void ) +{ + const struct propertymap_row *row = (const struct propertymap_row *)tables[TABLE_PROPERTYMAP].ptr; + UINT i; + + for (i = 0; i < tables[TABLE_PROPERTYMAP].count; i++) + { + serialize_table_idx( row->parent, TABLE_TYPEDEF ); + serialize_table_idx( row->proplist, TABLE_PROPERTY ); + row++; + } +} + +struct property_row +{ + USHORT flags; + UINT name; + UINT type; +}; + +static UINT add_property_row( USHORT flags, UINT name, UINT type ) +{ + struct property_row row = { flags, name, type }; + return add_row( TABLE_PROPERTY, (const BYTE *)&row, sizeof(row) ); +} + +static void serialize_property_table( void ) +{ + const struct property_row *row = (const struct property_row *)tables[TABLE_PROPERTY].ptr; + UINT i; + + for (i = 0; i < tables[TABLE_PROPERTY].count; i++) + { + serialize_ushort( row->flags ); + serialize_string_idx( row->name ); + serialize_blob_idx( row->type ); + row++; + } +} + +struct methodsemantics_row +{ + USHORT semantics; + UINT method; + UINT association; +}; + +static UINT add_methodsemantics_row( USHORT flags, UINT name, UINT type ) +{ + struct methodsemantics_row row = { flags, name, type }; + return add_row( TABLE_METHODSEMANTICS, (const BYTE *)&row, sizeof(row) ); +} + +static int cmp_methodsemantics_row( const void *a, const void *b ) +{ + const struct methodsemantics_row *row = a, *row2 = b; + if (row->association > row2->association) return 1; + if (row->association < row2->association) return -1; + return 0; +} + +/* sorted by association */ +static void serialize_methodsemantics_table( void ) +{ + const struct methodsemantics_row *row = (const struct methodsemantics_row *)tables[TABLE_METHODSEMANTICS].ptr; + UINT i; + + qsort( tables[TABLE_METHODSEMANTICS].ptr, tables[TABLE_METHODSEMANTICS].count, sizeof(*row), + cmp_methodsemantics_row ); + + for (i = 0; i < tables[TABLE_METHODSEMANTICS].count; i++) + { + serialize_ushort( row->semantics ); + serialize_table_idx( row->method, TABLE_METHODDEF ); + serialize_table_idx( row->association, has_semantics_to_table(row->association) ); + row++; + } +} + static UINT typedef_or_ref( enum table table, UINT row ) { switch (table) @@ -1081,6 +1182,16 @@ static UINT customattribute_type( enum table table, UINT row ) } }
+static UINT has_semantics( enum table table, UINT row ) +{ + switch (table) + { + case TABLE_EVENT: return row << 1; + case TABLE_PROPERTY: return row << 1 | 1; + default: assert( 0 ); + } +} + enum element_type { ELEMENT_TYPE_END = 0x00, @@ -1196,6 +1307,15 @@ enum METHOD_IMPL_UNMANAGED = 0x0004 };
+enum +{ + METHOD_SEM_SETTER = 0x0001, + METHOD_SEM_GETTER = 0x0002, + METHOD_SEM_OTHER = 0x0004, + METHOD_SEM_ADDON = 0x0008, + METHOD_SEM_REMOVEON = 0x0010 +}; + enum { PARAM_ATTR_IN = 0x0001, @@ -1766,11 +1886,36 @@ static UINT add_method_params_step2( var_list_t *arg_list ) return first; }
+static void add_propget_method( const type_t *iface, const var_t *method ) +{ + static const BYTE sig_prop[] = { SIG_TYPE_HASTHIS | SIG_TYPE_PROPERTY, 0, ELEMENT_TYPE_I4 }; + UINT methoddef, property, sig_size, paramlist, attrs; + BYTE sig[256]; + char *name; + + property = add_property_row( 0, add_string(method->name), add_blob(sig_prop, sizeof(sig_prop)) ); + method->declspec.type->md.property = property; + add_propertymap_row( iface->md.def, property ); + + paramlist = add_method_params_step2( type_function_get_args(method->declspec.type) ); + sig_size = make_method_sig( method, sig ); + + attrs = METHOD_ATTR_FAMANDASSEM | METHOD_ATTR_FAMILY | METHOD_ATTR_VIRTUAL | METHOD_ATTR_HIDEBYSIG | + METHOD_ATTR_NEWSLOT | METHOD_ATTR_ABSTRACT | METHOD_ATTR_SPECIALNAME; + + name = strmake( "get_%s", method->name ); + methoddef = add_methoddef_row( 0, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); + free( name ); + + add_methodsemantics_row( METHOD_SEM_GETTER, methoddef, has_semantics(TABLE_PROPERTY, property) ); +} + static void add_interface_type_step2( type_t *type ) { UINT name, namespace, interface, flags = TYPE_ATTR_INTERFACE | TYPE_ATTR_ABSTRACT | TYPE_ATTR_UNKNOWN; const typeref_list_t *require_list = type_iface_get_requires( type ); const typeref_t *require; + const statement_t *stmt;
name = add_name( type, &namespace );
@@ -1783,6 +1928,13 @@ static void add_interface_type_step2( type_t *type ) add_interfaceimpl_row( type->md.def, interface ); }
+ STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(type) ) + { + const var_t *method = stmt->u.var; + + if (is_attr( method->attrs, ATTR_PROPGET )) add_propget_method( type, method ); + } + add_contract_attr_step2( type ); add_uuid_attr_step2( type ); add_exclusiveto_attr_step2( type ); @@ -2052,6 +2204,9 @@ static void build_table_stream( const statement_list_t *stmts ) serialize_memberref_table(); serialize_constant_table(); serialize_customattribute_table(); + serialize_propertymap_table(); + serialize_property_table(); + serialize_methodsemantics_table(); serialize_assembly_table(); serialize_assemblyref_table(); } diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index c76dea97a6c..bf2d6d4e8d8 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -518,6 +518,7 @@ struct metadata unsigned int def; unsigned int extends; unsigned int member[MD_ATTR_MAX]; + unsigned int property; /* get/put methods */ };
struct _type_t {
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/metadata.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index 4e10bce8898..4a19c633c07 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -1893,6 +1893,9 @@ static void add_propget_method( const type_t *iface, const var_t *method ) BYTE sig[256]; char *name;
+ /* method may already have been added by add_propput_method() */ + if (method->declspec.type->md.property) return; + property = add_property_row( 0, add_string(method->name), add_blob(sig_prop, sizeof(sig_prop)) ); method->declspec.type->md.property = property; add_propertymap_row( iface->md.def, property ); @@ -1910,6 +1913,42 @@ static void add_propget_method( const type_t *iface, const var_t *method ) add_methodsemantics_row( METHOD_SEM_GETTER, methoddef, has_semantics(TABLE_PROPERTY, property) ); }
+static const var_t *find_propget_method( const type_t *iface, const char *name ) +{ + const statement_t *stmt; + + STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) + { + const var_t *method = stmt->u.var; + if (is_attr( method->attrs, ATTR_PROPGET ) && !strcmp( method->name, name )) return method; + } + return NULL; +} + +static void add_propput_method( const type_t *iface, const var_t *method ) +{ + const var_t *propget = find_propget_method( iface, method->name ); + UINT methoddef, property, sig_size, paramlist, attrs; + BYTE sig[256]; + char *name; + + paramlist = add_method_params_step2( type_function_get_args(method->declspec.type) ); + sig_size = make_method_sig( method, sig ); + + attrs = METHOD_ATTR_FAMANDASSEM | METHOD_ATTR_FAMILY | METHOD_ATTR_VIRTUAL | METHOD_ATTR_HIDEBYSIG | + METHOD_ATTR_NEWSLOT | METHOD_ATTR_ABSTRACT | METHOD_ATTR_SPECIALNAME; + + name = strmake( "put_%s", method->name ); + methoddef = add_methoddef_row( 0, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); + free( name ); + + /* add propget method if not already added */ + if (!propget->declspec.type->md.property) add_propget_method( iface, propget ); + property = propget->declspec.type->md.property; + + add_methodsemantics_row( METHOD_SEM_SETTER, methoddef, has_semantics(TABLE_PROPERTY, property) ); +} + static void add_interface_type_step2( type_t *type ) { UINT name, namespace, interface, flags = TYPE_ATTR_INTERFACE | TYPE_ATTR_ABSTRACT | TYPE_ATTR_UNKNOWN; @@ -1933,6 +1972,7 @@ static void add_interface_type_step2( type_t *type ) const var_t *method = stmt->u.var;
if (is_attr( method->attrs, ATTR_PROPGET )) add_propget_method( type, method ); + else if (is_attr( method->attrs, ATTR_PROPPUT )) add_propput_method( type, method ); }
add_contract_attr_step2( type );
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/metadata.c | 111 +++++++++++++++++++++++++++++++++++++++++ tools/widl/widltypes.h | 1 + 2 files changed, 112 insertions(+)
diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index 4a19c633c07..2341b6a3597 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -1060,6 +1060,58 @@ static void serialize_property_table( void ) } }
+struct eventmap_row +{ + UINT parent; + UINT eventlist; +}; + +static UINT add_eventmap_row( UINT parent, UINT eventlist ) +{ + struct eventmap_row row = { parent, eventlist }; + return add_row( TABLE_EVENTMAP, (const BYTE *)&row, sizeof(row) ); +} + +static void serialize_eventmap_table( void ) +{ + const struct eventmap_row *row = (const struct eventmap_row *)tables[TABLE_EVENTMAP].ptr; + UINT i; + + for (i = 0; i < tables[TABLE_EVENTMAP].count; i++) + { + serialize_table_idx( row->parent, TABLE_TYPEDEF ); + serialize_table_idx( row->eventlist, TABLE_EVENT ); + row++; + } +} + +struct event_row +{ + USHORT flags; + UINT name; + UINT type; +}; + +static UINT add_event_row( USHORT flags, UINT name, UINT type ) +{ + struct event_row row = { flags, name, type }; + return add_row( TABLE_EVENT, (const BYTE *)&row, sizeof(row) ); +} + +static void serialize_event_table( void ) +{ + const struct event_row *row = (const struct event_row *)tables[TABLE_EVENT].ptr; + UINT i; + + for (i = 0; i < tables[TABLE_EVENT].count; i++) + { + serialize_ushort( row->flags ); + serialize_string_idx( row->name ); + serialize_table_idx( row->type, typedef_or_ref_to_table(row->type) ); + row++; + } +} + struct methodsemantics_row { USHORT semantics; @@ -1836,8 +1888,31 @@ static void add_exclusiveto_attr_step2( type_t *type ) add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); }
+static void add_method_params_step1( var_list_t *arg_list ) +{ + var_t *arg; + + if (!arg_list) return; + + LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry ) + { + type_t *type = arg->declspec.type; + + if (type_get_type( type ) == TYPE_POINTER) type = type_pointer_get_ref_type( type ); + + if (type->name && !strcmp( type->name, "EventRegistrationToken" )) + { + UINT assemblyref, scope; + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + type->md.ref = add_typeref_row( scope, add_string("EventRegistrationToken"), add_string("Windows.Foundation") ); + } + } +} + static void add_interface_type_step1( type_t *type ) { + const statement_t *stmt; UINT name, namespace;
name = add_name( type, &namespace ); @@ -1847,6 +1922,13 @@ static void add_interface_type_step1( type_t *type ) add_contract_attr_step1( type ); add_uuid_attr_step1( type ); add_exclusiveto_attr_step1( type ); + + STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(type) ) + { + const var_t *method = stmt->u.var; + + add_method_params_step1( type_function_get_args(method->declspec.type) ); + } }
static UINT get_param_attrs( const var_t *arg ) @@ -1949,6 +2031,32 @@ static void add_propput_method( const type_t *iface, const var_t *method ) add_methodsemantics_row( METHOD_SEM_SETTER, methoddef, has_semantics(TABLE_PROPERTY, property) ); }
+static void add_eventadd_method( const type_t *iface, const var_t *method ) +{ + UINT methoddef, event, sig_size, paramlist, attrs; + BYTE sig[256]; + char *name; + + event = add_event_row( 0, add_string(method->name), typedef_or_ref(TABLE_TYPEREF, method->declspec.type->md.ref) ); + method->declspec.type->md.event = event; + add_eventmap_row( iface->md.def, event ); + + /* method may already have been added by add_eventremove_method() */ + if (method->declspec.type->md.event) return; + + paramlist = add_method_params_step2( type_function_get_args(method->declspec.type) ); + sig_size = make_method_sig( method, sig ); + + attrs = METHOD_ATTR_FAMANDASSEM | METHOD_ATTR_FAMILY | METHOD_ATTR_VIRTUAL | METHOD_ATTR_HIDEBYSIG | + METHOD_ATTR_NEWSLOT | METHOD_ATTR_ABSTRACT | METHOD_ATTR_SPECIALNAME; + + name = strmake( "add_%s", method->name ); + methoddef = add_methoddef_row( 0, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); + free( name ); + + add_methodsemantics_row( METHOD_SEM_ADDON, methoddef, has_semantics(TABLE_EVENT, event) ); +} + static void add_interface_type_step2( type_t *type ) { UINT name, namespace, interface, flags = TYPE_ATTR_INTERFACE | TYPE_ATTR_ABSTRACT | TYPE_ATTR_UNKNOWN; @@ -1973,6 +2081,7 @@ static void add_interface_type_step2( type_t *type )
if (is_attr( method->attrs, ATTR_PROPGET )) add_propget_method( type, method ); else if (is_attr( method->attrs, ATTR_PROPPUT )) add_propput_method( type, method ); + else if (is_attr( method->attrs, ATTR_EVENTADD )) add_eventadd_method( type, method ); }
add_contract_attr_step2( type ); @@ -2244,6 +2353,8 @@ static void build_table_stream( const statement_list_t *stmts ) serialize_memberref_table(); serialize_constant_table(); serialize_customattribute_table(); + serialize_eventmap_table(); + serialize_event_table(); serialize_propertymap_table(); serialize_property_table(); serialize_methodsemantics_table(); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index bf2d6d4e8d8..73d593a6aee 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -519,6 +519,7 @@ struct metadata unsigned int extends; unsigned int member[MD_ATTR_MAX]; unsigned int property; /* get/put methods */ + unsigned int event; /* add/remove methods */ };
struct _type_t {
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/metadata.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)
diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index 2341b6a3597..a3b8c7bc6bb 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -2057,6 +2057,42 @@ static void add_eventadd_method( const type_t *iface, const var_t *method ) add_methodsemantics_row( METHOD_SEM_ADDON, methoddef, has_semantics(TABLE_EVENT, event) ); }
+static const var_t *find_eventadd_method( const type_t *iface, const char *name ) +{ + const statement_t *stmt; + + STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) + { + const var_t *method = stmt->u.var; + if (is_attr( method->attrs, ATTR_EVENTADD ) && !strcmp( method->name, name )) return method; + } + return NULL; +} + +static void add_eventremove_method( const type_t *iface, const var_t *method ) +{ + const var_t *eventadd = find_eventadd_method( iface, method->name ); + UINT methoddef, event, sig_size, paramlist, attrs; + BYTE sig[256]; + char *name; + + paramlist = add_method_params_step2( type_function_get_args(method->declspec.type) ); + sig_size = make_method_sig( method, sig ); + + attrs = METHOD_ATTR_FAMANDASSEM | METHOD_ATTR_FAMILY | METHOD_ATTR_VIRTUAL | METHOD_ATTR_HIDEBYSIG | + METHOD_ATTR_NEWSLOT | METHOD_ATTR_ABSTRACT | METHOD_ATTR_SPECIALNAME; + + name = strmake( "remove_%s", method->name ); + methoddef = add_methoddef_row( 0, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); + free( name ); + + /* add eventadd method if not already added */ + if (!eventadd->declspec.type->md.event) add_eventadd_method( iface, eventadd ); + event = eventadd->declspec.type->md.event; + + add_methodsemantics_row( METHOD_SEM_REMOVEON, methoddef, has_semantics(TABLE_EVENT, event) ); +} + static void add_interface_type_step2( type_t *type ) { UINT name, namespace, interface, flags = TYPE_ATTR_INTERFACE | TYPE_ATTR_ABSTRACT | TYPE_ATTR_UNKNOWN; @@ -2082,6 +2118,7 @@ static void add_interface_type_step2( type_t *type ) if (is_attr( method->attrs, ATTR_PROPGET )) add_propget_method( type, method ); else if (is_attr( method->attrs, ATTR_PROPPUT )) add_propput_method( type, method ); else if (is_attr( method->attrs, ATTR_EVENTADD )) add_eventadd_method( type, method ); + else if (is_attr( method->attrs, ATTR_EVENTREMOVE )) add_eventremove_method( type, method ); }
add_contract_attr_step2( type );
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/metadata.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index a3b8c7bc6bb..bf748dfd208 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -2093,6 +2093,20 @@ static void add_eventremove_method( const type_t *iface, const var_t *method ) add_methodsemantics_row( METHOD_SEM_REMOVEON, methoddef, has_semantics(TABLE_EVENT, event) ); }
+static void add_method( const type_t *iface, const var_t *method ) +{ + UINT paramlist, sig_size, attrs; + BYTE sig[256]; + + paramlist = add_method_params_step2( type_function_get_args(method->declspec.type) ); + sig_size = make_method_sig( method, sig ); + + attrs = METHOD_ATTR_FAMANDASSEM | METHOD_ATTR_FAMILY | METHOD_ATTR_VIRTUAL | METHOD_ATTR_HIDEBYSIG | + METHOD_ATTR_NEWSLOT | METHOD_ATTR_ABSTRACT; + + add_methoddef_row( 0, attrs, add_string(method->name), add_blob(sig, sig_size), paramlist ); +} + static void add_interface_type_step2( type_t *type ) { UINT name, namespace, interface, flags = TYPE_ATTR_INTERFACE | TYPE_ATTR_ABSTRACT | TYPE_ATTR_UNKNOWN; @@ -2119,6 +2133,7 @@ static void add_interface_type_step2( type_t *type ) else if (is_attr( method->attrs, ATTR_PROPPUT )) add_propput_method( type, method ); else if (is_attr( method->attrs, ATTR_EVENTADD )) add_eventadd_method( type, method ); else if (is_attr( method->attrs, ATTR_EVENTREMOVE )) add_eventremove_method( type, method ); + else add_method( type, method ); }
add_contract_attr_step2( type );
Rémi Bernon (@rbernon) commented about tools/widl/metadata.c:
+static void add_propget_method( const type_t *iface, const var_t *method ) +{
- static const BYTE sig_prop[] = { SIG_TYPE_HASTHIS | SIG_TYPE_PROPERTY, 0, ELEMENT_TYPE_I4 };
- UINT methoddef, property, sig_size, paramlist, attrs;
- BYTE sig[256];
- char *name;
- property = add_property_row( 0, add_string(method->name), add_blob(sig_prop, sizeof(sig_prop)) );
- method->declspec.type->md.property = property;
- add_propertymap_row( iface->md.def, property );
- paramlist = add_method_params_step2( type_function_get_args(method->declspec.type) );
- sig_size = make_method_sig( method, sig );
- attrs = METHOD_ATTR_FAMANDASSEM | METHOD_ATTR_FAMILY | METHOD_ATTR_VIRTUAL | METHOD_ATTR_HIDEBYSIG |
What about `METHOD_ATTR_PUBLIC` instead of `METHOD_ATTR_FAMANDASSEM | METHOD_ATTR_FAMILY`?
Rémi Bernon (@rbernon) commented about tools/widl/metadata.c:
- BYTE sig[256];
- char *name;
- property = add_property_row( 0, add_string(method->name), add_blob(sig_prop, sizeof(sig_prop)) );
- method->declspec.type->md.property = property;
- add_propertymap_row( iface->md.def, property );
- paramlist = add_method_params_step2( type_function_get_args(method->declspec.type) );
- sig_size = make_method_sig( method, sig );
- attrs = METHOD_ATTR_FAMANDASSEM | METHOD_ATTR_FAMILY | METHOD_ATTR_VIRTUAL | METHOD_ATTR_HIDEBYSIG |
METHOD_ATTR_NEWSLOT | METHOD_ATTR_ABSTRACT | METHOD_ATTR_SPECIALNAME;
- name = strmake( "get_%s", method->name );
- methoddef = add_methoddef_row( 0, attrs, add_string(name), add_blob(sig, sig_size), paramlist );
- free( name );
This seems to be missing a corresponding `MEMBERREF` row, monodis is now asserting with the new additions.
I believe it's probably also the case for the delegate `.ctor` and method btw, I missed it in last MR.
On Tue Jun 17 14:36:02 2025 +0000, Rémi Bernon wrote:
This seems to be missing a corresponding `MEMBERREF` row, monodis is now asserting with the new additions. I believe it's probably also the case for the delegate `.ctor` and method btw, I missed it in last MR.
monodis also asserts on native windows.foundation.winmd. It could be making assumptions that hold for .NET assemblies but not for WinRT metadata, or perhaps it's a plain bug. I doubt it was tested a lot against winmd files. This snippet produces equivalent rows according to winedump -j clr when compiled with widl and midlrt:
``` [ contract(Windows.Foundation.UniversalApiContract, 1.0), uuid(11111111-2222-3333-4444-555555555555), ] interface IWineInterface : IInspectable { [propget] HRESULT WineMethod([out, retval] int *param); [propput] HRESULT WineMethod(int param); }; ```
On Tue Jun 17 14:36:01 2025 +0000, Rémi Bernon wrote:
What about `METHOD_ATTR_PUBLIC` instead of `METHOD_ATTR_FAMANDASSEM | METHOD_ATTR_FAMILY`?
Sure.
On Wed Jun 18 09:02:59 2025 +0000, Hans Leidekker wrote:
monodis also asserts on native windows.foundation.winmd. It could be making assumptions that hold for .NET assemblies but not for WinRT metadata, or perhaps it's a plain bug. I doubt it was tested a lot against winmd files. This snippet produces equivalent rows according to winedump -j clr when compiled with widl and midlrt:
[ contract(Windows.Foundation.UniversalApiContract, 1.0), uuid(11111111-2222-3333-4444-555555555555), ] interface IWineInterface : IInspectable { [propget] HRESULT WineMethod([out, retval] int *param); [propput] HRESULT WineMethod(int param); };
Hmm... I was also looking at existing Windows metadata files with ILSpy and their getter/setters seem to have corresponding MEMBERREF rows, not sure why.
The sample seem to match, indeed (and monodis doesn't assert there, only does with more complex IDL), although it only does with int properties. The property signature is currently hardcoded and should probably use the proper type.
Rémi Bernon (@rbernon) commented about tools/widl/metadata.c:
- if (!arg_list) return;
- LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry )
- {
type_t *type = arg->declspec.type;
if (type_get_type( type ) == TYPE_POINTER) type = type_pointer_get_ref_type( type );
if (type->name && !strcmp( type->name, "EventRegistrationToken" ))
{
UINT assemblyref, scope;
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
type->md.ref = add_typeref_row( scope, add_string("EventRegistrationToken"), add_string("Windows.Foundation") );
}
This doesn't look right, why do we need to hardcode a specific case like that?
On Wed Jun 18 09:47:33 2025 +0000, Rémi Bernon wrote:
Hmm... I was also looking at existing Windows metadata files with ILSpy and their getter/setters seem to have corresponding MEMBERREF rows, not sure why. The sample seem to match, indeed (and monodis doesn't assert there, only does with more complex IDL), although it only does with int properties. The property signature is currently hardcoded and should probably use the proper type.
I've fixed the property signature.
On Wed Jun 18 09:49:25 2025 +0000, Rémi Bernon wrote:
This doesn't look right, why do we need to hardcode a specific case like that?
This is what midlrt generates as soon as you define an addevent method. It encodes the type of the event in the event table.