-- v2: widl: Require runtimeclass contract or version attribute. include: Add missing runtimeclass contract attributes. widl: Check composition method parameters. widl: Check activation method parameters. include: Comment reference to undefined activation interface.
From: Hans Leidekker hans@codeweavers.com
--- include/windows.devices.usb.idl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/windows.devices.usb.idl b/include/windows.devices.usb.idl index 40d4312d9de..abd036074bd 100644 --- a/include/windows.devices.usb.idl +++ b/include/windows.devices.usb.idl @@ -165,7 +165,7 @@ namespace Windows.Devices.Usb { }
[ - activatable(Windows.Devices.Usb.IUsbSetupPacketFactory, Windows.Foundation.UniversalApiContract, 1.0), + /* activatable(Windows.Devices.Usb.IUsbSetupPacketFactory, Windows.Foundation.UniversalApiContract, 1.0), */ activatable(Windows.Foundation.UniversalApiContract, 1.0), contract(Windows.Foundation.UniversalApiContract, 1.0), marshaling_behavior(agile)
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/parser.y | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 21ac014ccf0..e14f591b21f 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -2901,6 +2901,50 @@ static statement_list_t *append_parameterized_type_stmts(statement_list_t *stmts return stmts; }
+static void check_activation_interface( const type_t *iface ) +{ + const statement_t *stmt; + + STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts( iface ) ) + { + const var_t *arg, *func = stmt->u.var; + const var_list_t *arg_list = type_function_get_args( func->declspec.type ); + unsigned int count = 0; + + if (arg_list) LIST_FOR_EACH_ENTRY_REV( arg, arg_list, const var_t, entry ) + { + const type_t *type = arg->declspec.type; + + count++; + if (count == 1 && (!is_ptr( type ) || !is_attr( arg->attrs, ATTR_RETVAL ))) + error_at( &arg->where, "last parameter '%s' of function '%s' must be an [out, retval] pointer\n", + arg->name, func->name ); + + if (count > 1 && is_attr( arg->attrs, ATTR_OUT )) + error_at( &arg->where, "parameter '%s' of function '%s' must be an IN parameter\n", + arg->name, func->name ); + } + if (count < 2) + error_at( &func->where, "activation function '%s' must have at least 2 parameters\n", func->name ); + } +} + +static void check_constructor_interfaces( const type_t *runtimeclass ) +{ + const attr_t *attr; + + LIST_FOR_EACH_ENTRY( attr, runtimeclass->attrs, const attr_t, entry ) + { + const expr_t *value = attr->u.pval; + + if (attr->type == ATTR_ACTIVATABLE) + { + if (value->type != EXPR_MEMBER) continue; + check_activation_interface( value->u.var->declspec.type ); + } + } +} + static void check_statements(const statement_list_t *stmts, int is_inside_library) { const statement_t *stmt; @@ -2920,6 +2964,8 @@ static void check_statements(const statement_list_t *stmts, int is_inside_librar if(winrt_mode) error_loc("coclass is not allowed in Windows Runtime mode\n"); break; + case TYPE_RUNTIMECLASS: + check_constructor_interfaces( stmt->u.type ); default: break; }
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/parser.y | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index e14f591b21f..fb21a2417f1 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -2929,6 +2929,38 @@ static void check_activation_interface( const type_t *iface ) } }
+static void check_composition_interface( const type_t *iface ) +{ + const statement_t *stmt; + + STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts( iface ) ) + { + const var_t *arg, *func = stmt->u.var; + const var_list_t *arg_list = type_function_get_args( func->declspec.type ); + unsigned int count = 0; + + if (arg_list) LIST_FOR_EACH_ENTRY_REV( arg, arg_list, const var_t, entry ) + { + const type_t *type = arg->declspec.type; + + count++; + if (count == 1 && (!is_ptr( type ) || !is_attr( arg->attrs, ATTR_RETVAL ))) + error_at( &arg->where, "last parameter '%s' of function '%s' must be an [out, retval] pointer\n", + arg->name, func->name ); + + if (count == 2 && !is_attr( arg->attrs, ATTR_OUT )) + error_at( &arg->where, "parameter '%s' of function '%s' must be an OUT parameter\n", + arg->name, func->name ); + + if (count > 2 && is_attr( arg->attrs, ATTR_OUT )) + error_at( &arg->where, "parameter '%s' of function '%s' must be an IN parameter\n", + arg->name, func->name ); + } + if (count < 3) + error_at( &func->where, "composition function '%s' must have at least 3 parameters\n", func->name ); + } +} + static void check_constructor_interfaces( const type_t *runtimeclass ) { const attr_t *attr; @@ -2942,6 +2974,10 @@ static void check_constructor_interfaces( const type_t *runtimeclass ) if (value->type != EXPR_MEMBER) continue; check_activation_interface( value->u.var->declspec.type ); } + else if (attr->type == ATTR_COMPOSABLE) + { + check_composition_interface( value->u.var->declspec.type ); + } } }
From: Hans Leidekker hans@codeweavers.com
--- dlls/windows.gaming.input/provider.idl | 1 + include/windows.devices.enumeration.idl | 4 ++++ include/windows.devices.geolocation.idl | 1 + include/windows.media.devices.idl | 3 +++ 4 files changed, 9 insertions(+)
diff --git a/dlls/windows.gaming.input/provider.idl b/dlls/windows.gaming.input/provider.idl index 651c83fbd20..235c509b25f 100644 --- a/dlls/windows.gaming.input/provider.idl +++ b/dlls/windows.gaming.input/provider.idl @@ -192,6 +192,7 @@ namespace Windows.Gaming.Input.Custom { }
[ + contract(Windows.Foundation.UniversalApiContract, 1.0), marshaling_behavior(agile), threading(both) ] diff --git a/include/windows.devices.enumeration.idl b/include/windows.devices.enumeration.idl index 4f15ac811bc..555b07dad4e 100644 --- a/include/windows.devices.enumeration.idl +++ b/include/windows.devices.enumeration.idl @@ -324,6 +324,7 @@ namespace Windows.Devices.Enumeration { }
[ + contract(Windows.Foundation.UniversalApiContract, 1.0), marshaling_behavior(agile), ] runtimeclass DeviceInformationUpdate @@ -333,6 +334,7 @@ namespace Windows.Devices.Enumeration { }
[ + contract(Windows.Foundation.UniversalApiContract, 1.0), marshaling_behavior(agile), ] runtimeclass DeviceThumbnail @@ -346,6 +348,7 @@ namespace Windows.Devices.Enumeration { }
[ + contract(Windows.Foundation.UniversalApiContract, 1.0), marshaling_behavior(agile), ] runtimeclass DeviceWatcher @@ -355,6 +358,7 @@ namespace Windows.Devices.Enumeration { }
[ + contract(Windows.Foundation.UniversalApiContract, 1.0), marshaling_behavior(agile) ] runtimeclass EnclosureLocation diff --git a/include/windows.devices.geolocation.idl b/include/windows.devices.geolocation.idl index ce4853ffc9d..054c7955bae 100644 --- a/include/windows.devices.geolocation.idl +++ b/include/windows.devices.geolocation.idl @@ -208,6 +208,7 @@ namespace Windows.Devices.Geolocation { }
[ + contract(Windows.Foundation.UniversalApiContract, 1.0), marshaling_behavior(agile) ] runtimeclass StatusChangedEventArgs diff --git a/include/windows.media.devices.idl b/include/windows.media.devices.idl index d0b3fcef873..e538e71ea09 100644 --- a/include/windows.media.devices.idl +++ b/include/windows.media.devices.idl @@ -98,6 +98,7 @@ namespace Windows { }
[ + contract(Windows.Foundation.UniversalApiContract, 1.0), activatable(Windows.Foundation.UniversalApiContract, 1.0), marshaling_behavior(agile), static(Windows.Media.Devices.IMediaDeviceStatics, Windows.Foundation.UniversalApiContract, 1.0), @@ -107,6 +108,7 @@ namespace Windows { }
[ + contract(Windows.Foundation.UniversalApiContract, 1.0), marshaling_behavior(agile) ] runtimeclass DefaultAudioRenderDeviceChangedEventArgs @@ -115,6 +117,7 @@ namespace Windows { }
[ + contract(Windows.Foundation.UniversalApiContract, 1.0), marshaling_behavior(agile) ] runtimeclass DefaultAudioCaptureDeviceChangedEventArgs
From: Hans Leidekker hans@codeweavers.com
--- tools/widl/attribute.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/tools/widl/attribute.c b/tools/widl/attribute.c index bcd804e272f..84d62c753a7 100644 --- a/tools/widl/attribute.c +++ b/tools/widl/attribute.c @@ -477,13 +477,18 @@ attr_list_t *check_module_attrs( const char *name, attr_list_t *attrs ) attr_list_t *check_runtimeclass_attrs( const char *name, attr_list_t *attrs ) { const attr_t *attr; + bool found_version = FALSE; if (!attrs) return NULL; LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) { if (!allowed_attr[attr->type].on_runtimeclass) error_at( &attr->where, "inapplicable attribute %s for runtimeclass %s\n", allowed_attr[attr->type].display_name, name ); + if (attr->type == ATTR_CONTRACT || attr->type == ATTR_VERSION) + found_version = TRUE; } + if (!found_version) + error_at( NULL, "runtimeclass %s requires contract or version attribute\n", name ); return attrs; }
On Thu Jul 31 09:51:36 2025 +0000, Hans Leidekker wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/8681/diffs?diff_id=196812&start_sha=f453f9e6d806024bb7ad658f2ec371d680c15f60#2fce02bf14483e80c6976392d5999cf3b5d1ae7b_480_480)
Done, thanks.
On Thu Jul 31 09:54:09 2025 +0000, Hans Leidekker wrote:
Done, thanks.
Fwiw it should probably be `false`/`true` instead of `FALSE`/`TRUE`, but doesn't matter much.
This merge request was approved by Rémi Bernon.