From: Hans Leidekker hans@codeweavers.com
--- tools/widl/metadata.c | 108 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+)
diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index ee8222ee35e..a58089e3455 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -1112,6 +1112,65 @@ enum
static char *assembly_name;
+static enum element_type map_basic_type( enum type_basic_type type, int sign ) +{ + enum element_type elem_type; + + switch (type) + { + case TYPE_BASIC_CHAR: elem_type = ELEMENT_TYPE_BOOLEAN; break; + case TYPE_BASIC_INT16: elem_type = (sign > 0) ? ELEMENT_TYPE_U2 : ELEMENT_TYPE_I2; break; + case TYPE_BASIC_INT: + case TYPE_BASIC_INT32: + case TYPE_BASIC_LONG: elem_type = (sign > 0) ? ELEMENT_TYPE_U4 : ELEMENT_TYPE_I4; break; + case TYPE_BASIC_INT64: elem_type = (sign > 0) ? ELEMENT_TYPE_U8 : ELEMENT_TYPE_I8; break; + case TYPE_BASIC_BYTE: elem_type = ELEMENT_TYPE_U1; break; + case TYPE_BASIC_WCHAR: elem_type = ELEMENT_TYPE_CHAR; break; + case TYPE_BASIC_FLOAT: elem_type = ELEMENT_TYPE_R4; break; + case TYPE_BASIC_DOUBLE: elem_type = ELEMENT_TYPE_R8; break; + default: + fprintf( stderr, "Unhandled basic type %u.\n", type ); + exit( 1 ); + } + return elem_type; +} + +static UINT make_struct_field_sig( const var_t *var, BYTE *buf ) +{ + const type_t *type = var->declspec.type; + + if (!strcmp( type->name, "HSTRING" )) + { + buf[0] = SIG_TYPE_FIELD; + buf[1] = ELEMENT_TYPE_STRING; + return 2; + } + + if (!strcmp( type->name, "GUID" )) + { + UINT token = typedef_or_ref( TABLE_TYPEREF, type->md.ref ); + return make_field_value_sig( token, buf ); + } + + type = type_get_real_type( type ); + + if (type_get_type( type ) == TYPE_ENUM || type_get_type( type ) == TYPE_STRUCT) + { + UINT token = typedef_or_ref( TABLE_TYPEREF, type->md.ref ); + return make_field_value_sig( token, buf ); + } + + if (type_get_type( type ) != TYPE_BASIC) + { + fprintf( stderr, "Unhandled struct field type %u.\n", type_get_type( type ) ); + exit( 1 ); + } + + buf[0] = SIG_TYPE_FIELD; + buf[1] = map_basic_type( type_basic_get_type(type), type_basic_get_sign(type) ); + return 2; +} + static UINT make_member_sig( UINT token, BYTE *buf ) { UINT len = 4; @@ -1294,6 +1353,49 @@ static void add_enum_type_step2( type_t *type ) add_flags_attr_step2( type ); }
+static void add_struct_type_step1( type_t *type ) +{ + UINT name, namespace, scope, typeref; + const var_t *var; + + name = add_name( type, &namespace ); + scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); + + LIST_FOR_EACH_ENTRY( var, type_struct_get_fields(type), const var_t, entry ) + { + type_t *field_type = var->declspec.type; + if (!strcmp( field_type->name, "GUID" )) + field_type->md.ref = add_typeref_row( scope, add_string("Guid"), add_string("System") ); + } + + typeref = add_typeref_row( scope, add_string("ValueType"), add_string("System") ); + type->md.extends = typedef_or_ref( TABLE_TYPEREF, typeref ); + type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace ); + + add_contract_attr_step1( type ); +} + +static void add_struct_type_step2( type_t *type ) +{ + UINT name, namespace, field, flags, sig_size, first_field = 0; + const var_t *var; + BYTE sig[32]; + + name = add_name( type, &namespace ); + + LIST_FOR_EACH_ENTRY( var, type_struct_get_fields(type), const var_t, entry ) + { + sig_size = make_struct_field_sig( var, sig ); + field = add_field_row( FIELD_ATTR_PUBLIC, add_string(var->name), add_blob(sig, sig_size) ); + if (!first_field) first_field = field; + } + + flags = TYPE_ATTR_PUBLIC | TYPE_ATTR_SEQUENTIALLAYOUT | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN; + type->md.def = add_typedef_row( flags, name, namespace, type->md.extends, first_field, 0 ); + + add_contract_attr_step2( type ); +} + static UINT make_contractversion_value( const type_t *type, BYTE *buf ) { UINT version = get_attrv( type->attrs, ATTR_CONTRACTVERSION ), len = 2 + sizeof(version); @@ -1402,6 +1504,9 @@ static void build_tables( const statement_list_t *stmt_list ) case TYPE_ENUM: add_enum_type_step1( type ); break; + case TYPE_STRUCT: + add_struct_type_step1( type ); + break; case TYPE_APICONTRACT: add_apicontract_type_step1( type ); break; @@ -1422,6 +1527,9 @@ static void build_tables( const statement_list_t *stmt_list ) case TYPE_ENUM: add_enum_type_step2( type ); break; + case TYPE_STRUCT: + add_struct_type_step2( type ); + break; case TYPE_APICONTRACT: add_apicontract_type_step2( type ); break;
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/metadata.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index a58089e3455..22259eda121 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -1396,6 +1396,29 @@ static void add_struct_type_step2( type_t *type ) add_contract_attr_step2( type ); }
+static void add_interface_type_step1( type_t *type ) +{ + UINT name, namespace; + + name = add_name( type, &namespace ); + + type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace ); + + add_contract_attr_step1( type ); +} + +static void add_interface_type_step2( type_t *type ) +{ + UINT name, namespace, flags = TYPE_ATTR_INTERFACE | TYPE_ATTR_ABSTRACT | TYPE_ATTR_UNKNOWN; + + name = add_name( type, &namespace ); + + if (!is_attr( type->attrs, ATTR_EXCLUSIVETO )) flags |= TYPE_ATTR_PUBLIC; + type->md.def = add_typedef_row( flags, name, namespace, 0, 0, 0 ); + + add_contract_attr_step2( type ); +} + static UINT make_contractversion_value( const type_t *type, BYTE *buf ) { UINT version = get_attrv( type->attrs, ATTR_CONTRACTVERSION ), len = 2 + sizeof(version); @@ -1507,6 +1530,9 @@ static void build_tables( const statement_list_t *stmt_list ) case TYPE_STRUCT: add_struct_type_step1( type ); break; + case TYPE_INTERFACE: + add_interface_type_step1( type ); + break; case TYPE_APICONTRACT: add_apicontract_type_step1( type ); break; @@ -1530,6 +1556,9 @@ static void build_tables( const statement_list_t *stmt_list ) case TYPE_STRUCT: add_struct_type_step2( type ); break; + case TYPE_INTERFACE: + add_interface_type_step2( type ); + break; case TYPE_APICONTRACT: add_apicontract_type_step2( type ); break;
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/metadata.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index 22259eda121..c624cdbfeab 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -1396,6 +1396,38 @@ static void add_struct_type_step2( type_t *type ) add_contract_attr_step2( type ); }
+static void add_uuid_attr_step1( type_t *type ) +{ + static const BYTE sig[] = + { SIG_TYPE_HASTHIS, 11, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4, ELEMENT_TYPE_U2, ELEMENT_TYPE_U2, + ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, + ELEMENT_TYPE_U1, ELEMENT_TYPE_U1 }; + UINT assemblyref, scope, typeref, class; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref = add_typeref_row( scope, add_string("GuidAttribute"), add_string("Windows.Foundation.Metadata") ); + + class = memberref_parent( TABLE_TYPEREF, typeref ); + type->md.member[MD_ATTR_UUID] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) ); +} + +static void add_uuid_attr_step2( type_t *type ) +{ + static const BYTE default_uuid[] = + { 0xe7, 0x1f, 0xb5, 0x67, 0x6e, 0x38, 0x31, 0x5a, 0x8a, 0x1c, 0x89, 0x83, 0xc9, 0x49, 0x5c, 0x33 }; + const struct uuid *uuid = get_attrp( type->attrs, ATTR_UUID ); + BYTE value[sizeof(*uuid) + 4] = { 0x01 }; + UINT parent, attr_type; + + if (uuid) memcpy( value + 2, uuid, sizeof(*uuid) ); + else memcpy( value + 2, default_uuid, sizeof(default_uuid) ); + + parent = has_customattribute( TABLE_TYPEDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_UUID] ); + add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) ); +} + static void add_interface_type_step1( type_t *type ) { UINT name, namespace; @@ -1405,6 +1437,7 @@ static void add_interface_type_step1( type_t *type ) type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace );
add_contract_attr_step1( type ); + add_uuid_attr_step1( type ); }
static void add_interface_type_step2( type_t *type ) @@ -1417,6 +1450,7 @@ static void add_interface_type_step2( type_t *type ) type->md.def = add_typedef_row( flags, name, namespace, 0, 0, 0 );
add_contract_attr_step2( type ); + add_uuid_attr_step2( type ); }
static UINT make_contractversion_value( const type_t *type, BYTE *buf )
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/metadata.c | 64 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index c624cdbfeab..cc8b4cfa113 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -1184,6 +1184,18 @@ static UINT make_member_sig( UINT token, BYTE *buf ) return len; }
+static UINT make_member_sig2( UINT type, UINT token, BYTE *buf ) +{ + UINT len = 4; + + buf[0] = SIG_TYPE_HASTHIS; + buf[1] = 1; + buf[2] = ELEMENT_TYPE_VOID; + buf[3] = type; + len += encode_int( token, buf + 4 ); + return len; +} + static UINT make_contract_value( const type_t *type, BYTE *buf ) { const expr_t *contract = get_attrp( type->attrs, ATTR_CONTRACT ); @@ -1428,6 +1440,56 @@ static void add_uuid_attr_step2( type_t *type ) add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) ); }
+static UINT make_exclusiveto_value( const type_t *type, BYTE *buf ) +{ + const type_t *attr = get_attrp( type->attrs, ATTR_EXCLUSIVETO ); + char *name = format_namespace( attr->namespace, "", ".", attr->name, NULL ); + UINT len = strlen( name ); + + buf[0] = 1; + buf[1] = 0; + buf[2] = len; + memcpy( buf + 3, name, len ); + len += 3; + buf[len++] = 0; + buf[len++] = 0; + + free( name ); + return len; +} + +static void add_exclusiveto_attr_step1( type_t *type ) +{ + UINT assemblyref, scope, typeref, typeref_type, class, sig_size; + BYTE sig[32]; + + if (!is_attr( type->attrs, ATTR_EXCLUSIVETO )) return; + + scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); + typeref_type = add_typeref_row( scope, add_string("Type"), add_string("System") ); + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref = add_typeref_row( scope, add_string("ExclusiveToAttribute"), add_string("Windows.Foundation.Metadata") ); + + class = memberref_parent( TABLE_TYPEREF, typeref ); + sig_size = make_member_sig2( ELEMENT_TYPE_CLASS, typedef_or_ref(TABLE_TYPEREF, typeref_type), sig ); + type->md.member[MD_ATTR_EXCLUSIVETO] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) ); +} + +static void add_exclusiveto_attr_step2( type_t *type ) +{ + UINT parent, attr_type, value_size; + BYTE value[256 + 5]; + + if (!is_attr( type->attrs, ATTR_EXCLUSIVETO )) return; + + parent = has_customattribute( TABLE_TYPEDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_EXCLUSIVETO] ); + value_size = make_exclusiveto_value( type, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); +} + static void add_interface_type_step1( type_t *type ) { UINT name, namespace; @@ -1438,6 +1500,7 @@ static void add_interface_type_step1( type_t *type )
add_contract_attr_step1( type ); add_uuid_attr_step1( type ); + add_exclusiveto_attr_step1( type ); }
static void add_interface_type_step2( type_t *type ) @@ -1451,6 +1514,7 @@ static void add_interface_type_step2( type_t *type )
add_contract_attr_step2( type ); add_uuid_attr_step2( type ); + add_exclusiveto_attr_step2( type ); }
static UINT make_contractversion_value( const type_t *type, BYTE *buf )
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/metadata.c | 50 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-)
diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index cc8b4cfa113..5196da97cd1 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -718,6 +718,45 @@ static void serialize_field_table( void ) } }
+struct interfaceimpl_row +{ + UINT class; + UINT interface; +}; + +static UINT add_interfaceimpl_row( UINT class, UINT interface ) +{ + struct interfaceimpl_row row = { class, interface }; + return add_row( TABLE_INTERFACEIMPL, (const BYTE *)&row, sizeof(row) ); +} + +static int cmp_interfaceimpl_row( const void *a, const void *b ) +{ + const struct interfaceimpl_row *row = a, *row2 = b; + if (row->class > row2->class) return 1; + if (row->class < row2->class) return -1; + if (row->interface > row2->interface) return 1; + if (row->interface < row2->interface) return -1; + return 0; +} + +/* sorted by class, interface */ +static void serialize_interfaceimpl_table( void ) +{ + const struct interfaceimpl_row *row = (const struct interfaceimpl_row *)tables[TABLE_INTERFACEIMPL].ptr; + UINT i; + + qsort( tables[TABLE_INTERFACEIMPL].ptr, tables[TABLE_INTERFACEIMPL].count, sizeof(*row), + cmp_interfaceimpl_row ); + + for (i = 0; i < tables_idx[TABLE_INTERFACEIMPL].count; i++) + { + serialize_table_idx( row->class, TABLE_TYPEDEF ); + serialize_table_idx( row->interface, typedef_or_ref_to_table(row->interface) ); + row++; + } +} + struct memberref_row { UINT class; @@ -1505,13 +1544,21 @@ static void add_interface_type_step1( type_t *type )
static void add_interface_type_step2( type_t *type ) { - UINT name, namespace, flags = TYPE_ATTR_INTERFACE | TYPE_ATTR_ABSTRACT | TYPE_ATTR_UNKNOWN; + 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;
name = add_name( type, &namespace );
if (!is_attr( type->attrs, ATTR_EXCLUSIVETO )) flags |= TYPE_ATTR_PUBLIC; type->md.def = add_typedef_row( flags, name, namespace, 0, 0, 0 );
+ if (require_list) LIST_FOR_EACH_ENTRY( require, require_list, typeref_t, entry ) + { + interface = typedef_or_ref( TABLE_TYPEREF, require->type->md.ref ); + add_interfaceimpl_row( type->md.def, interface ); + } + add_contract_attr_step2( type ); add_uuid_attr_step2( type ); add_exclusiveto_attr_step2( type ); @@ -1704,6 +1751,7 @@ static void build_table_stream( const statement_list_t *stmts ) serialize_typeref_table(); serialize_typedef_table(); serialize_field_table(); + serialize_interfaceimpl_table(); serialize_memberref_table(); serialize_constant_table(); serialize_customattribute_table();
This outputs rows for the generic interfaces too, whereas the generic types should be outputted only once, as CLR generics.
``` .namespace Windows.Foundation.Collections { .class interface public auto ansi abstract 'IIterator<ABI::Windows::Gaming::Input::ArcadeStick* >' { } // end of class Windows.Foundation.Collections.IIterator<ABI::Windows::Gaming::Input::ArcadeStick* > } .namespace Windows.Foundation.Collections { .class interface public auto ansi abstract 'IIterator<ABI::Windows::Gaming::Input::RawGameController* >' { } // end of class Windows.Foundation.Collections.IIterator<ABI::Windows::Gaming::Input::RawGameController* > } /* etc... */ ```
Should be instead one:
``` .namespace Windows.Foundation.Collections { .class interface public auto ansi abstract IIterator`1<T> { /* interface details, using T */ } } ```
On Fri Jun 6 10:14:22 2025 +0000, Rémi Bernon wrote:
This outputs rows for the generic interfaces too, whereas the generic types should be outputted only once, as CLR generics.
.namespace Windows.Foundation.Collections { .class interface public auto ansi abstract 'IIterator<ABI::Windows::Gaming::Input::ArcadeStick* >' { } // end of class Windows.Foundation.Collections.IIterator<ABI::Windows::Gaming::Input::ArcadeStick* > } .namespace Windows.Foundation.Collections { .class interface public auto ansi abstract 'IIterator<ABI::Windows::Gaming::Input::RawGameController* >' { } // end of class Windows.Foundation.Collections.IIterator<ABI::Windows::Gaming::Input::RawGameController* > } /* etc... */
Should be instead one:
.namespace Windows.Foundation.Collections { .class interface public auto ansi abstract IIterator`1<T> { /* interface details, using T */ } }
It's probably fine to skip the generic interfaces entirely for now I don't think you can normally define new ones and I suspect their definition comes from a special handling in MIDL.
Still, for later when typerefs to parameterized types will be generated (for parameters, requires, etc), the names here seem to be wrong. I don't think it should be C++-style, and I think parameters should properly be referenced through typerefs too.