[PATCH v4 0/4] MR8375: widl: Add rows for the overload attribute.
-- v4: widl: Add rows for the deprecated attribute. widl: Add rows for the default_overload attribute. widl: Add rows for the overload attribute. widl: Use a define for maximum name length. https://gitlab.winehq.org/wine/wine/-/merge_requests/8375
From: Hans Leidekker <hans(a)codeweavers.com> --- tools/widl/metadata.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index 73b3b97a821..dc15704e2a7 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -1394,6 +1394,8 @@ enum #define MODULE_ROW 1 #define MSCORLIB_ROW 1 +#define MAX_NAME 256 + static UINT add_name( type_t *type, UINT *namespace ) { UINT name = add_string( type->name ); @@ -1672,7 +1674,7 @@ static void add_contract_attr_step1( type_t *type ) static void add_contract_attr_step2( type_t *type ) { UINT parent, attr_type, value_size; - BYTE value[256 + sizeof(UINT) + 5]; + BYTE value[MAX_NAME + sizeof(UINT) + 5]; if (!is_attr( type->attrs, ATTR_CONTRACT )) return; @@ -1900,7 +1902,7 @@ static void add_exclusiveto_attr_step1( type_t *type ) static void add_exclusiveto_attr_step2( type_t *type ) { UINT parent, attr_type, value_size; - BYTE value[256 + 5]; + BYTE value[MAX_NAME + 5]; if (!is_attr( type->attrs, ATTR_EXCLUSIVETO )) return; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/8375
From: Hans Leidekker <hans(a)codeweavers.com> --- tools/widl/metadata.c | 64 ++++++++++++++++++++++++++++++++++++++++-- tools/widl/widltypes.h | 1 + 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index dc15704e2a7..5f13e6b315c 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -1912,6 +1912,51 @@ static void add_exclusiveto_attr_step2( type_t *type ) add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); } +static UINT make_overload_value( const var_t *method, BYTE *buf ) +{ + UINT len = strlen( method->name ); + + buf[0] = 1; + buf[1] = 0; + buf[2] = len; + memcpy( buf + 3, method->name, len ); + len += 3; + buf[len++] = 0; + buf[len++] = 0; + + return len; +} + +static void add_overload_attr_step1( const var_t *method ) +{ + static const BYTE sig[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING }; + UINT assemblyref, scope, typeref, class; + type_t *type = method->declspec.type; + + if (!is_attr( method->attrs, ATTR_OVERLOAD )) return; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref = add_typeref_row( scope, add_string("OverloadAttribute"), add_string("Windows.Foundation.Metadata") ); + + class = memberref_parent( TABLE_TYPEREF, typeref ); + type->md.member[MD_ATTR_OVERLOAD] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) ); +} + +static void add_overload_attr_step2( const var_t *method ) +{ + const type_t *type = method->declspec.type; + UINT parent, attr_type, value_size; + BYTE value[MAX_NAME + 5]; + + if (!is_attr( method->attrs, ATTR_OVERLOAD )) return; + + parent = has_customattribute( TABLE_METHODDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_OVERLOAD] ); + value_size = make_overload_value( method, value ); + 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; @@ -1952,6 +1997,8 @@ static void add_interface_type_step1( type_t *type ) const var_t *method = stmt->u.var; add_method_params_step1( type_function_get_args(method->declspec.type) ); + + add_overload_attr_step1( method ); } } @@ -2117,8 +2164,17 @@ 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 ) +static const char *get_method_name( const var_t *method ) { + const char *name = get_attrp( method->attrs, ATTR_OVERLOAD ); + if (name) return name; + return method->name; +} + +static void add_method( const var_t *method ) +{ + const char *name = get_method_name( method ); + type_t *type = method->declspec.type; UINT paramlist, sig_size, attrs; BYTE sig[256]; @@ -2128,7 +2184,7 @@ static void add_method( const type_t *iface, const var_t *method ) attrs = METHOD_ATTR_PUBLIC | 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 ); + type->md.def = add_methoddef_row( 0, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); } static void add_interface_type_step2( type_t *type ) @@ -2157,7 +2213,9 @@ 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 ); + else add_method( method ); + + add_overload_attr_step2( method ); } add_contract_attr_step2( type ); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 73d593a6aee..c0a31679c69 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -509,6 +509,7 @@ enum MD_ATTR_ACTIVATABLE, MD_ATTR_THREADING, MD_ATTR_MARSHALINGBEHAVIOR, + MD_ATTR_OVERLOAD, MD_ATTR_MAX, }; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/8375
From: Hans Leidekker <hans(a)codeweavers.com> --- tools/widl/metadata.c | 31 +++++++++++++++++++++++++++++++ tools/widl/widltypes.h | 1 + 2 files changed, 32 insertions(+) diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index 5f13e6b315c..b9fd30da386 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -1957,6 +1957,35 @@ static void add_overload_attr_step2( const var_t *method ) add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); } +static void add_default_overload_attr_step1( const var_t *method ) +{ + static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID }; + UINT assemblyref, scope, typeref, class; + type_t *type = method->declspec.type; + + if (!is_attr( method->attrs, ATTR_DEFAULT_OVERLOAD ) || !is_attr( method->attrs, ATTR_OVERLOAD )) return; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref = add_typeref_row( scope, add_string("DefaultOverloadAttribute"), add_string("Windows.Foundation.Metadata") ); + + class = memberref_parent( TABLE_TYPEREF, typeref ); + type->md.member[MD_ATTR_DEFAULT_OVERLOAD] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) ); +} + +static void add_default_overload_attr_step2( const var_t *method ) +{ + static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 }; + const type_t *type = method->declspec.type; + UINT parent, attr_type; + + if (!is_attr( method->attrs, ATTR_DEFAULT_OVERLOAD ) || !is_attr( method->attrs, ATTR_OVERLOAD )) return; + + parent = has_customattribute( TABLE_METHODDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_DEFAULT_OVERLOAD] ); + add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) ); +} + static void add_method_params_step1( var_list_t *arg_list ) { var_t *arg; @@ -1999,6 +2028,7 @@ static void add_interface_type_step1( type_t *type ) add_method_params_step1( type_function_get_args(method->declspec.type) ); add_overload_attr_step1( method ); + add_default_overload_attr_step1( method ); } } @@ -2215,6 +2245,7 @@ static void add_interface_type_step2( type_t *type ) else if (is_attr( method->attrs, ATTR_EVENTREMOVE )) add_eventremove_method( type, method ); else add_method( method ); + add_default_overload_attr_step2( method ); add_overload_attr_step2( method ); } diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index c0a31679c69..307c8ed3379 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -510,6 +510,7 @@ enum MD_ATTR_THREADING, MD_ATTR_MARSHALINGBEHAVIOR, MD_ATTR_OVERLOAD, + MD_ATTR_DEFAULT_OVERLOAD, MD_ATTR_MAX, }; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/8375
From: Hans Leidekker <hans(a)codeweavers.com> --- tools/widl/metadata.c | 89 ++++++++++++++++++++++++++++++++++++++++++ tools/widl/widltypes.h | 1 + 2 files changed, 90 insertions(+) diff --git a/tools/widl/metadata.c b/tools/widl/metadata.c index b9fd30da386..9c8eee770ab 100644 --- a/tools/widl/metadata.c +++ b/tools/widl/metadata.c @@ -1618,6 +1618,22 @@ static UINT make_property_sig( const var_t *method, BYTE *buf ) return len; } +static UINT make_deprecated_sig( UINT token, BYTE *buf ) +{ + UINT len = 5; + + buf[0] = SIG_TYPE_HASTHIS; + buf[1] = 4; + buf[2] = ELEMENT_TYPE_VOID; + buf[3] = ELEMENT_TYPE_STRING; + buf[4] = ELEMENT_TYPE_VALUETYPE; + len += encode_int( token, buf + 5 ); + buf[len++] = ELEMENT_TYPE_U4; + buf[len++] = ELEMENT_TYPE_STRING; + + return len; +} + static UINT make_contract_value( const type_t *type, BYTE *buf ) { const expr_t *contract = get_attrp( type->attrs, ATTR_CONTRACT ); @@ -1986,6 +2002,77 @@ static void add_default_overload_attr_step2( const var_t *method ) add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) ); } +static UINT make_deprecated_value( const var_t *method, BYTE **ret_buf ) +{ + static const BYTE zero[] = { 0x00, 0x00, 0x00, 0x00 }, one[] = { 0x01, 0x00, 0x00, 0x00 }; + const expr_t *attr = get_attrp( method->attrs, ATTR_DEPRECATED ); + const char *text = attr->ref->u.sval; + const char *kind = attr->u.ext->u.sval; + BYTE encoded[4]; + UINT len, len_text = strlen( text ), len_encoded = encode_int( len_text, encoded ); + BYTE *buf = xmalloc( 2 + len_encoded + len_text + 6 + MAX_NAME + 5 ); + char *contract; + + buf[0] = 1; + buf[1] = 0; + memcpy( buf + 2, encoded, len_encoded ); + len = 2 + len_encoded; + memcpy( buf + len, text, len_text ); + len += len_text; + if (!strcmp( kind, "remove" )) memcpy( buf + len, one, sizeof(one) ); + else memcpy( buf + len, zero, sizeof(zero) ); + len += 4; + buf[len++] = 0; + buf[len++] = 0; + + buf[len++] = 1; + buf[len++] = 0; + contract = format_namespace( attr->ext2->u.tref.type->namespace, "", ".", attr->ext2->u.tref.type->name, NULL ); + len_text = strlen( contract ); + buf[len++] = len_text; + memcpy( buf + len, contract, len_text ); + free( contract ); + len += len_text; + buf[len++] = 0; + buf[len++] = 0; + + *ret_buf = buf; + return len; +} + +static void add_deprecated_attr_step1( const var_t *method ) +{ + UINT assemblyref, scope, typeref_type, typeref, class, sig_size; + type_t *type = method->declspec.type; + BYTE sig[32]; + + if (!is_attr( method->attrs, ATTR_DEPRECATED )) return; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref_type = add_typeref_row( scope, add_string("DeprecationType"), add_string("Windows.Foundation.Metadata") ); + typeref = add_typeref_row( scope, add_string("DeprecatedAttribute"), add_string("Windows.Foundation.Metadata") ); + + sig_size = make_deprecated_sig( typedef_or_ref(TABLE_TYPEREF, typeref_type), sig ); + class = memberref_parent( TABLE_TYPEREF, typeref ); + type->md.member[MD_ATTR_DEPRECATED] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) ); +} + +static void add_deprecated_attr_step2( const var_t *method ) +{ + const type_t *type = method->declspec.type; + UINT parent, attr_type, value_size; + BYTE *value; + + if (!is_attr( method->attrs, ATTR_DEPRECATED )) return; + + parent = has_customattribute( TABLE_METHODDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_DEPRECATED] ); + value_size = make_deprecated_value( method, &value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); + free( value ); +} + static void add_method_params_step1( var_list_t *arg_list ) { var_t *arg; @@ -2029,6 +2116,7 @@ static void add_interface_type_step1( type_t *type ) add_overload_attr_step1( method ); add_default_overload_attr_step1( method ); + add_deprecated_attr_step1( method ); } } @@ -2245,6 +2333,7 @@ static void add_interface_type_step2( type_t *type ) else if (is_attr( method->attrs, ATTR_EVENTREMOVE )) add_eventremove_method( type, method ); else add_method( method ); + add_deprecated_attr_step2( method ); add_default_overload_attr_step2( method ); add_overload_attr_step2( method ); } diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 307c8ed3379..c4e9a641ef4 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -511,6 +511,7 @@ enum MD_ATTR_MARSHALINGBEHAVIOR, MD_ATTR_OVERLOAD, MD_ATTR_DEFAULT_OVERLOAD, + MD_ATTR_DEPRECATED, MD_ATTR_MAX, }; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/8375
On Fri Jun 20 07:33:29 2025 +0000, Hans Leidekker wrote:
changed this line in [version 4 of the diff](/wine/wine/-/merge_requests/8375/diffs?diff_id=187276&start_sha=6eea79c73412578e065e60c35924b1e97cfc7b8f#f49663b3e534c4786aa268c34b6d635b3be9355d_1964_1966) It's not entirely arbitrary, names are limited to 256 characters and prefix + suffix add another 5 bytes. I added a define for maximum name length which hopefully makes that more clear.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/8375#note_107361
On Thu Jun 19 19:42:07 2025 +0000, Rémi Bernon wrote:
A particular reason this goes in reverse order from step1? midlrt adds the attributes in this order. It's strange because the other types have them in the same order but I prefer to follow midlrt here because it makes it easier to verify that we produce equivalent rows.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/8375#note_107362
This merge request was approved by Rémi Bernon. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/8375
This merge request was approved by Huw Davies. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/8375
participants (4)
-
Hans Leidekker -
Hans Leidekker (@hans) -
Huw Davies (@huw) -
Rémi Bernon