-- v2: widl: Add rows for composition interfaces.
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/metadata.c | 55 ++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 24 deletions(-)
diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index a9924a8a8da..1347ad8eda2 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -2903,49 +2903,56 @@ static void add_marshalingbehavior_attr_step2( type_t *type ) add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); }
-static void add_runtimeclass_type_step2( type_t *type ) +static void add_member_interfaces( type_t *class ) { - UINT name, namespace, scope, extends, typeref, interface, interfaceimpl_ref, flags; - typeref_list_t *iface_list = type_runtimeclass_get_ifaces( type ); - typeref_t *iface; - const statement_t *stmt; - - name = add_name( type, &namespace ); - - scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); - typeref = add_typeref_row( scope, add_string("Object"), add_string("System") ); - - extends = typedef_or_ref( TABLE_TYPEREF, typeref ); - flags = TYPE_ATTR_PUBLIC | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN; - if (!iface_list) flags |= TYPE_ATTR_ABSTRACT; - - type->md.def = add_typedef_row( flags, name, namespace, extends, 0, 0 ); + const typeref_list_t *iface_list = type_runtimeclass_get_ifaces( class ); + const typeref_t *iface;
if (iface_list) LIST_FOR_EACH_ENTRY( iface, iface_list, typeref_t, entry ) { - interface = typedef_or_ref( TABLE_TYPEREF, iface->type->md.ref ); - interfaceimpl_ref = add_interfaceimpl_row( type->md.def, interface ); + UINT interface = typedef_or_ref( TABLE_TYPEREF, iface->type->md.ref ); + UINT interfaceimpl_ref = add_interfaceimpl_row( class->md.def, interface ); + const statement_t *stmt;
- if (is_attr( iface->attrs, ATTR_DEFAULT )) add_default_attr( type, interfaceimpl_ref ); + if (is_attr( iface->attrs, ATTR_DEFAULT )) add_default_attr( class, interfaceimpl_ref );
/* add properties in reverse order like midlrt */ STATEMENTS_FOR_EACH_FUNC_REV( stmt, type_iface_get_stmts(iface->type) ) { const var_t *method = stmt->u.var;
- add_property( type, iface->type, method ); + add_property( class, iface->type, method ); }
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface->type) ) { const var_t *method = stmt->u.var;
- add_event( type, iface->type, method ); - add_method( type, iface->type, method ); - add_method_impl( type, iface->type, method ); - add_method_contract_attrs( type, iface->type, method->declspec.type ); + add_event( class, iface->type, method ); + add_method( class, iface->type, method ); + add_method_impl( class, iface->type, method ); + add_method_contract_attrs( class, iface->type, method->declspec.type ); } } +} + +static void add_runtimeclass_type_step2( type_t *type ) +{ + const typeref_list_t *iface_list = type_runtimeclass_get_ifaces( type ); + UINT name, namespace, scope, extends, typeref, flags; + + name = add_name( type, &namespace ); + + scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); + typeref = add_typeref_row( scope, add_string("Object"), add_string("System") ); + + extends = typedef_or_ref( TABLE_TYPEREF, typeref ); + flags = TYPE_ATTR_PUBLIC | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN; + if (!iface_list) flags |= TYPE_ATTR_ABSTRACT; + + type->md.def = add_typedef_row( flags, name, namespace, extends, 0, 0 ); + + add_member_interfaces( type );
add_contract_attr_step1( type ); add_static_attr_step1( type );
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/metadata.c | 98 +++++++++++++++++++++++++++++++++---------- 1 file changed, 75 insertions(+), 23 deletions(-)
diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index 1347ad8eda2..02c5f2b99f5 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -1628,13 +1628,13 @@ static UINT make_type_sig( const type_t *type, BYTE *buf ) return len; }
-static UINT make_method_sig( const var_t *method, BYTE *buf ) +static UINT make_method_sig( const var_t *method, BYTE *buf, BOOL is_static ) { const var_t *arg; const var_list_t *arg_list = type_function_get_args( method->declspec.type ); UINT len = 3;
- buf[0] = SIG_TYPE_HASTHIS; + buf[0] = is_static ? SIG_TYPE_DEFAULT : SIG_TYPE_HASTHIS; buf[1] = 0; buf[2] = ELEMENT_TYPE_VOID;
@@ -1660,13 +1660,13 @@ static UINT make_method_sig( const var_t *method, BYTE *buf ) return len; }
-static UINT make_property_sig( const var_t *method, BYTE *buf ) +static UINT make_property_sig( const var_t *method, BYTE *buf, BOOL is_static ) { const var_t *arg; const var_list_t *arg_list = type_function_get_args( method->declspec.type ); UINT len = 3;
- buf[0] = SIG_TYPE_HASTHIS | SIG_TYPE_PROPERTY; + buf[0] = is_static ? SIG_TYPE_PROPERTY : SIG_TYPE_HASTHIS | SIG_TYPE_PROPERTY; buf[1] = 0; buf[2] = ELEMENT_TYPE_VOID;
@@ -2237,28 +2237,53 @@ static char *get_method_name( const var_t *method ) return strmake( "%s", method->name ); }
-static UINT get_method_attrs( BOOL abstract, BOOL special, UINT *flags ) +static BOOL is_special_method( const var_t *method ) { - UINT attrs = METHOD_ATTR_PUBLIC | METHOD_ATTR_VIRTUAL | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_NEWSLOT; + if (is_attr( method->attrs, ATTR_PROPGET ) || is_attr( method->attrs, ATTR_PROPPUT ) || + is_attr( method->attrs, ATTR_EVENTADD ) || is_attr( method->attrs, ATTR_EVENTREMOVE )) return TRUE; + return FALSE; +} + +static BOOL is_static_iface( const type_t *class, const type_t *iface ) +{ + const attr_t *attr;
- if (abstract) + if (!class || !class->attrs) return FALSE; + + LIST_FOR_EACH_ENTRY( attr, class->attrs, const attr_t, entry ) + { + const expr_t *value = attr->u.pval; + + if (attr->type != ATTR_STATIC) continue; + if (value->u.var->declspec.type == iface) return TRUE; + } + + return FALSE; +} + +static UINT get_method_attrs( const type_t *class, const type_t *iface, const var_t *method, UINT *flags ) +{ + UINT attrs = METHOD_ATTR_PUBLIC | METHOD_ATTR_HIDEBYSIG; + + if (!class) { *flags = 0; - attrs |= METHOD_ATTR_ABSTRACT; + attrs |= METHOD_ATTR_ABSTRACT | METHOD_ATTR_VIRTUAL | METHOD_ATTR_NEWSLOT; } else { *flags = METHOD_IMPL_RUNTIME; - attrs |= METHOD_ATTR_FINAL; + if (is_static_iface( class, iface )) attrs |= METHOD_ATTR_STATIC; + else attrs |= METHOD_ATTR_VIRTUAL | METHOD_ATTR_NEWSLOT | METHOD_ATTR_FINAL; }
- if (special) attrs |= METHOD_ATTR_SPECIALNAME; + if (is_special_method( method )) attrs |= METHOD_ATTR_SPECIALNAME; return attrs; }
static void add_propget_method( const type_t *class, const type_t *iface, const var_t *method ) { - UINT sig_size, property, paramlist, flags, attrs = get_method_attrs( class == NULL, TRUE, &flags ); + UINT sig_size, property, paramlist, flags, attrs = get_method_attrs( class, iface, method, &flags ); char *name = get_method_name( method ); type_t *type = method->declspec.type; BYTE sig[256]; @@ -2267,7 +2292,7 @@ static void add_propget_method( const type_t *class, const type_t *iface, const else property = type->md.iface_property;
paramlist = add_method_params_step2( type_function_get_args(type) ); - sig_size = make_method_sig( method, sig ); + sig_size = make_method_sig( method, sig, is_static_iface(class, iface) );
type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); add_methodsemantics_row( METHOD_SEM_GETTER, type->md.def, has_semantics(TABLE_PROPERTY, property) ); @@ -2289,13 +2314,13 @@ static const var_t *find_propget_method( const type_t *iface, const char *name ) static void add_propput_method( const type_t *class, const type_t *iface, const var_t *method ) { const var_t *propget = find_propget_method( iface, method->name ); - UINT sig_size, paramlist, property, flags, attrs = get_method_attrs( class == NULL, TRUE, &flags ); + UINT sig_size, paramlist, property, flags, attrs = get_method_attrs( class, iface, method, &flags ); char *name = get_method_name( method ); type_t *type = method->declspec.type; BYTE sig[256];
paramlist = add_method_params_step2( type_function_get_args(method->declspec.type) ); - sig_size = make_method_sig( method, sig ); + sig_size = make_method_sig( method, sig, is_static_iface(class, iface) );
type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); free( name ); @@ -2317,7 +2342,7 @@ static void add_propput_method( const type_t *class, const type_t *iface, const
static void add_eventadd_method( const type_t *class, const type_t *iface, const var_t *method ) { - UINT event, sig_size, paramlist, flags, attrs = get_method_attrs( class == NULL, TRUE, &flags ); + UINT event, sig_size, paramlist, flags, attrs = get_method_attrs( class, iface, method, &flags ); char *name = get_method_name( method ); type_t *type = method->declspec.type; BYTE sig[256]; @@ -2326,7 +2351,7 @@ static void add_eventadd_method( const type_t *class, const type_t *iface, const else event = type->md.iface_event;
paramlist = add_method_params_step2( type_function_get_args(type) ); - sig_size = make_method_sig( method, sig ); + sig_size = make_method_sig( method, sig, is_static_iface(class, iface) );
type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); free( name ); @@ -2349,13 +2374,13 @@ static const var_t *find_eventadd_method( const type_t *iface, const char *name static void add_eventremove_method( const type_t *class, const type_t *iface, const var_t *method ) { const var_t *eventadd = find_eventadd_method( iface, method->name ); - UINT event, sig_size, paramlist, flags, attrs = get_method_attrs( class == NULL, TRUE, &flags ); + UINT event, sig_size, paramlist, flags, attrs = get_method_attrs( class, iface, method, &flags ); char *name = get_method_name( method ); type_t *type = method->declspec.type; BYTE sig[256];
paramlist = add_method_params_step2( type_function_get_args(type) ); - sig_size = make_method_sig( method, sig ); + sig_size = make_method_sig( method, sig, is_static_iface(class, iface) );
type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); free( name ); @@ -2377,13 +2402,13 @@ static void add_eventremove_method( const type_t *class, const type_t *iface, co
static void add_regular_method( const type_t *class, const type_t *iface, const var_t *method ) { - UINT paramlist, sig_size, flags, attrs = get_method_attrs( class == NULL, FALSE, &flags ); + UINT paramlist, sig_size, flags, attrs = get_method_attrs( class, iface, method, &flags ); char *name = get_method_name( method ); type_t *type = method->declspec.type; BYTE sig[256];
paramlist = add_method_params_step2( type_function_get_args(type) ); - sig_size = make_method_sig( method, sig ); + sig_size = make_method_sig( method, sig, is_static_iface(class, iface) );
type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); free( name ); @@ -2397,7 +2422,7 @@ static void add_property( type_t *class, type_t *iface, const var_t *method )
if (!is_attr( method->attrs, ATTR_PROPGET )) return;
- sig_size = make_property_sig( method, sig ); + sig_size = make_property_sig( method, sig, is_static_iface(class, iface) ); if (class) { type->md.class_property = add_property_row( 0, add_string(method->name), add_blob(sig, sig_size) ); @@ -2608,7 +2633,7 @@ static void add_method_impl( const type_t *class, const type_t *iface, const var BYTE sig[256];
parent = memberref_parent( TABLE_TYPEREF, iface->md.ref ); - sig_size = make_method_sig( method, sig ); + sig_size = make_method_sig( method, sig, FALSE );
memberref = add_memberref_row( parent, add_string(name), add_blob(sig, sig_size) ); free( name ); @@ -2936,6 +2961,32 @@ static void add_member_interfaces( type_t *class ) } }
+static void add_static_interfaces( type_t *class ) +{ + const attr_t *attr; + + if (class->attrs) LIST_FOR_EACH_ENTRY( attr, class->attrs, const attr_t, entry ) + { + const expr_t *value = attr->u.pval; + const statement_t *stmt; + type_t *iface; + + if (attr->type != ATTR_STATIC) continue; + + iface = value->u.var->declspec.type; + + STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) + { + const var_t *method = stmt->u.var; + + add_property( class, iface, method ); + add_event( class, iface, method ); + add_method( class, iface, method ); + add_method_contract_attrs( class, iface, method->declspec.type ); + } + } +} + static void add_runtimeclass_type_step2( type_t *type ) { const typeref_list_t *iface_list = type_runtimeclass_get_ifaces( type ); @@ -2953,6 +3004,7 @@ static void add_runtimeclass_type_step2( type_t *type ) type->md.def = add_typedef_row( flags, name, namespace, extends, 0, 0 );
add_member_interfaces( type ); + add_static_interfaces( type );
add_contract_attr_step1( type ); add_static_attr_step1( type ); @@ -3008,7 +3060,7 @@ static void add_delegate_type_step2( type_t *type ) UINT sig_size; BYTE sig[256];
- sig_size = make_method_sig( method, sig ); + sig_size = make_method_sig( method, sig, FALSE ); paramlist = add_method_params_step2( type_function_get_args(method->declspec.type) );
add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string("Invoke"), add_blob(sig, sig_size), paramlist );
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/metadata.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-)
diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index 02c5f2b99f5..24c8cd6c64f 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -2736,16 +2736,23 @@ static void add_static_attr_step2( type_t *type ) static UINT make_activatable_value( const expr_t *attr, BYTE *buf ) { char *name_iface = NULL, *name_contract; - UINT len_iface = 0, len_contract, len_extra = 5; - const type_t *type_iface = attr->u.var->declspec.type, *type_contract; + const type_t *type_iface, *type_contract; + UINT version, len_iface = 0, len_contract, len_extra = 5; BYTE *ptr = buf;
- if (attr->type != EXPR_MEMBER) type_contract = attr->u.var->declspec.type; - else + if (attr->type == EXPR_MEMBER) { + type_iface = attr->u.var->declspec.type; name_iface = format_namespace( type_iface->namespace, "", ".", type_iface->name, NULL ); len_iface = strlen( name_iface ); + type_contract = attr->ref->u.var->declspec.type; + version = attr->ref->ref->u.integer.value; + } + else + { + type_contract = attr->u.var->declspec.type; + version = attr->ref->u.integer.value; }
name_contract = format_namespace( type_contract->namespace, "", ".", type_contract->name, NULL ); @@ -2762,16 +2769,20 @@ static UINT make_activatable_value( const expr_t *attr, BYTE *buf ) ptr += 2; len_extra += 5; } + ptr[0] = 1; ptr[1] = 0; - ptr[2] = len_contract; - memcpy( ptr + 3, name_contract, len_contract ); - ptr += len_contract + 3; + memcpy( ptr + 2, &version, sizeof(version) ); + ptr += sizeof(version) + 2; + + ptr[0] = len_contract; + memcpy( ptr + 1, name_contract, len_contract ); + ptr += len_contract + 1; ptr[0] = ptr[1] = 0;
free( name_iface ); free( name_contract ); - return len_iface + len_contract + len_extra; + return len_iface + sizeof(version) + len_contract + len_extra; }
static void add_activatable_attr_step1( type_t *type ) @@ -2815,7 +2826,7 @@ static void add_activatable_attr_step2( type_t *type ) if (type->attrs) LIST_FOR_EACH_ENTRY_REV( attr, type->attrs, const attr_t, entry ) { UINT parent, attr_type, value_size; - BYTE value[MAX_NAME * 2 + 10]; + BYTE value[MAX_NAME * 2 + sizeof(UINT) + 10];
if (attr->type != ATTR_ACTIVATABLE) continue;
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/metadata.c | 123 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 120 insertions(+), 3 deletions(-)
diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index 24c8cd6c64f..dd2620cae4d 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -1682,6 +1682,25 @@ static UINT make_property_sig( const var_t *method, BYTE *buf, BOOL is_static ) return len; }
+static UINT make_activation_sig( const var_t *method, BYTE *buf ) +{ + const var_t *arg; + UINT len = 3; + + buf[0] = SIG_TYPE_HASTHIS; + buf[1] = 0; + buf[2] = ELEMENT_TYPE_VOID; + + if (method) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry ) + { + if (is_attr( arg->attrs, ATTR_RETVAL )) continue; + len += make_type_sig( arg->declspec.type, buf + len ); + buf[1]++; + } + + return len; +} + static UINT make_deprecated_sig( UINT token, BYTE *buf ) { UINT len = 5; @@ -2162,18 +2181,24 @@ static void add_method_params_step1( var_list_t *arg_list ) } }
+static void add_runtimeclass_type_step1( type_t * ); + static void add_interface_type_step1( type_t *type ) { const statement_t *stmt; UINT name, namespace; + type_t *class;
name = add_name( type, &namespace );
type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace );
+ add_exclusiveto_attr_step1( type ); + + if ((class = type->details.iface->runtime_class)) add_runtimeclass_type_step1( class ); + 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) ) { @@ -2473,12 +2498,15 @@ static void add_method( type_t *class, type_t *iface, const var_t *method ) else add_regular_method( class, iface, method ); }
+static void add_runtimeclass_type_step2( type_t *type ); + 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; + type_t *class;
name = add_name( type, &namespace );
@@ -2504,6 +2532,8 @@ static void add_interface_type_step2( type_t *type ) add_overload_attr_step2( method ); }
+ if ((class = type->details.iface->runtime_class)) add_runtimeclass_type_step2( class ); + add_contract_attr_step2( type ); add_uuid_attr_step2( type ); add_exclusiveto_attr_step2( type ); @@ -2603,8 +2633,9 @@ static void add_runtimeclass_type_step1( type_t *type ) { UINT name, namespace;
- name = add_name( type, &namespace ); + if (type->md.ref) return;
+ name = add_name( type, &namespace ); type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace ); }
@@ -2998,13 +3029,96 @@ static void add_static_interfaces( type_t *class ) } }
+static void add_activation_interfaces( const type_t *class ) +{ + UINT flags = METHOD_ATTR_PUBLIC | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_SPECIALNAME | METHOD_ATTR_RTSPECIALNAME; + const attr_t *attr; + + if (class->attrs) LIST_FOR_EACH_ENTRY_REV( attr, class->attrs, const attr_t, entry ) + { + UINT methoddef, parent, attr_type, value_size, paramlist = 0, sig_size; + BYTE value[MAX_NAME + sizeof(UINT) + 5], sig[256]; + const expr_t *activatable = attr->u.pval; + const type_t *iface = NULL; + const var_t *method = NULL, *arg; + const statement_t *stmt; + + if (attr->type != ATTR_ACTIVATABLE) continue; + + /* interface is optional */ + if (activatable->type == EXPR_MEMBER) iface = activatable->u.var->declspec.type; + + if (iface) STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) + { + UINT seq = 1, row; + + method = stmt->u.var; + + LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry ) + { + if (is_attr( arg->attrs, ATTR_RETVAL )) continue; + row = add_param_row( get_param_attrs(arg), seq++, add_string(arg->name) ); + if (!paramlist) paramlist = row; + } + break; + } + + sig_size = make_activation_sig( method, sig ); + methoddef = add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string(".ctor"), add_blob(sig, sig_size), paramlist ); + + parent = has_customattribute( TABLE_METHODDEF, methoddef ); + attr_type = customattribute_type( TABLE_MEMBERREF, class->md.member[MD_ATTR_CONTRACT] ); + value_size = make_contract_value( class, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); + } +} + +static void add_constructor_overload( const type_t *type ) +{ + static const BYTE sig_default[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID }; + static const BYTE sig_overload[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING }; + UINT name, namespace; + const attr_t *attr; + + if (type->attrs) LIST_FOR_EACH_ENTRY_REV( attr, type->attrs, const attr_t, entry ) + { + const expr_t *value = attr->u.pval; + + if (attr->type == ATTR_ACTIVATABLE && value->type == EXPR_MEMBER) + { + UINT assemblyref, scope, typeref_default, typeref_overload, class; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + + name = add_string( "DefaultOverloadAttribute" ); + namespace = add_string( "Windows.Foundation.Metadata" ); + typeref_default = add_typeref_row( scope, name, namespace ); + + class = memberref_parent( TABLE_TYPEREF, typeref_default ); + add_memberref_row( class, add_string(".ctor"), add_blob(sig_default, sizeof(sig_default)) ); + + name = add_string( "OverloadAttribute" ); + typeref_overload = add_typeref_row( scope, name, namespace ); + + class = memberref_parent( TABLE_TYPEREF, typeref_overload ); + add_memberref_row( class, add_string(".ctor"), add_blob(sig_overload, sizeof(sig_overload)) ); + break; + } + } +} + static void add_runtimeclass_type_step2( type_t *type ) { const typeref_list_t *iface_list = type_runtimeclass_get_ifaces( type ); UINT name, namespace, scope, extends, typeref, flags;
+ if (type->md.def) return; + name = add_name( type, &namespace );
+ add_constructor_overload( type ); + scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); typeref = add_typeref_row( scope, add_string("Object"), add_string("System") );
@@ -3014,10 +3128,13 @@ static void add_runtimeclass_type_step2( type_t *type )
type->md.def = add_typedef_row( flags, name, namespace, extends, 0, 0 );
+ /* add contract first so activation/composition constructors can inherit it */ + add_contract_attr_step1( type ); + + add_activation_interfaces( type ); add_member_interfaces( type ); add_static_interfaces( type );
- add_contract_attr_step1( type ); add_static_attr_step1( type ); add_activatable_attr_step1( type ); add_threading_attr_step1( type );
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/metadata.c | 100 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+)
diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index dd2620cae4d..256995627c7 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -1569,6 +1569,22 @@ static UINT make_member_sig3( UINT token, BYTE *buf ) return len; }
+static UINT make_member_sig4( UINT token, UINT token2, BYTE *buf ) +{ + UINT len = 4; + + buf[0] = SIG_TYPE_HASTHIS; + buf[1] = 4; + buf[2] = ELEMENT_TYPE_VOID; + buf[3] = ELEMENT_TYPE_CLASS; + len += encode_int( token, buf + 4 ); + buf[len++] = ELEMENT_TYPE_VALUETYPE; + len += encode_int( token2, buf + len ); + buf[len++] = ELEMENT_TYPE_U4; + buf[len++] = ELEMENT_TYPE_STRING; + return len; +} + static UINT make_type_sig( const type_t *type, BYTE *buf ) { UINT len = 0; @@ -2970,6 +2986,88 @@ static void add_marshalingbehavior_attr_step2( type_t *type ) add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); }
+static UINT make_composable_value( const expr_t *attr, BYTE *buf ) +{ + char *name_iface, *name_contract; + const expr_t *contract = attr->ref; + const type_t *type_iface = attr->u.var->declspec.type; + const type_t *type_contract = contract->u.var->declspec.type; + UINT access_type = 1, contract_version = contract->ref->u.integer.value; + UINT len_iface, len_contract; + BYTE *ptr = buf; + + name_iface = format_namespace( type_iface->namespace, "", ".", type_iface->name, NULL ); + len_iface = strlen( name_iface ); + + name_contract = format_namespace( type_contract->namespace, "", ".", type_contract->name, NULL ); + len_contract = strlen( name_contract ); + + ptr[0] = 1; + ptr[1] = 0; + ptr[2] = len_iface; + memcpy( ptr + 3, name_iface, len_iface ); + ptr += len_iface + 3; + + if (is_attr( attr->u.var->attrs, ATTR_PUBLIC)) access_type = 2; + memcpy( ptr, &access_type, sizeof(access_type) ); + ptr += sizeof(access_type); + + memcpy( ptr, &contract_version, sizeof(contract_version) ); + ptr += sizeof(contract_version); + + ptr[0] = len_contract; + memcpy( ptr + 1, name_contract, len_contract ); + ptr += len_contract + 1; + ptr[0] = ptr[1] = 0; + + free( name_iface ); + free( name_contract ); + return len_iface + sizeof(access_type) + sizeof(contract_version) + len_contract + 6; +} + +static void add_composable_attr_step1( type_t *type ) +{ + attr_t *attr; + + if (type->attrs) LIST_FOR_EACH_ENTRY( attr, type->attrs, attr_t, entry ) + { + UINT assemblyref, scope, typeref, typeref_attr, typeref_type, class, sig_size; + BYTE sig[64]; + + if (attr->type != ATTR_COMPOSABLE) continue; + + 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("CompositionType"), add_string("Windows.Foundation.Metadata") ); + typeref_attr = add_typeref_row( scope, add_string("ComposableAttribute"), add_string("Windows.Foundation.Metadata") ); + + class = memberref_parent( TABLE_TYPEREF, typeref_attr ); + sig_size = make_member_sig4( typedef_or_ref(TABLE_TYPEREF, typeref_type), typedef_or_ref(TABLE_TYPEREF, typeref), sig ); + attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) ); + } +} + +static void add_composable_attr_step2( type_t *type ) +{ + const attr_t *attr; + + if (type->attrs) LIST_FOR_EACH_ENTRY( attr, type->attrs, const attr_t, entry ) + { + UINT parent, attr_type, value_size; + BYTE value[MAX_NAME + sizeof(UINT) * 2 + 6]; + + if (attr->type != ATTR_COMPOSABLE) continue; + + parent = has_customattribute( TABLE_TYPEDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member ); + value_size = make_composable_value( attr->u.pval, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); + } +} + static void add_member_interfaces( type_t *class ) { const typeref_list_t *iface_list = type_runtimeclass_get_ifaces( class ); @@ -3135,12 +3233,14 @@ static void add_runtimeclass_type_step2( type_t *type ) add_member_interfaces( type ); add_static_interfaces( type );
+ add_composable_attr_step1( type ); add_static_attr_step1( type ); add_activatable_attr_step1( type ); add_threading_attr_step1( type ); add_marshalingbehavior_attr_step1( type );
add_contract_attr_step2( type ); + add_composable_attr_step2( type ); add_static_attr_step2( type ); add_activatable_attr_step2( type ); add_threading_attr_step2( type );
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/metadata.c | 74 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-)
diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index 256995627c7..962f0abf2b4 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -1717,6 +1717,27 @@ static UINT make_activation_sig( const var_t *method, BYTE *buf ) return len; }
+static UINT make_composition_sig( const var_t *method, BYTE *buf ) +{ + const var_t *arg; + UINT len = 3, count = 0; + + buf[0] = SIG_TYPE_HASTHIS; + buf[1] = 0; + buf[2] = ELEMENT_TYPE_VOID; + + if (method) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry ) count++; + + if (count > 3) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry ) + { + if (--count < 3) break; /* omit last 3 standard composition args */ + len += make_type_sig( arg->declspec.type, buf + len ); + buf[1]++; + } + + return len; +} + static UINT make_deprecated_sig( UINT token, BYTE *buf ) { UINT len = 5; @@ -3171,6 +3192,51 @@ static void add_activation_interfaces( const type_t *class ) } }
+static void add_composition_interfaces( const type_t *class ) +{ + UINT flags = METHOD_ATTR_FAMILY | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_SPECIALNAME | METHOD_ATTR_RTSPECIALNAME; + const attr_t *attr; + + if (class->attrs) LIST_FOR_EACH_ENTRY_REV( attr, class->attrs, const attr_t, entry ) + { + UINT methoddef, parent, attr_type, value_size, paramlist = 0, sig_size; + BYTE value[MAX_NAME + sizeof(UINT) + 5], sig[256]; + const expr_t *composable = attr->u.pval; + const var_t *method = NULL, *arg; + const statement_t *stmt; + const type_t *iface; + + if (attr->type != ATTR_COMPOSABLE) continue; + + iface = composable->u.var->declspec.type; + + STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) + { + UINT seq = 1, row, count = 0; + + method = stmt->u.var; + + LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry ) count++; + + if (count > 3) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry ) + { + if (--count < 3) break; /* omit last 3 standard composition args */ + row = add_param_row( get_param_attrs(arg), seq++, add_string(arg->name) ); + if (!paramlist) paramlist = row; + } + break; + } + + sig_size = make_composition_sig( method, sig ); + methoddef = add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string(".ctor"), add_blob(sig, sig_size), paramlist ); + + parent = has_customattribute( TABLE_METHODDEF, methoddef ); + attr_type = customattribute_type( TABLE_MEMBERREF, class->md.member[MD_ATTR_CONTRACT] ); + value_size = make_contract_value( class, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); + } +} + static void add_constructor_overload( const type_t *type ) { static const BYTE sig_default[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID }; @@ -3182,7 +3248,7 @@ static void add_constructor_overload( const type_t *type ) { const expr_t *value = attr->u.pval;
- if (attr->type == ATTR_ACTIVATABLE && value->type == EXPR_MEMBER) + if (attr->type == ATTR_COMPOSABLE || (attr->type == ATTR_ACTIVATABLE && value->type == EXPR_MEMBER)) { UINT assemblyref, scope, typeref_default, typeref_overload, class;
@@ -3219,9 +3285,10 @@ static void add_runtimeclass_type_step2( type_t *type )
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); typeref = add_typeref_row( scope, add_string("Object"), add_string("System") ); - extends = typedef_or_ref( TABLE_TYPEREF, typeref ); - flags = TYPE_ATTR_PUBLIC | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN; + + flags = TYPE_ATTR_PUBLIC | TYPE_ATTR_UNKNOWN; + if (!is_attr( type->attrs, ATTR_COMPOSABLE )) flags |= TYPE_ATTR_SEALED; if (!iface_list) flags |= TYPE_ATTR_ABSTRACT;
type->md.def = add_typedef_row( flags, name, namespace, extends, 0, 0 ); @@ -3230,6 +3297,7 @@ static void add_runtimeclass_type_step2( type_t *type ) add_contract_attr_step1( type );
add_activation_interfaces( type ); + add_composition_interfaces( type ); add_member_interfaces( type ); add_static_interfaces( type );
v2: Fix constructor flags.
On Wed Jul 9 08:32:45 2025 +0000, Rémi Bernon wrote:
If they are mandatory I think we should check that they are written like this when parsing composing interfaces, and emit errors if they aren't, before making assumptions about them later on.
I've made many more assumptions like this. I was planning to address them after this code settles, or do you think we should do that now?
On Wed Jul 9 08:49:53 2025 +0000, Hans Leidekker wrote:
I've made many more assumptions like this. I was planning to address them after this code settles, or do you think we should do that now?
I think it's better to check and emit proper errors before making assumptions yes. I also don't want to block progress if you have more patches pending, but this is particularly noticeable.
I think changing the if into an assert would make it better, and explicit that the last 3 arguments are mandatory.