From ae8bdc6121a2d7179bd0b0203dc537c46eba088d Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Wed, 14 Oct 2020 17:33:30 +1100 Subject: [PATCH] Added widl-winrt-support patchset --- patches/patchinstall.sh | 104 ++- ...dows.media.speechsynthesis.idl-draft.patch | 69 ++ ...ict-some-keywords-to-WinRT-mode-only.patch | 381 +++++++++ ...oduce-format_namespace_buffer-helper.patch | 129 +++ ...RT-contractversion-attribute-parsing.patch | 89 +++ ...-widl-Support-WinRT-apicontract-type.patch | 551 +++++++++++++ ...gled-name-over-typedef-in-WinRT-mode.patch | 74 ++ ...tput-typedef-statement-in-WinRT-mode.patch | 27 + ...idl-Support-WinRT-contract-attribute.patch | 341 ++++++++ ...RT-marshaling_behavior-attribute-par.patch | 173 ++++ ...inRT-mta-threading-attribute-parsing.patch | 79 ++ ...-WinRT-exclusiveto-attribute-parsing.patch | 92 +++ ...widl-Support-WinRT-runtimeclass-type.patch | 742 ++++++++++++++++++ ...inRT-eventadd-eventremove-attributes.patch | 95 +++ ...upport-WinRT-flags-attribute-parsing.patch | 66 ++ ...using-qualified-names-for-interfaces.patch | 156 ++++ ...repeated-attributes-for-WinRT-static.patch | 297 +++++++ ...pport-WinRT-static-attribute-parsing.patch | 134 ++++ ...-widl-Support-WinRT-requires-keyword.patch | 254 ++++++ ...-Support-WinRT-activatable-attribute.patch | 96 +++ ...ort-WinRT-parameterized-type-parsing.patch | 391 +++++++++ ...tially-specialized-parameterized-typ.patch | 203 +++++ ...t-WinRT-parameterized-interface-type.patch | 542 +++++++++++++ ...023-widl-Support-WinRT-delegate-type.patch | 346 ++++++++ ...rt-WinRT-parameterized-delegate-type.patch | 181 +++++ ...e-signatures-for-parameterized-types.patch | 253 ++++++ ...ompute-uuids-for-parameterized-types.patch | 317 ++++++++ ...lper-macros-for-WinRT-implementation.patch | 206 +++++ ...torView-HSTRING-declaration-to-windo.patch | 29 + patches/widl-winrt-support/definition | 1 + patches/windows.globalization-dll/definition | 1 + .../definition | 1 + 32 files changed, 6362 insertions(+), 58 deletions(-) create mode 100644 patches/widl-winrt-support/0001-include-Add-windows.media.speechsynthesis.idl-draft.patch create mode 100644 patches/widl-winrt-support/0002-widl-Restrict-some-keywords-to-WinRT-mode-only.patch create mode 100644 patches/widl-winrt-support/0003-widl-Introduce-format_namespace_buffer-helper.patch create mode 100644 patches/widl-winrt-support/0004-widl-Support-WinRT-contractversion-attribute-parsing.patch create mode 100644 patches/widl-winrt-support/0005-widl-Support-WinRT-apicontract-type.patch create mode 100644 patches/widl-winrt-support/0006-widl-Prefer-mangled-name-over-typedef-in-WinRT-mode.patch create mode 100644 patches/widl-winrt-support/0007-widl-Don-t-output-typedef-statement-in-WinRT-mode.patch create mode 100644 patches/widl-winrt-support/0008-widl-Support-WinRT-contract-attribute.patch create mode 100644 patches/widl-winrt-support/0009-widl-Support-WinRT-marshaling_behavior-attribute-par.patch create mode 100644 patches/widl-winrt-support/0010-widl-Support-WinRT-mta-threading-attribute-parsing.patch create mode 100644 patches/widl-winrt-support/0011-widl-Support-WinRT-exclusiveto-attribute-parsing.patch create mode 100644 patches/widl-winrt-support/0012-widl-Support-WinRT-runtimeclass-type.patch create mode 100644 patches/widl-winrt-support/0013-widl-Support-WinRT-eventadd-eventremove-attributes.patch create mode 100644 patches/widl-winrt-support/0014-widl-Support-WinRT-flags-attribute-parsing.patch create mode 100644 patches/widl-winrt-support/0015-widl-Support-using-qualified-names-for-interfaces.patch create mode 100644 patches/widl-winrt-support/0016-widl-Support-repeated-attributes-for-WinRT-static.patch create mode 100644 patches/widl-winrt-support/0017-widl-Support-WinRT-static-attribute-parsing.patch create mode 100644 patches/widl-winrt-support/0018-widl-Support-WinRT-requires-keyword.patch create mode 100644 patches/widl-winrt-support/0019-widl-Support-WinRT-activatable-attribute.patch create mode 100644 patches/widl-winrt-support/0020-widl-Support-WinRT-parameterized-type-parsing.patch create mode 100644 patches/widl-winrt-support/0021-widl-Support-partially-specialized-parameterized-typ.patch create mode 100644 patches/widl-winrt-support/0022-widl-Support-WinRT-parameterized-interface-type.patch create mode 100644 patches/widl-winrt-support/0023-widl-Support-WinRT-delegate-type.patch create mode 100644 patches/widl-winrt-support/0024-widl-Support-WinRT-parameterized-delegate-type.patch create mode 100644 patches/widl-winrt-support/0025-widl-Compute-signatures-for-parameterized-types.patch create mode 100644 patches/widl-winrt-support/0026-widl-Compute-uuids-for-parameterized-types.patch create mode 100644 patches/widl-winrt-support/0027-widl-Generate-helper-macros-for-WinRT-implementation.patch create mode 100644 patches/widl-winrt-support/0028-include-Add-IVectorView-HSTRING-declaration-to-windo.patch create mode 100644 patches/widl-winrt-support/definition diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index bcedc06d..d5a7adfd 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -268,10 +268,9 @@ patch_enable_all () enable_uxtheme_GTK_Theming="$1" enable_version_VerQueryValue="$1" enable_widl_SLTG_Typelib_Support="$1" + enable_widl_winrt_support="$1" enable_windows_gaming_input_dll="$1" - enable_windows_globalization_dll="$1" enable_windows_media_speech_dll="$1" - enable_windows_networking_connectivity_dll="$1" enable_windowscodecs_GIF_Encoder="$1" enable_windowscodecs_TIFF_Support="$1" enable_wine_inf_Directory_ContextMenuHandlers="$1" @@ -893,18 +892,15 @@ patch_enable () widl-SLTG_Typelib_Support) enable_widl_SLTG_Typelib_Support="$2" ;; + widl-winrt-support) + enable_widl_winrt_support="$2" + ;; windows.gaming.input-dll) enable_windows_gaming_input_dll="$2" ;; - windows.globalization-dll) - enable_windows_globalization_dll="$2" - ;; windows.media.speech.dll) enable_windows_media_speech_dll="$2" ;; - windows.networking.connectivity.dll) - enable_windows_networking_connectivity_dll="$2" - ;; windowscodecs-GIF_Encoder) enable_windowscodecs_GIF_Encoder="$2" ;; @@ -1455,20 +1451,6 @@ if test "$enable_wineboot_ProxySettings" -eq 1; then enable_wineboot_drivers_etc_Stubs=1 fi -if test "$enable_windows_networking_connectivity_dll" -eq 1; then - if test "$enable_windows_globalization_dll" -gt 1; then - abort "Patchset windows.globalization-dll disabled, but windows.networking.connectivity.dll depends on that." - fi - enable_windows_globalization_dll=1 -fi - -if test "$enable_windows_globalization_dll" -eq 1; then - if test "$enable_windows_media_speech_dll" -gt 1; then - abort "Patchset windows.media.speech.dll disabled, but windows.globalization-dll depends on that." - fi - enable_windows_media_speech_dll=1 -fi - if test "$enable_windows_media_speech_dll" -eq 1; then if test "$enable_windows_gaming_input_dll" -gt 1; then abort "Patchset windows.gaming.input-dll disabled, but windows.media.speech.dll depends on that." @@ -4332,6 +4314,48 @@ if test "$enable_version_VerQueryValue" -eq 1; then patch_apply version-VerQueryValue/0001-version-Test-for-VerQueryValueA-try-2.patch fi +# Patchset widl-winrt-support +# | +# | This patchset fixes the following Wine bugs: +# | * [#68403] widl - Support WinRT idls +# | +# | Modified files: +# | * include/Makefile.in, include/windows.foundation.idl, include/windows.media.speechsynthesis.idl, +# | include/windowscontracts.idl, tools/widl/expr.c, tools/widl/hash.c, tools/widl/hash.h, tools/widl/header.c, +# | tools/widl/parser.l, tools/widl/parser.y, tools/widl/typegen.c, tools/widl/typelib.c, tools/widl/typetree.c, +# | tools/widl/typetree.h, tools/widl/widltypes.h +# | +if test "$enable_widl_winrt_support" -eq 1; then + patch_apply widl-winrt-support/0001-include-Add-windows.media.speechsynthesis.idl-draft.patch + patch_apply widl-winrt-support/0002-widl-Restrict-some-keywords-to-WinRT-mode-only.patch + patch_apply widl-winrt-support/0003-widl-Introduce-format_namespace_buffer-helper.patch + patch_apply widl-winrt-support/0004-widl-Support-WinRT-contractversion-attribute-parsing.patch + patch_apply widl-winrt-support/0005-widl-Support-WinRT-apicontract-type.patch + patch_apply widl-winrt-support/0006-widl-Prefer-mangled-name-over-typedef-in-WinRT-mode.patch + patch_apply widl-winrt-support/0007-widl-Don-t-output-typedef-statement-in-WinRT-mode.patch + patch_apply widl-winrt-support/0008-widl-Support-WinRT-contract-attribute.patch + patch_apply widl-winrt-support/0009-widl-Support-WinRT-marshaling_behavior-attribute-par.patch + patch_apply widl-winrt-support/0010-widl-Support-WinRT-mta-threading-attribute-parsing.patch + patch_apply widl-winrt-support/0011-widl-Support-WinRT-exclusiveto-attribute-parsing.patch + patch_apply widl-winrt-support/0012-widl-Support-WinRT-runtimeclass-type.patch + patch_apply widl-winrt-support/0013-widl-Support-WinRT-eventadd-eventremove-attributes.patch + patch_apply widl-winrt-support/0014-widl-Support-WinRT-flags-attribute-parsing.patch + patch_apply widl-winrt-support/0015-widl-Support-using-qualified-names-for-interfaces.patch + patch_apply widl-winrt-support/0016-widl-Support-repeated-attributes-for-WinRT-static.patch + patch_apply widl-winrt-support/0017-widl-Support-WinRT-static-attribute-parsing.patch + patch_apply widl-winrt-support/0018-widl-Support-WinRT-requires-keyword.patch + patch_apply widl-winrt-support/0019-widl-Support-WinRT-activatable-attribute.patch + patch_apply widl-winrt-support/0020-widl-Support-WinRT-parameterized-type-parsing.patch + patch_apply widl-winrt-support/0021-widl-Support-partially-specialized-parameterized-typ.patch + patch_apply widl-winrt-support/0022-widl-Support-WinRT-parameterized-interface-type.patch + patch_apply widl-winrt-support/0023-widl-Support-WinRT-delegate-type.patch + patch_apply widl-winrt-support/0024-widl-Support-WinRT-parameterized-delegate-type.patch + patch_apply widl-winrt-support/0025-widl-Compute-signatures-for-parameterized-types.patch + patch_apply widl-winrt-support/0026-widl-Compute-uuids-for-parameterized-types.patch + patch_apply widl-winrt-support/0027-widl-Generate-helper-macros-for-WinRT-implementation.patch + patch_apply widl-winrt-support/0028-include-Add-IVectorView-HSTRING-declaration-to-windo.patch +fi + # Patchset windows.gaming.input-dll # | # | This patchset fixes the following Wine bugs: @@ -4364,42 +4388,6 @@ if test "$enable_windows_media_speech_dll" -eq 1; then patch_apply windows.media.speech.dll/0001-windows.media.speech-Add-stub-dll.patch fi -# Patchset windows.globalization-dll -# | -# | This patchset has the following (direct or indirect) dependencies: -# | * windows.gaming.input-dll, windows.media.speech.dll -# | -# | This patchset fixes the following Wine bugs: -# | * [#49740] windows.globalization: New DLL -# | -# | Modified files: -# | * configure.ac, dlls/windows.globalization.dll/Makefile.in, dlls/windows.globalization.dll/windows.globalization.spec, -# | dlls/windows.globalization.dll/windows.globalization_main.c, include/Makefile.in, include/windows.globalization.idl, -# | loader/wine.inf.in -# | -if test "$enable_windows_globalization_dll" -eq 1; then - patch_apply windows.globalization-dll/0001-windows.globalization-Add-stub-dll.patch -fi - -# Patchset windows.networking.connectivity.dll -# | -# | This patchset has the following (direct or indirect) dependencies: -# | * windows.gaming.input-dll, windows.media.speech.dll, windows.globalization-dll -# | -# | This patchset fixes the following Wine bugs: -# | * [#46534] windows.networking.connectivity: New DLL -# | -# | Modified files: -# | * configure.ac, dlls/windows.networking.connectivity.dll/Makefile.in, -# | dlls/windows.networking.connectivity.dll/windows.networking.connectivity.spec, -# | dlls/windows.networking.connectivity.dll/windows.networking.connectivity_main.c, loader/wine.inf.in -# | -if test "$enable_windows_networking_connectivity_dll" -eq 1; then - patch_apply windows.networking.connectivity.dll/0001-windows.networking.connectivity-Add-stub-dll.patch - patch_apply windows.networking.connectivity.dll/0002-windows.networking.connectivity-Implement-IActivatio.patch - patch_apply windows.networking.connectivity.dll/0003-windows.networking.connectivity-Implement-INetworkIn.patch -fi - # Patchset windowscodecs-GIF_Encoder # | # | Modified files: diff --git a/patches/widl-winrt-support/0001-include-Add-windows.media.speechsynthesis.idl-draft.patch b/patches/widl-winrt-support/0001-include-Add-windows.media.speechsynthesis.idl-draft.patch new file mode 100644 index 00000000..8d276a95 --- /dev/null +++ b/patches/widl-winrt-support/0001-include-Add-windows.media.speechsynthesis.idl-draft.patch @@ -0,0 +1,69 @@ +From 5dc312c4a09e51410c217919511b84323923607e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Wed, 23 Sep 2020 19:23:45 +0200 +Subject: [PATCH 01/28] include: Add windows.media.speechsynthesis.idl draft. + +This IDL is used by windows.media.speech.dll, which is itself required +by Flight Simulator. It will here be used as an illustration and test +case for WIDL WinRT features. +--- + include/Makefile.in | 1 + + include/windows.media.speechsynthesis.idl | 34 +++++++++++++++++++++++ + 2 files changed, 35 insertions(+) + create mode 100644 include/windows.media.speechsynthesis.idl + +diff --git a/include/Makefile.in b/include/Makefile.in +index 23306689cab..d59b0be715d 100644 +--- a/include/Makefile.in ++++ b/include/Makefile.in +@@ -735,6 +735,7 @@ SOURCES = \ + windef.h \ + windns.h \ + windows.foundation.idl \ ++ windows.media.speechsynthesis.idl \ + windows.h \ + windowsx.h \ + wine/debug.h \ +diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl +new file mode 100644 +index 00000000000..d3dedfe0709 +--- /dev/null ++++ b/include/windows.media.speechsynthesis.idl +@@ -0,0 +1,34 @@ ++/* ++ * Copyright 2020 Rémi Bernon for CodeWeavers ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ */ ++ ++#ifdef __WIDL__ ++#pragma winrt ns_prefix ++#endif ++ ++import "inspectable.idl"; ++import "windows.foundation.idl"; ++ ++namespace Windows { ++ namespace Media { ++ namespace SpeechSynthesis { ++ typedef enum VoiceGender VoiceGender; ++ interface IInstalledVoicesStatic; ++ interface IVoiceInformation; ++ } ++ } ++} +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0002-widl-Restrict-some-keywords-to-WinRT-mode-only.patch b/patches/widl-winrt-support/0002-widl-Restrict-some-keywords-to-WinRT-mode-only.patch new file mode 100644 index 00000000..d896d467 --- /dev/null +++ b/patches/widl-winrt-support/0002-widl-Restrict-some-keywords-to-WinRT-mode-only.patch @@ -0,0 +1,381 @@ +From 58eea69462505e4ea88675adcbe85b49b9cf2e35 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Tue, 22 Sep 2020 18:03:23 +0200 +Subject: [PATCH 02/28] widl: Restrict some keywords to WinRT mode only. + +--- + tools/widl/parser.l | 333 ++++++++++++++++++++++---------------------- + 1 file changed, 167 insertions(+), 166 deletions(-) + +diff --git a/tools/widl/parser.l b/tools/widl/parser.l +index 925265d00db..eb1782d32f5 100644 +--- a/tools/widl/parser.l ++++ b/tools/widl/parser.l +@@ -248,67 +248,68 @@ int parser_wrap(void) + struct keyword { + const char *kw; + int token; ++ int winrt_only : 1; + }; + + /* This table MUST be alphabetically sorted on the kw field */ + static const struct keyword keywords[] = { +- {"FALSE", tFALSE}, +- {"NULL", tNULL}, +- {"TRUE", tTRUE}, +- {"__cdecl", tCDECL}, +- {"__fastcall", tFASTCALL}, +- {"__int32", tINT32}, +- {"__int3264", tINT3264}, +- {"__int64", tINT64}, +- {"__pascal", tPASCAL}, +- {"__stdcall", tSTDCALL}, +- {"_cdecl", tCDECL}, +- {"_fastcall", tFASTCALL}, +- {"_pascal", tPASCAL}, +- {"_stdcall", tSTDCALL}, +- {"boolean", tBOOLEAN}, +- {"byte", tBYTE}, +- {"case", tCASE}, +- {"cdecl", tCDECL}, +- {"char", tCHAR}, +- {"coclass", tCOCLASS}, +- {"const", tCONST}, +- {"cpp_quote", tCPPQUOTE}, +- {"default", tDEFAULT}, +- {"dispinterface", tDISPINTERFACE}, +- {"double", tDOUBLE}, +- {"enum", tENUM}, +- {"error_status_t", tERRORSTATUST}, +- {"extern", tEXTERN}, +- {"float", tFLOAT}, +- {"handle_t", tHANDLET}, +- {"hyper", tHYPER}, +- {"import", tIMPORT}, +- {"importlib", tIMPORTLIB}, +- {"inline", tINLINE}, +- {"int", tINT}, +- {"interface", tINTERFACE}, +- {"library", tLIBRARY}, +- {"long", tLONG}, +- {"methods", tMETHODS}, +- {"module", tMODULE}, +- {"namespace", tNAMESPACE}, +- {"pascal", tPASCAL}, +- {"properties", tPROPERTIES}, +- {"register", tREGISTER}, +- {"short", tSHORT}, +- {"signed", tSIGNED}, +- {"sizeof", tSIZEOF}, +- {"small", tSMALL}, +- {"static", tSTATIC}, +- {"stdcall", tSTDCALL}, +- {"struct", tSTRUCT}, +- {"switch", tSWITCH}, +- {"typedef", tTYPEDEF}, +- {"union", tUNION}, +- {"unsigned", tUNSIGNED}, +- {"void", tVOID}, +- {"wchar_t", tWCHAR}, ++ {"FALSE", tFALSE, 0}, ++ {"NULL", tNULL, 0}, ++ {"TRUE", tTRUE, 0}, ++ {"__cdecl", tCDECL, 0}, ++ {"__fastcall", tFASTCALL, 0}, ++ {"__int32", tINT32, 0}, ++ {"__int3264", tINT3264, 0}, ++ {"__int64", tINT64, 0}, ++ {"__pascal", tPASCAL, 0}, ++ {"__stdcall", tSTDCALL, 0}, ++ {"_cdecl", tCDECL, 0}, ++ {"_fastcall", tFASTCALL, 0}, ++ {"_pascal", tPASCAL, 0}, ++ {"_stdcall", tSTDCALL, 0}, ++ {"boolean", tBOOLEAN, 0}, ++ {"byte", tBYTE, 0}, ++ {"case", tCASE, 0}, ++ {"cdecl", tCDECL, 0}, ++ {"char", tCHAR, 0}, ++ {"coclass", tCOCLASS, 0}, ++ {"const", tCONST, 0}, ++ {"cpp_quote", tCPPQUOTE, 0}, ++ {"default", tDEFAULT, 0}, ++ {"dispinterface", tDISPINTERFACE, 0}, ++ {"double", tDOUBLE, 0}, ++ {"enum", tENUM, 0}, ++ {"error_status_t", tERRORSTATUST, 0}, ++ {"extern", tEXTERN, 0}, ++ {"float", tFLOAT, 0}, ++ {"handle_t", tHANDLET, 0}, ++ {"hyper", tHYPER, 0}, ++ {"import", tIMPORT, 0}, ++ {"importlib", tIMPORTLIB, 0}, ++ {"inline", tINLINE, 0}, ++ {"int", tINT, 0}, ++ {"interface", tINTERFACE, 0}, ++ {"library", tLIBRARY, 0}, ++ {"long", tLONG, 0}, ++ {"methods", tMETHODS, 0}, ++ {"module", tMODULE, 0}, ++ {"namespace", tNAMESPACE, 1}, ++ {"pascal", tPASCAL, 0}, ++ {"properties", tPROPERTIES, 0}, ++ {"register", tREGISTER, 0}, ++ {"short", tSHORT, 0}, ++ {"signed", tSIGNED, 0}, ++ {"sizeof", tSIZEOF, 0}, ++ {"small", tSMALL, 0}, ++ {"static", tSTATIC, 0}, ++ {"stdcall", tSTDCALL, 0}, ++ {"struct", tSTRUCT, 0}, ++ {"switch", tSWITCH, 0}, ++ {"typedef", tTYPEDEF, 0}, ++ {"union", tUNION, 0}, ++ {"unsigned", tUNSIGNED, 0}, ++ {"void", tVOID, 0}, ++ {"wchar_t", tWCHAR, 0}, + }; + #define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0])) + +@@ -317,113 +318,113 @@ static const struct keyword keywords[] = { + */ + static const struct keyword attr_keywords[] = + { +- {"aggregatable", tAGGREGATABLE}, +- {"allocate", tALLOCATE}, +- {"annotation", tANNOTATION}, +- {"apartment", tAPARTMENT}, +- {"appobject", tAPPOBJECT}, +- {"async", tASYNC}, +- {"async_uuid", tASYNCUUID}, +- {"auto_handle", tAUTOHANDLE}, +- {"bindable", tBINDABLE}, +- {"both", tBOTH}, +- {"broadcast", tBROADCAST}, +- {"byte_count", tBYTECOUNT}, +- {"call_as", tCALLAS}, +- {"callback", tCALLBACK}, +- {"code", tCODE}, +- {"comm_status", tCOMMSTATUS}, +- {"context_handle", tCONTEXTHANDLE}, +- {"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE}, +- {"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE}, +- {"control", tCONTROL}, +- {"decode", tDECODE}, +- {"defaultbind", tDEFAULTBIND}, +- {"defaultcollelem", tDEFAULTCOLLELEM}, +- {"defaultvalue", tDEFAULTVALUE}, +- {"defaultvtable", tDEFAULTVTABLE}, +- {"disable_consistency_check", tDISABLECONSISTENCYCHECK}, +- {"displaybind", tDISPLAYBIND}, +- {"dllname", tDLLNAME}, +- {"dual", tDUAL}, +- {"enable_allocate", tENABLEALLOCATE}, +- {"encode", tENCODE}, +- {"endpoint", tENDPOINT}, +- {"entry", tENTRY}, +- {"explicit_handle", tEXPLICITHANDLE}, +- {"fault_status", tFAULTSTATUS}, +- {"force_allocate", tFORCEALLOCATE}, +- {"free", tFREE}, +- {"handle", tHANDLE}, +- {"helpcontext", tHELPCONTEXT}, +- {"helpfile", tHELPFILE}, +- {"helpstring", tHELPSTRING}, +- {"helpstringcontext", tHELPSTRINGCONTEXT}, +- {"helpstringdll", tHELPSTRINGDLL}, +- {"hidden", tHIDDEN}, +- {"id", tID}, +- {"idempotent", tIDEMPOTENT}, +- {"ignore", tIGNORE}, +- {"iid_is", tIIDIS}, +- {"immediatebind", tIMMEDIATEBIND}, +- {"implicit_handle", tIMPLICITHANDLE}, +- {"in", tIN}, +- {"in_line", tIN_LINE}, +- {"input_sync", tINPUTSYNC}, +- {"lcid", tLCID}, +- {"length_is", tLENGTHIS}, +- {"licensed", tLICENSED}, +- {"local", tLOCAL}, +- {"maybe", tMAYBE}, +- {"message", tMESSAGE}, +- {"neutral", tNEUTRAL}, +- {"nocode", tNOCODE}, +- {"nonbrowsable", tNONBROWSABLE}, +- {"noncreatable", tNONCREATABLE}, +- {"nonextensible", tNONEXTENSIBLE}, +- {"notify", tNOTIFY}, +- {"notify_flag", tNOTIFYFLAG}, +- {"object", tOBJECT}, +- {"odl", tODL}, +- {"oleautomation", tOLEAUTOMATION}, +- {"optimize", tOPTIMIZE}, +- {"optional", tOPTIONAL}, +- {"out", tOUT}, +- {"partial_ignore", tPARTIALIGNORE}, +- {"pointer_default", tPOINTERDEFAULT}, +- {"progid", tPROGID}, +- {"propget", tPROPGET}, +- {"propput", tPROPPUT}, +- {"propputref", tPROPPUTREF}, +- {"proxy", tPROXY}, +- {"ptr", tPTR}, +- {"public", tPUBLIC}, +- {"range", tRANGE}, +- {"readonly", tREADONLY}, +- {"ref", tREF}, +- {"represent_as", tREPRESENTAS}, +- {"requestedit", tREQUESTEDIT}, +- {"restricted", tRESTRICTED}, +- {"retval", tRETVAL}, +- {"single", tSINGLE}, +- {"size_is", tSIZEIS}, +- {"source", tSOURCE}, +- {"strict_context_handle", tSTRICTCONTEXTHANDLE}, +- {"string", tSTRING}, +- {"switch_is", tSWITCHIS}, +- {"switch_type", tSWITCHTYPE}, +- {"threading", tTHREADING}, +- {"transmit_as", tTRANSMITAS}, +- {"uidefault", tUIDEFAULT}, +- {"unique", tUNIQUE}, +- {"user_marshal", tUSERMARSHAL}, +- {"usesgetlasterror", tUSESGETLASTERROR}, +- {"uuid", tUUID}, +- {"v1_enum", tV1ENUM}, +- {"vararg", tVARARG}, +- {"version", tVERSION}, +- {"vi_progid", tVIPROGID}, +- {"wire_marshal", tWIREMARSHAL}, ++ {"aggregatable", tAGGREGATABLE, 0}, ++ {"allocate", tALLOCATE, 0}, ++ {"annotation", tANNOTATION, 0}, ++ {"apartment", tAPARTMENT, 0}, ++ {"appobject", tAPPOBJECT, 0}, ++ {"async", tASYNC, 0}, ++ {"async_uuid", tASYNCUUID, 0}, ++ {"auto_handle", tAUTOHANDLE, 0}, ++ {"bindable", tBINDABLE, 0}, ++ {"both", tBOTH, 0}, ++ {"broadcast", tBROADCAST, 0}, ++ {"byte_count", tBYTECOUNT, 0}, ++ {"call_as", tCALLAS, 0}, ++ {"callback", tCALLBACK, 0}, ++ {"code", tCODE, 0}, ++ {"comm_status", tCOMMSTATUS, 0}, ++ {"context_handle", tCONTEXTHANDLE, 0}, ++ {"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE, 0}, ++ {"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE, 0}, ++ {"control", tCONTROL, 0}, ++ {"decode", tDECODE, 0}, ++ {"defaultbind", tDEFAULTBIND, 0}, ++ {"defaultcollelem", tDEFAULTCOLLELEM, 0}, ++ {"defaultvalue", tDEFAULTVALUE, 0}, ++ {"defaultvtable", tDEFAULTVTABLE, 0}, ++ {"disable_consistency_check", tDISABLECONSISTENCYCHECK, 0}, ++ {"displaybind", tDISPLAYBIND, 0}, ++ {"dllname", tDLLNAME, 0}, ++ {"dual", tDUAL, 0}, ++ {"enable_allocate", tENABLEALLOCATE, 0}, ++ {"encode", tENCODE, 0}, ++ {"endpoint", tENDPOINT, 0}, ++ {"entry", tENTRY, 0}, ++ {"explicit_handle", tEXPLICITHANDLE, 0}, ++ {"fault_status", tFAULTSTATUS, 0}, ++ {"force_allocate", tFORCEALLOCATE, 0}, ++ {"free", tFREE, 0}, ++ {"handle", tHANDLE, 0}, ++ {"helpcontext", tHELPCONTEXT, 0}, ++ {"helpfile", tHELPFILE, 0}, ++ {"helpstring", tHELPSTRING, 0}, ++ {"helpstringcontext", tHELPSTRINGCONTEXT, 0}, ++ {"helpstringdll", tHELPSTRINGDLL, 0}, ++ {"hidden", tHIDDEN, 0}, ++ {"id", tID, 0}, ++ {"idempotent", tIDEMPOTENT, 0}, ++ {"ignore", tIGNORE, 0}, ++ {"iid_is", tIIDIS, 0}, ++ {"immediatebind", tIMMEDIATEBIND, 0}, ++ {"implicit_handle", tIMPLICITHANDLE, 0}, ++ {"in", tIN, 0}, ++ {"in_line", tIN_LINE, 0}, ++ {"input_sync", tINPUTSYNC, 0}, ++ {"lcid", tLCID, 0}, ++ {"length_is", tLENGTHIS, 0}, ++ {"licensed", tLICENSED, 0}, ++ {"local", tLOCAL, 0}, ++ {"maybe", tMAYBE, 0}, ++ {"message", tMESSAGE, 0}, ++ {"neutral", tNEUTRAL, 0}, ++ {"nocode", tNOCODE, 0}, ++ {"nonbrowsable", tNONBROWSABLE, 0}, ++ {"noncreatable", tNONCREATABLE, 0}, ++ {"nonextensible", tNONEXTENSIBLE, 0}, ++ {"notify", tNOTIFY, 0}, ++ {"notify_flag", tNOTIFYFLAG, 0}, ++ {"object", tOBJECT, 0}, ++ {"odl", tODL, 0}, ++ {"oleautomation", tOLEAUTOMATION, 0}, ++ {"optimize", tOPTIMIZE, 0}, ++ {"optional", tOPTIONAL, 0}, ++ {"out", tOUT, 0}, ++ {"partial_ignore", tPARTIALIGNORE, 0}, ++ {"pointer_default", tPOINTERDEFAULT, 0}, ++ {"progid", tPROGID, 0}, ++ {"propget", tPROPGET, 0}, ++ {"propput", tPROPPUT, 0}, ++ {"propputref", tPROPPUTREF, 0}, ++ {"proxy", tPROXY, 0}, ++ {"ptr", tPTR, 0}, ++ {"public", tPUBLIC, 0}, ++ {"range", tRANGE, 0}, ++ {"readonly", tREADONLY, 0}, ++ {"ref", tREF, 0}, ++ {"represent_as", tREPRESENTAS, 0}, ++ {"requestedit", tREQUESTEDIT, 0}, ++ {"restricted", tRESTRICTED, 0}, ++ {"retval", tRETVAL, 0}, ++ {"single", tSINGLE, 0}, ++ {"size_is", tSIZEIS, 0}, ++ {"source", tSOURCE, 0}, ++ {"strict_context_handle", tSTRICTCONTEXTHANDLE, 0}, ++ {"string", tSTRING, 0}, ++ {"switch_is", tSWITCHIS, 0}, ++ {"switch_type", tSWITCHTYPE, 0}, ++ {"threading", tTHREADING, 0}, ++ {"transmit_as", tTRANSMITAS, 0}, ++ {"uidefault", tUIDEFAULT, 0}, ++ {"unique", tUNIQUE, 0}, ++ {"user_marshal", tUSERMARSHAL, 0}, ++ {"usesgetlasterror", tUSESGETLASTERROR, 0}, ++ {"uuid", tUUID, 0}, ++ {"v1_enum", tV1ENUM, 0}, ++ {"vararg", tVARARG, 0}, ++ {"version", tVERSION, 0}, ++ {"vi_progid", tVIPROGID, 0}, ++ {"wire_marshal", tWIREMARSHAL, 0}, + }; + + /* attributes TODO: +@@ -446,7 +447,7 @@ static int kw_token(const char *kw) + struct keyword key, *kwp; + key.kw = kw; + kwp = bsearch(&key, keywords, NKEYWORDS, sizeof(keywords[0]), kw_cmp_func); +- if (kwp && (winrt_mode || kwp->token != tNAMESPACE)) { ++ if (kwp && (!kwp->winrt_only || winrt_mode)) { + parser_lval.str = xstrdup(kwp->kw); + return kwp->token; + } +@@ -460,7 +461,7 @@ static int attr_token(const char *kw) + key.kw = kw; + kwp = bsearch(&key, attr_keywords, sizeof(attr_keywords)/sizeof(attr_keywords[0]), + sizeof(attr_keywords[0]), kw_cmp_func); +- if (kwp) { ++ if (kwp && (!kwp->winrt_only || winrt_mode)) { + parser_lval.str = xstrdup(kwp->kw); + return kwp->token; + } +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0003-widl-Introduce-format_namespace_buffer-helper.patch b/patches/widl-winrt-support/0003-widl-Introduce-format_namespace_buffer-helper.patch new file mode 100644 index 00000000..aa410c0e --- /dev/null +++ b/patches/widl-winrt-support/0003-widl-Introduce-format_namespace_buffer-helper.patch @@ -0,0 +1,129 @@ +From ee1ce628835376e5054972ef3c39996a2b015309 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Wed, 23 Sep 2020 14:14:01 +0200 +Subject: [PATCH 03/28] widl: Introduce format_namespace_buffer helper. + +To compute format_namespace length and write to an existing buffer. + +Also add explicit abi_prefix parameter. +--- + tools/widl/header.c | 2 +- + tools/widl/parser.y | 2 +- + tools/widl/typetree.c | 54 +++++++++++++++++++----------------------- + tools/widl/widltypes.h | 3 ++- + 4 files changed, 29 insertions(+), 32 deletions(-) + +diff --git a/tools/widl/header.c b/tools/widl/header.c +index 743d86f0ee9..d67fea4cc95 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -132,7 +132,7 @@ static void write_guid(FILE *f, const char *guid_prefix, const char *name, const + + static void write_uuid_decl(FILE *f, type_t *type, const UUID *uuid) + { +- char *name = format_namespace(type->namespace, "", "::", type->name); ++ char *name = format_namespace(type->namespace, "", "::", type->name, use_abi_namespace ? "ABI" : NULL); + fprintf(f, "#ifdef __CRT_UUID_DECL\n"); + fprintf(f, "__CRT_UUID_DECL(%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x," + "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index 5bc0d82703e..306e5194467 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -1905,7 +1905,7 @@ type_t *reg_type(type_t *type, const char *name, struct namespace *namespace, in + if (is_global_namespace(namespace)) + type->c_name = name; + else +- type->c_name = format_namespace(namespace, "__x_", "_C", name); ++ type->c_name = format_namespace(namespace, "__x_", "_C", name, use_abi_namespace ? "ABI" : NULL); + nt->type = type; + nt->t = t; + nt->next = namespace->type_hash[hash]; +diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c +index e9afc6fdd28..ebba2c4c6bb 100644 +--- a/tools/widl/typetree.c ++++ b/tools/widl/typetree.c +@@ -89,41 +89,37 @@ const char *type_get_name(const type_t *type, enum name_type name_type) + return NULL; + } + +-static char *append_namespace(char *ptr, struct namespace *namespace, const char *separator) +-{ +- if(is_global_namespace(namespace)) { +- if(!use_abi_namespace) +- return ptr; +- strcpy(ptr, "ABI"); +- strcat(ptr, separator); +- return ptr + strlen(ptr); +- } ++#define append_buf(f, ...) \ ++ do { int r = f(buf + ret, max(ret, len) - ret, __VA_ARGS__); assert(r >= 0); ret += r; } while(0) + +- ptr = append_namespace(ptr, namespace->parent, separator); +- strcpy(ptr, namespace->name); +- strcat(ptr, separator); +- return ptr + strlen(ptr); ++static int append_namespace(char *buf, size_t len, struct namespace *namespace, const char *separator, const char *abi_prefix) ++{ ++ const char *name = namespace && !is_global_namespace(namespace) ? namespace->name : abi_prefix; ++ int ret = 0; ++ if (!name) return 0; ++ if (namespace && !is_global_namespace(namespace)) append_buf(append_namespace, namespace->parent, separator, abi_prefix); ++ append_buf(snprintf, "%s%s", name, separator); ++ return ret; + } + +-char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix) ++static int format_namespace_buffer(char *buf, size_t len, struct namespace *namespace, const char *prefix, ++ const char *separator, const char *suffix, const char *abi_prefix) + { +- unsigned len = strlen(prefix) + strlen(suffix); +- unsigned sep_len = strlen(separator); +- struct namespace *iter; +- char *ret, *ptr; +- +- if(use_abi_namespace && !is_global_namespace(namespace)) +- len += 3 /* strlen("ABI") */ + sep_len; +- +- for(iter = namespace; !is_global_namespace(iter); iter = iter->parent) +- len += strlen(iter->name) + sep_len; ++ int ret = 0; ++ append_buf(snprintf, "%s", prefix); ++ append_buf(append_namespace, namespace, separator, abi_prefix); ++ append_buf(snprintf, "%s", suffix); ++ return ret; ++} + +- ret = xmalloc(len+1); +- strcpy(ret, prefix); +- ptr = append_namespace(ret + strlen(ret), namespace, separator); +- strcpy(ptr, suffix); ++#undef append_buf + +- return ret; ++char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix) ++{ ++ int len = format_namespace_buffer(NULL, 0, namespace, prefix, separator, suffix, abi_prefix); ++ char *buf = xmalloc(len + 1); ++ format_namespace_buffer(buf, len + 1, namespace, prefix, separator, suffix, abi_prefix); ++ return buf; + } + + type_t *type_new_function(var_list_t *args) +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index 085a0ff55f5..630f42860f1 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -605,7 +605,8 @@ var_list_t *append_var(var_list_t *list, var_t *var); + + void init_loc_info(loc_info_t *); + +-char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix); ++char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, ++ const char *abi_prefix); + + static inline enum type_type type_get_type_detect_alias(const type_t *type) + { +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0004-widl-Support-WinRT-contractversion-attribute-parsing.patch b/patches/widl-winrt-support/0004-widl-Support-WinRT-contractversion-attribute-parsing.patch new file mode 100644 index 00000000..33f09fd4 --- /dev/null +++ b/patches/widl-winrt-support/0004-widl-Support-WinRT-contractversion-attribute-parsing.patch @@ -0,0 +1,89 @@ +From 8f57c43dd3adceb5baf529a6e42a1e813c024e20 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Tue, 13 Oct 2020 14:04:28 +0200 +Subject: [PATCH 04/28] widl: Support WinRT contractversion attribute parsing. + +--- + tools/widl/parser.l | 1 + + tools/widl/parser.y | 12 +++++++++++- + tools/widl/widltypes.h | 1 + + 3 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/tools/widl/parser.l b/tools/widl/parser.l +index eb1782d32f5..dafd17ab2f9 100644 +--- a/tools/widl/parser.l ++++ b/tools/widl/parser.l +@@ -337,6 +337,7 @@ static const struct keyword attr_keywords[] = + {"context_handle", tCONTEXTHANDLE, 0}, + {"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE, 0}, + {"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE, 0}, ++ {"contractversion", tCONTRACTVERSION, 1}, + {"control", tCONTROL, 0}, + {"decode", tDECODE, 0}, + {"defaultbind", tDEFAULTBIND, 0}, +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index 306e5194467..88cb9a10863 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -176,7 +176,9 @@ static typelib_t *current_typelib; + %token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT + %token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS + %token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE +-%token tCONTEXTHANDLESERIALIZE tCONTROL tCPPQUOTE ++%token tCONTEXTHANDLESERIALIZE ++%token tCONTRACTVERSION ++%token tCONTROL tCPPQUOTE + %token tDECODE tDEFAULT tDEFAULTBIND + %token tDEFAULTCOLLELEM + %token tDEFAULTVALUE +@@ -288,6 +290,7 @@ static typelib_t *current_typelib; + %type m_abstract_declarator abstract_declarator abstract_declarator_no_direct abstract_direct_declarator + %type declarator_list struct_declarator_list + %type coclass coclasshdr coclassdef ++%type contract_ver + %type pointer_type threading_type version + %type libraryhdr callconv cppquote importlib import t_ident + %type uuid_string +@@ -489,6 +492,11 @@ str_list: aSTRING { $$ = append_str( NULL, $1 ); } + | str_list ',' aSTRING { $$ = append_str( $1, $3 ); } + ; + ++contract_ver: ++ aNUM { $$ = MAKEVERSION(0, $1); } ++ | aNUM '.' aNUM { $$ = MAKEVERSION($3, $1); } ++ ; ++ + attribute: { $$ = NULL; } + | tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); } + | tANNOTATION '(' aSTRING ')' { $$ = make_attrp(ATTR_ANNOTATION, $3); } +@@ -504,6 +512,7 @@ attribute: { $$ = NULL; } + | tCONTEXTHANDLE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); } + | tCONTEXTHANDLENOSERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ } + | tCONTEXTHANDLESERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ } ++ | tCONTRACTVERSION '(' contract_ver ')' { $$ = make_attrv(ATTR_CONTRACTVERSION, $3); } + | tCONTROL { $$ = make_attr(ATTR_CONTROL); } + | tDECODE { $$ = make_attr(ATTR_DECODE); } + | tDEFAULT { $$ = make_attr(ATTR_DEFAULT); } +@@ -2135,6 +2144,7 @@ struct allowed_attr allowed_attr[] = + /* ATTR_CODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" }, + /* ATTR_COMMSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" }, + /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" }, ++ /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "contractversion" }, + /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, "control" }, + /* ATTR_DECODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" }, + /* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, "default" }, +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index 630f42860f1..1b00b8da002 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -82,6 +82,7 @@ enum attr_type + ATTR_CODE, + ATTR_COMMSTATUS, + ATTR_CONTEXTHANDLE, ++ ATTR_CONTRACTVERSION, + ATTR_CONTROL, + ATTR_DECODE, + ATTR_DEFAULT, +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0005-widl-Support-WinRT-apicontract-type.patch b/patches/widl-winrt-support/0005-widl-Support-WinRT-apicontract-type.patch new file mode 100644 index 00000000..bd89e8a2 --- /dev/null +++ b/patches/widl-winrt-support/0005-widl-Support-WinRT-apicontract-type.patch @@ -0,0 +1,551 @@ +From 70534016bc2963703a003e9a0888ad21f5bf026e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Tue, 13 Oct 2020 13:37:19 +0200 +Subject: [PATCH 05/28] widl: Support WinRT apicontract type. + +--- + include/Makefile.in | 1 + + include/windows.foundation.idl | 1 + + include/windowscontracts.idl | 33 +++++ + tools/widl/expr.c | 1 + + tools/widl/header.c | 24 ++++ + tools/widl/parser.l | 1 + + tools/widl/parser.y | 235 +++++++++++++++++++-------------- + tools/widl/typegen.c | 6 + + tools/widl/typelib.c | 3 +- + tools/widl/typetree.h | 3 + + tools/widl/widltypes.h | 1 + + 11 files changed, 206 insertions(+), 103 deletions(-) + create mode 100644 include/windowscontracts.idl + +diff --git a/include/Makefile.in b/include/Makefile.in +index d59b0be715d..91297753b12 100644 +--- a/include/Makefile.in ++++ b/include/Makefile.in +@@ -737,6 +737,7 @@ SOURCES = \ + windows.foundation.idl \ + windows.media.speechsynthesis.idl \ + windows.h \ ++ windowscontracts.idl \ + windowsx.h \ + wine/debug.h \ + wine/exception.h \ +diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl +index 2c16fa2da22..2a38e9f671b 100644 +--- a/include/windows.foundation.idl ++++ b/include/windows.foundation.idl +@@ -22,6 +22,7 @@ + + import "inspectable.idl"; + /* import "asyncinfo.idl"; */ ++import "windowscontracts.idl"; + /* import "eventtoken.idl"; */ + /* import "ivectorchangedeventargs.idl"; */ + +diff --git a/include/windowscontracts.idl b/include/windowscontracts.idl +new file mode 100644 +index 00000000000..6bcf80ac954 +--- /dev/null ++++ b/include/windowscontracts.idl +@@ -0,0 +1,33 @@ ++/* ++ * Copyright 2020 Rémi Bernon for CodeWeavers ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ */ ++ ++#ifdef __WIDL__ ++#pragma winrt ns_prefix ++#endif ++ ++namespace Windows { ++ namespace Foundation { ++ [contractversion(4)] ++ apicontract FoundationContract ++ {}; ++ ++ [contractversion(10)] ++ apicontract UniversalApiContract ++ {}; ++ } ++} +diff --git a/tools/widl/expr.c b/tools/widl/expr.c +index d1ee599a39e..be8311cfb7f 100644 +--- a/tools/widl/expr.c ++++ b/tools/widl/expr.c +@@ -462,6 +462,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, + case TYPE_POINTER: + case TYPE_ARRAY: + case TYPE_BITFIELD: ++ case TYPE_APICONTRACT: + /* nothing to do */ + break; + case TYPE_ALIAS: +diff --git a/tools/widl/header.c b/tools/widl/header.c +index d67fea4cc95..607d156ccf4 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -464,6 +464,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i + break; + } + case TYPE_ALIAS: ++ case TYPE_APICONTRACT: + /* handled elsewhere */ + assert(0); + break; +@@ -529,6 +530,10 @@ void write_type_right(FILE *h, type_t *t, int is_field) + case TYPE_COCLASS: + case TYPE_INTERFACE: + break; ++ case TYPE_APICONTRACT: ++ /* not supposed to be here */ ++ assert(0); ++ break; + } + } + +@@ -1446,6 +1451,14 @@ static void write_forward(FILE *header, type_t *iface) + fprintf(header, "#endif\n\n" ); + } + ++static char *format_apicontract_macro(const type_t *type) ++{ ++ char *name = format_namespace(type->namespace, "", "_", type->name, NULL); ++ int i; ++ for (i = strlen(name); i > 0; --i) name[i - 1] = toupper(name[i - 1]); ++ return name; ++} ++ + static void write_com_interface_start(FILE *header, const type_t *iface) + { + int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); +@@ -1610,6 +1623,15 @@ static void write_coclass_forward(FILE *header, type_t *cocl) + fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", cocl->name ); + } + ++static void write_apicontract(FILE *header, type_t *apicontract) ++{ ++ char *name = format_apicontract_macro(apicontract); ++ fprintf(header, "#if !defined(%s_VERSION)\n", name); ++ fprintf(header, "#define %s_VERSION %#x\n", name, get_attrv(apicontract->attrs, ATTR_CONTRACTVERSION)); ++ fprintf(header, "#endif // defined(%s_VERSION)\n\n", name); ++ free(name); ++} ++ + static void write_import(FILE *header, const char *fname) + { + char *hname, *p; +@@ -1728,6 +1750,8 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons + } + else if (type_get_type(stmt->u.type) == TYPE_COCLASS) + write_coclass(header, stmt->u.type); ++ else if (type_get_type(stmt->u.type) == TYPE_APICONTRACT) ++ write_apicontract(header, stmt->u.type); + else + { + write_type_definition(header, stmt->u.type, stmt->declonly); +diff --git a/tools/widl/parser.l b/tools/widl/parser.l +index dafd17ab2f9..11debca2ebd 100644 +--- a/tools/widl/parser.l ++++ b/tools/widl/parser.l +@@ -267,6 +267,7 @@ static const struct keyword keywords[] = { + {"_fastcall", tFASTCALL, 0}, + {"_pascal", tPASCAL, 0}, + {"_stdcall", tSTDCALL, 0}, ++ {"apicontract", tAPICONTRACT, 1}, + {"boolean", tBOOLEAN, 0}, + {"byte", tBYTE, 0}, + {"case", tCASE, 0}, +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index 88cb9a10863..bdd019a2880 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -99,6 +99,7 @@ static attr_list_t *check_library_attrs(const char *name, attr_list_t *attrs); + static attr_list_t *check_dispiface_attrs(const char *name, attr_list_t *attrs); + static attr_list_t *check_module_attrs(const char *name, attr_list_t *attrs); + static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs); ++static attr_list_t *check_apicontract_attrs(const char *name, attr_list_t *attrs); + const char *get_attr_display_name(enum attr_type type); + static void add_explicit_handle_if_necessary(const type_t *iface, var_t *func); + static void check_def(const type_t *t); +@@ -172,7 +173,9 @@ static typelib_t *current_typelib; + %token GREATEREQUAL LESSEQUAL + %token LOGICALOR LOGICALAND + %token ELLIPSIS +-%token tAGGREGATABLE tALLOCATE tANNOTATION tAPPOBJECT tASYNC tASYNCUUID ++%token tAGGREGATABLE tALLOCATE tANNOTATION ++%token tAPICONTRACT ++%token tAPPOBJECT tASYNC tASYNCUUID + %token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT + %token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS + %token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE +@@ -290,6 +293,7 @@ static typelib_t *current_typelib; + %type m_abstract_declarator abstract_declarator abstract_declarator_no_direct abstract_direct_declarator + %type declarator_list struct_declarator_list + %type coclass coclasshdr coclassdef ++%type apicontract + %type contract_ver + %type pointer_type threading_type version + %type libraryhdr callconv cppquote importlib import t_ident +@@ -346,6 +350,8 @@ gbl_statements: { $$ = NULL; } + | gbl_statements coclassdef { $$ = append_statement($1, make_statement_type_decl($2)); + reg_type($2, $2->name, current_namespace, 0); + } ++ | gbl_statements apicontract ';' { $$ = append_statement($1, make_statement_type_decl($2)); ++ reg_type($2, $2->name, current_namespace, 0); } + | gbl_statements moduledef { $$ = append_statement($1, make_statement_module($2)); } + | gbl_statements librarydef { $$ = append_statement($1, make_statement_library($2)); } + | gbl_statements statement { $$ = append_statement($1, $2); } +@@ -360,6 +366,8 @@ imp_statements: { $$ = NULL; } + | imp_statements coclassdef { $$ = append_statement($1, make_statement_type_decl($2)); + reg_type($2, $2->name, current_namespace, 0); + } ++ | imp_statements apicontract ';' { $$ = append_statement($1, make_statement_type_decl($2)); ++ reg_type($2, $2->name, current_namespace, 0); } + | imp_statements moduledef { $$ = append_statement($1, make_statement_module($2)); } + | imp_statements statement { $$ = append_statement($1, $2); } + | imp_statements importlib { $$ = append_statement($1, make_statement_importlib($2)); } +@@ -864,6 +872,13 @@ coclassdef: coclasshdr '{' coclass_ints '}' semicolon_opt + { $$ = type_coclass_define($1, $3); } + ; + ++apicontract: attributes tAPICONTRACT aIDENTIFIER '{' '}' ++ { $$ = get_type(TYPE_APICONTRACT, $3, current_namespace, 0); ++ check_def($$); ++ $$->attrs = check_apicontract_attrs($$->name, $1); ++ } ++ ; ++ + namespacedef: tNAMESPACE aIDENTIFIER { $$ = $2; } + | tNAMESPACE aNAMESPACE { $$ = $2; } + ; +@@ -2124,112 +2139,113 @@ struct allowed_attr + unsigned int on_dispinterface : 1; + unsigned int on_module : 1; + unsigned int on_coclass : 1; ++ unsigned int on_apicontract : 1; + const char *display_name; + }; + + struct allowed_attr allowed_attr[] = + { +- /* attr { D ACF I Fn ARG T En Enm St Un Fi L DI M C } */ +- /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "aggregatable" }, +- /* ATTR_ANNOTATION */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "annotation" }, +- /* ATTR_APPOBJECT */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "appobject" }, +- /* ATTR_ASYNC */ { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" }, +- /* ATTR_ASYNCUUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, "async_uuid" }, +- /* ATTR_AUTO_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "auto_handle" }, +- /* ATTR_BINDABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bindable" }, +- /* ATTR_BROADCAST */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "broadcast" }, +- /* ATTR_CALLAS */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "call_as" }, +- /* ATTR_CALLCONV */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, +- /* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "case" }, +- /* ATTR_CODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" }, +- /* ATTR_COMMSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" }, +- /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" }, +- /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "contractversion" }, +- /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, "control" }, +- /* ATTR_DECODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" }, +- /* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, "default" }, +- /* ATTR_DEFAULTBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultbind" }, +- /* ATTR_DEFAULTCOLLELEM */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultcollelem" }, +- /* ATTR_DEFAULTVALUE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultvalue" }, +- /* ATTR_DEFAULTVTABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "defaultvtable" }, +- /* ATTR_DISABLECONSISTENCYCHECK */{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "disable_consistency_check" }, +- /* ATTR_DISPINTERFACE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, +- /* ATTR_DISPLAYBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "displaybind" }, +- /* ATTR_DLLNAME */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "dllname" }, +- /* ATTR_DUAL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "dual" }, +- /* ATTR_ENABLEALLOCATE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "enable_allocate" }, +- /* ATTR_ENCODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "encode" }, +- /* ATTR_ENDPOINT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" }, +- /* ATTR_ENTRY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" }, +- /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" }, +- /* ATTR_FAULTSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" }, +- /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" }, +- /* ATTR_HANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "handle" }, +- /* ATTR_HELPCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, "helpcontext" }, +- /* ATTR_HELPFILE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "helpfile" }, +- /* ATTR_HELPSTRING */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, "helpstring" }, +- /* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, "helpstringcontext" }, +- /* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "helpstringdll" }, +- /* ATTR_HIDDEN */ { 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, "hidden" }, +- /* ATTR_ID */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, "id" }, +- /* ATTR_IDEMPOTENT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "idempotent" }, +- /* ATTR_IGNORE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "ignore" }, +- /* ATTR_IIDIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "iid_is" }, +- /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" }, +- /* ATTR_IMPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" }, +- /* ATTR_IN */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" }, +- /* ATTR_INPUTSYNC */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" }, +- /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "length_is" }, +- /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "lcid" }, +- /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "licensed" }, +- /* ATTR_LOCAL */ { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" }, +- /* ATTR_MAYBE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "maybe" }, +- /* ATTR_MESSAGE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "message" }, +- /* ATTR_NOCODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" }, +- /* ATTR_NONBROWSABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonbrowsable" }, +- /* ATTR_NONCREATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "noncreatable" }, +- /* ATTR_NONEXTENSIBLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonextensible" }, +- /* ATTR_NOTIFY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify" }, +- /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify_flag" }, +- /* ATTR_OBJECT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "object" }, +- /* ATTR_ODL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "odl" }, +- /* ATTR_OLEAUTOMATION */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "oleautomation" }, +- /* ATTR_OPTIMIZE */ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optimize" }, +- /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optional" }, +- /* ATTR_OUT */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "out" }, +- /* ATTR_PARAMLCID */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "lcid" }, +- /* ATTR_PARTIALIGNORE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "partial_ignore" }, +- /* ATTR_POINTERDEFAULT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" }, +- /* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "ref, unique or ptr" }, +- /* ATTR_PROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "progid" }, +- /* ATTR_PROPGET */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propget" }, +- /* ATTR_PROPPUT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propput" }, +- /* ATTR_PROPPUTREF */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propputref" }, +- /* ATTR_PROXY */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "proxy" }, +- /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "public" }, +- /* ATTR_RANGE */ { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, "range" }, +- /* ATTR_READONLY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "readonly" }, +- /* ATTR_REPRESENTAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "represent_as" }, +- /* ATTR_REQUESTEDIT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "requestedit" }, +- /* ATTR_RESTRICTED */ { 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, "restricted" }, +- /* ATTR_RETVAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" }, +- /* ATTR_SIZEIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "size_is" }, +- /* ATTR_SOURCE */ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "source" }, +- /* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "strict_context_handle" }, +- /* ATTR_STRING */ { 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "string" }, +- /* ATTR_SWITCHIS */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "switch_is" }, +- /* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "switch_type" }, +- /* ATTR_THREADING */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "threading" }, +- /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "transmit_as" }, +- /* ATTR_UIDEFAULT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "uidefault" }, +- /* ATTR_USESGETLASTERROR */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "usesgetlasterror" }, +- /* ATTR_USERMARSHAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "user_marshal" }, +- /* ATTR_UUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, "uuid" }, +- /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "v1_enum" }, +- /* ATTR_VARARG */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "vararg" }, +- /* ATTR_VERSION */ { 1, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 1, 0, 0, 1, "version" }, +- /* ATTR_VIPROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "vi_progid" }, +- /* ATTR_WIREMARSHAL */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" }, ++ /* attr { D ACF I Fn ARG T En Enm St Un Fi L DI M C AC } */ ++ /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "aggregatable" }, ++ /* ATTR_ANNOTATION */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "annotation" }, ++ /* ATTR_APPOBJECT */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "appobject" }, ++ /* ATTR_ASYNC */ { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" }, ++ /* ATTR_ASYNCUUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "async_uuid" }, ++ /* ATTR_AUTO_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "auto_handle" }, ++ /* ATTR_BINDABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bindable" }, ++ /* ATTR_BROADCAST */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "broadcast" }, ++ /* ATTR_CALLAS */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "call_as" }, ++ /* ATTR_CALLCONV */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, ++ /* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "case" }, ++ /* ATTR_CODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" }, ++ /* ATTR_COMMSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" }, ++ /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" }, ++ /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "contractversion" }, ++ /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, "control" }, ++ /* ATTR_DECODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" }, ++ /* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, "default" }, ++ /* ATTR_DEFAULTBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultbind" }, ++ /* ATTR_DEFAULTCOLLELEM */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultcollelem" }, ++ /* ATTR_DEFAULTVALUE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultvalue" }, ++ /* ATTR_DEFAULTVTABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "defaultvtable" }, ++ /* ATTR_DISABLECONSISTENCYCHECK */{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "disable_consistency_check" }, ++ /* ATTR_DISPINTERFACE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, ++ /* ATTR_DISPLAYBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "displaybind" }, ++ /* ATTR_DLLNAME */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "dllname" }, ++ /* ATTR_DUAL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "dual" }, ++ /* ATTR_ENABLEALLOCATE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "enable_allocate" }, ++ /* ATTR_ENCODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "encode" }, ++ /* ATTR_ENDPOINT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" }, ++ /* ATTR_ENTRY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" }, ++ /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" }, ++ /* ATTR_FAULTSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" }, ++ /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" }, ++ /* ATTR_HANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "handle" }, ++ /* ATTR_HELPCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpcontext" }, ++ /* ATTR_HELPFILE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "helpfile" }, ++ /* ATTR_HELPSTRING */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpstring" }, ++ /* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpstringcontext" }, ++ /* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "helpstringdll" }, ++ /* ATTR_HIDDEN */ { 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, "hidden" }, ++ /* ATTR_ID */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, "id" }, ++ /* ATTR_IDEMPOTENT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "idempotent" }, ++ /* ATTR_IGNORE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "ignore" }, ++ /* ATTR_IIDIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "iid_is" }, ++ /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" }, ++ /* ATTR_IMPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" }, ++ /* ATTR_IN */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" }, ++ /* ATTR_INPUTSYNC */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" }, ++ /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "length_is" }, ++ /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "lcid" }, ++ /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "licensed" }, ++ /* ATTR_LOCAL */ { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" }, ++ /* ATTR_MAYBE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "maybe" }, ++ /* ATTR_MESSAGE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "message" }, ++ /* ATTR_NOCODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" }, ++ /* ATTR_NONBROWSABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonbrowsable" }, ++ /* ATTR_NONCREATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "noncreatable" }, ++ /* ATTR_NONEXTENSIBLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonextensible" }, ++ /* ATTR_NOTIFY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify" }, ++ /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify_flag" }, ++ /* ATTR_OBJECT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "object" }, ++ /* ATTR_ODL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "odl" }, ++ /* ATTR_OLEAUTOMATION */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "oleautomation" }, ++ /* ATTR_OPTIMIZE */ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optimize" }, ++ /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optional" }, ++ /* ATTR_OUT */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "out" }, ++ /* ATTR_PARAMLCID */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "lcid" }, ++ /* ATTR_PARTIALIGNORE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "partial_ignore" }, ++ /* ATTR_POINTERDEFAULT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" }, ++ /* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "ref, unique or ptr" }, ++ /* ATTR_PROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "progid" }, ++ /* ATTR_PROPGET */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propget" }, ++ /* ATTR_PROPPUT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propput" }, ++ /* ATTR_PROPPUTREF */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propputref" }, ++ /* ATTR_PROXY */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "proxy" }, ++ /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "public" }, ++ /* ATTR_RANGE */ { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, "range" }, ++ /* ATTR_READONLY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "readonly" }, ++ /* ATTR_REPRESENTAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "represent_as" }, ++ /* ATTR_REQUESTEDIT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "requestedit" }, ++ /* ATTR_RESTRICTED */ { 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, "restricted" }, ++ /* ATTR_RETVAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" }, ++ /* ATTR_SIZEIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "size_is" }, ++ /* ATTR_SOURCE */ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "source" }, ++ /* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "strict_context_handle" }, ++ /* ATTR_STRING */ { 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "string" }, ++ /* ATTR_SWITCHIS */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "switch_is" }, ++ /* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "switch_type" }, ++ /* ATTR_THREADING */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "threading" }, ++ /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "transmit_as" }, ++ /* ATTR_UIDEFAULT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "uidefault" }, ++ /* ATTR_USESGETLASTERROR */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "usesgetlasterror" }, ++ /* ATTR_USERMARSHAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "user_marshal" }, ++ /* ATTR_UUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, "uuid" }, ++ /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "v1_enum" }, ++ /* ATTR_VARARG */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "vararg" }, ++ /* ATTR_VERSION */ { 1, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 1, 0, 0, 1, 0, "version" }, ++ /* ATTR_VIPROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "vi_progid" }, ++ /* ATTR_WIREMARSHAL */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" }, + }; + + const char *get_attr_display_name(enum attr_type type) +@@ -2420,6 +2436,17 @@ static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs) + return attrs; + } + ++static attr_list_t *check_apicontract_attrs(const char *name, attr_list_t *attrs) ++{ ++ const attr_t *attr; ++ if (!attrs) return attrs; ++ LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) ++ if (!allowed_attr[attr->type].on_apicontract) ++ error_loc("inapplicable attribute %s for apicontract %s\n", ++ allowed_attr[attr->type].display_name, name); ++ return attrs; ++} ++ + static int is_allowed_conf_type(const type_t *type) + { + switch (type_get_type(type)) +@@ -2459,6 +2486,10 @@ static int is_allowed_conf_type(const type_t *type) + case TYPE_INTERFACE: + case TYPE_BITFIELD: + return FALSE; ++ case TYPE_APICONTRACT: ++ /* not supposed to be here */ ++ assert(0); ++ break; + } + return FALSE; + } +diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c +index 04280cbb722..46aae9b69e9 100644 +--- a/tools/widl/typegen.c ++++ b/tools/widl/typegen.c +@@ -374,6 +374,10 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att + case TYPE_ALIAS: + case TYPE_BITFIELD: + break; ++ case TYPE_APICONTRACT: ++ /* not supposed to be here */ ++ assert(0); ++ break; + } + return TGT_INVALID; + } +@@ -1966,6 +1970,7 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align) + case TYPE_MODULE: + case TYPE_FUNCTION: + case TYPE_BITFIELD: ++ case TYPE_APICONTRACT: + /* these types should not be encountered here due to language + * restrictions (interface, void, coclass, module), logical + * restrictions (alias - due to type_get_type call above) or +@@ -2067,6 +2072,7 @@ static unsigned int type_buffer_alignment(const type_t *t) + case TYPE_MODULE: + case TYPE_FUNCTION: + case TYPE_BITFIELD: ++ case TYPE_APICONTRACT: + /* these types should not be encountered here due to language + * restrictions (interface, void, coclass, module), logical + * restrictions (alias - due to type_get_type call above) or +diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c +index cf027558d0a..faf76440f93 100644 +--- a/tools/widl/typelib.c ++++ b/tools/widl/typelib.c +@@ -224,7 +224,8 @@ unsigned short get_type_vt(type_t *t) + return VT_VOID; + + case TYPE_ALIAS: +- /* aliases should be filtered out by the type_get_type call above */ ++ case TYPE_APICONTRACT: ++ /* not supposed to be here */ + assert(0); + break; + +diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h +index e288c574002..7abec41a8fd 100644 +--- a/tools/widl/typetree.h ++++ b/tools/widl/typetree.h +@@ -223,6 +223,9 @@ static inline int type_is_complete(const type_t *type) + case TYPE_ARRAY: + case TYPE_BITFIELD: + return TRUE; ++ case TYPE_APICONTRACT: ++ assert(0); ++ break; + } + return FALSE; + } +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index 1b00b8da002..add7cedfacc 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -432,6 +432,7 @@ enum type_type + TYPE_POINTER, + TYPE_ARRAY, + TYPE_BITFIELD, ++ TYPE_APICONTRACT, + }; + + struct _type_t { +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0006-widl-Prefer-mangled-name-over-typedef-in-WinRT-mode.patch b/patches/widl-winrt-support/0006-widl-Prefer-mangled-name-over-typedef-in-WinRT-mode.patch new file mode 100644 index 00000000..d0c4a633 --- /dev/null +++ b/patches/widl-winrt-support/0006-widl-Prefer-mangled-name-over-typedef-in-WinRT-mode.patch @@ -0,0 +1,74 @@ +From 9e4292bb0ed2953f71ebe6c835db790d3cd5f954 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Mon, 12 Oct 2020 19:11:44 +0200 +Subject: [PATCH 06/28] widl: Prefer mangled name over typedef in WinRT mode. + +MIDL generates prefixed mangled name for every use of enum, struct and +union types, in fields types as well as function arguments. When the +types are in the global namespace, the typedef name is used instead. +--- + tools/widl/header.c | 13 ++++++++++--- + tools/widl/typetree.c | 2 +- + 2 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/tools/widl/header.c b/tools/widl/header.c +index 607d156ccf4..d8dfcf4f4c3 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -250,7 +250,7 @@ static void write_fields(FILE *h, var_list_t *fields) + default: + ; + } +- write_type_v(h, &v->declspec, TRUE, v->declonly, name, NAME_DEFAULT); ++ write_type_v(h, &v->declspec, TRUE, v->declonly, name, NAME_C); + fprintf(h, ";\n"); + } + } +@@ -322,7 +322,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i + if ((ds->qualifier & TYPE_QUALIFIER_CONST) && (type_is_alias(t) || !is_ptr(t))) + fprintf(h, "const "); + +- if (type_is_alias(t)) fprintf(h, "%s", t->name); ++ if (!winrt_mode && type_is_alias(t)) fprintf(h, "%s", t->name); + else { + switch (type_get_type_detect_alias(t)) { + case TYPE_ENUM: +@@ -464,6 +464,13 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i + break; + } + case TYPE_ALIAS: ++ { ++ const decl_spec_t *ds = type_alias_get_aliasee(t); ++ int in_namespace = ds && ds->type && ds->type->namespace && !is_global_namespace(ds->type->namespace); ++ if (!in_namespace) fprintf(h, "%s", t->name); ++ else write_type_left(h, ds, name_type, declonly, write_callconv); ++ break; ++ } + case TYPE_APICONTRACT: + /* handled elsewhere */ + assert(0); +@@ -807,7 +814,7 @@ static void write_generic_handle_routines(FILE *header) + static void write_typedef(FILE *header, type_t *type, int declonly) + { + fprintf(header, "typedef "); +- write_type_v(header, type_alias_get_aliasee(type), FALSE, declonly, type->name, NAME_DEFAULT); ++ write_type_v(header, type_alias_get_aliasee(type), FALSE, declonly, type->name, NAME_C); + fprintf(header, ";\n"); + } + +diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c +index ebba2c4c6bb..d8dcd5d80b0 100644 +--- a/tools/widl/typetree.c ++++ b/tools/widl/typetree.c +@@ -82,7 +82,7 @@ const char *type_get_name(const type_t *type, enum name_type name_type) + case NAME_DEFAULT: + return type->name; + case NAME_C: +- return type->c_name; ++ return type->c_name ? type->c_name : type->name; + } + + assert(0); +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0007-widl-Don-t-output-typedef-statement-in-WinRT-mode.patch b/patches/widl-winrt-support/0007-widl-Don-t-output-typedef-statement-in-WinRT-mode.patch new file mode 100644 index 00000000..72e74c4d --- /dev/null +++ b/patches/widl-winrt-support/0007-widl-Don-t-output-typedef-statement-in-WinRT-mode.patch @@ -0,0 +1,27 @@ +From 98a3b25143161e249102eceef6face6833ba19ea Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Mon, 12 Oct 2020 19:11:44 +0200 +Subject: [PATCH 07/28] widl: Don't output typedef statement in WinRT mode. + +For types under a non-global namespace, since we reference them with +their prefixed mangled names. +--- + tools/widl/header.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/widl/header.c b/tools/widl/header.c +index d8dfcf4f4c3..0a8272fdbb4 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -813,6 +813,8 @@ static void write_generic_handle_routines(FILE *header) + + static void write_typedef(FILE *header, type_t *type, int declonly) + { ++ type_t *t = type_alias_get_aliasee_type(type); ++ if (winrt_mode && t->namespace && !is_global_namespace(t->namespace)) return; + fprintf(header, "typedef "); + write_type_v(header, type_alias_get_aliasee(type), FALSE, declonly, type->name, NAME_C); + fprintf(header, ";\n"); +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0008-widl-Support-WinRT-contract-attribute.patch b/patches/widl-winrt-support/0008-widl-Support-WinRT-contract-attribute.patch new file mode 100644 index 00000000..935676b8 --- /dev/null +++ b/patches/widl-winrt-support/0008-widl-Support-WinRT-contract-attribute.patch @@ -0,0 +1,341 @@ +From 9b5039017bd7072164042bf7b739f373134978ea Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Wed, 23 Sep 2020 19:23:45 +0200 +Subject: [PATCH 08/28] widl: Support WinRT contract attribute. + +--- + include/windows.foundation.idl | 14 ++--- + include/windows.media.speechsynthesis.idl | 13 ++++ + tools/widl/header.c | 72 ++++++++++++++++++++++- + tools/widl/parser.l | 1 + + tools/widl/parser.y | 10 ++++ + tools/widl/widltypes.h | 1 + + 6 files changed, 101 insertions(+), 10 deletions(-) + +diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl +index 2a38e9f671b..5e17062f399 100644 +--- a/include/windows.foundation.idl ++++ b/include/windows.foundation.idl +@@ -28,7 +28,7 @@ import "windowscontracts.idl"; + + namespace Windows { + namespace Foundation { +- [version(0x06020000)] ++ [contract(Windows.Foundation.FoundationContract, 1.0)] + enum PropertyType { + Empty = 0, + UInt8 = 1, +@@ -73,19 +73,19 @@ namespace Windows { + OtherTypeArray = 1044 + }; + +- [version(0x06020000)] ++ [contract(Windows.Foundation.FoundationContract, 1.0)] + struct Point { + FLOAT X; + FLOAT Y; + }; + +- [version(0x06020000)] ++ [contract(Windows.Foundation.FoundationContract, 1.0)] + struct Size { + FLOAT Width; + FLOAT Height; + }; + +- [version(0x06020000)] ++ [contract(Windows.Foundation.FoundationContract, 1.0)] + struct Rect { + FLOAT X; + FLOAT Y; +@@ -93,18 +93,18 @@ namespace Windows { + FLOAT Height; + }; + +- [version(0x06020000)] ++ [contract(Windows.Foundation.FoundationContract, 1.0)] + struct DateTime { + INT64 UniversalTime; + }; + +- [version(0x06020000)] ++ [contract(Windows.Foundation.FoundationContract, 1.0)] + struct TimeSpan { + INT64 Duration; + }; + + [ +- version(0x06030000), ++ contract(Windows.Foundation.FoundationContract, 1.0), + uuid(96369f54-8eb6-48f0-abce-c1b211e627c3) + ] + interface IStringable : IInspectable +diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl +index d3dedfe0709..7a1de5fcba6 100644 +--- a/include/windows.media.speechsynthesis.idl ++++ b/include/windows.media.speechsynthesis.idl +@@ -32,3 +32,16 @@ namespace Windows { + } + } + } ++ ++namespace Windows { ++ namespace Media { ++ namespace SpeechSynthesis { ++ [contract(Windows.Foundation.UniversalApiContract, 1.0)] ++ enum VoiceGender ++ { ++ Male = 0, ++ Female = 1 ++ }; ++ } ++ } ++} +diff --git a/tools/widl/header.c b/tools/widl/header.c +index 0a8272fdbb4..0fd3eb917ea 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -45,6 +45,11 @@ generic_handle_list_t generic_handle_list = LIST_INIT(generic_handle_list); + + static void write_type_v(FILE *f, const decl_spec_t *t, int is_field, int declonly, const char *name, enum name_type name_type); + ++static void write_winrt_type_comments(FILE *header, const type_t *type); ++ ++static void write_apicontract_guard_start(FILE *header, const expr_t *expr); ++static void write_apicontract_guard_end(FILE *header, const expr_t *expr); ++ + static void indent(FILE *h, int delta) + { + int c; +@@ -218,7 +223,9 @@ static void write_fields(FILE *h, var_list_t *fields) + } + + LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) { ++ expr_t *contract = get_attrp(v->attrs, ATTR_CONTRACT); + if (!v || !v->declspec.type) continue; ++ if (contract) write_apicontract_guard_start(h, contract); + + indent(h, 0); + name = v->name; +@@ -252,6 +259,7 @@ static void write_fields(FILE *h, var_list_t *fields) + } + write_type_v(h, &v->declspec, TRUE, v->declonly, name, NAME_C); + fprintf(h, ";\n"); ++ if (contract) write_apicontract_guard_end(h, contract); + } + } + +@@ -261,6 +269,8 @@ static void write_enums(FILE *h, var_list_t *enums, const char *enum_name) + if (!enums) return; + LIST_FOR_EACH_ENTRY( v, enums, var_t, entry ) + { ++ expr_t *contract = get_attrp(v->attrs, ATTR_CONTRACT); ++ if (contract) write_apicontract_guard_start(h, contract); + if (v->name) { + indent(h, 0); + if(!enum_name) +@@ -273,8 +283,9 @@ static void write_enums(FILE *h, var_list_t *enums, const char *enum_name) + } + } + if (list_next( enums, &v->entry )) fprintf(h, ",\n"); ++ else fprintf(h, "\n"); ++ if (contract) write_apicontract_guard_end(h, contract); + } +- fprintf(h, "\n"); + } + + int needs_space_after(type_t *t) +@@ -563,7 +574,9 @@ static void write_type_definition(FILE *f, type_t *t, int declonly) + int in_namespace = t->namespace && !is_global_namespace(t->namespace); + int save_written = t->written; + decl_spec_t ds = {.type = t}; ++ expr_t *contract = get_attrp(t->attrs, ATTR_CONTRACT); + ++ if (contract) write_apicontract_guard_start(f, contract); + if(in_namespace) { + fprintf(f, "#ifdef __cplusplus\n"); + fprintf(f, "} /* extern \"C\" */\n"); +@@ -581,6 +594,7 @@ static void write_type_definition(FILE *f, type_t *t, int declonly) + fprintf(f, ";\n"); + fprintf(f, "#endif\n\n"); + } ++ if (contract) write_apicontract_guard_end(f, contract); + } + + void write_type_decl(FILE *f, const decl_spec_t *t, const char *name) +@@ -1468,12 +1482,55 @@ static char *format_apicontract_macro(const type_t *type) + return name; + } + ++static void write_winrt_type_comments(FILE *header, const type_t *type) ++{ ++ expr_t *contract = get_attrp(type->attrs, ATTR_CONTRACT); ++ fprintf(header, " *\n"); ++ if (contract) ++ { ++ const type_t *type = contract->u.tref.type; ++ char *name = format_namespace(type->namespace, "", ".", type->name, NULL); ++ int ver = contract->ref->u.lval; ++ fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff); ++ free(name); ++ } ++} ++ ++static void write_apicontract_guard_start(FILE *header, const expr_t *expr) ++{ ++ const type_t *type; ++ char *name; ++ int ver; ++ if (!winrt_mode) return; ++ type = expr->u.tref.type; ++ ver = expr->ref->u.lval; ++ name = format_apicontract_macro(type); ++ fprintf(header, "#if %s_VERSION >= %#x\n", name, ver); ++ free(name); ++} ++ ++static void write_apicontract_guard_end(FILE *header, const expr_t *expr) ++{ ++ const type_t *type; ++ char *name; ++ int ver; ++ if (!winrt_mode) return; ++ type = expr->u.tref.type; ++ ver = expr->ref->u.lval; ++ name = format_apicontract_macro(type); ++ fprintf(header, "#endif /* %s_VERSION >= %#x */\n", name, ver); ++ free(name); ++} ++ + static void write_com_interface_start(FILE *header, const type_t *iface) + { + int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); ++ expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT); + fprintf(header, "/*****************************************************************************\n"); + fprintf(header, " * %s %sinterface\n", iface->name, dispinterface ? "disp" : ""); ++ if (winrt_mode) write_winrt_type_comments(header, iface); + fprintf(header, " */\n"); ++ if (contract) write_apicontract_guard_start(header, contract); + fprintf(header,"#ifndef __%s_%sINTERFACE_DEFINED__\n", iface->c_name, dispinterface ? "DISP" : ""); + fprintf(header,"#define __%s_%sINTERFACE_DEFINED__\n\n", iface->c_name, dispinterface ? "DISP" : ""); + } +@@ -1482,6 +1539,7 @@ static void write_com_interface_end(FILE *header, type_t *iface) + { + int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); + const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); ++ expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT); + type_t *type; + + if (uuid) +@@ -1559,17 +1617,22 @@ static void write_com_interface_end(FILE *header, type_t *iface) + write_locals(header, iface, FALSE); + fprintf(header, "\n"); + } +- fprintf(header,"#endif /* __%s_%sINTERFACE_DEFINED__ */\n\n", iface->c_name, dispinterface ? "DISP" : ""); ++ fprintf(header, "#endif /* __%s_%sINTERFACE_DEFINED__ */\n", iface->c_name, dispinterface ? "DISP" : ""); ++ if (contract) write_apicontract_guard_end(header, contract); ++ fprintf(header, "\n"); + } + + static void write_rpc_interface_start(FILE *header, const type_t *iface) + { + unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION); + const var_t *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); ++ expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT); + + fprintf(header, "/*****************************************************************************\n"); + fprintf(header, " * %s interface (v%d.%d)\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver)); ++ if (winrt_mode) write_winrt_type_comments(header, iface); + fprintf(header, " */\n"); ++ if (contract) write_apicontract_guard_start(header, contract); + fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name); + fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name); + if (var) +@@ -1594,7 +1657,10 @@ static void write_rpc_interface_start(FILE *header, const type_t *iface) + + static void write_rpc_interface_end(FILE *header, const type_t *iface) + { +- fprintf(header,"\n#endif /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name); ++ expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT); ++ fprintf(header, "\n#endif /* __%s_INTERFACE_DEFINED__ */\n", iface->name); ++ if (contract) write_apicontract_guard_end(header, contract); ++ fprintf(header, "\n"); + } + + static void write_coclass(FILE *header, type_t *cocl) +diff --git a/tools/widl/parser.l b/tools/widl/parser.l +index 11debca2ebd..c3d0e9e2746 100644 +--- a/tools/widl/parser.l ++++ b/tools/widl/parser.l +@@ -338,6 +338,7 @@ static const struct keyword attr_keywords[] = + {"context_handle", tCONTEXTHANDLE, 0}, + {"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE, 0}, + {"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE, 0}, ++ {"contract", tCONTRACT, 1}, + {"contractversion", tCONTRACTVERSION, 1}, + {"control", tCONTROL, 0}, + {"decode", tDECODE, 0}, +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index bdd019a2880..28d7e16dad4 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -180,6 +180,7 @@ static typelib_t *current_typelib; + %token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS + %token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE + %token tCONTEXTHANDLESERIALIZE ++%token tCONTRACT + %token tCONTRACTVERSION + %token tCONTROL tCPPQUOTE + %token tDECODE tDEFAULT tDEFAULTBIND +@@ -269,6 +270,7 @@ static typelib_t *current_typelib; + %type str_list + %type m_expr expr expr_const expr_int_const array m_bitfield + %type m_exprs /* exprs expr_list */ expr_list_int_const ++%type contract_req + %type interfacehdr + %type storage_cls_spec + %type type_qualifier m_type_qual_list +@@ -505,6 +507,12 @@ contract_ver: + | aNUM '.' aNUM { $$ = MAKEVERSION($3, $1); } + ; + ++contract_req: decl_spec ',' contract_ver { if ($1->type->type_type != TYPE_APICONTRACT) ++ error_loc("type %s is not an apicontract\n", $1->type->name); ++ $$ = make_exprl(EXPR_NUM, $3); ++ $$ = make_exprt(EXPR_GTREQL, declare_var(NULL, $1, make_declarator(NULL), 0), $$); ++ } ++ + attribute: { $$ = NULL; } + | tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); } + | tANNOTATION '(' aSTRING ')' { $$ = make_attrp(ATTR_ANNOTATION, $3); } +@@ -520,6 +528,7 @@ attribute: { $$ = NULL; } + | tCONTEXTHANDLE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); } + | tCONTEXTHANDLENOSERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ } + | tCONTEXTHANDLESERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ } ++ | tCONTRACT '(' contract_req ')' { $$ = make_attrp(ATTR_CONTRACT, $3); } + | tCONTRACTVERSION '(' contract_ver ')' { $$ = make_attrv(ATTR_CONTRACTVERSION, $3); } + | tCONTROL { $$ = make_attr(ATTR_CONTROL); } + | tDECODE { $$ = make_attr(ATTR_DECODE); } +@@ -2160,6 +2169,7 @@ struct allowed_attr allowed_attr[] = + /* ATTR_CODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" }, + /* ATTR_COMMSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" }, + /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" }, ++ /* ATTR_CONTRACT */ { 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, "contract" }, + /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "contractversion" }, + /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, "control" }, + /* ATTR_DECODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" }, +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index add7cedfacc..3f358efecd1 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -82,6 +82,7 @@ enum attr_type + ATTR_CODE, + ATTR_COMMSTATUS, + ATTR_CONTEXTHANDLE, ++ ATTR_CONTRACT, + ATTR_CONTRACTVERSION, + ATTR_CONTROL, + ATTR_DECODE, +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0009-widl-Support-WinRT-marshaling_behavior-attribute-par.patch b/patches/widl-winrt-support/0009-widl-Support-WinRT-marshaling_behavior-attribute-par.patch new file mode 100644 index 00000000..2837ef48 --- /dev/null +++ b/patches/widl-winrt-support/0009-widl-Support-WinRT-marshaling_behavior-attribute-par.patch @@ -0,0 +1,173 @@ +From 1a75069e45df24a09e8f364c61ad5d77115d48cd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Mon, 12 Oct 2020 20:34:28 +0200 +Subject: [PATCH 09/28] widl: Support WinRT marshaling_behavior attribute + parsing. + +--- + tools/widl/header.c | 7 +++++++ + tools/widl/parser.l | 4 ++++ + tools/widl/parser.y | 18 ++++++++++++++++-- + tools/widl/widltypes.h | 9 +++++++++ + 4 files changed, 36 insertions(+), 2 deletions(-) + +diff --git a/tools/widl/header.c b/tools/widl/header.c +index 0fd3eb917ea..6d5987bd4c1 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -1494,6 +1494,13 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) + fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff); + free(name); + } ++ switch (get_attrv(type->attrs, ATTR_MARSHALING_BEHAVIOR)) ++ { ++ case MARSHALING_AGILE: fprintf(header, " * Class Marshaling Behavior: Agile - Class is agile\n *\n"); break; ++ case MARSHALING_STANDARD: fprintf(header, " * Class Marshaling Behavior: Standard - Class marshals using the standard marshaler\n *\n"); break; ++ case MARSHALING_NONE: fprintf(header, " * Class Marshaling Behavior: None - Class cannot be marshaled\n *\n"); break; ++ default: break; ++ } + } + + static void write_apicontract_guard_start(FILE *header, const expr_t *expr) +diff --git a/tools/widl/parser.l b/tools/widl/parser.l +index c3d0e9e2746..39a19a3c1de 100644 +--- a/tools/widl/parser.l ++++ b/tools/widl/parser.l +@@ -320,6 +320,7 @@ static const struct keyword keywords[] = { + static const struct keyword attr_keywords[] = + { + {"aggregatable", tAGGREGATABLE, 0}, ++ {"agile", tAGILE, 1}, + {"allocate", tALLOCATE, 0}, + {"annotation", tANNOTATION, 0}, + {"apartment", tAPARTMENT, 0}, +@@ -378,12 +379,14 @@ static const struct keyword attr_keywords[] = + {"length_is", tLENGTHIS, 0}, + {"licensed", tLICENSED, 0}, + {"local", tLOCAL, 0}, ++ {"marshaling_behavior", tMARSHALINGBEHAVIOR, 1}, + {"maybe", tMAYBE, 0}, + {"message", tMESSAGE, 0}, + {"neutral", tNEUTRAL, 0}, + {"nocode", tNOCODE, 0}, + {"nonbrowsable", tNONBROWSABLE, 0}, + {"noncreatable", tNONCREATABLE, 0}, ++ {"none", tNONE, 1}, + {"nonextensible", tNONEXTENSIBLE, 0}, + {"notify", tNOTIFY, 0}, + {"notify_flag", tNOTIFYFLAG, 0}, +@@ -412,6 +415,7 @@ static const struct keyword attr_keywords[] = + {"single", tSINGLE, 0}, + {"size_is", tSIZEIS, 0}, + {"source", tSOURCE, 0}, ++ {"standard", tSTANDARD, 1}, + {"strict_context_handle", tSTRICTCONTEXTHANDLE, 0}, + {"string", tSTRING, 0}, + {"switch_is", tSWITCHIS, 0}, +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index 28d7e16dad4..ebaa0fc514b 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -173,7 +173,9 @@ static typelib_t *current_typelib; + %token GREATEREQUAL LESSEQUAL + %token LOGICALOR LOGICALAND + %token ELLIPSIS +-%token tAGGREGATABLE tALLOCATE tANNOTATION ++%token tAGGREGATABLE ++%token tAGILE ++%token tALLOCATE tANNOTATION + %token tAPICONTRACT + %token tAPPOBJECT tASYNC tASYNCUUID + %token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT +@@ -214,12 +216,14 @@ static typelib_t *current_typelib; + %token tLENGTHIS tLIBRARY + %token tLICENSED tLOCAL + %token tLONG ++%token tMARSHALINGBEHAVIOR + %token tMAYBE tMESSAGE + %token tMETHODS + %token tMODULE + %token tNAMESPACE + %token tNOCODE tNONBROWSABLE + %token tNONCREATABLE ++%token tNONE + %token tNONEXTENSIBLE + %token tNOTIFY tNOTIFYFLAG + %token tNULL +@@ -245,6 +249,7 @@ static typelib_t *current_typelib; + %token tSIZEIS tSIZEOF + %token tSMALL + %token tSOURCE ++%token tSTANDARD + %token tSTATIC + %token tSTDCALL + %token tSTRICTCONTEXTHANDLE +@@ -297,7 +302,7 @@ static typelib_t *current_typelib; + %type coclass coclasshdr coclassdef + %type apicontract + %type contract_ver +-%type pointer_type threading_type version ++%type pointer_type threading_type marshaling_behavior version + %type libraryhdr callconv cppquote importlib import t_ident + %type uuid_string + %type import_start +@@ -502,6 +507,12 @@ str_list: aSTRING { $$ = append_str( NULL, $1 ); } + | str_list ',' aSTRING { $$ = append_str( $1, $3 ); } + ; + ++marshaling_behavior: ++ tAGILE { $$ = MARSHALING_AGILE; } ++ | tNONE { $$ = MARSHALING_NONE; } ++ | tSTANDARD { $$ = MARSHALING_STANDARD; } ++ ; ++ + contract_ver: + aNUM { $$ = MAKEVERSION(0, $1); } + | aNUM '.' aNUM { $$ = MAKEVERSION($3, $1); } +@@ -568,6 +579,8 @@ attribute: { $$ = NULL; } + | tLCID { $$ = make_attr(ATTR_PARAMLCID); } + | tLICENSED { $$ = make_attr(ATTR_LICENSED); } + | tLOCAL { $$ = make_attr(ATTR_LOCAL); } ++ | tMARSHALINGBEHAVIOR '(' marshaling_behavior ')' ++ { $$ = make_attrv(ATTR_MARSHALING_BEHAVIOR, $3); } + | tMAYBE { $$ = make_attr(ATTR_MAYBE); } + | tMESSAGE { $$ = make_attr(ATTR_MESSAGE); } + | tNOCODE { $$ = make_attr(ATTR_NOCODE); } +@@ -2209,6 +2222,7 @@ struct allowed_attr allowed_attr[] = + /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "lcid" }, + /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "licensed" }, + /* ATTR_LOCAL */ { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" }, ++ /* ATTR_MARSHALING_BEHAVIOR */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "marshaling_behavior" }, + /* ATTR_MAYBE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "maybe" }, + /* ATTR_MESSAGE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "message" }, + /* ATTR_NOCODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" }, +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index 3f358efecd1..62a018ab5a5 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -122,6 +122,7 @@ enum attr_type + ATTR_LIBLCID, + ATTR_LICENSED, + ATTR_LOCAL, ++ ATTR_MARSHALING_BEHAVIOR, + ATTR_MAYBE, + ATTR_MESSAGE, + ATTR_NOCODE, +@@ -268,6 +269,14 @@ enum threading_type + THREADING_BOTH + }; + ++enum marshaling_type ++{ ++ MARSHALING_INVALID = 0, ++ MARSHALING_NONE, ++ MARSHALING_AGILE, ++ MARSHALING_STANDARD, ++}; ++ + enum type_basic_type + { + TYPE_BASIC_INT8 = 1, +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0010-widl-Support-WinRT-mta-threading-attribute-parsing.patch b/patches/widl-winrt-support/0010-widl-Support-WinRT-mta-threading-attribute-parsing.patch new file mode 100644 index 00000000..1bc3bf16 --- /dev/null +++ b/patches/widl-winrt-support/0010-widl-Support-WinRT-mta-threading-attribute-parsing.patch @@ -0,0 +1,79 @@ +From d2013864b6a28fabca3678172ab95b95ab2bb9af Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Tue, 13 Oct 2020 11:35:49 +0200 +Subject: [PATCH 10/28] widl: Support WinRT mta threading attribute parsing. + +--- + tools/widl/header.c | 7 +++++++ + tools/widl/parser.l | 1 + + tools/widl/parser.y | 2 ++ + tools/widl/widltypes.h | 3 ++- + 4 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/tools/widl/header.c b/tools/widl/header.c +index 6d5987bd4c1..843aba214a4 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -1494,6 +1494,13 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) + fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff); + free(name); + } ++ switch (get_attrv(type->attrs, ATTR_THREADING)) ++ { ++ case THREADING_SINGLE: fprintf(header, " * Class Threading Model: Single Threaded Apartment\n *\n"); break; ++ case THREADING_BOTH: fprintf(header, " * Class Threading Model: Both Single and Multi Threaded Apartment\n *\n"); break; ++ case THREADING_MTA: fprintf(header, " * Class Threading Model: Multi Threaded Apartment\n *\n"); break; ++ default: break; ++ } + switch (get_attrv(type->attrs, ATTR_MARSHALING_BEHAVIOR)) + { + case MARSHALING_AGILE: fprintf(header, " * Class Marshaling Behavior: Agile - Class is agile\n *\n"); break; +diff --git a/tools/widl/parser.l b/tools/widl/parser.l +index 39a19a3c1de..c99feffb5d6 100644 +--- a/tools/widl/parser.l ++++ b/tools/widl/parser.l +@@ -382,6 +382,7 @@ static const struct keyword attr_keywords[] = + {"marshaling_behavior", tMARSHALINGBEHAVIOR, 1}, + {"maybe", tMAYBE, 0}, + {"message", tMESSAGE, 0}, ++ {"mta" , tMTA, 1}, + {"neutral", tNEUTRAL, 0}, + {"nocode", tNOCODE, 0}, + {"nonbrowsable", tNONBROWSABLE, 0}, +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index ebaa0fc514b..a4ad03ef037 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -220,6 +220,7 @@ static typelib_t *current_typelib; + %token tMAYBE tMESSAGE + %token tMETHODS + %token tMODULE ++%token tMTA + %token tNAMESPACE + %token tNOCODE tNONBROWSABLE + %token tNONCREATABLE +@@ -1150,6 +1151,7 @@ threading_type: + | tSINGLE { $$ = THREADING_SINGLE; } + | tFREE { $$ = THREADING_FREE; } + | tBOTH { $$ = THREADING_BOTH; } ++ | tMTA { $$ = THREADING_MTA; } + ; + + pointer_type: +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index 62a018ab5a5..26634fa7f7d 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -266,7 +266,8 @@ enum threading_type + THREADING_NEUTRAL, + THREADING_SINGLE, + THREADING_FREE, +- THREADING_BOTH ++ THREADING_BOTH, ++ THREADING_MTA, + }; + + enum marshaling_type +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0011-widl-Support-WinRT-exclusiveto-attribute-parsing.patch b/patches/widl-winrt-support/0011-widl-Support-WinRT-exclusiveto-attribute-parsing.patch new file mode 100644 index 00000000..4c0e2852 --- /dev/null +++ b/patches/widl-winrt-support/0011-widl-Support-WinRT-exclusiveto-attribute-parsing.patch @@ -0,0 +1,92 @@ +From 1d70d60ab7af24ba47e98c00d4673347883f065b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Tue, 13 Oct 2020 00:11:08 +0200 +Subject: [PATCH 11/28] widl: Support WinRT exclusiveto attribute parsing. + +--- + tools/widl/header.c | 7 +++++++ + tools/widl/parser.l | 1 + + tools/widl/parser.y | 3 +++ + tools/widl/widltypes.h | 1 + + 4 files changed, 12 insertions(+) + +diff --git a/tools/widl/header.c b/tools/widl/header.c +index 843aba214a4..8aed9be3f57 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -1485,6 +1485,7 @@ static char *format_apicontract_macro(const type_t *type) + static void write_winrt_type_comments(FILE *header, const type_t *type) + { + expr_t *contract = get_attrp(type->attrs, ATTR_CONTRACT); ++ type_t *exclusiveto = get_attrp(type->attrs, ATTR_EXCLUSIVETO); + fprintf(header, " *\n"); + if (contract) + { +@@ -1494,6 +1495,12 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) + fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff); + free(name); + } ++ if (exclusiveto) ++ { ++ char *name = format_namespace(exclusiveto->namespace, "", ".", exclusiveto->name, NULL); ++ fprintf(header, " * Interface is a part of the implementation of type %s\n *\n", name); ++ free(name); ++ } + switch (get_attrv(type->attrs, ATTR_THREADING)) + { + case THREADING_SINGLE: fprintf(header, " * Class Threading Model: Single Threaded Apartment\n *\n"); break; +diff --git a/tools/widl/parser.l b/tools/widl/parser.l +index c99feffb5d6..498071a1992 100644 +--- a/tools/widl/parser.l ++++ b/tools/widl/parser.l +@@ -355,6 +355,7 @@ static const struct keyword attr_keywords[] = + {"encode", tENCODE, 0}, + {"endpoint", tENDPOINT, 0}, + {"entry", tENTRY, 0}, ++ {"exclusiveto", tEXCLUSIVETO, 1}, + {"explicit_handle", tEXPLICITHANDLE, 0}, + {"fault_status", tFAULTSTATUS, 0}, + {"force_allocate", tFORCEALLOCATE, 0}, +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index a4ad03ef037..88cc029c3ae 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -194,6 +194,7 @@ static typelib_t *current_typelib; + %token tDLLNAME tDOUBLE tDUAL + %token tENABLEALLOCATE tENCODE tENDPOINT + %token tENTRY tENUM tERRORSTATUST ++%token tEXCLUSIVETO + %token tEXPLICITHANDLE tEXTERN + %token tFALSE + %token tFASTCALL tFAULTSTATUS +@@ -557,6 +558,7 @@ attribute: { $$ = NULL; } + | tENCODE { $$ = make_attr(ATTR_ENCODE); } + | tENDPOINT '(' str_list ')' { $$ = make_attrp(ATTR_ENDPOINT, $3); } + | tENTRY '(' expr_const ')' { $$ = make_attrp(ATTR_ENTRY, $3); } ++ | tEXCLUSIVETO '(' decl_spec ')' { $$ = make_attrp(ATTR_EXCLUSIVETO, $3->type); } + | tEXPLICITHANDLE { $$ = make_attr(ATTR_EXPLICIT_HANDLE); } + | tFAULTSTATUS { $$ = make_attr(ATTR_FAULTSTATUS); } + | tFORCEALLOCATE { $$ = make_attr(ATTR_FORCEALLOCATE); } +@@ -2202,6 +2204,7 @@ struct allowed_attr allowed_attr[] = + /* ATTR_ENCODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "encode" }, + /* ATTR_ENDPOINT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" }, + /* ATTR_ENTRY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" }, ++ /* ATTR_EXCLUSIVETO */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" }, + /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" }, + /* ATTR_FAULTSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" }, + /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" }, +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index 26634fa7f7d..e945cad33b2 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -100,6 +100,7 @@ enum attr_type + ATTR_ENCODE, + ATTR_ENDPOINT, + ATTR_ENTRY, ++ ATTR_EXCLUSIVETO, + ATTR_EXPLICIT_HANDLE, + ATTR_FAULTSTATUS, + ATTR_FORCEALLOCATE, +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0012-widl-Support-WinRT-runtimeclass-type.patch b/patches/widl-winrt-support/0012-widl-Support-WinRT-runtimeclass-type.patch new file mode 100644 index 00000000..10054a4e --- /dev/null +++ b/patches/widl-winrt-support/0012-widl-Support-WinRT-runtimeclass-type.patch @@ -0,0 +1,742 @@ +From ef00d7d2e0178d9f3ad3405613c6c4a1ddd3c2b1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Tue, 13 Oct 2020 15:57:04 +0200 +Subject: [PATCH 12/28] widl: Support WinRT runtimeclass type. + +MIDL doesn't generate anything special in the header files for these +types. They can however be used instead of interfaces as function +arguments or type parameters, but pointer to their default interface +type is instead used in the generated code. +--- + include/windows.media.speechsynthesis.idl | 25 ++ + tools/widl/expr.c | 1 + + tools/widl/header.c | 65 +++++- + tools/widl/parser.l | 1 + + tools/widl/parser.y | 265 +++++++++++++--------- + tools/widl/typegen.c | 4 + + tools/widl/typelib.c | 1 + + tools/widl/typetree.c | 17 ++ + tools/widl/typetree.h | 24 ++ + tools/widl/widltypes.h | 7 + + 10 files changed, 298 insertions(+), 112 deletions(-) + +diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl +index 7a1de5fcba6..90bc9f279c6 100644 +--- a/include/windows.media.speechsynthesis.idl ++++ b/include/windows.media.speechsynthesis.idl +@@ -29,6 +29,8 @@ namespace Windows { + typedef enum VoiceGender VoiceGender; + interface IInstalledVoicesStatic; + interface IVoiceInformation; ++ runtimeclass VoiceInformation; ++ runtimeclass SpeechSynthesizer; + } + } + } +@@ -42,6 +44,29 @@ namespace Windows { + Male = 0, + Female = 1 + }; ++ ++ [ ++ contract(Windows.Foundation.UniversalApiContract, 1.0), ++ exclusiveto(Windows.Media.SpeechSynthesis.VoiceInformation), ++ uuid(b127d6a4-1291-4604-aa9c-83134083352c) ++ ] ++ interface IVoiceInformation : IInspectable ++ { ++ [propget] HRESULT DisplayName([out] [retval] HSTRING* value); ++ [propget] HRESULT Id([out] [retval] HSTRING* value); ++ [propget] HRESULT Language([out] [retval] HSTRING* value); ++ [propget] HRESULT Description([out] [retval] HSTRING* value); ++ [propget] HRESULT Gender([out] [retval] VoiceGender* value); ++ } ++ ++ [ ++ contract(Windows.Foundation.UniversalApiContract, 1.0), ++ marshaling_behavior(agile) ++ ] ++ runtimeclass VoiceInformation ++ { ++ [default] interface IVoiceInformation; ++ } + } + } + } +diff --git a/tools/widl/expr.c b/tools/widl/expr.c +index be8311cfb7f..13bd5a889aa 100644 +--- a/tools/widl/expr.c ++++ b/tools/widl/expr.c +@@ -463,6 +463,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, + case TYPE_ARRAY: + case TYPE_BITFIELD: + case TYPE_APICONTRACT: ++ case TYPE_RUNTIMECLASS: + /* nothing to do */ + break; + case TYPE_ALIAS: +diff --git a/tools/widl/header.c b/tools/widl/header.c +index 8aed9be3f57..065a82ea384 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -465,6 +465,9 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i + case TYPE_COCLASS: + fprintf(h, "%s", name); + break; ++ case TYPE_RUNTIMECLASS: ++ fprintf(h, "%s", type_get_name(type_runtimeclass_get_default_iface(t), name_type)); ++ break; + case TYPE_VOID: + fprintf(h, "void"); + break; +@@ -547,6 +550,7 @@ void write_type_right(FILE *h, type_t *t, int is_field) + case TYPE_MODULE: + case TYPE_COCLASS: + case TYPE_INTERFACE: ++ case TYPE_RUNTIMECLASS: + break; + case TYPE_APICONTRACT: + /* not supposed to be here */ +@@ -1033,7 +1037,8 @@ static int is_aggregate_return(const var_t *func) + { + enum type_type type = type_get_type(type_function_get_rettype(func->declspec.type)); + return type == TYPE_STRUCT || type == TYPE_UNION || +- type == TYPE_COCLASS || type == TYPE_INTERFACE; ++ type == TYPE_COCLASS || type == TYPE_INTERFACE || ++ type == TYPE_RUNTIMECLASS; + } + + static char *get_vtbl_entry_name(const type_t *iface, const var_t *func) +@@ -1501,6 +1506,21 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) + fprintf(header, " * Interface is a part of the implementation of type %s\n *\n", name); + free(name); + } ++ if (type_get_type(type) == TYPE_RUNTIMECLASS) ++ { ++ ifref_list_t *ifaces = type_runtimeclass_get_ifaces(type); ++ ifref_t *entry; ++ fprintf(header, " * Class implements the following interfaces:\n"); ++ LIST_FOR_EACH_ENTRY(entry, ifaces, ifref_t, entry) ++ { ++ char *name = format_namespace(entry->iface->namespace, "", ".", entry->iface->name, NULL); ++ fprintf(header, " * %s", name); ++ if (is_attr(entry->attrs, ATTR_DEFAULT)) fprintf(header, " ** Default Interface **"); ++ fprintf(header, "\n"); ++ free(name); ++ } ++ fprintf(header, " *\n"); ++ } + switch (get_attrv(type->attrs, ATTR_THREADING)) + { + case THREADING_SINGLE: fprintf(header, " * Class Threading Model: Single Threaded Apartment\n *\n"); break; +@@ -1728,6 +1748,45 @@ static void write_apicontract(FILE *header, type_t *apicontract) + free(name); + } + ++static void write_runtimeclass(FILE *header, type_t *runtimeclass) ++{ ++ expr_t *contract = get_attrp(runtimeclass->attrs, ATTR_CONTRACT); ++ size_t i, len; ++ char *name, *c_name; ++ name = format_namespace(runtimeclass->namespace, "", ".", runtimeclass->name, NULL); ++ c_name = format_namespace(runtimeclass->namespace, "", "_", runtimeclass->name, NULL); ++ fprintf(header, "/*\n"); ++ fprintf(header, " * Class %s\n", name); ++ write_winrt_type_comments(header, runtimeclass); ++ fprintf(header, " */\n"); ++ if (contract) write_apicontract_guard_start(header, contract); ++ fprintf(header, "#ifndef RUNTIMECLASS_%s_DEFINED\n", c_name); ++ fprintf(header, "#define RUNTIMECLASS_%s_DEFINED\n", c_name); ++ /* MIDL generates extern const here */ ++ fprintf(header, "static const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = {", c_name); ++ for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]); ++ fprintf(header, "0};\n"); ++ fprintf(header, "#endif /* RUNTIMECLASS_%s_DEFINED */\n", c_name); ++ free(c_name); ++ free(name); ++ if (contract) write_apicontract_guard_end(header, contract); ++ fprintf(header, "\n"); ++} ++ ++static void write_runtimeclass_forward(FILE *header, type_t *runtimeclass) ++{ ++ fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", runtimeclass->c_name); ++ fprintf(header, "#define __%s_FWD_DEFINED__\n", runtimeclass->c_name); ++ fprintf(header, "#ifdef __cplusplus\n"); ++ write_namespace_start(header, runtimeclass->namespace); ++ write_line(header, 0, "class %s;", runtimeclass->name); ++ write_namespace_end(header, runtimeclass->namespace); ++ fprintf(header, "#else\n"); ++ fprintf(header, "typedef struct %s %s;\n", runtimeclass->c_name, runtimeclass->c_name); ++ fprintf(header, "#endif /* defined __cplusplus */\n"); ++ fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", runtimeclass->c_name); ++} ++ + static void write_import(FILE *header, const char *fname) + { + char *hname, *p; +@@ -1792,6 +1851,8 @@ static void write_forward_decls(FILE *header, const statement_list_t *stmts) + } + else if (type_get_type(stmt->u.type) == TYPE_COCLASS) + write_coclass_forward(header, stmt->u.type); ++ else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS) ++ write_runtimeclass_forward(header, stmt->u.type); + break; + case STMT_TYPEREF: + case STMT_IMPORTLIB: +@@ -1848,6 +1909,8 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons + write_coclass(header, stmt->u.type); + else if (type_get_type(stmt->u.type) == TYPE_APICONTRACT) + write_apicontract(header, stmt->u.type); ++ else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS) ++ write_runtimeclass(header, stmt->u.type); + else + { + write_type_definition(header, stmt->u.type, stmt->declonly); +diff --git a/tools/widl/parser.l b/tools/widl/parser.l +index 498071a1992..31b97951b31 100644 +--- a/tools/widl/parser.l ++++ b/tools/widl/parser.l +@@ -298,6 +298,7 @@ static const struct keyword keywords[] = { + {"pascal", tPASCAL, 0}, + {"properties", tPROPERTIES, 0}, + {"register", tREGISTER, 0}, ++ {"runtimeclass", tRUNTIMECLASS, 1}, + {"short", tSHORT, 0}, + {"signed", tSIGNED, 0}, + {"sizeof", tSIZEOF, 0}, +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index 88cc029c3ae..8b88e031fb5 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -99,6 +99,7 @@ static attr_list_t *check_library_attrs(const char *name, attr_list_t *attrs); + static attr_list_t *check_dispiface_attrs(const char *name, attr_list_t *attrs); + static attr_list_t *check_module_attrs(const char *name, attr_list_t *attrs); + static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs); ++static attr_list_t *check_runtimeclass_attrs(const char *name, attr_list_t *attrs); + static attr_list_t *check_apicontract_attrs(const char *name, attr_list_t *attrs); + const char *get_attr_display_name(enum attr_type type); + static void add_explicit_handle_if_necessary(const type_t *iface, var_t *func); +@@ -245,6 +246,7 @@ static typelib_t *current_typelib; + %token tREQUESTEDIT + %token tRESTRICTED + %token tRETVAL ++%token tRUNTIMECLASS + %token tSAFEARRAY + %token tSHORT + %token tSIGNED +@@ -290,8 +292,8 @@ static typelib_t *current_typelib; + %type base_type int_std + %type enumdef structdef uniondef typedecl + %type type qualified_seq qualified_type +-%type coclass_int +-%type coclass_ints ++%type class_interface ++%type class_interfaces + %type arg ne_union_field union_field s_field case enum enum_member declaration + %type funcdef + %type m_args arg_list args dispint_meths +@@ -302,6 +304,7 @@ static typelib_t *current_typelib; + %type m_abstract_declarator abstract_declarator abstract_declarator_no_direct abstract_direct_declarator + %type declarator_list struct_declarator_list + %type coclass coclasshdr coclassdef ++%type runtimeclass runtimeclass_hdr runtimeclass_def + %type apicontract + %type contract_ver + %type pointer_type threading_type marshaling_behavior version +@@ -361,6 +364,9 @@ gbl_statements: { $$ = NULL; } + } + | gbl_statements apicontract ';' { $$ = append_statement($1, make_statement_type_decl($2)); + reg_type($2, $2->name, current_namespace, 0); } ++ | gbl_statements runtimeclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); } ++ | gbl_statements runtimeclass_def { $$ = append_statement($1, make_statement_type_decl($2)); ++ reg_type($2, $2->name, current_namespace, 0); } + | gbl_statements moduledef { $$ = append_statement($1, make_statement_module($2)); } + | gbl_statements librarydef { $$ = append_statement($1, make_statement_library($2)); } + | gbl_statements statement { $$ = append_statement($1, $2); } +@@ -377,6 +383,9 @@ imp_statements: { $$ = NULL; } + } + | imp_statements apicontract ';' { $$ = append_statement($1, make_statement_type_decl($2)); + reg_type($2, $2->name, current_namespace, 0); } ++ | imp_statements runtimeclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); } ++ | imp_statements runtimeclass_def { $$ = append_statement($1, make_statement_type_decl($2)); ++ reg_type($2, $2->name, current_namespace, 0); } + | imp_statements moduledef { $$ = append_statement($1, make_statement_module($2)); } + | imp_statements statement { $$ = append_statement($1, $2); } + | imp_statements importlib { $$ = append_statement($1, make_statement_importlib($2)); } +@@ -558,7 +567,9 @@ attribute: { $$ = NULL; } + | tENCODE { $$ = make_attr(ATTR_ENCODE); } + | tENDPOINT '(' str_list ')' { $$ = make_attrp(ATTR_ENDPOINT, $3); } + | tENTRY '(' expr_const ')' { $$ = make_attrp(ATTR_ENTRY, $3); } +- | tEXCLUSIVETO '(' decl_spec ')' { $$ = make_attrp(ATTR_EXCLUSIVETO, $3->type); } ++ | tEXCLUSIVETO '(' decl_spec ')' { if ($3->type->type_type != TYPE_RUNTIMECLASS) ++ error_loc("type %s is not a runtimeclass\n", $3->type->name); ++ $$ = make_attrp(ATTR_EXCLUSIVETO, $3->type); } + | tEXPLICITHANDLE { $$ = make_attr(ATTR_EXPLICIT_HANDLE); } + | tFAULTSTATUS { $$ = make_attr(ATTR_FAULTSTATUS); } + | tFORCEALLOCATE { $$ = make_attr(ATTR_FORCEALLOCATE); } +@@ -893,10 +904,29 @@ coclasshdr: attributes coclass { $$ = $2; + } + ; + +-coclassdef: coclasshdr '{' coclass_ints '}' semicolon_opt ++coclassdef: coclasshdr '{' class_interfaces '}' semicolon_opt + { $$ = type_coclass_define($1, $3); } + ; + ++runtimeclass: ++ tRUNTIMECLASS aIDENTIFIER { $$ = type_new_runtimeclass($2, current_namespace); } ++ | tRUNTIMECLASS aKNOWNTYPE { $$ = find_type($2, NULL, 0); ++ if (type_get_type_detect_alias($$) != TYPE_RUNTIMECLASS) ++ error_loc("%s was not declared a runtimeclass at %s:%d\n", $2, ++ $$->loc_info.input_name, $$->loc_info.line_number); ++ } ++ ; ++ ++runtimeclass_hdr: attributes runtimeclass { $$ = $2; ++ check_def($$); ++ $$->attrs = check_runtimeclass_attrs($2->name, $1); ++ } ++ ; ++ ++runtimeclass_def: runtimeclass_hdr '{' class_interfaces '}' semicolon_opt ++ { $$ = type_runtimeclass_define($1, $3); } ++ ; ++ + apicontract: attributes tAPICONTRACT aIDENTIFIER '{' '}' + { $$ = get_type(TYPE_APICONTRACT, $3, current_namespace, 0); + check_def($$); +@@ -908,11 +938,11 @@ namespacedef: tNAMESPACE aIDENTIFIER { $$ = $2; } + | tNAMESPACE aNAMESPACE { $$ = $2; } + ; + +-coclass_ints: { $$ = NULL; } +- | coclass_ints coclass_int { $$ = append_ifref( $1, $2 ); } ++class_interfaces: { $$ = NULL; } ++ | class_interfaces class_interface { $$ = append_ifref( $1, $2 ); } + ; + +-coclass_int: ++class_interface: + m_attributes interfacedec { $$ = make_ifref($2); $$->attrs = $1; } + ; + +@@ -2166,115 +2196,116 @@ struct allowed_attr + unsigned int on_module : 1; + unsigned int on_coclass : 1; + unsigned int on_apicontract : 1; ++ unsigned int on_runtimeclass : 1; + const char *display_name; + }; + + struct allowed_attr allowed_attr[] = + { +- /* attr { D ACF I Fn ARG T En Enm St Un Fi L DI M C AC } */ +- /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "aggregatable" }, +- /* ATTR_ANNOTATION */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "annotation" }, +- /* ATTR_APPOBJECT */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "appobject" }, +- /* ATTR_ASYNC */ { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" }, +- /* ATTR_ASYNCUUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "async_uuid" }, +- /* ATTR_AUTO_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "auto_handle" }, +- /* ATTR_BINDABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bindable" }, +- /* ATTR_BROADCAST */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "broadcast" }, +- /* ATTR_CALLAS */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "call_as" }, +- /* ATTR_CALLCONV */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, +- /* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "case" }, +- /* ATTR_CODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" }, +- /* ATTR_COMMSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" }, +- /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" }, +- /* ATTR_CONTRACT */ { 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, "contract" }, +- /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "contractversion" }, +- /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, "control" }, +- /* ATTR_DECODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" }, +- /* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, "default" }, +- /* ATTR_DEFAULTBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultbind" }, +- /* ATTR_DEFAULTCOLLELEM */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultcollelem" }, +- /* ATTR_DEFAULTVALUE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultvalue" }, +- /* ATTR_DEFAULTVTABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "defaultvtable" }, +- /* ATTR_DISABLECONSISTENCYCHECK */{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "disable_consistency_check" }, +- /* ATTR_DISPINTERFACE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, +- /* ATTR_DISPLAYBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "displaybind" }, +- /* ATTR_DLLNAME */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "dllname" }, +- /* ATTR_DUAL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "dual" }, +- /* ATTR_ENABLEALLOCATE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "enable_allocate" }, +- /* ATTR_ENCODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "encode" }, +- /* ATTR_ENDPOINT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" }, +- /* ATTR_ENTRY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" }, +- /* ATTR_EXCLUSIVETO */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" }, +- /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" }, +- /* ATTR_FAULTSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" }, +- /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" }, +- /* ATTR_HANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "handle" }, +- /* ATTR_HELPCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpcontext" }, +- /* ATTR_HELPFILE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "helpfile" }, +- /* ATTR_HELPSTRING */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpstring" }, +- /* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpstringcontext" }, +- /* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "helpstringdll" }, +- /* ATTR_HIDDEN */ { 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, "hidden" }, +- /* ATTR_ID */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, "id" }, +- /* ATTR_IDEMPOTENT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "idempotent" }, +- /* ATTR_IGNORE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "ignore" }, +- /* ATTR_IIDIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "iid_is" }, +- /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" }, +- /* ATTR_IMPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" }, +- /* ATTR_IN */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" }, +- /* ATTR_INPUTSYNC */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" }, +- /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "length_is" }, +- /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "lcid" }, +- /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "licensed" }, +- /* ATTR_LOCAL */ { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" }, +- /* ATTR_MARSHALING_BEHAVIOR */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "marshaling_behavior" }, +- /* ATTR_MAYBE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "maybe" }, +- /* ATTR_MESSAGE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "message" }, +- /* ATTR_NOCODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" }, +- /* ATTR_NONBROWSABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonbrowsable" }, +- /* ATTR_NONCREATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "noncreatable" }, +- /* ATTR_NONEXTENSIBLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonextensible" }, +- /* ATTR_NOTIFY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify" }, +- /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify_flag" }, +- /* ATTR_OBJECT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "object" }, +- /* ATTR_ODL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "odl" }, +- /* ATTR_OLEAUTOMATION */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "oleautomation" }, +- /* ATTR_OPTIMIZE */ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optimize" }, +- /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optional" }, +- /* ATTR_OUT */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "out" }, +- /* ATTR_PARAMLCID */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "lcid" }, +- /* ATTR_PARTIALIGNORE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "partial_ignore" }, +- /* ATTR_POINTERDEFAULT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" }, +- /* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "ref, unique or ptr" }, +- /* ATTR_PROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "progid" }, +- /* ATTR_PROPGET */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propget" }, +- /* ATTR_PROPPUT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propput" }, +- /* ATTR_PROPPUTREF */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propputref" }, +- /* ATTR_PROXY */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "proxy" }, +- /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "public" }, +- /* ATTR_RANGE */ { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, "range" }, +- /* ATTR_READONLY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "readonly" }, +- /* ATTR_REPRESENTAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "represent_as" }, +- /* ATTR_REQUESTEDIT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "requestedit" }, +- /* ATTR_RESTRICTED */ { 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, "restricted" }, +- /* ATTR_RETVAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" }, +- /* ATTR_SIZEIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "size_is" }, +- /* ATTR_SOURCE */ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "source" }, +- /* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "strict_context_handle" }, +- /* ATTR_STRING */ { 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "string" }, +- /* ATTR_SWITCHIS */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "switch_is" }, +- /* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "switch_type" }, +- /* ATTR_THREADING */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "threading" }, +- /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "transmit_as" }, +- /* ATTR_UIDEFAULT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "uidefault" }, +- /* ATTR_USESGETLASTERROR */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "usesgetlasterror" }, +- /* ATTR_USERMARSHAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "user_marshal" }, +- /* ATTR_UUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, "uuid" }, +- /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "v1_enum" }, +- /* ATTR_VARARG */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "vararg" }, +- /* ATTR_VERSION */ { 1, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 1, 0, 0, 1, 0, "version" }, +- /* ATTR_VIPROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "vi_progid" }, +- /* ATTR_WIREMARSHAL */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" }, ++ /* attr { D ACF I Fn ARG T En Enm St Un Fi L DI M C AC R } */ ++ /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "aggregatable" }, ++ /* ATTR_ANNOTATION */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "annotation" }, ++ /* ATTR_APPOBJECT */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "appobject" }, ++ /* ATTR_ASYNC */ { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" }, ++ /* ATTR_ASYNCUUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "async_uuid" }, ++ /* ATTR_AUTO_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "auto_handle" }, ++ /* ATTR_BINDABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bindable" }, ++ /* ATTR_BROADCAST */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "broadcast" }, ++ /* ATTR_CALLAS */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "call_as" }, ++ /* ATTR_CALLCONV */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, ++ /* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "case" }, ++ /* ATTR_CODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" }, ++ /* ATTR_COMMSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" }, ++ /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" }, ++ /* ATTR_CONTRACT */ { 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, "contract" }, ++ /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "contractversion" }, ++ /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, "control" }, ++ /* ATTR_DECODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" }, ++ /* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "default" }, ++ /* ATTR_DEFAULTBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultbind" }, ++ /* ATTR_DEFAULTCOLLELEM */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultcollelem" }, ++ /* ATTR_DEFAULTVALUE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultvalue" }, ++ /* ATTR_DEFAULTVTABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "defaultvtable" }, ++ /* ATTR_DISABLECONSISTENCYCHECK */{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "disable_consistency_check" }, ++ /* ATTR_DISPINTERFACE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, ++ /* ATTR_DISPLAYBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "displaybind" }, ++ /* ATTR_DLLNAME */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "dllname" }, ++ /* ATTR_DUAL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "dual" }, ++ /* ATTR_ENABLEALLOCATE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "enable_allocate" }, ++ /* ATTR_ENCODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "encode" }, ++ /* ATTR_ENDPOINT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" }, ++ /* ATTR_ENTRY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" }, ++ /* ATTR_EXCLUSIVETO */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" }, ++ /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" }, ++ /* ATTR_FAULTSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" }, ++ /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" }, ++ /* ATTR_HANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "handle" }, ++ /* ATTR_HELPCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpcontext" }, ++ /* ATTR_HELPFILE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "helpfile" }, ++ /* ATTR_HELPSTRING */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpstring" }, ++ /* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpstringcontext" }, ++ /* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "helpstringdll" }, ++ /* ATTR_HIDDEN */ { 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, "hidden" }, ++ /* ATTR_ID */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, "id" }, ++ /* ATTR_IDEMPOTENT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "idempotent" }, ++ /* ATTR_IGNORE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "ignore" }, ++ /* ATTR_IIDIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "iid_is" }, ++ /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" }, ++ /* ATTR_IMPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" }, ++ /* ATTR_IN */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" }, ++ /* ATTR_INPUTSYNC */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" }, ++ /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "length_is" }, ++ /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "lcid" }, ++ /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "licensed" }, ++ /* ATTR_LOCAL */ { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" }, ++ /* ATTR_MARSHALING_BEHAVIOR */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "marshaling_behavior" }, ++ /* ATTR_MAYBE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "maybe" }, ++ /* ATTR_MESSAGE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "message" }, ++ /* ATTR_NOCODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" }, ++ /* ATTR_NONBROWSABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonbrowsable" }, ++ /* ATTR_NONCREATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "noncreatable" }, ++ /* ATTR_NONEXTENSIBLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonextensible" }, ++ /* ATTR_NOTIFY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify" }, ++ /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify_flag" }, ++ /* ATTR_OBJECT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "object" }, ++ /* ATTR_ODL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "odl" }, ++ /* ATTR_OLEAUTOMATION */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "oleautomation" }, ++ /* ATTR_OPTIMIZE */ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optimize" }, ++ /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optional" }, ++ /* ATTR_OUT */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "out" }, ++ /* ATTR_PARAMLCID */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "lcid" }, ++ /* ATTR_PARTIALIGNORE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "partial_ignore" }, ++ /* ATTR_POINTERDEFAULT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" }, ++ /* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "ref, unique or ptr" }, ++ /* ATTR_PROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "progid" }, ++ /* ATTR_PROPGET */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propget" }, ++ /* ATTR_PROPPUT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propput" }, ++ /* ATTR_PROPPUTREF */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propputref" }, ++ /* ATTR_PROXY */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "proxy" }, ++ /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "public" }, ++ /* ATTR_RANGE */ { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "range" }, ++ /* ATTR_READONLY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "readonly" }, ++ /* ATTR_REPRESENTAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "represent_as" }, ++ /* ATTR_REQUESTEDIT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "requestedit" }, ++ /* ATTR_RESTRICTED */ { 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, "restricted" }, ++ /* ATTR_RETVAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" }, ++ /* ATTR_SIZEIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "size_is" }, ++ /* ATTR_SOURCE */ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "source" }, ++ /* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "strict_context_handle" }, ++ /* ATTR_STRING */ { 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "string" }, ++ /* ATTR_SWITCHIS */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "switch_is" }, ++ /* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "switch_type" }, ++ /* ATTR_THREADING */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, "threading" }, ++ /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "transmit_as" }, ++ /* ATTR_UIDEFAULT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "uidefault" }, ++ /* ATTR_USESGETLASTERROR */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "usesgetlasterror" }, ++ /* ATTR_USERMARSHAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "user_marshal" }, ++ /* ATTR_UUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, "uuid" }, ++ /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "v1_enum" }, ++ /* ATTR_VARARG */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "vararg" }, ++ /* ATTR_VERSION */ { 1, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 1, 0, 0, 1, 0, 1, "version" }, ++ /* ATTR_VIPROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "vi_progid" }, ++ /* ATTR_WIREMARSHAL */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" }, + }; + + const char *get_attr_display_name(enum attr_type type) +@@ -2465,6 +2496,17 @@ static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs) + return attrs; + } + ++static attr_list_t *check_runtimeclass_attrs(const char *name, attr_list_t *attrs) ++{ ++ const attr_t *attr; ++ if (!attrs) return attrs; ++ LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) ++ if (!allowed_attr[attr->type].on_runtimeclass) ++ error_loc("inapplicable attribute %s for runtimeclass %s\n", ++ allowed_attr[attr->type].display_name, name); ++ return attrs; ++} ++ + static attr_list_t *check_apicontract_attrs(const char *name, attr_list_t *attrs) + { + const attr_t *attr; +@@ -2514,6 +2556,7 @@ static int is_allowed_conf_type(const type_t *type) + case TYPE_FUNCTION: + case TYPE_INTERFACE: + case TYPE_BITFIELD: ++ case TYPE_RUNTIMECLASS: + return FALSE; + case TYPE_APICONTRACT: + /* not supposed to be here */ +diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c +index 46aae9b69e9..86c010aa6ae 100644 +--- a/tools/widl/typegen.c ++++ b/tools/widl/typegen.c +@@ -353,6 +353,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att + return TGT_ENUM; + case TYPE_POINTER: + if (type_get_type(type_pointer_get_ref_type(type)) == TYPE_INTERFACE || ++ type_get_type(type_pointer_get_ref_type(type)) == TYPE_RUNTIMECLASS || + (type_get_type(type_pointer_get_ref_type(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS))) + return TGT_IFACE_POINTER; + else if (is_aliaschain_attr(type_pointer_get_ref_type(type), ATTR_CONTEXTHANDLE)) +@@ -373,6 +374,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att + case TYPE_VOID: + case TYPE_ALIAS: + case TYPE_BITFIELD: ++ case TYPE_RUNTIMECLASS: + break; + case TYPE_APICONTRACT: + /* not supposed to be here */ +@@ -1971,6 +1973,7 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align) + case TYPE_FUNCTION: + case TYPE_BITFIELD: + case TYPE_APICONTRACT: ++ case TYPE_RUNTIMECLASS: + /* these types should not be encountered here due to language + * restrictions (interface, void, coclass, module), logical + * restrictions (alias - due to type_get_type call above) or +@@ -2073,6 +2076,7 @@ static unsigned int type_buffer_alignment(const type_t *t) + case TYPE_FUNCTION: + case TYPE_BITFIELD: + case TYPE_APICONTRACT: ++ case TYPE_RUNTIMECLASS: + /* these types should not be encountered here due to language + * restrictions (interface, void, coclass, module), logical + * restrictions (alias - due to type_get_type call above) or +diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c +index faf76440f93..ace6424e3a0 100644 +--- a/tools/widl/typelib.c ++++ b/tools/widl/typelib.c +@@ -218,6 +218,7 @@ unsigned short get_type_vt(type_t *t) + case TYPE_MODULE: + case TYPE_UNION: + case TYPE_ENCAPSULATED_UNION: ++ case TYPE_RUNTIMECLASS: + return VT_USERDEFINED; + + case TYPE_VOID: +diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c +index d8dcd5d80b0..d075619448d 100644 +--- a/tools/widl/typetree.c ++++ b/tools/widl/typetree.c +@@ -211,6 +211,16 @@ type_t *type_new_coclass(char *name) + return type; + } + ++type_t *type_new_runtimeclass(char *name, struct namespace *namespace) ++{ ++ type_t *type = get_type(TYPE_RUNTIMECLASS, name, NULL, 0); ++ if (type->type_type != TYPE_RUNTIMECLASS || type->defined) ++ error_loc("%s: redefinition error; original definition was at %s:%d\n", ++ type->name, type->loc_info.input_name, type->loc_info.line_number); ++ type->name = name; ++ type->namespace = namespace; ++ return type; ++} + + type_t *type_new_array(const char *name, const decl_spec_t *element, int declptr, + unsigned int dim, expr_t *size_is, expr_t *length_is) +@@ -505,6 +515,13 @@ type_t *type_coclass_define(type_t *coclass, ifref_list_t *ifaces) + return coclass; + } + ++type_t *type_runtimeclass_define(type_t *runtimeclass, ifref_list_t *ifaces) ++{ ++ runtimeclass->details.runtimeclass.ifaces = ifaces; ++ runtimeclass->defined = TRUE; ++ return runtimeclass; ++} ++ + int type_is_equal(const type_t *type1, const type_t *type2) + { + if (type_get_type_detect_alias(type1) != type_get_type_detect_alias(type2)) +diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h +index 7abec41a8fd..951084cf875 100644 +--- a/tools/widl/typetree.h ++++ b/tools/widl/typetree.h +@@ -44,11 +44,13 @@ type_t *type_new_struct(char *name, struct namespace *namespace, int defined, va + type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t *fields); + type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases); + type_t *type_new_bitfield(type_t *field_type, const expr_t *bits); ++type_t *type_new_runtimeclass(char *name, struct namespace *namespace); + void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts); + void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *methods); + void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface); + void type_module_define(type_t *module, statement_list_t *stmts); + type_t *type_coclass_define(type_t *coclass, ifref_list_t *ifaces); ++type_t *type_runtimeclass_define(type_t *runtimeclass, ifref_list_t *ifaces); + int type_is_equal(const type_t *type1, const type_t *type2); + const char *type_get_name(const type_t *type, enum name_type name_type); + char *gen_name(void); +@@ -222,6 +224,7 @@ static inline int type_is_complete(const type_t *type) + case TYPE_POINTER: + case TYPE_ARRAY: + case TYPE_BITFIELD: ++ case TYPE_RUNTIMECLASS: + return TRUE; + case TYPE_APICONTRACT: + assert(0); +@@ -322,6 +325,27 @@ static inline ifref_list_t *type_coclass_get_ifaces(const type_t *type) + return type->details.coclass.ifaces; + } + ++static inline ifref_list_t *type_runtimeclass_get_ifaces(const type_t *type) ++{ ++ type = type_get_real_type(type); ++ assert(type_get_type(type) == TYPE_RUNTIMECLASS); ++ return type->details.runtimeclass.ifaces; ++} ++ ++static inline type_t *type_runtimeclass_get_default_iface(const type_t *type) ++{ ++ ifref_list_t *ifaces = type_runtimeclass_get_ifaces(type); ++ ifref_t *entry; ++ attr_t *attr; ++ ++ LIST_FOR_EACH_ENTRY(entry, ifaces, ifref_t, entry) ++ LIST_FOR_EACH_ENTRY(attr, entry->attrs, attr_t, entry) ++ if (attr->type == ATTR_DEFAULT) return entry->iface; ++ ++ assert(0); ++ return NULL; ++} ++ + static inline const decl_spec_t *type_pointer_get_ref(const type_t *type) + { + type = type_get_real_type(type); +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index e945cad33b2..0a2088574d3 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -418,6 +418,11 @@ struct alias_details + struct _decl_spec_t aliasee; + }; + ++struct runtimeclass_details ++{ ++ ifref_list_t *ifaces; ++}; ++ + #define HASHMAX 64 + + struct namespace { +@@ -445,6 +450,7 @@ enum type_type + TYPE_ARRAY, + TYPE_BITFIELD, + TYPE_APICONTRACT, ++ TYPE_RUNTIMECLASS, + }; + + struct _type_t { +@@ -465,6 +471,7 @@ struct _type_t { + struct pointer_details pointer; + struct bitfield_details bitfield; + struct alias_details alias; ++ struct runtimeclass_details runtimeclass; + } details; + const char *c_name; + unsigned int typestring_offset; +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0013-widl-Support-WinRT-eventadd-eventremove-attributes.patch b/patches/widl-winrt-support/0013-widl-Support-WinRT-eventadd-eventremove-attributes.patch new file mode 100644 index 00000000..f46148cb --- /dev/null +++ b/patches/widl-winrt-support/0013-widl-Support-WinRT-eventadd-eventremove-attributes.patch @@ -0,0 +1,95 @@ +From 4f9ad72a4381348591151271107caea8a83cef84 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Thu, 1 Oct 2020 20:10:02 +0200 +Subject: [PATCH 13/28] widl: Support WinRT eventadd/eventremove attributes. + +--- + tools/widl/header.c | 4 ++++ + tools/widl/parser.l | 2 ++ + tools/widl/parser.y | 7 +++++++ + tools/widl/widltypes.h | 2 ++ + 4 files changed, 15 insertions(+) + +diff --git a/tools/widl/header.c b/tools/widl/header.c +index 065a82ea384..812becad63b 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -187,6 +187,10 @@ const char *get_name(const var_t *v) + { + static char *buffer; + free( buffer ); ++ if (is_attr( v->attrs, ATTR_EVENTADD )) ++ return buffer = strmake( "add_%s", v->name ); ++ if (is_attr( v->attrs, ATTR_EVENTREMOVE )) ++ return buffer = strmake( "remove_%s", v->name ); + if (is_attr( v->attrs, ATTR_PROPGET )) + return buffer = strmake( "get_%s", v->name ); + if (is_attr( v->attrs, ATTR_PROPPUT )) +diff --git a/tools/widl/parser.l b/tools/widl/parser.l +index 31b97951b31..02a6b47e225 100644 +--- a/tools/widl/parser.l ++++ b/tools/widl/parser.l +@@ -356,6 +356,8 @@ static const struct keyword attr_keywords[] = + {"encode", tENCODE, 0}, + {"endpoint", tENDPOINT, 0}, + {"entry", tENTRY, 0}, ++ {"eventadd", tEVENTADD, 1}, ++ {"eventremove", tEVENTREMOVE, 1}, + {"exclusiveto", tEXCLUSIVETO, 1}, + {"explicit_handle", tEXPLICITHANDLE, 0}, + {"fault_status", tFAULTSTATUS, 0}, +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index 8b88e031fb5..b1b3201042f 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -195,6 +195,7 @@ static typelib_t *current_typelib; + %token tDLLNAME tDOUBLE tDUAL + %token tENABLEALLOCATE tENCODE tENDPOINT + %token tENTRY tENUM tERRORSTATUST ++%token tEVENTADD tEVENTREMOVE + %token tEXCLUSIVETO + %token tEXPLICITHANDLE tEXTERN + %token tFALSE +@@ -567,6 +568,8 @@ attribute: { $$ = NULL; } + | tENCODE { $$ = make_attr(ATTR_ENCODE); } + | tENDPOINT '(' str_list ')' { $$ = make_attrp(ATTR_ENDPOINT, $3); } + | tENTRY '(' expr_const ')' { $$ = make_attrp(ATTR_ENTRY, $3); } ++ | tEVENTADD { $$ = make_attr(ATTR_EVENTADD); } ++ | tEVENTREMOVE { $$ = make_attr(ATTR_EVENTREMOVE); } + | tEXCLUSIVETO '(' decl_spec ')' { if ($3->type->type_type != TYPE_RUNTIMECLASS) + error_loc("type %s is not a runtimeclass\n", $3->type->name); + $$ = make_attrp(ATTR_EXCLUSIVETO, $3->type); } +@@ -2235,6 +2238,8 @@ struct allowed_attr allowed_attr[] = + /* ATTR_ENCODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "encode" }, + /* ATTR_ENDPOINT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" }, + /* ATTR_ENTRY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" }, ++ /* ATTR_EVENTADD */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "eventadd" }, ++ /* ATTR_EVENTREMOVE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "eventremove" }, + /* ATTR_EXCLUSIVETO */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" }, + /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" }, + /* ATTR_FAULTSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" }, +@@ -2884,6 +2889,8 @@ static void check_functions(const type_t *iface, int is_inside_library) + { + if (func == func_iter) break; + if (strcmp(func->name, func_iter->name)) continue; ++ if (is_attr(func->attrs, ATTR_EVENTADD) != is_attr(func_iter->attrs, ATTR_EVENTADD)) continue; ++ if (is_attr(func->attrs, ATTR_EVENTREMOVE) != is_attr(func_iter->attrs, ATTR_EVENTREMOVE)) continue; + if (is_attr(func->attrs, ATTR_PROPGET) != is_attr(func_iter->attrs, ATTR_PROPGET)) continue; + if (is_attr(func->attrs, ATTR_PROPPUT) != is_attr(func_iter->attrs, ATTR_PROPPUT)) continue; + if (is_attr(func->attrs, ATTR_PROPPUTREF) != is_attr(func_iter->attrs, ATTR_PROPPUTREF)) continue; +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index 0a2088574d3..da70a8f97d5 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -100,6 +100,8 @@ enum attr_type + ATTR_ENCODE, + ATTR_ENDPOINT, + ATTR_ENTRY, ++ ATTR_EVENTADD, ++ ATTR_EVENTREMOVE, + ATTR_EXCLUSIVETO, + ATTR_EXPLICIT_HANDLE, + ATTR_FAULTSTATUS, +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0014-widl-Support-WinRT-flags-attribute-parsing.patch b/patches/widl-winrt-support/0014-widl-Support-WinRT-flags-attribute-parsing.patch new file mode 100644 index 00000000..37548b4b --- /dev/null +++ b/patches/widl-winrt-support/0014-widl-Support-WinRT-flags-attribute-parsing.patch @@ -0,0 +1,66 @@ +From c64bd2a13a6ec07122d08bc81d4933b38eec5edf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Mon, 12 Oct 2020 18:02:59 +0200 +Subject: [PATCH 14/28] widl: Support WinRT flags attribute parsing. + +--- + tools/widl/parser.l | 1 + + tools/widl/parser.y | 3 +++ + tools/widl/widltypes.h | 1 + + 3 files changed, 5 insertions(+) + +diff --git a/tools/widl/parser.l b/tools/widl/parser.l +index 02a6b47e225..f5a57db4797 100644 +--- a/tools/widl/parser.l ++++ b/tools/widl/parser.l +@@ -361,6 +361,7 @@ static const struct keyword attr_keywords[] = + {"exclusiveto", tEXCLUSIVETO, 1}, + {"explicit_handle", tEXPLICITHANDLE, 0}, + {"fault_status", tFAULTSTATUS, 0}, ++ {"flags", tFLAGS, 1}, + {"force_allocate", tFORCEALLOCATE, 0}, + {"free", tFREE, 0}, + {"handle", tHANDLE, 0}, +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index b1b3201042f..131226ba7be 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -200,6 +200,7 @@ static typelib_t *current_typelib; + %token tEXPLICITHANDLE tEXTERN + %token tFALSE + %token tFASTCALL tFAULTSTATUS ++%token tFLAGS + %token tFLOAT tFORCEALLOCATE + %token tHANDLE + %token tHANDLET +@@ -575,6 +576,7 @@ attribute: { $$ = NULL; } + $$ = make_attrp(ATTR_EXCLUSIVETO, $3->type); } + | tEXPLICITHANDLE { $$ = make_attr(ATTR_EXPLICIT_HANDLE); } + | tFAULTSTATUS { $$ = make_attr(ATTR_FAULTSTATUS); } ++ | tFLAGS { $$ = make_attr(ATTR_FLAGS); } + | tFORCEALLOCATE { $$ = make_attr(ATTR_FORCEALLOCATE); } + | tHANDLE { $$ = make_attr(ATTR_HANDLE); } + | tHELPCONTEXT '(' expr_int_const ')' { $$ = make_attrp(ATTR_HELPCONTEXT, $3); } +@@ -2243,6 +2245,7 @@ struct allowed_attr allowed_attr[] = + /* ATTR_EXCLUSIVETO */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" }, + /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" }, + /* ATTR_FAULTSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" }, ++ /* ATTR_FLAGS */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "flags" }, + /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" }, + /* ATTR_HANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "handle" }, + /* ATTR_HELPCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpcontext" }, +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index da70a8f97d5..0bf7b644fff 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -105,6 +105,7 @@ enum attr_type + ATTR_EXCLUSIVETO, + ATTR_EXPLICIT_HANDLE, + ATTR_FAULTSTATUS, ++ ATTR_FLAGS, + ATTR_FORCEALLOCATE, + ATTR_HANDLE, + ATTR_HELPCONTEXT, +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0015-widl-Support-using-qualified-names-for-interfaces.patch b/patches/widl-winrt-support/0015-widl-Support-using-qualified-names-for-interfaces.patch new file mode 100644 index 00000000..61f44b4f --- /dev/null +++ b/patches/widl-winrt-support/0015-widl-Support-using-qualified-names-for-interfaces.patch @@ -0,0 +1,156 @@ +From 65fefdad1ecb8bc45a89bee1393acf2cfcbb63b8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Fri, 25 Sep 2020 17:13:47 +0200 +Subject: [PATCH 15/28] widl: Support using qualified names for interfaces. + +And make qualified name lookup more robust, only looking for types in +the lookup namespace if it's active. +--- + include/windows.media.speechsynthesis.idl | 2 +- + tools/widl/parser.y | 58 +++++++++++++++-------- + 2 files changed, 38 insertions(+), 22 deletions(-) + +diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl +index 90bc9f279c6..89fe616b9b3 100644 +--- a/include/windows.media.speechsynthesis.idl ++++ b/include/windows.media.speechsynthesis.idl +@@ -65,7 +65,7 @@ namespace Windows { + ] + runtimeclass VoiceInformation + { +- [default] interface IVoiceInformation; ++ [default] interface Windows.Media.SpeechSynthesis.IVoiceInformation; + } + } + } +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index 131226ba7be..8e79ce3660f 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -74,6 +74,8 @@ static void append_chain_callconv(type_t *chain, char *callconv); + static warning_list_t *append_warning(warning_list_t *, int); + + static type_t *reg_typedefs(decl_spec_t *decl_spec, var_list_t *names, attr_list_t *attrs); ++static type_t *get_qualified_type(enum type_type type, char *name, int t); ++static type_t *find_qualified_type_or_error(const char *name, int t); + static type_t *find_type_or_error(const char *name, int t); + static type_t *find_type_or_error2(char *name, int t); + +@@ -81,7 +83,6 @@ static var_t *reg_const(var_t *var); + + static void push_namespace(const char *name); + static void pop_namespace(const char *name); +-static void init_lookup_namespace(const char *name); + static void push_lookup_namespace(const char *name); + + static void check_arg_attrs(const var_t *arg); +@@ -293,7 +294,7 @@ static typelib_t *current_typelib; + %type namespacedef + %type base_type int_std + %type enumdef structdef uniondef typedecl +-%type type qualified_seq qualified_type ++%type type qualified_type + %type class_interface + %type class_interfaces + %type arg ne_union_field union_field s_field case enum enum_member declaration +@@ -884,15 +885,15 @@ int_std: tINT { $$ = type_new_int(TYPE_BASIC_INT, 0); } + | tINT3264 { $$ = type_new_int(TYPE_BASIC_INT3264, 0); } + ; + +-qualified_seq: +- aKNOWNTYPE { $$ = find_type_or_error($1, 0); } +- | aIDENTIFIER '.' { push_lookup_namespace($1); } qualified_seq { $$ = $4; } +- ; ++namespace_pfx: ++ aNAMESPACE '.' { push_lookup_namespace($1); } ++ | namespace_pfx aNAMESPACE '.' { push_lookup_namespace($2); } ++ ; + + qualified_type: +- aKNOWNTYPE { $$ = find_type_or_error($1, 0); } +- | aNAMESPACE '.' { init_lookup_namespace($1); } qualified_seq { $$ = $4; } +- ; ++ aKNOWNTYPE { $$ = find_type_or_error($1, 0); } ++ | namespace_pfx aKNOWNTYPE { $$ = find_qualified_type_or_error($2, 0); } ++ ; + + coclass: tCOCLASS aIDENTIFIER { $$ = type_new_coclass($2); } + | tCOCLASS aKNOWNTYPE { $$ = find_type($2, NULL, 0); +@@ -990,6 +991,8 @@ inherit: { $$ = NULL; } + + interface: tINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } + | tINTERFACE aKNOWNTYPE { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } ++ | tINTERFACE namespace_pfx aIDENTIFIER { $$ = get_qualified_type(TYPE_INTERFACE, $3, 0); } ++ | tINTERFACE namespace_pfx aKNOWNTYPE { $$ = get_qualified_type(TYPE_INTERFACE, $3, 0); } + ; + + interfacehdr: attributes interface { $$ = $2; +@@ -1953,12 +1956,6 @@ static void pop_namespace(const char *name) + current_namespace = current_namespace->parent; + } + +-static void init_lookup_namespace(const char *name) +-{ +- if (!(lookup_namespace = find_sub_namespace(&global_namespace, name))) +- error_loc("namespace '%s' not found\n", name); +-} +- + static void push_lookup_namespace(const char *name) + { + struct namespace *namespace; +@@ -2076,11 +2073,29 @@ type_t *find_type(const char *name, struct namespace *namespace, int t) + return NULL; + } + ++static type_t *get_qualified_type(enum type_type type_type, char *name, int t) ++{ ++ type_t *type = get_type(type_type, name, lookup_namespace, t); ++ lookup_namespace = &global_namespace; ++ return type; ++} ++ ++static type_t *find_qualified_type_or_error(const char *name, int t) ++{ ++ type_t *type; ++ if (!(type = find_type(name, lookup_namespace, t))) ++ { ++ error_loc("type '%s' not found\n", name); ++ return NULL; ++ } ++ lookup_namespace = &global_namespace; ++ return type; ++} ++ + static type_t *find_type_or_error(const char *name, int t) + { + type_t *type; +- if (!(type = find_type(name, current_namespace, t)) && +- !(type = find_type(name, lookup_namespace, t))) ++ if (!(type = find_type(name, current_namespace, t))) + { + error_loc("type '%s' not found\n", name); + return NULL; +@@ -2097,15 +2112,16 @@ static type_t *find_type_or_error2(char *name, int t) + + int is_type(const char *name) + { +- return find_type(name, current_namespace, 0) != NULL || +- find_type(name, lookup_namespace, 0) != NULL; ++ if (lookup_namespace != &global_namespace) ++ return find_type(name, lookup_namespace, 0) != NULL; ++ else ++ return find_type(name, current_namespace, 0) != NULL; + } + + int is_namespace(const char *name) + { + if (!winrt_mode) return 0; +- return find_sub_namespace(current_namespace, name) != NULL || +- find_sub_namespace(&global_namespace, name) != NULL; ++ return find_sub_namespace(lookup_namespace, name) != NULL; + } + + type_t *get_type(enum type_type type, char *name, struct namespace *namespace, int t) +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0016-widl-Support-repeated-attributes-for-WinRT-static.patch b/patches/widl-winrt-support/0016-widl-Support-repeated-attributes-for-WinRT-static.patch new file mode 100644 index 00000000..74322d87 --- /dev/null +++ b/patches/widl-winrt-support/0016-widl-Support-repeated-attributes-for-WinRT-static.patch @@ -0,0 +1,297 @@ +From 734f1257696ef221883e92d23f653dc7188b1fcd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Tue, 13 Oct 2020 13:52:34 +0200 +Subject: [PATCH 16/28] widl: Support repeated attributes for WinRT static. + +--- + tools/widl/parser.y | 258 ++++++++++++++++++++++---------------------- + 1 file changed, 130 insertions(+), 128 deletions(-) + +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index 8e79ce3660f..1727b5bb396 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -1310,27 +1310,6 @@ static str_list_t *append_str(str_list_t *list, char *str) + return list; + } + +-static attr_list_t *append_attr(attr_list_t *list, attr_t *attr) +-{ +- attr_t *attr_existing; +- if (!attr) return list; +- if (!list) +- { +- list = xmalloc( sizeof(*list) ); +- list_init( list ); +- } +- LIST_FOR_EACH_ENTRY(attr_existing, list, attr_t, entry) +- if (attr_existing->type == attr->type) +- { +- parser_warning("duplicate attribute %s\n", get_attr_display_name(attr->type)); +- /* use the last attribute, like MIDL does */ +- list_remove(&attr_existing->entry); +- break; +- } +- list_add_tail( list, &attr->entry ); +- return list; +-} +- + static attr_list_t *move_attr(attr_list_t *dst, attr_list_t *src, enum attr_type type) + { + attr_t *attr; +@@ -2203,6 +2182,8 @@ struct allowed_attr + { + unsigned int dce_compatible : 1; + unsigned int acf : 1; ++ unsigned int multiple : 1; ++ + unsigned int on_interface : 1; + unsigned int on_function : 1; + unsigned int on_arg : 1; +@@ -2223,115 +2204,136 @@ struct allowed_attr + + struct allowed_attr allowed_attr[] = + { +- /* attr { D ACF I Fn ARG T En Enm St Un Fi L DI M C AC R } */ +- /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "aggregatable" }, +- /* ATTR_ANNOTATION */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "annotation" }, +- /* ATTR_APPOBJECT */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "appobject" }, +- /* ATTR_ASYNC */ { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" }, +- /* ATTR_ASYNCUUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "async_uuid" }, +- /* ATTR_AUTO_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "auto_handle" }, +- /* ATTR_BINDABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bindable" }, +- /* ATTR_BROADCAST */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "broadcast" }, +- /* ATTR_CALLAS */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "call_as" }, +- /* ATTR_CALLCONV */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, +- /* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "case" }, +- /* ATTR_CODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" }, +- /* ATTR_COMMSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" }, +- /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" }, +- /* ATTR_CONTRACT */ { 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, "contract" }, +- /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "contractversion" }, +- /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, "control" }, +- /* ATTR_DECODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" }, +- /* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "default" }, +- /* ATTR_DEFAULTBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultbind" }, +- /* ATTR_DEFAULTCOLLELEM */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultcollelem" }, +- /* ATTR_DEFAULTVALUE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultvalue" }, +- /* ATTR_DEFAULTVTABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "defaultvtable" }, +- /* ATTR_DISABLECONSISTENCYCHECK */{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "disable_consistency_check" }, +- /* ATTR_DISPINTERFACE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, +- /* ATTR_DISPLAYBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "displaybind" }, +- /* ATTR_DLLNAME */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "dllname" }, +- /* ATTR_DUAL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "dual" }, +- /* ATTR_ENABLEALLOCATE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "enable_allocate" }, +- /* ATTR_ENCODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "encode" }, +- /* ATTR_ENDPOINT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" }, +- /* ATTR_ENTRY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" }, +- /* ATTR_EVENTADD */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "eventadd" }, +- /* ATTR_EVENTREMOVE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "eventremove" }, +- /* ATTR_EXCLUSIVETO */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" }, +- /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" }, +- /* ATTR_FAULTSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" }, +- /* ATTR_FLAGS */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "flags" }, +- /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" }, +- /* ATTR_HANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "handle" }, +- /* ATTR_HELPCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpcontext" }, +- /* ATTR_HELPFILE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "helpfile" }, +- /* ATTR_HELPSTRING */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpstring" }, +- /* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpstringcontext" }, +- /* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "helpstringdll" }, +- /* ATTR_HIDDEN */ { 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, "hidden" }, +- /* ATTR_ID */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, "id" }, +- /* ATTR_IDEMPOTENT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "idempotent" }, +- /* ATTR_IGNORE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "ignore" }, +- /* ATTR_IIDIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "iid_is" }, +- /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" }, +- /* ATTR_IMPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" }, +- /* ATTR_IN */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" }, +- /* ATTR_INPUTSYNC */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" }, +- /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "length_is" }, +- /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "lcid" }, +- /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "licensed" }, +- /* ATTR_LOCAL */ { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" }, +- /* ATTR_MARSHALING_BEHAVIOR */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "marshaling_behavior" }, +- /* ATTR_MAYBE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "maybe" }, +- /* ATTR_MESSAGE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "message" }, +- /* ATTR_NOCODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" }, +- /* ATTR_NONBROWSABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonbrowsable" }, +- /* ATTR_NONCREATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "noncreatable" }, +- /* ATTR_NONEXTENSIBLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonextensible" }, +- /* ATTR_NOTIFY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify" }, +- /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify_flag" }, +- /* ATTR_OBJECT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "object" }, +- /* ATTR_ODL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "odl" }, +- /* ATTR_OLEAUTOMATION */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "oleautomation" }, +- /* ATTR_OPTIMIZE */ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optimize" }, +- /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optional" }, +- /* ATTR_OUT */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "out" }, +- /* ATTR_PARAMLCID */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "lcid" }, +- /* ATTR_PARTIALIGNORE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "partial_ignore" }, +- /* ATTR_POINTERDEFAULT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" }, +- /* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "ref, unique or ptr" }, +- /* ATTR_PROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "progid" }, +- /* ATTR_PROPGET */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propget" }, +- /* ATTR_PROPPUT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propput" }, +- /* ATTR_PROPPUTREF */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propputref" }, +- /* ATTR_PROXY */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "proxy" }, +- /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "public" }, +- /* ATTR_RANGE */ { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "range" }, +- /* ATTR_READONLY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "readonly" }, +- /* ATTR_REPRESENTAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "represent_as" }, +- /* ATTR_REQUESTEDIT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "requestedit" }, +- /* ATTR_RESTRICTED */ { 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, "restricted" }, +- /* ATTR_RETVAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" }, +- /* ATTR_SIZEIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "size_is" }, +- /* ATTR_SOURCE */ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "source" }, +- /* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "strict_context_handle" }, +- /* ATTR_STRING */ { 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "string" }, +- /* ATTR_SWITCHIS */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "switch_is" }, +- /* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "switch_type" }, +- /* ATTR_THREADING */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, "threading" }, +- /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "transmit_as" }, +- /* ATTR_UIDEFAULT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "uidefault" }, +- /* ATTR_USESGETLASTERROR */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "usesgetlasterror" }, +- /* ATTR_USERMARSHAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "user_marshal" }, +- /* ATTR_UUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, "uuid" }, +- /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "v1_enum" }, +- /* ATTR_VARARG */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "vararg" }, +- /* ATTR_VERSION */ { 1, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 1, 0, 0, 1, 0, 1, "version" }, +- /* ATTR_VIPROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "vi_progid" }, +- /* ATTR_WIREMARSHAL */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" }, ++ /* attr { D ACF M I Fn ARG T En Enm St Un Fi L DI M C AC R } */ ++ /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "aggregatable" }, ++ /* ATTR_ANNOTATION */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "annotation" }, ++ /* ATTR_APPOBJECT */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "appobject" }, ++ /* ATTR_ASYNC */ { 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" }, ++ /* ATTR_ASYNCUUID */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "async_uuid" }, ++ /* ATTR_AUTO_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "auto_handle" }, ++ /* ATTR_BINDABLE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bindable" }, ++ /* ATTR_BROADCAST */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "broadcast" }, ++ /* ATTR_CALLAS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "call_as" }, ++ /* ATTR_CALLCONV */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, ++ /* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "case" }, ++ /* ATTR_CODE */ { 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" }, ++ /* ATTR_COMMSTATUS */ { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" }, ++ /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" }, ++ /* ATTR_CONTRACT */ { 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, "contract" }, ++ /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "contractversion" }, ++ /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, "control" }, ++ /* ATTR_DECODE */ { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" }, ++ /* ATTR_DEFAULT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "default" }, ++ /* ATTR_DEFAULTBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultbind" }, ++ /* ATTR_DEFAULTCOLLELEM */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultcollelem" }, ++ /* ATTR_DEFAULTVALUE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultvalue" }, ++ /* ATTR_DEFAULTVTABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "defaultvtable" }, ++ /* ATTR_DISABLECONSISTENCYCHECK */{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "disable_consistency_check" }, ++ /* ATTR_DISPINTERFACE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, ++ /* ATTR_DISPLAYBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "displaybind" }, ++ /* ATTR_DLLNAME */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "dllname" }, ++ /* ATTR_DUAL */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "dual" }, ++ /* ATTR_ENABLEALLOCATE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "enable_allocate" }, ++ /* ATTR_ENCODE */ { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "encode" }, ++ /* ATTR_ENDPOINT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" }, ++ /* ATTR_ENTRY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" }, ++ /* ATTR_EVENTADD */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "eventadd" }, ++ /* ATTR_EVENTREMOVE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "eventremove" }, ++ /* ATTR_EXCLUSIVETO */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" }, ++ /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" }, ++ /* ATTR_FAULTSTATUS */ { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" }, ++ /* ATTR_FLAGS */ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "flags" }, ++ /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" }, ++ /* ATTR_HANDLE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "handle" }, ++ /* ATTR_HELPCONTEXT */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpcontext" }, ++ /* ATTR_HELPFILE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "helpfile" }, ++ /* ATTR_HELPSTRING */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpstring" }, ++ /* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpstringcontext" }, ++ /* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "helpstringdll" }, ++ /* ATTR_HIDDEN */ { 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, "hidden" }, ++ /* ATTR_ID */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, "id" }, ++ /* ATTR_IDEMPOTENT */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "idempotent" }, ++ /* ATTR_IGNORE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "ignore" }, ++ /* ATTR_IIDIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "iid_is" }, ++ /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" }, ++ /* ATTR_IMPLICIT_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" }, ++ /* ATTR_IN */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" }, ++ /* ATTR_INPUTSYNC */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" }, ++ /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "length_is" }, ++ /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "lcid" }, ++ /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "licensed" }, ++ /* ATTR_LOCAL */ { 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" }, ++ /* ATTR_MARSHALING_BEHAVIOR */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "marshaling_behavior" }, ++ /* ATTR_MAYBE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "maybe" }, ++ /* ATTR_MESSAGE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "message" }, ++ /* ATTR_NOCODE */ { 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" }, ++ /* ATTR_NONBROWSABLE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonbrowsable" }, ++ /* ATTR_NONCREATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "noncreatable" }, ++ /* ATTR_NONEXTENSIBLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonextensible" }, ++ /* ATTR_NOTIFY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify" }, ++ /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify_flag" }, ++ /* ATTR_OBJECT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "object" }, ++ /* ATTR_ODL */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "odl" }, ++ /* ATTR_OLEAUTOMATION */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "oleautomation" }, ++ /* ATTR_OPTIMIZE */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optimize" }, ++ /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optional" }, ++ /* ATTR_OUT */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "out" }, ++ /* ATTR_PARAMLCID */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "lcid" }, ++ /* ATTR_PARTIALIGNORE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "partial_ignore" }, ++ /* ATTR_POINTERDEFAULT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" }, ++ /* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "ref, unique or ptr" }, ++ /* ATTR_PROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "progid" }, ++ /* ATTR_PROPGET */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propget" }, ++ /* ATTR_PROPPUT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propput" }, ++ /* ATTR_PROPPUTREF */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propputref" }, ++ /* ATTR_PROXY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "proxy" }, ++ /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "public" }, ++ /* ATTR_RANGE */ { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "range" }, ++ /* ATTR_READONLY */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "readonly" }, ++ /* ATTR_REPRESENTAS */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "represent_as" }, ++ /* ATTR_REQUESTEDIT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "requestedit" }, ++ /* ATTR_RESTRICTED */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, "restricted" }, ++ /* ATTR_RETVAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" }, ++ /* ATTR_SIZEIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "size_is" }, ++ /* ATTR_SOURCE */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "source" }, ++ /* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "strict_context_handle" }, ++ /* ATTR_STRING */ { 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "string" }, ++ /* ATTR_SWITCHIS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "switch_is" }, ++ /* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "switch_type" }, ++ /* ATTR_THREADING */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, "threading" }, ++ /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "transmit_as" }, ++ /* ATTR_UIDEFAULT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "uidefault" }, ++ /* ATTR_USESGETLASTERROR */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "usesgetlasterror" }, ++ /* ATTR_USERMARSHAL */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "user_marshal" }, ++ /* ATTR_UUID */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, "uuid" }, ++ /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "v1_enum" }, ++ /* ATTR_VARARG */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "vararg" }, ++ /* ATTR_VERSION */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 1, 0, 0, 1, 0, 1, "version" }, ++ /* ATTR_VIPROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "vi_progid" }, ++ /* ATTR_WIREMARSHAL */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" }, + }; + ++static attr_list_t *append_attr(attr_list_t *list, attr_t *attr) ++{ ++ attr_t *attr_existing; ++ if (!attr) return list; ++ if (!list) ++ { ++ list = xmalloc( sizeof(*list) ); ++ list_init( list ); ++ } ++ LIST_FOR_EACH_ENTRY(attr_existing, list, attr_t, entry) ++ if (attr_existing->type == attr->type && !allowed_attr[attr->type].multiple) ++ { ++ parser_warning("duplicate attribute %s\n", get_attr_display_name(attr->type)); ++ /* use the last attribute, like MIDL does */ ++ list_remove(&attr_existing->entry); ++ break; ++ } ++ list_add_tail( list, &attr->entry ); ++ return list; ++} ++ + const char *get_attr_display_name(enum attr_type type) + { + return allowed_attr[type].display_name; +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0017-widl-Support-WinRT-static-attribute-parsing.patch b/patches/widl-winrt-support/0017-widl-Support-WinRT-static-attribute-parsing.patch new file mode 100644 index 00000000..2d0e0f0e --- /dev/null +++ b/patches/widl-winrt-support/0017-widl-Support-WinRT-static-attribute-parsing.patch @@ -0,0 +1,134 @@ +From ca0364f1bd90bb35821c6ffb620e502f2b4afb7a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Tue, 13 Oct 2020 14:30:32 +0200 +Subject: [PATCH 17/28] widl: Support WinRT static attribute parsing. + +--- + tools/widl/header.c | 30 ++++++++++++++++++++++++++++++ + tools/widl/parser.l | 1 + + tools/widl/parser.y | 8 ++++++++ + tools/widl/widltypes.h | 1 + + 4 files changed, 40 insertions(+) + +diff --git a/tools/widl/header.c b/tools/widl/header.c +index 812becad63b..3bc6b452177 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -109,6 +109,17 @@ int is_attr(const attr_list_t *list, enum attr_type t) + return 0; + } + ++static void get_attr_statics(const attr_list_t *attrs, expr_list_t *list) ++{ ++ const attr_t *attr; ++ if (!attrs) return; ++ LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) ++ { ++ if (attr->type != ATTR_STATIC) continue; ++ list_add_tail(list, &((expr_t *)attr->u.pval)->entry); ++ } ++} ++ + void *get_attrp(const attr_list_t *list, enum attr_type t) + { + const attr_t *attr; +@@ -1495,6 +1506,8 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) + { + expr_t *contract = get_attrp(type->attrs, ATTR_CONTRACT); + type_t *exclusiveto = get_attrp(type->attrs, ATTR_EXCLUSIVETO); ++ expr_list_t statics = LIST_INIT(statics); ++ get_attr_statics(type->attrs, &statics); + fprintf(header, " *\n"); + if (contract) + { +@@ -1510,6 +1523,23 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) + fprintf(header, " * Interface is a part of the implementation of type %s\n *\n", name); + free(name); + } ++ if (!list_empty(&statics)) ++ { ++ expr_t *expr; ++ fprintf(header, " * RuntimeClass contains static methods.\n"); ++ LIST_FOR_EACH_ENTRY(expr, &statics, expr_t, entry) ++ { ++ const type_t *iface = expr->u.tref.type, *apicontract = expr->ref->u.tref.type; ++ int version_req = expr->ref->ref->u.lval; ++ char *iface_name = format_namespace(iface->namespace, "", ".", iface->name, NULL); ++ char *name = format_namespace(apicontract->namespace, "", ".", apicontract->name, NULL); ++ fprintf(header, " * Static Methods exist on the %s interface starting with version %d.%d of the %s API contract\n", ++ iface_name, (version_req >> 16) & 0xffff, version_req & 0xffff, name); ++ free(iface_name); ++ free(name); ++ } ++ fprintf(header, " *\n"); ++ } + if (type_get_type(type) == TYPE_RUNTIMECLASS) + { + ifref_list_t *ifaces = type_runtimeclass_get_ifaces(type); +diff --git a/tools/widl/parser.l b/tools/widl/parser.l +index f5a57db4797..90791543db2 100644 +--- a/tools/widl/parser.l ++++ b/tools/widl/parser.l +@@ -422,6 +422,7 @@ static const struct keyword attr_keywords[] = + {"size_is", tSIZEIS, 0}, + {"source", tSOURCE, 0}, + {"standard", tSTANDARD, 1}, ++ {"static", tSTATIC, 1}, + {"strict_context_handle", tSTRICTCONTEXTHANDLE, 0}, + {"string", tSTRING, 0}, + {"switch_is", tSWITCHIS, 0}, +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index 1727b5bb396..e6e67826a8f 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -283,6 +283,7 @@ static typelib_t *current_typelib; + %type m_expr expr expr_const expr_int_const array m_bitfield + %type m_exprs /* exprs expr_list */ expr_list_int_const + %type contract_req ++%type static_attr + %type interfacehdr + %type storage_cls_spec + %type type_qualifier m_type_qual_list +@@ -538,6 +539,11 @@ contract_req: decl_spec ',' contract_ver { if ($1->type->type_type != TYPE_APICO + $$ = make_exprt(EXPR_GTREQL, declare_var(NULL, $1, make_declarator(NULL), 0), $$); + } + ++static_attr: decl_spec ',' contract_req { if ($1->type->type_type != TYPE_INTERFACE) ++ error_loc("type %s is not an interface\n", $1->type->name); ++ $$ = make_exprt(EXPR_MEMBER, declare_var(NULL, $1, make_declarator(NULL), 0), $3); ++ } ++ + attribute: { $$ = NULL; } + | tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); } + | tANNOTATION '(' aSTRING ')' { $$ = make_attrp(ATTR_ANNOTATION, $3); } +@@ -634,6 +640,7 @@ attribute: { $$ = NULL; } + | tRETVAL { $$ = make_attr(ATTR_RETVAL); } + | tSIZEIS '(' m_exprs ')' { $$ = make_attrp(ATTR_SIZEIS, $3); } + | tSOURCE { $$ = make_attr(ATTR_SOURCE); } ++ | tSTATIC '(' static_attr ')' { $$ = make_attrp(ATTR_STATIC, $3); } + | tSTRICTCONTEXTHANDLE { $$ = make_attr(ATTR_STRICTCONTEXTHANDLE); } + | tSTRING { $$ = make_attr(ATTR_STRING); } + | tSWITCHIS '(' expr ')' { $$ = make_attrp(ATTR_SWITCHIS, $3); } +@@ -2296,6 +2303,7 @@ struct allowed_attr allowed_attr[] = + /* ATTR_RETVAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" }, + /* ATTR_SIZEIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "size_is" }, + /* ATTR_SOURCE */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "source" }, ++ /* ATTR_STATIC */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "static" }, + /* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "strict_context_handle" }, + /* ATTR_STRING */ { 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "string" }, + /* ATTR_SWITCHIS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "switch_is" }, +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index 0bf7b644fff..aa3e6e75898 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -159,6 +159,7 @@ enum attr_type + ATTR_RETVAL, + ATTR_SIZEIS, + ATTR_SOURCE, ++ ATTR_STATIC, + ATTR_STRICTCONTEXTHANDLE, + ATTR_STRING, + ATTR_SWITCHIS, +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0018-widl-Support-WinRT-requires-keyword.patch b/patches/widl-winrt-support/0018-widl-Support-WinRT-requires-keyword.patch new file mode 100644 index 00000000..0b6f4b01 --- /dev/null +++ b/patches/widl-winrt-support/0018-widl-Support-WinRT-requires-keyword.patch @@ -0,0 +1,254 @@ +From 0d3503123e3f0cb458ada24b052e1d39f1c4dddb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Tue, 13 Oct 2020 00:31:57 +0200 +Subject: [PATCH 18/28] widl: Support WinRT requires keyword. + +--- + tools/widl/header.c | 13 +++++++++++ + tools/widl/parser.l | 1 + + tools/widl/parser.y | 49 ++++++++++++++++++++++++++++++++---------- + tools/widl/typetree.c | 5 ++++- + tools/widl/typetree.h | 9 +++++++- + tools/widl/widltypes.h | 1 + + 6 files changed, 65 insertions(+), 13 deletions(-) + +diff --git a/tools/widl/header.c b/tools/widl/header.c +index 3bc6b452177..5dfc5e2ff8c 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -1506,6 +1506,7 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) + { + expr_t *contract = get_attrp(type->attrs, ATTR_CONTRACT); + type_t *exclusiveto = get_attrp(type->attrs, ATTR_EXCLUSIVETO); ++ type_list_t *requires = type->type_type == TYPE_INTERFACE ? type_iface_get_requires(type) : NULL; + expr_list_t statics = LIST_INIT(statics); + get_attr_statics(type->attrs, &statics); + fprintf(header, " *\n"); +@@ -1523,6 +1524,18 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) + fprintf(header, " * Interface is a part of the implementation of type %s\n *\n", name); + free(name); + } ++ if (requires) ++ { ++ type_list_t *req; ++ fprintf(header, " * Any object which implements this interface must also implement the following interfaces:\n"); ++ for (req = requires; req; req = req->next) ++ { ++ char *name = format_namespace(req->type->namespace, "", ".", req->type->name, NULL); ++ fprintf(header, " * %s\n", name); ++ free(name); ++ } ++ fprintf(header, " *\n"); ++ } + if (!list_empty(&statics)) + { + expr_t *expr; +diff --git a/tools/widl/parser.l b/tools/widl/parser.l +index 90791543db2..2b41bea1bc9 100644 +--- a/tools/widl/parser.l ++++ b/tools/widl/parser.l +@@ -298,6 +298,7 @@ static const struct keyword keywords[] = { + {"pascal", tPASCAL, 0}, + {"properties", tPROPERTIES, 0}, + {"register", tREGISTER, 0}, ++ {"requires", tREQUIRES, 1}, + {"runtimeclass", tRUNTIMECLASS, 1}, + {"short", tSHORT, 0}, + {"signed", tSIGNED, 0}, +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index e6e67826a8f..1da667e0ced 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -38,12 +38,6 @@ + #include "expr.h" + #include "typetree.h" + +-typedef struct list typelist_t; +-struct typenode { +- type_t *type; +- struct list entry; +-}; +- + struct _import_t + { + char *name; +@@ -51,6 +45,8 @@ struct _import_t + }; + + static str_list_t *append_str(str_list_t *list, char *str); ++static type_list_t *append_type(type_list_t *list, type_t *type); ++static type_list_t *append_types(type_list_t *list, type_list_t *types); + static attr_list_t *append_attr(attr_list_t *list, attr_t *attr); + static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list); + static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, +@@ -140,6 +136,7 @@ static typelib_t *current_typelib; + expr_t *expr; + expr_list_t *expr_list; + type_t *type; ++ type_list_t *typelist; + var_t *var; + var_list_t *var_list; + declarator_t *declarator; +@@ -247,6 +244,7 @@ static typelib_t *current_typelib; + %token tREADONLY tREF + %token tREGISTER tREPRESENTAS + %token tREQUESTEDIT ++%token tREQUIRES + %token tRESTRICTED + %token tRETVAL + %token tRUNTIMECLASS +@@ -296,6 +294,7 @@ static typelib_t *current_typelib; + %type base_type int_std + %type enumdef structdef uniondef typedecl + %type type qualified_type ++%type requires required_types + %type class_interface + %type class_interfaces + %type arg ne_union_field union_field s_field case enum enum_member declaration +@@ -1009,19 +1008,27 @@ interfacehdr: attributes interface { $$ = $2; + } + ; + +-interfacedef: interfacehdr inherit ++required_types: ++ qualified_type { $$ = append_type(NULL, $1); } ++ | required_types ',' required_types { $$ = append_types($1, $3); } ++ ++requires: { $$ = NULL; } ++ | tREQUIRES required_types { $$ = $2; } ++ ; ++ ++interfacedef: interfacehdr inherit requires + '{' int_statements '}' semicolon_opt { $$ = $1; + if($$ == $2) + error_loc("Interface can't inherit from itself\n"); +- type_interface_define($$, $2, $4); ++ type_interface_define($$, $2, $5, $3); + check_async_uuid($$); + } + /* MIDL is able to import the definition of a base class from inside the + * definition of a derived class, I'll try to support it with this rule */ +- | interfacehdr ':' aIDENTIFIER ++ | interfacehdr ':' aIDENTIFIER requires + '{' import int_statements '}' + semicolon_opt { $$ = $1; +- type_interface_define($$, find_type_or_error2($3, 0), $6); ++ type_interface_define($$, find_type_or_error2($3, 0), $7, $4); + } + | dispinterfacedef semicolon_opt { $$ = $1; } + ; +@@ -1317,6 +1324,26 @@ static str_list_t *append_str(str_list_t *list, char *str) + return list; + } + ++static type_list_t *append_type(type_list_t *list, type_t *type) ++{ ++ type_list_t *entry; ++ if (!type) return list; ++ entry = xmalloc( sizeof(*entry) ); ++ entry->type = type; ++ entry->next = list; ++ return entry; ++} ++ ++static type_list_t *append_types(type_list_t *list, type_list_t *types) ++{ ++ type_list_t *entry; ++ if (!list) return types; ++ if (!types) return list; ++ for (entry = list; entry->next; entry = entry->next) {} ++ entry->next = types; ++ return list; ++} ++ + static attr_list_t *move_attr(attr_list_t *dst, attr_list_t *src, enum attr_type type) + { + attr_t *attr; +@@ -3015,7 +3042,7 @@ static void check_async_uuid(type_t *iface) + stmts = append_statement(stmts, make_statement_declaration(finish_func)); + } + +- type_interface_define(async_iface, inherit, stmts); ++ type_interface_define(async_iface, inherit, stmts, NULL); + iface->details.iface->async_iface = async_iface->details.iface->async_iface = async_iface; + } + +diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c +index d075619448d..3d26fd23b26 100644 +--- a/tools/widl/typetree.c ++++ b/tools/widl/typetree.c +@@ -459,7 +459,7 @@ static unsigned int compute_method_indexes(type_t *iface) + return idx; + } + +-void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts) ++void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts, type_list_t *requires) + { + iface->details.iface = xmalloc(sizeof(*iface->details.iface)); + iface->details.iface->disp_props = NULL; +@@ -468,6 +468,7 @@ void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stm + iface->details.iface->inherit = inherit; + iface->details.iface->disp_inherit = NULL; + iface->details.iface->async_iface = NULL; ++ iface->details.iface->requires = requires; + iface->defined = TRUE; + compute_method_indexes(iface); + } +@@ -482,6 +483,7 @@ void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *met + if (!iface->details.iface->inherit) error_loc("IDispatch is undefined\n"); + iface->details.iface->disp_inherit = NULL; + iface->details.iface->async_iface = NULL; ++ iface->details.iface->requires = NULL; + iface->defined = TRUE; + compute_method_indexes(iface); + } +@@ -496,6 +498,7 @@ void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface) + if (!dispiface->details.iface->inherit) error_loc("IDispatch is undefined\n"); + dispiface->details.iface->disp_inherit = iface; + dispiface->details.iface->async_iface = NULL; ++ dispiface->details.iface->requires = NULL; + dispiface->defined = TRUE; + compute_method_indexes(dispiface); + } +diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h +index 951084cf875..8c555b91656 100644 +--- a/tools/widl/typetree.h ++++ b/tools/widl/typetree.h +@@ -45,7 +45,7 @@ type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t + type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases); + type_t *type_new_bitfield(type_t *field_type, const expr_t *bits); + type_t *type_new_runtimeclass(char *name, struct namespace *namespace); +-void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts); ++void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts, type_list_t *requires); + void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *methods); + void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface); + void type_module_define(type_t *module, statement_list_t *stmts); +@@ -169,6 +169,13 @@ static inline type_t *type_iface_get_inherit(const type_t *type) + return type->details.iface->inherit; + } + ++static inline type_list_t *type_iface_get_requires(const type_t *type) ++{ ++ type = type_get_real_type(type); ++ assert(type_get_type(type) == TYPE_INTERFACE); ++ return type->details.iface->requires; ++} ++ + static inline type_t *type_iface_get_async_iface(const type_t *type) + { + type = type_get_real_type(type); +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index aa3e6e75898..be71886260b 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -378,6 +378,7 @@ struct iface_details + struct _type_t *inherit; + struct _type_t *disp_inherit; + struct _type_t *async_iface; ++ type_list_t *requires; + }; + + struct module_details +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0019-widl-Support-WinRT-activatable-attribute.patch b/patches/widl-winrt-support/0019-widl-Support-WinRT-activatable-attribute.patch new file mode 100644 index 00000000..cae05311 --- /dev/null +++ b/patches/widl-winrt-support/0019-widl-Support-WinRT-activatable-attribute.patch @@ -0,0 +1,96 @@ +From c0c0bfcf80077cd2b5db3f7c1fb3fa597ae57321 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Tue, 13 Oct 2020 11:35:29 +0200 +Subject: [PATCH 19/28] widl: Support WinRT activatable attribute. + +--- + tools/widl/header.c | 11 +++++++++++ + tools/widl/parser.l | 1 + + tools/widl/parser.y | 3 +++ + tools/widl/widltypes.h | 1 + + 4 files changed, 16 insertions(+) + +diff --git a/tools/widl/header.c b/tools/widl/header.c +index 5dfc5e2ff8c..5c87a997349 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -1505,6 +1505,7 @@ static char *format_apicontract_macro(const type_t *type) + static void write_winrt_type_comments(FILE *header, const type_t *type) + { + expr_t *contract = get_attrp(type->attrs, ATTR_CONTRACT); ++ expr_t *activatable = get_attrp(type->attrs, ATTR_ACTIVATABLE); + type_t *exclusiveto = get_attrp(type->attrs, ATTR_EXCLUSIVETO); + type_list_t *requires = type->type_type == TYPE_INTERFACE ? type_iface_get_requires(type) : NULL; + expr_list_t statics = LIST_INIT(statics); +@@ -1518,6 +1519,16 @@ static void write_winrt_type_comments(FILE *header, const type_t *type) + fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff); + free(name); + } ++ if (activatable) ++ { ++ const type_t *apicontract = activatable->u.tref.type; ++ int version_req = activatable->ref->u.lval; ++ char *name = format_namespace(apicontract->namespace, "", ".", apicontract->name, NULL); ++ fprintf(header, " * RuntimeClass can be activated.\n"); ++ fprintf(header, " * Type can be activated via RoActivateInstance starting with version %d.%d of the %s API contract\n *\n", ++ (version_req >> 16) & 0xffff, version_req & 0xffff, name); ++ free(name); ++ } + if (exclusiveto) + { + char *name = format_namespace(exclusiveto->namespace, "", ".", exclusiveto->name, NULL); +diff --git a/tools/widl/parser.l b/tools/widl/parser.l +index 2b41bea1bc9..a47c490ec4c 100644 +--- a/tools/widl/parser.l ++++ b/tools/widl/parser.l +@@ -321,6 +321,7 @@ static const struct keyword keywords[] = { + */ + static const struct keyword attr_keywords[] = + { ++ {"activatable", tACTIVATABLE, 1}, + {"aggregatable", tAGGREGATABLE, 0}, + {"agile", tAGILE, 1}, + {"allocate", tALLOCATE, 0}, +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index 1da667e0ced..d24f8881147 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -172,6 +172,7 @@ static typelib_t *current_typelib; + %token GREATEREQUAL LESSEQUAL + %token LOGICALOR LOGICALAND + %token ELLIPSIS ++%token tACTIVATABLE + %token tAGGREGATABLE + %token tAGILE + %token tALLOCATE tANNOTATION +@@ -544,6 +545,7 @@ static_attr: decl_spec ',' contract_req { if ($1->type->type_type != TYPE_INTER + } + + attribute: { $$ = NULL; } ++ | tACTIVATABLE '(' contract_req ')' { $$ = make_attrp(ATTR_ACTIVATABLE, $3); } + | tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); } + | tANNOTATION '(' aSTRING ')' { $$ = make_attrp(ATTR_ANNOTATION, $3); } + | tAPPOBJECT { $$ = make_attr(ATTR_APPOBJECT); } +@@ -2239,6 +2241,7 @@ struct allowed_attr + struct allowed_attr allowed_attr[] = + { + /* attr { D ACF M I Fn ARG T En Enm St Un Fi L DI M C AC R } */ ++ /* ATTR_ACTIVATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "activatable" }, + /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "aggregatable" }, + /* ATTR_ANNOTATION */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "annotation" }, + /* ATTR_APPOBJECT */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "appobject" }, +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index be71886260b..7ca770b67ea 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -68,6 +68,7 @@ typedef struct list warning_list_t; + + enum attr_type + { ++ ATTR_ACTIVATABLE, + ATTR_AGGREGATABLE, + ATTR_ANNOTATION, + ATTR_APPOBJECT, +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0020-widl-Support-WinRT-parameterized-type-parsing.patch b/patches/widl-winrt-support/0020-widl-Support-WinRT-parameterized-type-parsing.patch new file mode 100644 index 00000000..9b1f3f70 --- /dev/null +++ b/patches/widl-winrt-support/0020-widl-Support-WinRT-parameterized-type-parsing.patch @@ -0,0 +1,391 @@ +From 46f497692aa6da875d56764538eefaadb9a8ec38 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Tue, 13 Oct 2020 16:31:16 +0200 +Subject: [PATCH 20/28] widl: Support WinRT parameterized type parsing. + +And add IVectorView and IIterator parameterized interfaces to +windows.foundation.idl for illustration and future use. They won't +generate any additional code until they are fully specialized. + +This is a WIDL-specific feature, but MIDL has some magic knowledge of +these Windows.Foundation.Collections interface templates, and we need a +way to instruct WIDL about them too. + +Having these interfaces declared in the IDL, guarded with __WIDL__ ifdef +is easier and more flexible than re-creating the types by hand in WIDL +source. +--- + include/windows.foundation.idl | 29 +++++++++++++++++ + tools/widl/expr.c | 2 ++ + tools/widl/header.c | 10 +++--- + tools/widl/parser.y | 57 ++++++++++++++++++++++++++++++++-- + tools/widl/typegen.c | 6 ++++ + tools/widl/typelib.c | 2 ++ + tools/widl/typetree.c | 30 ++++++++++++++++++ + tools/widl/typetree.h | 4 +++ + tools/widl/widltypes.h | 9 ++++++ + 9 files changed, 143 insertions(+), 6 deletions(-) + +diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl +index 5e17062f399..ab7c4753c3b 100644 +--- a/include/windows.foundation.idl ++++ b/include/windows.foundation.idl +@@ -111,5 +111,34 @@ namespace Windows { + { + HRESULT ToString([out, retval] HSTRING *value); + } ++ ++#ifdef __WIDL__ ++ namespace Collections ++ { ++ [ ++ contract(Windows.Foundation.FoundationContract, 1.0), ++ uuid(6a79e863-4300-459a-9966-cbb660963ee1) ++ ] ++ interface IIterator : IInspectable ++ { ++ [propget] HRESULT Current([out, retval] T *value); ++ [propget] HRESULT HasCurrent([out, retval] BOOL *value); ++ HRESULT MoveNext([out, retval] BOOL *value); ++ HRESULT GetMany([in] UINT32 count, [out] T *items, [out, retval] UINT32 *value); ++ } ++ ++ [ ++ contract(Windows.Foundation.FoundationContract, 1.0), ++ uuid(bbe1fa4c-b0e3-4583-baef-1f1b2e483e56) ++ ] ++ interface IVectorView : IInspectable ++ { ++ HRESULT GetAt([in] ULONG index, [out, retval] T *value); ++ [propget] HRESULT Size([out, retval] ULONG *value); ++ HRESULT IndexOf([in, optional] T element, [out] ULONG *index, [out, retval] BOOLEAN *value); ++ HRESULT GetMany([in] ULONG start_index, [out] T *items, [out, retval] ULONG *value); ++ } ++ } ++#endif + } + } +diff --git a/tools/widl/expr.c b/tools/widl/expr.c +index 13bd5a889aa..c83e9aa5ec0 100644 +--- a/tools/widl/expr.c ++++ b/tools/widl/expr.c +@@ -464,6 +464,8 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, + case TYPE_BITFIELD: + case TYPE_APICONTRACT: + case TYPE_RUNTIMECLASS: ++ case TYPE_PARAMETERIZED_TYPE: ++ case TYPE_PARAMETER: + /* nothing to do */ + break; + case TYPE_ALIAS: +diff --git a/tools/widl/header.c b/tools/widl/header.c +index 5c87a997349..283f2372fee 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -501,7 +501,9 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i + break; + } + case TYPE_APICONTRACT: +- /* handled elsewhere */ ++ case TYPE_PARAMETERIZED_TYPE: ++ case TYPE_PARAMETER: ++ /* handled elsewhere / shouldn't be here */ + assert(0); + break; + } +@@ -568,6 +570,8 @@ void write_type_right(FILE *h, type_t *t, int is_field) + case TYPE_RUNTIMECLASS: + break; + case TYPE_APICONTRACT: ++ case TYPE_PARAMETERIZED_TYPE: ++ case TYPE_PARAMETER: + /* not supposed to be here */ + assert(0); + break; +@@ -1969,10 +1973,8 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons + write_apicontract(header, stmt->u.type); + else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS) + write_runtimeclass(header, stmt->u.type); +- else +- { ++ else if (type_get_type(stmt->u.type) != TYPE_PARAMETERIZED_TYPE) + write_type_definition(header, stmt->u.type, stmt->declonly); +- } + break; + case STMT_TYPEREF: + /* FIXME: shouldn't write out forward declarations for undefined +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index d24f8881147..aa6ded5ba89 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -80,6 +80,8 @@ static var_t *reg_const(var_t *var); + static void push_namespace(const char *name); + static void pop_namespace(const char *name); + static void push_lookup_namespace(const char *name); ++static void push_parameters_namespace(const char *name); ++static void pop_parameters_namespace(const char *name); + + static void check_arg_attrs(const var_t *arg); + static void check_statements(const statement_list_t *stmts, int is_inside_library); +@@ -125,6 +127,7 @@ static struct namespace global_namespace = { + + static struct namespace *current_namespace = &global_namespace; + static struct namespace *lookup_namespace = &global_namespace; ++static struct namespace *parameters_namespace = NULL; + + static typelib_t *current_typelib; + +@@ -295,6 +298,8 @@ static typelib_t *current_typelib; + %type base_type int_std + %type enumdef structdef uniondef typedecl + %type type qualified_type ++%type type_parameter ++%type type_parameters + %type requires required_types + %type class_interface + %type class_interfaces +@@ -1010,6 +1015,15 @@ interfacehdr: attributes interface { $$ = $2; + } + ; + ++type_parameter: aIDENTIFIER { $$ = get_type(TYPE_PARAMETER, $1, parameters_namespace, 0); } ++ | aKNOWNTYPE { $$ = get_type(TYPE_PARAMETER, $1, parameters_namespace, 0); } ++ ; ++ ++type_parameters: ++ type_parameter { $$ = append_type(NULL, $1); } ++ | type_parameters ',' type_parameter { $$ = append_type($1, $3); } ++ ; ++ + required_types: + qualified_type { $$ = append_type(NULL, $1); } + | required_types ',' required_types { $$ = append_types($1, $3); } +@@ -1025,6 +1039,13 @@ interfacedef: interfacehdr inherit requires + type_interface_define($$, $2, $5, $3); + check_async_uuid($$); + } ++ | interfacehdr '<' { push_parameters_namespace($1->name); } type_parameters '>' inherit ++ '{' int_statements '}' semicolon_opt { $$ = $1; ++ if($$ == $6) error_loc("Interface can't inherit from itself\n"); ++ type_parameterized_interface_define($$, $4, $6, $8); ++ check_async_uuid($$); ++ pop_parameters_namespace($1->name); ++ } + /* MIDL is able to import the definition of a base class from inside the + * definition of a derived class, I'll try to support it with this rule */ + | interfacehdr ':' aIDENTIFIER requires +@@ -1037,6 +1058,11 @@ interfacedef: interfacehdr inherit requires + + interfacedec: + interface ';' { $$ = $1; } ++ | interface '<' { push_parameters_namespace($1->name); } type_parameters '>' ';' ++ { $$ = $1; ++ type_parameterized_interface_declare($$, $4); ++ pop_parameters_namespace($1->name); ++ } + | dispinterface ';' { $$ = $1; } + ; + +@@ -1979,6 +2005,29 @@ static void push_lookup_namespace(const char *name) + lookup_namespace = namespace; + } + ++static void push_parameters_namespace(const char *name) ++{ ++ struct namespace *namespace; ++ ++ if (!(namespace = find_sub_namespace(current_namespace, name))) ++ { ++ namespace = xmalloc(sizeof(*namespace)); ++ namespace->name = xstrdup(name); ++ namespace->parent = current_namespace; ++ list_add_tail(¤t_namespace->children, &namespace->entry); ++ list_init(&namespace->children); ++ memset(namespace->type_hash, 0, sizeof(namespace->type_hash)); ++ } ++ ++ parameters_namespace = namespace; ++} ++ ++static void pop_parameters_namespace(const char *name) ++{ ++ assert(!strcmp(parameters_namespace->name, name) && parameters_namespace->parent); ++ parameters_namespace = NULL; ++} ++ + struct rtype { + const char *name; + type_t *type; +@@ -2110,7 +2159,8 @@ static type_t *find_qualified_type_or_error(const char *name, int t) + static type_t *find_type_or_error(const char *name, int t) + { + type_t *type; +- if (!(type = find_type(name, current_namespace, t))) ++ if (!(type = find_type(name, current_namespace, t)) && ++ !(type = find_type(name, parameters_namespace, t))) + { + error_loc("type '%s' not found\n", name); + return NULL; +@@ -2130,7 +2180,8 @@ int is_type(const char *name) + if (lookup_namespace != &global_namespace) + return find_type(name, lookup_namespace, 0) != NULL; + else +- return find_type(name, current_namespace, 0) != NULL; ++ return find_type(name, current_namespace, 0) != NULL || ++ find_type(name, parameters_namespace, 0) != NULL; + } + + int is_namespace(const char *name) +@@ -2623,6 +2674,8 @@ static int is_allowed_conf_type(const type_t *type) + case TYPE_RUNTIMECLASS: + return FALSE; + case TYPE_APICONTRACT: ++ case TYPE_PARAMETERIZED_TYPE: ++ case TYPE_PARAMETER: + /* not supposed to be here */ + assert(0); + break; +diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c +index 86c010aa6ae..f37b54eb65d 100644 +--- a/tools/widl/typegen.c ++++ b/tools/widl/typegen.c +@@ -377,6 +377,8 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att + case TYPE_RUNTIMECLASS: + break; + case TYPE_APICONTRACT: ++ case TYPE_PARAMETERIZED_TYPE: ++ case TYPE_PARAMETER: + /* not supposed to be here */ + assert(0); + break; +@@ -1974,6 +1976,8 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align) + case TYPE_BITFIELD: + case TYPE_APICONTRACT: + case TYPE_RUNTIMECLASS: ++ case TYPE_PARAMETERIZED_TYPE: ++ case TYPE_PARAMETER: + /* these types should not be encountered here due to language + * restrictions (interface, void, coclass, module), logical + * restrictions (alias - due to type_get_type call above) or +@@ -2077,6 +2081,8 @@ static unsigned int type_buffer_alignment(const type_t *t) + case TYPE_BITFIELD: + case TYPE_APICONTRACT: + case TYPE_RUNTIMECLASS: ++ case TYPE_PARAMETERIZED_TYPE: ++ case TYPE_PARAMETER: + /* these types should not be encountered here due to language + * restrictions (interface, void, coclass, module), logical + * restrictions (alias - due to type_get_type call above) or +diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c +index ace6424e3a0..6f6c5f3ccc8 100644 +--- a/tools/widl/typelib.c ++++ b/tools/widl/typelib.c +@@ -226,6 +226,8 @@ unsigned short get_type_vt(type_t *t) + + case TYPE_ALIAS: + case TYPE_APICONTRACT: ++ case TYPE_PARAMETERIZED_TYPE: ++ case TYPE_PARAMETER: + /* not supposed to be here */ + assert(0); + break; +diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c +index 3d26fd23b26..bbd519d98ab 100644 +--- a/tools/widl/typetree.c ++++ b/tools/widl/typetree.c +@@ -459,6 +459,36 @@ static unsigned int compute_method_indexes(type_t *iface) + return idx; + } + ++void type_parameterized_interface_declare(type_t *type, type_list_t *params) ++{ ++ type_t *iface = make_type(TYPE_INTERFACE); ++ type->type_type = TYPE_PARAMETERIZED_TYPE; ++ type->details.parameterized.type = iface; ++ type->details.parameterized.params = params; ++} ++ ++void type_parameterized_interface_define(type_t *type, type_list_t *params, type_t *inherit, statement_list_t *stmts) ++{ ++ type_t *iface; ++ ++ if (type->type_type != TYPE_PARAMETERIZED_TYPE) type_parameterized_interface_declare(type, params); ++ iface = type->details.parameterized.type; ++ ++ /* The parameterized type UUID is actually a PIID that is then used as a seed to generate ++ * a new type GUID with the rules described in: ++ * https://docs.microsoft.com/en-us/uwp/winrt-cref/winrt-type-system#parameterized-types ++ * FIXME: store type signatures for generated interfaces, and generate their GUIDs ++ */ ++ iface->details.iface = xmalloc(sizeof(*iface->details.iface)); ++ iface->details.iface->disp_props = NULL; ++ iface->details.iface->disp_methods = NULL; ++ iface->details.iface->stmts = stmts; ++ iface->details.iface->inherit = inherit; ++ iface->details.iface->disp_inherit = NULL; ++ iface->details.iface->async_iface = NULL; ++ iface->details.iface->requires = NULL; ++} ++ + void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts, type_list_t *requires) + { + iface->details.iface = xmalloc(sizeof(*iface->details.iface)); +diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h +index 8c555b91656..b04a67f6b47 100644 +--- a/tools/widl/typetree.h ++++ b/tools/widl/typetree.h +@@ -45,6 +45,8 @@ type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t + type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases); + type_t *type_new_bitfield(type_t *field_type, const expr_t *bits); + type_t *type_new_runtimeclass(char *name, struct namespace *namespace); ++void type_parameterized_interface_declare(type_t *type, type_list_t *params); ++void type_parameterized_interface_define(type_t *type, type_list_t *params, type_t *inherit, statement_list_t *stmts); + void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts, type_list_t *requires); + void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *methods); + void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface); +@@ -234,6 +236,8 @@ static inline int type_is_complete(const type_t *type) + case TYPE_RUNTIMECLASS: + return TRUE; + case TYPE_APICONTRACT: ++ case TYPE_PARAMETERIZED_TYPE: ++ case TYPE_PARAMETER: + assert(0); + break; + } +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index 7ca770b67ea..e2ffec6da8a 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -429,6 +429,12 @@ struct runtimeclass_details + ifref_list_t *ifaces; + }; + ++struct parameterized_details ++{ ++ type_t *type; ++ type_list_t *params; ++}; ++ + #define HASHMAX 64 + + struct namespace { +@@ -457,6 +463,8 @@ enum type_type + TYPE_BITFIELD, + TYPE_APICONTRACT, + TYPE_RUNTIMECLASS, ++ TYPE_PARAMETERIZED_TYPE, ++ TYPE_PARAMETER, + }; + + struct _type_t { +@@ -478,6 +486,7 @@ struct _type_t { + struct bitfield_details bitfield; + struct alias_details alias; + struct runtimeclass_details runtimeclass; ++ struct parameterized_details parameterized; + } details; + const char *c_name; + unsigned int typestring_offset; +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0021-widl-Support-partially-specialized-parameterized-typ.patch b/patches/widl-winrt-support/0021-widl-Support-partially-specialized-parameterized-typ.patch new file mode 100644 index 00000000..10019330 --- /dev/null +++ b/patches/widl-winrt-support/0021-widl-Support-partially-specialized-parameterized-typ.patch @@ -0,0 +1,203 @@ +From dfec9f64f5f1058ce394c8a39ae759ea027106a8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Mon, 12 Oct 2020 23:23:18 +0200 +Subject: [PATCH 21/28] widl: Support partially specialized parameterized type. + +This allows parameterized types to reference each other with a different +set of parameters. This is required for instance for IIterable, that +needs to reference IIterator. + +The partial specialization is recorded by adding a new parameterized +type, referencing the original one as its template. The parameterized +type chain will be resolved all at once when the type is declared. +--- + include/windows.foundation.idl | 9 +++++++++ + tools/widl/parser.y | 35 ++++++++++++++++++++++++++++++++++ + tools/widl/typetree.c | 32 +++++++++++++++++++++++++++++++ + tools/widl/typetree.h | 2 ++ + tools/widl/widltypes.h | 1 + + 5 files changed, 79 insertions(+) + +diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl +index ab7c4753c3b..5f7a49c38e4 100644 +--- a/include/windows.foundation.idl ++++ b/include/windows.foundation.idl +@@ -127,6 +127,15 @@ namespace Windows { + HRESULT GetMany([in] UINT32 count, [out] T *items, [out, retval] UINT32 *value); + } + ++ [ ++ contract(Windows.Foundation.FoundationContract, 1.0), ++ uuid(faa585ea-6214-4217-afda-7f46de5869b3) ++ ] ++ interface IIterable : IInspectable ++ { ++ HRESULT First([out, retval] Windows.Foundation.Collections.IIterator **value); ++ } ++ + [ + contract(Windows.Foundation.FoundationContract, 1.0), + uuid(bbe1fa4c-b0e3-4583-baef-1f1b2e483e56) +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index aa6ded5ba89..c9806ced633 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -300,6 +300,8 @@ static typelib_t *current_typelib; + %type type qualified_type + %type type_parameter + %type type_parameters ++%type parameterized_type ++%type parameterized_types + %type requires required_types + %type class_interface + %type class_interfaces +@@ -908,6 +910,20 @@ qualified_type: + | namespace_pfx aKNOWNTYPE { $$ = find_qualified_type_or_error($2, 0); } + ; + ++parameterized_type: qualified_type '<' parameterized_types '>' ++ { $$ = find_parameterized_type($1, $3, 0); } ++ ; ++ ++parameterized_types: ++ base_type { $$ = append_type(NULL, $1); } ++ | qualified_type { $$ = append_type(NULL, $1); } ++ | qualified_type '*' { $$ = append_type(NULL, type_new_pointer($1)); } ++ | parameterized_type { $$ = append_type(NULL, $1); } ++ | parameterized_type '*' { $$ = append_type(NULL, type_new_pointer($1)); } ++ | parameterized_types ',' parameterized_types ++ { $$ = append_types($1, $3); } ++ ; ++ + coclass: tCOCLASS aIDENTIFIER { $$ = type_new_coclass($2); } + | tCOCLASS aKNOWNTYPE { $$ = find_type($2, NULL, 0); + if (type_get_type_detect_alias($$) != TYPE_COCLASS) +@@ -1000,6 +1016,7 @@ dispinterfacedef: dispinterfacehdr '{' + + inherit: { $$ = NULL; } + | ':' qualified_type { $$ = $2; } ++ | ':' parameterized_type { $$ = $2; } + ; + + interface: tINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } +@@ -1026,6 +1043,7 @@ type_parameters: + + required_types: + qualified_type { $$ = append_type(NULL, $1); } ++ | parameterized_type { $$ = append_type(NULL, $1); } + | required_types ',' required_types { $$ = append_types($1, $3); } + + requires: { $$ = NULL; } +@@ -1247,6 +1265,7 @@ structdef: tSTRUCT t_ident '{' fields '}' { $$ = type_new_struct($2, current_nam + + type: tVOID { $$ = type_new_void(); } + | qualified_type { $$ = $1; } ++ | parameterized_type { $$ = $1; } + | base_type { $$ = $1; } + | enumdef { $$ = $1; } + | tENUM aIDENTIFIER { $$ = type_new_enum($2, current_namespace, FALSE, NULL); } +@@ -3324,3 +3343,19 @@ static void check_def(const type_t *t) + error_loc("%s: redefinition error; original definition was at %s:%d\n", + t->name, t->loc_info.input_name, t->loc_info.line_number); + } ++ ++type_t *find_parameterized_type(type_t *type, type_list_t *params, int t) ++{ ++ char *name = format_parameterized_type_name(type, params); ++ ++ if (parameters_namespace) ++ { ++ assert(type->type_type == TYPE_PARAMETERIZED_TYPE); ++ type = type_parameterized_type_specialize_partial(type, params); ++ } ++ /* FIXME: If not in another parameterized type, we'll have to look for the declared specialization. */ ++ else error_loc("parameterized type '%s' not declared\n", name); ++ ++ free(name); ++ return type; ++} +diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c +index bbd519d98ab..9d50cabf172 100644 +--- a/tools/widl/typetree.c ++++ b/tools/widl/typetree.c +@@ -112,6 +112,22 @@ static int format_namespace_buffer(char *buf, size_t len, struct namespace *name + return ret; + } + ++static int format_parameterized_type_name_buffer(char *buf, size_t len, type_t *type, type_list_t *params) ++{ ++ type_list_t *entry; ++ int ret = 0; ++ append_buf(snprintf, "%s<", type->name); ++ for (entry = params; entry; entry = entry->next) ++ { ++ for (type = entry->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {} ++ append_buf(format_namespace_buffer, type->namespace, "", "::", type->name, use_abi_namespace ? "ABI" : NULL); ++ for (type = entry->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) append_buf(snprintf, "*"); ++ if (entry->next) append_buf(snprintf, ","); ++ } ++ append_buf(snprintf, ">"); ++ return ret; ++} ++ + #undef append_buf + + char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix) +@@ -122,6 +138,14 @@ char *format_namespace(struct namespace *namespace, const char *prefix, const ch + return buf; + } + ++char *format_parameterized_type_name(type_t *type, type_list_t *params) ++{ ++ int len = format_parameterized_type_name_buffer(NULL, 0, type, params); ++ char *buf = xmalloc(len + 1); ++ format_parameterized_type_name_buffer(buf, len + 1, type, params); ++ return buf; ++} ++ + type_t *type_new_function(var_list_t *args) + { + var_t *arg; +@@ -459,6 +483,14 @@ static unsigned int compute_method_indexes(type_t *iface) + return idx; + } + ++type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *params) ++{ ++ type_t *new_type = duptype(type, 0); ++ new_type->details.parameterized.type = type; ++ new_type->details.parameterized.params = params; ++ return new_type; ++} ++ + void type_parameterized_interface_declare(type_t *type, type_list_t *params) + { + type_t *iface = make_type(TYPE_INTERFACE); +diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h +index b04a67f6b47..472fdf2d5fc 100644 +--- a/tools/widl/typetree.h ++++ b/tools/widl/typetree.h +@@ -45,6 +45,8 @@ type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t + type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases); + type_t *type_new_bitfield(type_t *field_type, const expr_t *bits); + type_t *type_new_runtimeclass(char *name, struct namespace *namespace); ++type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *params); ++type_t *find_parameterized_type(type_t *type, type_list_t *params, int t); + void type_parameterized_interface_declare(type_t *type, type_list_t *params); + void type_parameterized_interface_define(type_t *type, type_list_t *params, type_t *inherit, statement_list_t *stmts); + void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts, type_list_t *requires); +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index e2ffec6da8a..9863c4f72ff 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -643,6 +643,7 @@ void init_loc_info(loc_info_t *); + + char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, + const char *abi_prefix); ++char *format_parameterized_type_name(type_t *type, type_list_t *params); + + static inline enum type_type type_get_type_detect_alias(const type_t *type) + { +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0022-widl-Support-WinRT-parameterized-interface-type.patch b/patches/widl-winrt-support/0022-widl-Support-WinRT-parameterized-interface-type.patch new file mode 100644 index 00000000..83cabefe --- /dev/null +++ b/patches/widl-winrt-support/0022-widl-Support-WinRT-parameterized-interface-type.patch @@ -0,0 +1,542 @@ +From dfbafe5f504cc35003199e63716c9ce5c6a5729e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Mon, 12 Oct 2020 17:38:53 +0200 +Subject: [PATCH 22/28] widl: Support WinRT parameterized interface type. + +This allows parameterized interfaces to be instanciated in declare +blocks, in the same way MIDL does, generating a new interface to the +header from the parameterized type template, replacing its parameters +with the given types. +--- + include/windows.media.speechsynthesis.idl | 23 ++ + tools/widl/header.c | 7 +- + tools/widl/parser.l | 1 + + tools/widl/parser.y | 63 +++++- + tools/widl/typetree.c | 243 ++++++++++++++++++++++ + tools/widl/typetree.h | 2 + + 6 files changed, 334 insertions(+), 5 deletions(-) + +diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl +index 89fe616b9b3..40c45c82051 100644 +--- a/include/windows.media.speechsynthesis.idl ++++ b/include/windows.media.speechsynthesis.idl +@@ -35,6 +35,18 @@ namespace Windows { + } + } + ++namespace Windows { ++ namespace Media { ++ namespace SpeechSynthesis { ++ declare { ++ interface Windows.Foundation.Collections.IIterator; ++ interface Windows.Foundation.Collections.IIterable; ++ interface Windows.Foundation.Collections.IVectorView; ++ } ++ } ++ } ++} ++ + namespace Windows { + namespace Media { + namespace SpeechSynthesis { +@@ -59,6 +71,17 @@ namespace Windows { + [propget] HRESULT Gender([out] [retval] VoiceGender* value); + } + ++ [ ++ contract(Windows.Foundation.UniversalApiContract, 1.0), ++ exclusiveto(Windows.Media.SpeechSynthesis.SpeechSynthesizer), ++ uuid(7d526ecc-7533-4c3f-85be-888c2baeebdc) ++ ] ++ interface IInstalledVoicesStatic : IInspectable ++ { ++ [propget] HRESULT AllVoices([out, retval] Windows.Foundation.Collections.IVectorView** value); ++ [propget] HRESULT DefaultVoice([out, retval] VoiceInformation** value); ++ } ++ + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile) +diff --git a/tools/widl/header.c b/tools/widl/header.c +index 283f2372fee..db83f3aac13 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -1492,7 +1492,8 @@ static void write_forward(FILE *header, type_t *iface) + fprintf(header, "typedef interface %s %s;\n", iface->c_name, iface->c_name); + fprintf(header, "#ifdef __cplusplus\n"); + write_namespace_start(header, iface->namespace); +- write_line(header, 0, "interface %s;", iface->name); ++ if (strchr(iface->name, '<')) write_line(header, 0, "template<> struct %s;", iface->name); ++ else write_line(header, 0, "interface %s;", iface->name); + write_namespace_end(header, iface->namespace); + fprintf(header, "#endif /* __cplusplus */\n"); + fprintf(header, "#endif\n\n" ); +@@ -1655,11 +1656,13 @@ static void write_com_interface_end(FILE *header, type_t *iface) + write_namespace_start(header, iface->namespace); + } + if (uuid) { ++ if (strchr(iface->name, '<')) write_line(header, 0, "template<>"); + write_line(header, 0, "MIDL_INTERFACE(\"%s\")", uuid_string(uuid)); + indent(header, 0); + }else { + indent(header, 0); +- fprintf(header, "interface "); ++ if (strchr(iface->name, '<')) fprintf(header, "template<> struct "); ++ else fprintf(header, "interface "); + } + if (type_iface_get_inherit(iface)) + { +diff --git a/tools/widl/parser.l b/tools/widl/parser.l +index a47c490ec4c..b7f8844c7a9 100644 +--- a/tools/widl/parser.l ++++ b/tools/widl/parser.l +@@ -276,6 +276,7 @@ static const struct keyword keywords[] = { + {"coclass", tCOCLASS, 0}, + {"const", tCONST, 0}, + {"cpp_quote", tCPPQUOTE, 0}, ++ {"declare", tDECLARE, 1}, + {"default", tDEFAULT, 0}, + {"dispinterface", tDISPINTERFACE, 0}, + {"double", tDOUBLE, 0}, +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index c9806ced633..2fb73a46dc1 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -83,6 +83,7 @@ static void push_lookup_namespace(const char *name); + static void push_parameters_namespace(const char *name); + static void pop_parameters_namespace(const char *name); + ++static statement_list_t *append_parameterized_type_stmts(statement_list_t *stmts); + static void check_arg_attrs(const var_t *arg); + static void check_statements(const statement_list_t *stmts, int is_inside_library); + static void check_all_user_types(const statement_list_t *stmts); +@@ -117,6 +118,7 @@ static statement_t *make_statement_importlib(const char *str); + static statement_t *make_statement_module(type_t *type); + static statement_t *make_statement_typedef(var_list_t *names, int declonly); + static statement_t *make_statement_import(const char *str); ++static statement_t *make_statement_parameterized_type(type_t *type, type_list_t *params); + static statement_list_t *append_statement(statement_list_t *list, statement_t *stmt); + static statement_list_t *append_statements(statement_list_t *, statement_list_t *); + static attr_list_t *append_attribs(attr_list_t *, attr_list_t *); +@@ -128,6 +130,7 @@ static struct namespace global_namespace = { + static struct namespace *current_namespace = &global_namespace; + static struct namespace *lookup_namespace = &global_namespace; + static struct namespace *parameters_namespace = NULL; ++static statement_list_t *parameterized_type_stmts = NULL; + + static typelib_t *current_typelib; + +@@ -188,6 +191,7 @@ static typelib_t *current_typelib; + %token tCONTRACT + %token tCONTRACTVERSION + %token tCONTROL tCPPQUOTE ++%token tDECLARE + %token tDECODE tDEFAULT tDEFAULTBIND + %token tDEFAULTCOLLELEM + %token tDEFAULTVALUE +@@ -325,6 +329,8 @@ static typelib_t *current_typelib; + %type library_start librarydef + %type statement typedef pragma_warning + %type gbl_statements imp_statements int_statements ++%type decl_block decl_statements ++%type imp_decl_block imp_decl_statements + %type warnings + + %left ',' +@@ -346,7 +352,8 @@ static typelib_t *current_typelib; + + %% + +-input: gbl_statements m_acf { check_statements($1, FALSE); ++input: gbl_statements m_acf { $1 = append_parameterized_type_stmts($1); ++ check_statements($1, FALSE); + check_all_user_types($1); + write_header($1); + write_id_data($1); +@@ -362,6 +369,22 @@ input: gbl_statements m_acf { check_statements($1, FALSE); + + m_acf: /* empty */ | aACF acf_statements + ++decl_statements: { $$ = NULL; } ++ | decl_statements tINTERFACE qualified_type '<' parameterized_types '>' ';' ++ { parameterized_type_stmts = append_statement(parameterized_type_stmts, make_statement_parameterized_type($3, $5)); ++ $$ = append_statement($1, make_statement_reference(type_parameterized_type_specialize_declare($3, $5))); ++ } ++ ; ++ ++decl_block: tDECLARE '{' decl_statements '}' { $$ = $3; } ++ ++imp_decl_statements: { $$ = NULL; } ++ | imp_decl_statements tINTERFACE qualified_type '<' parameterized_types '>' ';' ++ { $$ = append_statement($1, make_statement_reference(type_parameterized_type_specialize_declare($3, $5))); } ++ ; ++ ++imp_decl_block: tDECLARE '{' imp_decl_statements '}' { $$ = $3; } ++ + gbl_statements: { $$ = NULL; } + | gbl_statements namespacedef '{' { push_namespace($2); } gbl_statements '}' + { pop_namespace($2); $$ = append_statements($1, $5); } +@@ -381,6 +404,7 @@ gbl_statements: { $$ = NULL; } + | gbl_statements moduledef { $$ = append_statement($1, make_statement_module($2)); } + | gbl_statements librarydef { $$ = append_statement($1, make_statement_library($2)); } + | gbl_statements statement { $$ = append_statement($1, $2); } ++ | gbl_statements decl_block { $$ = append_statements($1, $2); } + ; + + imp_statements: { $$ = NULL; } +@@ -401,6 +425,7 @@ imp_statements: { $$ = NULL; } + | imp_statements statement { $$ = append_statement($1, $2); } + | imp_statements importlib { $$ = append_statement($1, make_statement_importlib($2)); } + | imp_statements librarydef { $$ = append_statement($1, make_statement_library($2)); } ++ | imp_statements imp_decl_block { $$ = append_statements($1, $2); } + ; + + int_statements: { $$ = NULL; } +@@ -3121,6 +3146,27 @@ static void check_async_uuid(type_t *iface) + iface->details.iface->async_iface = async_iface->details.iface->async_iface = async_iface; + } + ++static statement_list_t *append_parameterized_type_stmts(statement_list_t *stmts) ++{ ++ statement_t *stmt, *next; ++ if (stmts && parameterized_type_stmts) LIST_FOR_EACH_ENTRY_SAFE(stmt, next, parameterized_type_stmts, statement_t, entry) ++ { ++ switch(stmt->type) { ++ case STMT_TYPE: ++ stmt->u.type = type_parameterized_type_specialize_define(stmt->u.type_list->type, stmt->u.type_list->next); ++ stmt->declonly = FALSE; ++ list_remove(&stmt->entry); ++ stmts = append_statement(stmts, stmt); ++ break; ++ default: ++ assert(0); /* should not be there */ ++ break; ++ } ++ } ++ ++ return stmts; ++} ++ + static void check_statements(const statement_list_t *stmts, int is_inside_library) + { + const statement_t *stmt; +@@ -3302,6 +3348,15 @@ static statement_t *make_statement_typedef(declarator_list_t *decls, int declonl + return stmt; + } + ++static statement_t *make_statement_parameterized_type(type_t *type, type_list_t *params) ++{ ++ statement_t *stmt = make_statement(STMT_TYPE); ++ stmt->u.type_list = xmalloc(sizeof(type_list_t)); ++ stmt->u.type_list->type = type; ++ stmt->u.type_list->next = params; ++ return stmt; ++} ++ + static statement_list_t *append_statements(statement_list_t *l1, statement_list_t *l2) + { + if (!l2) return l1; +@@ -3353,8 +3408,10 @@ type_t *find_parameterized_type(type_t *type, type_list_t *params, int t) + assert(type->type_type == TYPE_PARAMETERIZED_TYPE); + type = type_parameterized_type_specialize_partial(type, params); + } +- /* FIXME: If not in another parameterized type, we'll have to look for the declared specialization. */ +- else error_loc("parameterized type '%s' not declared\n", name); ++ else if ((type = find_type(name, type->namespace, t))) ++ assert(type->type_type != TYPE_PARAMETERIZED_TYPE); ++ else ++ error_loc("parameterized type '%s' not declared\n", name); + + free(name); + return type; +diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c +index 9d50cabf172..8f1e2d71aff 100644 +--- a/tools/widl/typetree.c ++++ b/tools/widl/typetree.c +@@ -128,6 +128,21 @@ static int format_parameterized_type_name_buffer(char *buf, size_t len, type_t * + return ret; + } + ++static int format_parameterized_type_c_name_buffer(char *buf, size_t len, type_t *type, type_list_t *params) ++{ ++ type_list_t *entry; ++ int ret = 0, count = 0; ++ append_buf(format_namespace_buffer, type->namespace, "__x_", "_C", type->name, use_abi_namespace ? "ABI" : NULL); ++ for (entry = params; entry; entry = entry->next) count++; ++ append_buf(snprintf, "_%d", count); ++ for (entry = params; entry; entry = entry->next) ++ { ++ for (type = entry->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {} ++ append_buf(format_namespace_buffer, type->namespace, "_", "__C", type->name, NULL); ++ } ++ return ret; ++} ++ + #undef append_buf + + char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix) +@@ -146,6 +161,31 @@ char *format_parameterized_type_name(type_t *type, type_list_t *params) + return buf; + } + ++static char const *parameterized_type_shorthands[][2] = { ++ {"Windows_CFoundation_CCollections_C", "__F"}, ++ {"Windows_CFoundation_C", "__F"}, ++}; ++ ++static char *format_parameterized_type_c_name(type_t *type, type_list_t *params) ++{ ++ int i, len = format_parameterized_type_c_name_buffer(NULL, 0, type, params); ++ char *buf = xmalloc(len + 1), *tmp; ++ format_parameterized_type_c_name_buffer(buf, len + 1, type, params); ++ ++ for (i = 0; i < ARRAY_SIZE(parameterized_type_shorthands); ++i) ++ { ++ if ((tmp = strstr(buf, parameterized_type_shorthands[i][0])) && ++ (tmp - buf) == strlen(use_abi_namespace ? "__x_ABI_C" : "__x_C")) ++ { ++ tmp += strlen(parameterized_type_shorthands[i][0]); ++ strcpy(buf, parameterized_type_shorthands[i][1]); ++ memmove(buf + 3, tmp, len - (tmp - buf) + 1); ++ } ++ } ++ ++ return buf; ++} ++ + type_t *type_new_function(var_list_t *args) + { + var_t *arg; +@@ -483,6 +523,177 @@ static unsigned int compute_method_indexes(type_t *iface) + return idx; + } + ++static type_t *replace_type_parameters_in_type(type_t *type, type_list_t *orig, type_list_t *repl); ++ ++static type_list_t *replace_type_parameters_in_type_list(type_list_t *type_list, type_list_t *orig, type_list_t *repl) ++{ ++ type_list_t *entry, *new_entry, **next, *first = NULL; ++ ++ if (!type_list) return type_list; ++ ++ next = &first; ++ for (entry = type_list; entry; entry = entry->next) ++ { ++ new_entry = xmalloc(sizeof(*new_entry)); ++ new_entry->type = replace_type_parameters_in_type(entry->type, orig, repl); ++ new_entry->next = NULL; ++ *next = new_entry; ++ next = &new_entry->next; ++ } ++ ++ return first; ++} ++ ++static var_t *replace_type_parameters_in_var(var_t *var, type_list_t *orig, type_list_t *repl) ++{ ++ var_t *new_var = xmalloc(sizeof(*new_var)); ++ *new_var = *var; ++ list_init(&new_var->entry); ++ new_var->declspec.type = replace_type_parameters_in_type(var->declspec.type, orig, repl); ++ return new_var; ++} ++ ++static var_list_t *replace_type_parameters_in_var_list(var_list_t *var_list, type_list_t *orig, type_list_t *repl) ++{ ++ var_list_t *new_var_list; ++ var_t *var, *new_var; ++ ++ if (!var_list) return var_list; ++ ++ new_var_list = xmalloc(sizeof(*new_var_list)); ++ list_init(new_var_list); ++ ++ LIST_FOR_EACH_ENTRY(var, var_list, var_t, entry) ++ { ++ new_var = replace_type_parameters_in_var(var, orig, repl); ++ list_add_tail(new_var_list, &new_var->entry); ++ } ++ ++ return new_var_list; ++} ++ ++static statement_t *replace_type_parameters_in_statement(statement_t *stmt, type_list_t *orig, type_list_t *repl) ++{ ++ statement_t *new_stmt = xmalloc(sizeof(*new_stmt)); ++ *new_stmt = *stmt; ++ list_init(&new_stmt->entry); ++ ++ switch (stmt->type) ++ { ++ case STMT_DECLARATION: ++ new_stmt->u.var = replace_type_parameters_in_var(stmt->u.var, orig, repl); ++ break; ++ case STMT_LIBRARY: ++ case STMT_TYPE: ++ case STMT_TYPEREF: ++ case STMT_MODULE: ++ case STMT_TYPEDEF: ++ new_stmt->u.type_list = replace_type_parameters_in_type_list(stmt->u.type_list, orig, repl); ++ break; ++ case STMT_IMPORT: ++ case STMT_IMPORTLIB: ++ case STMT_PRAGMA: ++ case STMT_CPPQUOTE: ++ fprintf(stderr, "%d\n", stmt->type); ++ assert(0); ++ break; ++ } ++ ++ return new_stmt; ++} ++ ++static statement_list_t *replace_type_parameters_in_statement_list(statement_list_t *stmt_list, type_list_t *orig, type_list_t *repl) ++{ ++ statement_list_t *new_stmt_list; ++ statement_t *stmt, *new_stmt; ++ ++ if (!stmt_list) return stmt_list; ++ ++ new_stmt_list = xmalloc(sizeof(*new_stmt_list)); ++ list_init(new_stmt_list); ++ ++ LIST_FOR_EACH_ENTRY(stmt, stmt_list, statement_t, entry) ++ { ++ new_stmt = replace_type_parameters_in_statement(stmt, orig, repl); ++ list_add_tail(new_stmt_list, &new_stmt->entry); ++ } ++ ++ return new_stmt_list; ++} ++ ++static type_t *replace_type_parameters_in_type(type_t *type, type_list_t *orig, type_list_t *repl) ++{ ++ type_list_t *o, *r; ++ type_t *t; ++ ++ if (!type) return type; ++ switch (type->type_type) ++ { ++ case TYPE_VOID: ++ case TYPE_BASIC: ++ case TYPE_ENUM: ++ case TYPE_BITFIELD: ++ case TYPE_INTERFACE: ++ case TYPE_RUNTIMECLASS: ++ return type; ++ case TYPE_PARAMETER: ++ for (o = orig, r = repl; o && r; o = o->next, r = r->next) ++ if (type == o->type) return r->type; ++ return type; ++ case TYPE_POINTER: ++ t = replace_type_parameters_in_type(type->details.pointer.ref.type, orig, repl); ++ if (t == type->details.pointer.ref.type) return type; ++ type = duptype(type, 0); ++ type->details.pointer.ref.type = t; ++ return type; ++ case TYPE_ALIAS: ++ t = replace_type_parameters_in_type(type->details.alias.aliasee.type, orig, repl); ++ if (t == type->details.alias.aliasee.type) return type; ++ type = duptype(type, 0); ++ type->details.alias.aliasee.type = t; ++ return type; ++ case TYPE_ARRAY: ++ t = replace_type_parameters_in_type(type->details.array.elem.type, orig, repl); ++ if (t == t->details.array.elem.type) return type; ++ type = duptype(type, 0); ++ t->details.array.elem.type = t; ++ return type; ++ case TYPE_FUNCTION: ++ t = duptype(type, 0); ++ t->details.function = xmalloc(sizeof(*t->details.function)); ++ t->details.function->args = replace_type_parameters_in_var_list(type->details.function->args, orig, repl); ++ t->details.function->retval = replace_type_parameters_in_var(type->details.function->retval, orig, repl); ++ return t; ++ case TYPE_PARAMETERIZED_TYPE: ++ t = type->details.parameterized.type; ++ if (t->type_type != TYPE_PARAMETERIZED_TYPE) return find_parameterized_type(type, repl, 0); ++ repl = replace_type_parameters_in_type_list(type->details.parameterized.params, orig, repl); ++ return replace_type_parameters_in_type(t, t->details.parameterized.params, repl); ++ case TYPE_STRUCT: ++ case TYPE_ENCAPSULATED_UNION: ++ case TYPE_UNION: ++ case TYPE_MODULE: ++ case TYPE_COCLASS: ++ case TYPE_APICONTRACT: ++ assert(0); /* FIXME: implement when needed */ ++ break; ++ } ++ ++ return type; ++} ++ ++static void type_parameterized_interface_specialize(type_t *tmpl, type_t *iface, type_list_t *orig, type_list_t *repl) ++{ ++ iface->details.iface = xmalloc(sizeof(*iface->details.iface)); ++ iface->details.iface->disp_methods = NULL; ++ iface->details.iface->disp_props = NULL; ++ iface->details.iface->stmts = replace_type_parameters_in_statement_list(tmpl->details.iface->stmts, orig, repl); ++ iface->details.iface->inherit = replace_type_parameters_in_type(tmpl->details.iface->inherit, orig, repl); ++ iface->details.iface->disp_inherit = NULL; ++ iface->details.iface->async_iface = NULL; ++ iface->details.iface->requires = NULL; ++} ++ + type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *params) + { + type_t *new_type = duptype(type, 0); +@@ -491,6 +702,38 @@ type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *pa + return new_type; + } + ++type_t *type_parameterized_type_specialize_declare(type_t *type, type_list_t *params) ++{ ++ type_t *tmpl = type->details.parameterized.type; ++ type_t *new_type = duptype(tmpl, 0); ++ ++ new_type->namespace = type->namespace; ++ new_type->name = format_parameterized_type_name(type, params); ++ reg_type(new_type, new_type->name, new_type->namespace, 0); ++ new_type->c_name = format_parameterized_type_c_name(type, params); ++ ++ return new_type; ++} ++ ++type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *params) ++{ ++ type_list_t *orig = type->details.parameterized.params; ++ type_t *tmpl = type->details.parameterized.type; ++ type_t *iface = find_parameterized_type(type, params, 0); ++ ++ if (tmpl->type_type == TYPE_INTERFACE) ++ type_parameterized_interface_specialize(tmpl, iface, orig, params); ++ else ++ { ++ error_loc("Unsupported parameterized type template %d\n", tmpl->type_type); ++ return NULL; ++ } ++ ++ iface->defined = TRUE; ++ compute_method_indexes(iface); ++ return iface; ++} ++ + void type_parameterized_interface_declare(type_t *type, type_list_t *params) + { + type_t *iface = make_type(TYPE_INTERFACE); +diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h +index 472fdf2d5fc..e1a52d21d09 100644 +--- a/tools/widl/typetree.h ++++ b/tools/widl/typetree.h +@@ -46,6 +46,8 @@ type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *unio + type_t *type_new_bitfield(type_t *field_type, const expr_t *bits); + type_t *type_new_runtimeclass(char *name, struct namespace *namespace); + type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *params); ++type_t *type_parameterized_type_specialize_declare(type_t *type, type_list_t *params); ++type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *params); + type_t *find_parameterized_type(type_t *type, type_list_t *params, int t); + void type_parameterized_interface_declare(type_t *type, type_list_t *params); + void type_parameterized_interface_define(type_t *type, type_list_t *params, type_t *inherit, statement_list_t *stmts); +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0023-widl-Support-WinRT-delegate-type.patch b/patches/widl-winrt-support/0023-widl-Support-WinRT-delegate-type.patch new file mode 100644 index 00000000..fe92a3e1 --- /dev/null +++ b/patches/widl-winrt-support/0023-widl-Support-WinRT-delegate-type.patch @@ -0,0 +1,346 @@ +From 82c354b2275a33863181fc7660f8e63db51c131a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Thu, 24 Sep 2020 00:00:54 +0200 +Subject: [PATCH 23/28] widl: Support WinRT delegate type. + +--- + tools/widl/expr.c | 1 + + tools/widl/header.c | 14 ++++++++++---- + tools/widl/parser.l | 1 + + tools/widl/parser.y | 25 +++++++++++++++++++++++++ + tools/widl/typegen.c | 4 ++++ + tools/widl/typelib.c | 1 + + tools/widl/typetree.c | 29 +++++++++++++++++++++++++++++ + tools/widl/typetree.h | 9 +++++++++ + tools/widl/widltypes.h | 7 +++++++ + 9 files changed, 87 insertions(+), 4 deletions(-) + +diff --git a/tools/widl/expr.c b/tools/widl/expr.c +index c83e9aa5ec0..88d59290d6b 100644 +--- a/tools/widl/expr.c ++++ b/tools/widl/expr.c +@@ -466,6 +466,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, + case TYPE_RUNTIMECLASS: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: ++ case TYPE_DELEGATE: + /* nothing to do */ + break; + case TYPE_ALIAS: +diff --git a/tools/widl/header.c b/tools/widl/header.c +index db83f3aac13..64faf89c36a 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -483,6 +483,9 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i + case TYPE_RUNTIMECLASS: + fprintf(h, "%s", type_get_name(type_runtimeclass_get_default_iface(t), name_type)); + break; ++ case TYPE_DELEGATE: ++ fprintf(h, "%s", type_get_name(type_delegate_get_iface(t), name_type)); ++ break; + case TYPE_VOID: + fprintf(h, "void"); + break; +@@ -568,6 +571,7 @@ void write_type_right(FILE *h, type_t *t, int is_field) + case TYPE_COCLASS: + case TYPE_INTERFACE: + case TYPE_RUNTIMECLASS: ++ case TYPE_DELEGATE: + break; + case TYPE_APICONTRACT: + case TYPE_PARAMETERIZED_TYPE: +@@ -1904,9 +1908,10 @@ static void write_forward_decls(FILE *header, const statement_list_t *stmts) + switch (stmt->type) + { + case STMT_TYPE: +- if (type_get_type(stmt->u.type) == TYPE_INTERFACE) ++ if (type_get_type(stmt->u.type) == TYPE_INTERFACE || type_get_type(stmt->u.type) == TYPE_DELEGATE) + { + type_t *iface = stmt->u.type; ++ if (type_get_type(iface) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface); + if (is_object(iface) || is_attr(iface->attrs, ATTR_DISPINTERFACE)) + { + write_forward(header, iface); +@@ -1946,10 +1951,11 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons + switch (stmt->type) + { + case STMT_TYPE: +- if (type_get_type(stmt->u.type) == TYPE_INTERFACE) ++ if (type_get_type(stmt->u.type) == TYPE_INTERFACE || type_get_type(stmt->u.type) == TYPE_DELEGATE) + { +- type_t *iface = stmt->u.type; +- type_t *async_iface = type_iface_get_async_iface(iface); ++ type_t *iface = stmt->u.type, *async_iface; ++ if (type_get_type(stmt->u.type) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface); ++ async_iface = type_iface_get_async_iface(iface); + if (is_object(iface)) is_object_interface++; + if (is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE) || is_object(stmt->u.type)) + { +diff --git a/tools/widl/parser.l b/tools/widl/parser.l +index b7f8844c7a9..5de85e43a94 100644 +--- a/tools/widl/parser.l ++++ b/tools/widl/parser.l +@@ -278,6 +278,7 @@ static const struct keyword keywords[] = { + {"cpp_quote", tCPPQUOTE, 0}, + {"declare", tDECLARE, 1}, + {"default", tDEFAULT, 0}, ++ {"delegate", tDELEGATE, 1}, + {"dispinterface", tDISPINTERFACE, 0}, + {"double", tDOUBLE, 0}, + {"enum", tENUM, 0}, +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index 2fb73a46dc1..d0166eb3af2 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -119,6 +119,7 @@ static statement_t *make_statement_module(type_t *type); + static statement_t *make_statement_typedef(var_list_t *names, int declonly); + static statement_t *make_statement_import(const char *str); + static statement_t *make_statement_parameterized_type(type_t *type, type_list_t *params); ++static statement_t *make_statement_delegate(type_t *ret, var_list_t *args); + static statement_list_t *append_statement(statement_list_t *list, statement_t *stmt); + static statement_list_t *append_statements(statement_list_t *, statement_list_t *); + static attr_list_t *append_attribs(attr_list_t *, attr_list_t *); +@@ -193,6 +194,7 @@ static typelib_t *current_typelib; + %token tCONTROL tCPPQUOTE + %token tDECLARE + %token tDECODE tDEFAULT tDEFAULTBIND ++%token tDELEGATE + %token tDEFAULTCOLLELEM + %token tDEFAULTVALUE + %token tDEFAULTVTABLE +@@ -291,6 +293,7 @@ static typelib_t *current_typelib; + %type contract_req + %type static_attr + %type interfacehdr ++%type delegatedef + %type storage_cls_spec + %type type_qualifier m_type_qual_list + %type function_specifier +@@ -390,6 +393,7 @@ gbl_statements: { $$ = NULL; } + { pop_namespace($2); $$ = append_statements($1, $5); } + | gbl_statements interfacedec { $$ = append_statement($1, make_statement_reference($2)); } + | gbl_statements interfacedef { $$ = append_statement($1, make_statement_type_decl($2)); } ++ | gbl_statements delegatedef { $$ = append_statement($1, make_statement_type_decl($2)); } + | gbl_statements coclass ';' { $$ = $1; + reg_type($2, $2->name, current_namespace, 0); + } +@@ -412,6 +416,7 @@ imp_statements: { $$ = NULL; } + | imp_statements namespacedef '{' { push_namespace($2); } imp_statements '}' + { pop_namespace($2); $$ = append_statements($1, $5); } + | imp_statements interfacedef { $$ = append_statement($1, make_statement_type_decl($2)); } ++ | imp_statements delegatedef { $$ = append_statement($1, make_statement_type_decl($2)); } + | imp_statements coclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); } + | imp_statements coclassdef { $$ = append_statement($1, make_statement_type_decl($2)); + reg_type($2, $2->name, current_namespace, 0); +@@ -1066,6 +1071,17 @@ type_parameters: + | type_parameters ',' type_parameter { $$ = append_type($1, $3); } + ; + ++delegatedef: ++ m_attributes tDELEGATE type ident '(' m_args ')' ++ semicolon_opt { $$ = get_type(TYPE_DELEGATE, $4->name, current_namespace, 0); ++ check_def($$); ++ $$->attrs = check_iface_attrs($$->name, $1); ++ $$->defined = TRUE; ++ type_delegate_define($$, append_statement(NULL, make_statement_delegate($3, $6))); ++ check_async_uuid($$); ++ } ++ ; ++ + required_types: + qualified_type { $$ = append_type(NULL, $1); } + | parameterized_type { $$ = append_type(NULL, $1); } +@@ -2716,6 +2732,7 @@ static int is_allowed_conf_type(const type_t *type) + case TYPE_INTERFACE: + case TYPE_BITFIELD: + case TYPE_RUNTIMECLASS: ++ case TYPE_DELEGATE: + return FALSE; + case TYPE_APICONTRACT: + case TYPE_PARAMETERIZED_TYPE: +@@ -3357,6 +3374,14 @@ static statement_t *make_statement_parameterized_type(type_t *type, type_list_t + return stmt; + } + ++static statement_t *make_statement_delegate(type_t *ret, var_list_t *args) ++{ ++ declarator_t *decl = make_declarator(make_var(xstrdup("Invoke"))); ++ decl_spec_t *spec = make_decl_spec(ret, NULL, NULL, STG_NONE, 0, 0); ++ append_chain_type(decl, type_new_function(args), 0); ++ return make_statement_declaration(declare_var(NULL, spec, decl, FALSE)); ++} ++ + static statement_list_t *append_statements(statement_list_t *l1, statement_list_t *l2) + { + if (!l2) return l1; +diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c +index f37b54eb65d..4557d24b3ff 100644 +--- a/tools/widl/typegen.c ++++ b/tools/widl/typegen.c +@@ -354,6 +354,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att + case TYPE_POINTER: + if (type_get_type(type_pointer_get_ref_type(type)) == TYPE_INTERFACE || + type_get_type(type_pointer_get_ref_type(type)) == TYPE_RUNTIMECLASS || ++ type_get_type(type_pointer_get_ref_type(type)) == TYPE_DELEGATE || + (type_get_type(type_pointer_get_ref_type(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS))) + return TGT_IFACE_POINTER; + else if (is_aliaschain_attr(type_pointer_get_ref_type(type), ATTR_CONTEXTHANDLE)) +@@ -375,6 +376,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att + case TYPE_ALIAS: + case TYPE_BITFIELD: + case TYPE_RUNTIMECLASS: ++ case TYPE_DELEGATE: + break; + case TYPE_APICONTRACT: + case TYPE_PARAMETERIZED_TYPE: +@@ -1978,6 +1980,7 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align) + case TYPE_RUNTIMECLASS: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: ++ case TYPE_DELEGATE: + /* these types should not be encountered here due to language + * restrictions (interface, void, coclass, module), logical + * restrictions (alias - due to type_get_type call above) or +@@ -2083,6 +2086,7 @@ static unsigned int type_buffer_alignment(const type_t *t) + case TYPE_RUNTIMECLASS: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: ++ case TYPE_DELEGATE: + /* these types should not be encountered here due to language + * restrictions (interface, void, coclass, module), logical + * restrictions (alias - due to type_get_type call above) or +diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c +index 6f6c5f3ccc8..8b2a2401367 100644 +--- a/tools/widl/typelib.c ++++ b/tools/widl/typelib.c +@@ -219,6 +219,7 @@ unsigned short get_type_vt(type_t *t) + case TYPE_UNION: + case TYPE_ENCAPSULATED_UNION: + case TYPE_RUNTIMECLASS: ++ case TYPE_DELEGATE: + return VT_USERDEFINED; + + case TYPE_VOID: +diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c +index 8f1e2d71aff..15629113cec 100644 +--- a/tools/widl/typetree.c ++++ b/tools/widl/typetree.c +@@ -523,6 +523,13 @@ static unsigned int compute_method_indexes(type_t *iface) + return idx; + } + ++static void compute_delegate_iface_name(type_t *delegate) ++{ ++ char *name = xmalloc(strlen(delegate->name) + 2); ++ sprintf(name, "I%s", delegate->name); ++ delegate->details.delegate.iface->name = name; ++} ++ + static type_t *replace_type_parameters_in_type(type_t *type, type_list_t *orig, type_list_t *repl); + + static type_list_t *replace_type_parameters_in_type_list(type_list_t *type_list, type_list_t *orig, type_list_t *repl) +@@ -635,6 +642,7 @@ static type_t *replace_type_parameters_in_type(type_t *type, type_list_t *orig, + case TYPE_BITFIELD: + case TYPE_INTERFACE: + case TYPE_RUNTIMECLASS: ++ case TYPE_DELEGATE: + return type; + case TYPE_PARAMETER: + for (o = orig, r = repl; o && r; o = o->next, r = r->next) +@@ -778,6 +786,27 @@ void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stm + compute_method_indexes(iface); + } + ++void type_delegate_define(type_t *delegate, statement_list_t *stmts) ++{ ++ type_t *iface = make_type(TYPE_INTERFACE); ++ ++ iface->namespace = delegate->namespace; ++ iface->details.iface = xmalloc(sizeof(*iface->details.iface)); ++ iface->details.iface->disp_props = NULL; ++ iface->details.iface->disp_methods = NULL; ++ iface->details.iface->stmts = stmts; ++ iface->details.iface->inherit = find_type("IUnknown", NULL, 0); ++ if (!iface->details.iface->inherit) error_loc("IUnknown is undefined\n"); ++ iface->details.iface->disp_inherit = NULL; ++ iface->details.iface->async_iface = NULL; ++ iface->details.iface->requires = NULL; ++ iface->defined = TRUE; ++ compute_method_indexes(iface); ++ ++ delegate->details.delegate.iface = iface; ++ compute_delegate_iface_name(delegate); ++} ++ + void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *methods) + { + iface->details.iface = xmalloc(sizeof(*iface->details.iface)); +diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h +index e1a52d21d09..de3db4e7c7e 100644 +--- a/tools/widl/typetree.h ++++ b/tools/widl/typetree.h +@@ -52,6 +52,7 @@ type_t *find_parameterized_type(type_t *type, type_list_t *params, int t); + void type_parameterized_interface_declare(type_t *type, type_list_t *params); + void type_parameterized_interface_define(type_t *type, type_list_t *params, type_t *inherit, statement_list_t *stmts); + void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts, type_list_t *requires); ++void type_delegate_define(type_t *iface, statement_list_t *stmts); + void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *methods); + void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface); + void type_module_define(type_t *module, statement_list_t *stmts); +@@ -238,6 +239,7 @@ static inline int type_is_complete(const type_t *type) + case TYPE_ARRAY: + case TYPE_BITFIELD: + case TYPE_RUNTIMECLASS: ++ case TYPE_DELEGATE: + return TRUE; + case TYPE_APICONTRACT: + case TYPE_PARAMETERIZED_TYPE: +@@ -361,6 +363,13 @@ static inline type_t *type_runtimeclass_get_default_iface(const type_t *type) + return NULL; + } + ++static inline type_t *type_delegate_get_iface(const type_t *type) ++{ ++ type = type_get_real_type(type); ++ assert(type_get_type(type) == TYPE_DELEGATE); ++ return type->details.delegate.iface; ++} ++ + static inline const decl_spec_t *type_pointer_get_ref(const type_t *type) + { + type = type_get_real_type(type); +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index 9863c4f72ff..3938d0d5294 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -435,6 +435,11 @@ struct parameterized_details + type_list_t *params; + }; + ++struct delegate_details ++{ ++ type_t *iface; ++}; ++ + #define HASHMAX 64 + + struct namespace { +@@ -465,6 +470,7 @@ enum type_type + TYPE_RUNTIMECLASS, + TYPE_PARAMETERIZED_TYPE, + TYPE_PARAMETER, ++ TYPE_DELEGATE, + }; + + struct _type_t { +@@ -487,6 +493,7 @@ struct _type_t { + struct alias_details alias; + struct runtimeclass_details runtimeclass; + struct parameterized_details parameterized; ++ struct delegate_details delegate; + } details; + const char *c_name; + unsigned int typestring_offset; +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0024-widl-Support-WinRT-parameterized-delegate-type.patch b/patches/widl-winrt-support/0024-widl-Support-WinRT-parameterized-delegate-type.patch new file mode 100644 index 00000000..5beb4b1d --- /dev/null +++ b/patches/widl-winrt-support/0024-widl-Support-WinRT-parameterized-delegate-type.patch @@ -0,0 +1,181 @@ +From f8fa58f5bdfac8adc9fba4af5ff294a11f48b556 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Mon, 28 Sep 2020 16:46:34 +0200 +Subject: [PATCH 24/28] widl: Support WinRT parameterized delegate type. + +--- + include/windows.foundation.idl | 6 ++++ + tools/widl/parser.y | 11 +++++++ + tools/widl/typetree.c | 56 +++++++++++++++++++++++++++++----- + tools/widl/typetree.h | 1 + + 4 files changed, 67 insertions(+), 7 deletions(-) + +diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl +index 5f7a49c38e4..9583fa5bcc8 100644 +--- a/include/windows.foundation.idl ++++ b/include/windows.foundation.idl +@@ -113,6 +113,12 @@ namespace Windows { + } + + #ifdef __WIDL__ ++ [ ++ contract(Windows.Foundation.FoundationContract, 1.0), ++ uuid(9de1c535-6ae1-11e0-84e1-18a905bcc53f) ++ ] ++ delegate void EventHandler([in] IInspectable *sender, [in] T args); ++ + namespace Collections + { + [ +diff --git a/tools/widl/parser.y b/tools/widl/parser.y +index d0166eb3af2..f7fb7a303a8 100644 +--- a/tools/widl/parser.y ++++ b/tools/widl/parser.y +@@ -1080,6 +1080,17 @@ delegatedef: + type_delegate_define($$, append_statement(NULL, make_statement_delegate($3, $6))); + check_async_uuid($$); + } ++ | m_attributes tDELEGATE type ident ++ '<' { push_parameters_namespace($4->name); } type_parameters '>' ++ '(' m_args ')' ++ semicolon_opt { $$ = get_type(TYPE_DELEGATE, $4->name, current_namespace, 0); ++ check_def($$); ++ $$->attrs = check_iface_attrs($$->name, $1); ++ $$->defined = TRUE; ++ type_parameterized_delegate_define($$, $7, append_statement(NULL, make_statement_delegate($3, $10))); ++ check_async_uuid($$); ++ pop_parameters_namespace($4->name); ++ } + ; + + required_types: +diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c +index 15629113cec..03778aa75c3 100644 +--- a/tools/widl/typetree.c ++++ b/tools/widl/typetree.c +@@ -128,13 +128,13 @@ static int format_parameterized_type_name_buffer(char *buf, size_t len, type_t * + return ret; + } + +-static int format_parameterized_type_c_name_buffer(char *buf, size_t len, type_t *type, type_list_t *params) ++static int format_parameterized_type_c_name_buffer(char *buf, size_t len, type_t *type, type_list_t *params, const char *prefix) + { + type_list_t *entry; + int ret = 0, count = 0; +- append_buf(format_namespace_buffer, type->namespace, "__x_", "_C", type->name, use_abi_namespace ? "ABI" : NULL); ++ append_buf(format_namespace_buffer, type->namespace, "__x_", "_C", "", use_abi_namespace ? "ABI" : NULL); + for (entry = params; entry; entry = entry->next) count++; +- append_buf(snprintf, "_%d", count); ++ append_buf(snprintf, "%s%s_%d", prefix, type->name, count); + for (entry = params; entry; entry = entry->next) + { + for (type = entry->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {} +@@ -166,11 +166,11 @@ static char const *parameterized_type_shorthands[][2] = { + {"Windows_CFoundation_C", "__F"}, + }; + +-static char *format_parameterized_type_c_name(type_t *type, type_list_t *params) ++static char *format_parameterized_type_c_name(type_t *type, type_list_t *params, const char *prefix) + { +- int i, len = format_parameterized_type_c_name_buffer(NULL, 0, type, params); ++ int i, len = format_parameterized_type_c_name_buffer(NULL, 0, type, params, prefix); + char *buf = xmalloc(len + 1), *tmp; +- format_parameterized_type_c_name_buffer(buf, len + 1, type, params); ++ format_parameterized_type_c_name_buffer(buf, len + 1, type, params, prefix); + + for (i = 0; i < ARRAY_SIZE(parameterized_type_shorthands); ++i) + { +@@ -702,6 +702,11 @@ static void type_parameterized_interface_specialize(type_t *tmpl, type_t *iface, + iface->details.iface->requires = NULL; + } + ++static void type_parameterized_delegate_specialize(type_t *tmpl, type_t *delegate, type_list_t *orig, type_list_t *repl) ++{ ++ type_parameterized_interface_specialize(tmpl->details.delegate.iface, delegate->details.delegate.iface, orig, repl); ++} ++ + type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *params) + { + type_t *new_type = duptype(type, 0); +@@ -718,7 +723,15 @@ type_t *type_parameterized_type_specialize_declare(type_t *type, type_list_t *pa + new_type->namespace = type->namespace; + new_type->name = format_parameterized_type_name(type, params); + reg_type(new_type, new_type->name, new_type->namespace, 0); +- new_type->c_name = format_parameterized_type_c_name(type, params); ++ new_type->c_name = format_parameterized_type_c_name(type, params, ""); ++ ++ if (new_type->type_type == TYPE_DELEGATE) ++ { ++ new_type->details.delegate.iface = duptype(tmpl->details.delegate.iface, 0); ++ compute_delegate_iface_name(new_type); ++ new_type->details.delegate.iface->namespace = new_type->namespace; ++ new_type->details.delegate.iface->c_name = format_parameterized_type_c_name(type, params, "I"); ++ } + + return new_type; + } +@@ -731,6 +744,8 @@ type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *par + + if (tmpl->type_type == TYPE_INTERFACE) + type_parameterized_interface_specialize(tmpl, iface, orig, params); ++ else if (tmpl->type_type == TYPE_DELEGATE) ++ type_parameterized_delegate_specialize(tmpl, iface, orig, params); + else + { + error_loc("Unsupported parameterized type template %d\n", tmpl->type_type); +@@ -738,6 +753,11 @@ type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *par + } + + iface->defined = TRUE; ++ if (iface->type_type == TYPE_DELEGATE) ++ { ++ iface = iface->details.delegate.iface; ++ iface->defined = TRUE; ++ } + compute_method_indexes(iface); + return iface; + } +@@ -807,6 +827,28 @@ void type_delegate_define(type_t *delegate, statement_list_t *stmts) + compute_delegate_iface_name(delegate); + } + ++void type_parameterized_delegate_define(type_t *type, type_list_t *params, statement_list_t *stmts) ++{ ++ type_t *delegate = make_type(TYPE_DELEGATE); ++ type_t *iface = make_type(TYPE_INTERFACE); ++ ++ type->type_type = TYPE_PARAMETERIZED_TYPE; ++ type->details.parameterized.type = delegate; ++ type->details.parameterized.params = params; ++ ++ delegate->details.delegate.iface = iface; ++ ++ iface->details.iface = xmalloc(sizeof(*iface->details.iface)); ++ iface->details.iface->disp_props = NULL; ++ iface->details.iface->disp_methods = NULL; ++ iface->details.iface->stmts = stmts; ++ iface->details.iface->inherit = find_type("IUnknown", NULL, 0); ++ if (!iface->details.iface->inherit) error_loc("IUnknown is undefined\n"); ++ iface->details.iface->disp_inherit = NULL; ++ iface->details.iface->async_iface = NULL; ++ iface->details.iface->requires = NULL; ++} ++ + void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *methods) + { + iface->details.iface = xmalloc(sizeof(*iface->details.iface)); +diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h +index de3db4e7c7e..939bc5b412e 100644 +--- a/tools/widl/typetree.h ++++ b/tools/widl/typetree.h +@@ -53,6 +53,7 @@ void type_parameterized_interface_declare(type_t *type, type_list_t *params); + void type_parameterized_interface_define(type_t *type, type_list_t *params, type_t *inherit, statement_list_t *stmts); + void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts, type_list_t *requires); + void type_delegate_define(type_t *iface, statement_list_t *stmts); ++void type_parameterized_delegate_define(type_t *type, type_list_t *params, statement_list_t *stmts); + void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *methods); + void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface); + void type_module_define(type_t *module, statement_list_t *stmts); +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0025-widl-Compute-signatures-for-parameterized-types.patch b/patches/widl-winrt-support/0025-widl-Compute-signatures-for-parameterized-types.patch new file mode 100644 index 00000000..31ec45ae --- /dev/null +++ b/patches/widl-winrt-support/0025-widl-Compute-signatures-for-parameterized-types.patch @@ -0,0 +1,253 @@ +From c98f225368cdeac02b7c67b14d1e448f80c645e4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Fri, 25 Sep 2020 13:39:08 +0200 +Subject: [PATCH 25/28] widl: Compute signatures for parameterized types. + +--- + tools/widl/typetree.c | 155 +++++++++++++++++++++++++++++++++++++++++ + tools/widl/typetree.h | 10 +++ + tools/widl/widltypes.h | 2 + + 3 files changed, 167 insertions(+) + +diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c +index 03778aa75c3..b3718b5dc6d 100644 +--- a/tools/widl/typetree.c ++++ b/tools/widl/typetree.c +@@ -49,6 +49,7 @@ type_t *make_type(enum type_type type) + t->type_type = type; + t->attrs = NULL; + t->c_name = NULL; ++ t->signature = NULL; + memset(&t->details, 0, sizeof(t->details)); + t->typestring_offset = 0; + t->ptrdesc = 0; +@@ -143,6 +144,142 @@ static int format_parameterized_type_c_name_buffer(char *buf, size_t len, type_t + return ret; + } + ++static int format_type_signature_buffer(char *buf, size_t len, type_t *type); ++ ++static int format_var_list_signature_buffer(char *buf, size_t len, var_list_t *var_list) ++{ ++ var_t *var; ++ int ret = 0; ++ if (!var_list) append_buf(snprintf, ";"); ++ else LIST_FOR_EACH_ENTRY(var, var_list, var_t, entry) ++ { ++ append_buf(snprintf, ";"); ++ append_buf(format_type_signature_buffer, var->declspec.type); ++ } ++ return ret; ++} ++ ++static int format_type_signature_buffer(char *buf, size_t len, type_t *type) ++{ ++ const GUID *uuid; ++ int ret = 0; ++ if (!type) return 0; ++ switch (type->type_type) ++ { ++ case TYPE_INTERFACE: ++ if (type->signature) append_buf(snprintf, "%s", type->signature); ++ else ++ { ++ uuid = type_get_uuid(type); ++ append_buf(snprintf, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", ++ uuid->Data1, uuid->Data2, uuid->Data3, ++ uuid->Data4[0], uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], ++ uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7]); ++ } ++ return ret; ++ case TYPE_DELEGATE: ++ append_buf(snprintf, "delegate("); ++ append_buf(format_type_signature_buffer, type_delegate_get_iface(type)); ++ append_buf(snprintf, ")"); ++ return ret; ++ case TYPE_RUNTIMECLASS: ++ append_buf(snprintf, "rc("); ++ append_buf(format_namespace_buffer, type->namespace, "", ".", type->name, NULL); ++ append_buf(snprintf, ";"); ++ append_buf(format_type_signature_buffer, type_runtimeclass_get_default_iface(type)); ++ append_buf(snprintf, ")"); ++ return ret; ++ case TYPE_POINTER: ++ return format_type_signature_buffer(buf, len, type->details.pointer.ref.type); ++ case TYPE_ALIAS: ++ if (!strcmp(type->name, "boolean")) append_buf(snprintf, "b1"); ++ else ret = format_type_signature_buffer(buf, len, type->details.alias.aliasee.type); ++ return ret; ++ case TYPE_STRUCT: ++ append_buf(snprintf, "struct("); ++ append_buf(format_namespace_buffer, type->namespace, "", ".", type->name, NULL); ++ append_buf(format_var_list_signature_buffer, type->details.structure->fields); ++ append_buf(snprintf, ")"); ++ return ret; ++ case TYPE_BASIC: ++ switch (type_basic_get_type(type)) ++ { ++ case TYPE_BASIC_INT: ++ case TYPE_BASIC_INT32: ++ append_buf(snprintf, type_basic_get_sign(type) < 0 ? "i4" : "u4"); ++ return ret; ++ case TYPE_BASIC_INT64: ++ append_buf(snprintf, type_basic_get_sign(type) < 0 ? "i8" : "u8"); ++ return ret; ++ case TYPE_BASIC_INT8: ++ assert(type_basic_get_sign(type) >= 0); /* signature string for signed char isn't specified */ ++ append_buf(snprintf, "u1"); ++ return ret; ++ case TYPE_BASIC_FLOAT: ++ append_buf(snprintf, "f4"); ++ return ret; ++ case TYPE_BASIC_DOUBLE: ++ append_buf(snprintf, "f8"); ++ return ret; ++ case TYPE_BASIC_INT16: ++ case TYPE_BASIC_INT3264: ++ case TYPE_BASIC_LONG: ++ case TYPE_BASIC_CHAR: ++ case TYPE_BASIC_HYPER: ++ case TYPE_BASIC_BYTE: ++ case TYPE_BASIC_WCHAR: ++ case TYPE_BASIC_ERROR_STATUS_T: ++ case TYPE_BASIC_HANDLE: ++ error("basic type '%d' signature not implemented\n", type_basic_get_type(type)); ++ assert(0); /* FIXME: implement when needed */ ++ break; ++ } ++ case TYPE_ENUM: ++ append_buf(snprintf, "enum("); ++ append_buf(format_namespace_buffer, type->namespace, "", ".", type->name, NULL); ++ if (is_attr(type->attrs, ATTR_FLAGS)) append_buf(snprintf, ";u4"); ++ else append_buf(snprintf, ";i4"); ++ append_buf(snprintf, ")"); ++ return ret; ++ case TYPE_ARRAY: ++ case TYPE_ENCAPSULATED_UNION: ++ case TYPE_UNION: ++ case TYPE_COCLASS: ++ error("type '%d' signature for '%s' not implemented\n", type->type_type, type->name); ++ assert(0); /* FIXME: implement when needed */ ++ break; ++ case TYPE_VOID: ++ case TYPE_FUNCTION: ++ case TYPE_BITFIELD: ++ case TYPE_MODULE: ++ case TYPE_PARAMETERIZED_TYPE: ++ case TYPE_PARAMETER: ++ case TYPE_APICONTRACT: ++ assert(0); /* should not be there */ ++ break; ++ } ++ ++ return ret; ++} ++ ++static int format_parameterized_type_signature_buffer(char *buf, size_t len, type_t *type, type_list_t *params) ++{ ++ type_list_t *entry; ++ const GUID *uuid = type_get_uuid(type); ++ int ret = 0; ++ append_buf(snprintf, "pinterface({%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", ++ uuid->Data1, uuid->Data2, uuid->Data3, ++ uuid->Data4[0], uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], ++ uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7]); ++ for (entry = params; entry; entry = entry->next) ++ { ++ append_buf(snprintf, ";"); ++ append_buf(format_type_signature_buffer, entry->type); ++ } ++ append_buf(snprintf, ")"); ++ return ret; ++} ++ + #undef append_buf + + char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix) +@@ -161,6 +298,14 @@ char *format_parameterized_type_name(type_t *type, type_list_t *params) + return buf; + } + ++char *format_type_signature(type_t *type) ++{ ++ int len = format_type_signature_buffer(NULL, 0, type); ++ char *buf = xmalloc(len + 1); ++ format_type_signature_buffer(buf, len + 1, type); ++ return buf; ++} ++ + static char const *parameterized_type_shorthands[][2] = { + {"Windows_CFoundation_CCollections_C", "__F"}, + {"Windows_CFoundation_C", "__F"}, +@@ -186,6 +331,14 @@ static char *format_parameterized_type_c_name(type_t *type, type_list_t *params, + return buf; + } + ++static char *format_parameterized_type_signature(type_t *type, type_list_t *params) ++{ ++ int len = format_parameterized_type_signature_buffer(NULL, 0, type, params); ++ char *buf = xmalloc(len + 1); ++ format_parameterized_type_signature_buffer(buf, len + 1, type, params); ++ return buf; ++} ++ + type_t *type_new_function(var_list_t *args) + { + var_t *arg; +@@ -752,10 +905,12 @@ type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *par + return NULL; + } + ++ iface->signature = format_parameterized_type_signature(type, params); + iface->defined = TRUE; + if (iface->type_type == TYPE_DELEGATE) + { + iface = iface->details.delegate.iface; ++ iface->signature = format_parameterized_type_signature(type, params); + iface->defined = TRUE; + } + compute_method_indexes(iface); +diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h +index 939bc5b412e..b4257fe615f 100644 +--- a/tools/widl/typetree.h ++++ b/tools/widl/typetree.h +@@ -80,6 +80,16 @@ static inline enum type_type type_get_type(const type_t *type) + return type_get_type_detect_alias(type_get_real_type(type)); + } + ++static inline const GUID *type_get_uuid(const type_t *type) ++{ ++ static const GUID empty; ++ attr_t *attr; ++ LIST_FOR_EACH_ENTRY(attr, type->attrs, attr_t, entry) ++ if (attr->type == ATTR_UUID) return attr->u.pval; ++ error("type '%s' uuid not found\n", type->name); ++ return ∅ ++} ++ + static inline enum type_basic_type type_basic_get_type(const type_t *type) + { + type = type_get_real_type(type); +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index 3938d0d5294..58828a4f8e2 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -496,6 +496,7 @@ struct _type_t { + struct delegate_details delegate; + } details; + const char *c_name; ++ const char *signature; + unsigned int typestring_offset; + unsigned int ptrdesc; /* used for complex structs */ + int typelib_idx; +@@ -651,6 +652,7 @@ void init_loc_info(loc_info_t *); + char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, + const char *abi_prefix); + char *format_parameterized_type_name(type_t *type, type_list_t *params); ++char *format_type_signature(type_t *type); + + static inline enum type_type type_get_type_detect_alias(const type_t *type) + { +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0026-widl-Compute-uuids-for-parameterized-types.patch b/patches/widl-winrt-support/0026-widl-Compute-uuids-for-parameterized-types.patch new file mode 100644 index 00000000..2358ade8 --- /dev/null +++ b/patches/widl-winrt-support/0026-widl-Compute-uuids-for-parameterized-types.patch @@ -0,0 +1,317 @@ +From a8e1b96947308faf90d1686bf14743c5da7b90bd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Mon, 28 Sep 2020 17:00:41 +0200 +Subject: [PATCH 26/28] widl: Compute uuids for parameterized types. + +--- + tools/widl/hash.c | 178 ++++++++++++++++++++++++++++++++++++++++++ + tools/widl/hash.h | 14 ++++ + tools/widl/typetree.c | 53 +++++++++++++ + tools/widl/typetree.h | 2 +- + 4 files changed, 246 insertions(+), 1 deletion(-) + +diff --git a/tools/widl/hash.c b/tools/widl/hash.c +index 15ec88001d6..df6133866e0 100644 +--- a/tools/widl/hash.c ++++ b/tools/widl/hash.c +@@ -639,3 +639,181 @@ unsigned int lhash_val_of_name_sys( syskind_t skind, LCID lcid, LPCSTR lpStr) + + return nHiWord | nLoWord; + } ++ ++/* SHA1 algorithm ++ * ++ * Based on public domain SHA code by Steve Reid ++ */ ++ ++#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) ++/* FIXME: This definition of DWORD2BE is little endian specific! */ ++#define DWORD2BE(x) (((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) | (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000); ++/* FIXME: This definition of blk0 is little endian specific! */ ++#define blk0(i) (Block[i] = (rol(Block[i],24)&0xFF00FF00)|(rol(Block[i],8)&0x00FF00FF)) ++#define blk1(i) (Block[i&15] = rol(Block[(i+13)&15]^Block[(i+8)&15]^Block[(i+2)&15]^Block[i&15],1)) ++#define f1(x,y,z) (z^(x&(y^z))) ++#define f2(x,y,z) (x^y^z) ++#define f3(x,y,z) ((x&y)|(z&(x|y))) ++#define f4(x,y,z) (x^y^z) ++/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ ++#define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); ++#define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rol(v,5);w=rol(w,30); ++#define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); ++#define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); ++#define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); ++ ++/* Hash a single 512-bit block. This is the core of the algorithm. */ ++static void SHA1Transform(ULONG State[5], UCHAR Buffer[64]) ++{ ++ ULONG a, b, c, d, e; ++ ULONG *Block; ++ ++ Block = (ULONG*)Buffer; ++ ++ /* Copy Context->State[] to working variables */ ++ a = State[0]; ++ b = State[1]; ++ c = State[2]; ++ d = State[3]; ++ e = State[4]; ++ ++ /* 4 rounds of 20 operations each. Loop unrolled. */ ++ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); ++ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); ++ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); ++ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); ++ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); ++ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); ++ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); ++ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); ++ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); ++ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); ++ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); ++ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); ++ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); ++ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); ++ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); ++ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); ++ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); ++ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); ++ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); ++ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); ++ ++ /* Add the working variables back into Context->State[] */ ++ State[0] += a; ++ State[1] += b; ++ State[2] += c; ++ State[3] += d; ++ State[4] += e; ++ ++ /* Wipe variables */ ++ a = b = c = d = e = 0; ++} ++ ++ ++/****************************************************************************** ++ * A_SHAInit (ntdll.@) ++ * ++ * Initialize a SHA context structure. ++ * ++ * PARAMS ++ * Context [O] SHA context ++ * ++ * RETURNS ++ * Nothing ++ */ ++void A_SHAInit(SHA_CTX *Context) ++{ ++ /* SHA1 initialization constants */ ++ Context->State[0] = 0x67452301; ++ Context->State[1] = 0xEFCDAB89; ++ Context->State[2] = 0x98BADCFE; ++ Context->State[3] = 0x10325476; ++ Context->State[4] = 0xC3D2E1F0; ++ Context->Count[0] = ++ Context->Count[1] = 0; ++} ++ ++/****************************************************************************** ++ * A_SHAUpdate (ntdll.@) ++ * ++ * Update a SHA context with a hashed data from supplied buffer. ++ * ++ * PARAMS ++ * Context [O] SHA context ++ * Buffer [I] hashed data ++ * BufferSize [I] hashed data size ++ * ++ * RETURNS ++ * Nothing ++ */ ++void A_SHAUpdate(SHA_CTX *Context, const unsigned char *Buffer, UINT BufferSize) ++{ ++ ULONG BufferContentSize; ++ ++ BufferContentSize = Context->Count[1] & 63; ++ Context->Count[1] += BufferSize; ++ if (Context->Count[1] < BufferSize) ++ Context->Count[0]++; ++ Context->Count[0] += (BufferSize >> 29); ++ ++ if (BufferContentSize + BufferSize < 64) ++ { ++ RtlCopyMemory(&Context->Buffer[BufferContentSize], Buffer, ++ BufferSize); ++ } ++ else ++ { ++ while (BufferContentSize + BufferSize >= 64) ++ { ++ RtlCopyMemory(Context->Buffer + BufferContentSize, Buffer, ++ 64 - BufferContentSize); ++ Buffer += 64 - BufferContentSize; ++ BufferSize -= 64 - BufferContentSize; ++ SHA1Transform(Context->State, Context->Buffer); ++ BufferContentSize = 0; ++ } ++ RtlCopyMemory(Context->Buffer + BufferContentSize, Buffer, BufferSize); ++ } ++} ++ ++/****************************************************************************** ++ * A_SHAFinal (ntdll.@) ++ * ++ * Finalize SHA context and return the resulting hash. ++ * ++ * PARAMS ++ * Context [I/O] SHA context ++ * Result [O] resulting hash ++ * ++ * RETURNS ++ * Nothing ++ */ ++void A_SHAFinal(SHA_CTX *Context, PULONG Result) ++{ ++ INT Pad, Index; ++ UCHAR Buffer[72]; ++ ULONG *Count; ++ ULONG BufferContentSize, LengthHi, LengthLo; ++ ++ BufferContentSize = Context->Count[1] & 63; ++ if (BufferContentSize >= 56) ++ Pad = 56 + 64 - BufferContentSize; ++ else ++ Pad = 56 - BufferContentSize; ++ ++ LengthHi = (Context->Count[0] << 3) | (Context->Count[1] >> (32 - 3)); ++ LengthLo = (Context->Count[1] << 3); ++ ++ RtlZeroMemory(Buffer + 1, Pad - 1); ++ Buffer[0] = 0x80; ++ Count = (ULONG*)(Buffer + Pad); ++ Count[0] = DWORD2BE(LengthHi); ++ Count[1] = DWORD2BE(LengthLo); ++ A_SHAUpdate(Context, Buffer, Pad + 8); ++ ++ for (Index = 0; Index < 5; Index++) ++ Result[Index] = DWORD2BE(Context->State[Index]); ++ ++ A_SHAInit(Context); ++} +diff --git a/tools/widl/hash.h b/tools/widl/hash.h +index 3c2fd2914bf..208b193ac87 100644 +--- a/tools/widl/hash.h ++++ b/tools/widl/hash.h +@@ -22,6 +22,20 @@ + #ifndef __WIDL_HASH_H + #define __WIDL_HASH_H + ++#include "windef.h" ++ + extern unsigned int lhash_val_of_name_sys( syskind_t skind, LCID lcid, LPCSTR lpStr); + ++typedef struct ++{ ++ ULONG Unknown[6]; ++ ULONG State[5]; ++ ULONG Count[2]; ++ UCHAR Buffer[64]; ++} SHA_CTX; ++ ++VOID A_SHAInit(SHA_CTX *ctx); ++VOID A_SHAUpdate(SHA_CTX *ctx, const UCHAR *buffer, UINT size); ++VOID A_SHAFinal(SHA_CTX *ctx, PULONG result); ++ + #endif +diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c +index b3718b5dc6d..2d060363d8e 100644 +--- a/tools/widl/typetree.c ++++ b/tools/widl/typetree.c +@@ -29,6 +29,7 @@ + #include "parser.h" + #include "typetree.h" + #include "header.h" ++#include "hash.h" + + type_t *duptype(type_t *t, int dupname) + { +@@ -683,6 +684,57 @@ static void compute_delegate_iface_name(type_t *delegate) + delegate->details.delegate.iface->name = name; + } + ++static void compute_interface_signature_uuid(type_t *iface) ++{ ++ static unsigned char const wrt_pinterface_namespace[] = {0x11,0xf4,0x7a,0xd5,0x7b,0x73,0x42,0xc0,0xab,0xae,0x87,0x8b,0x1e,0x16,0xad,0xee}; ++ static const int version = 5; ++ unsigned char hash[20]; ++ SHA_CTX sha_ctx; ++ attr_t *attr; ++ GUID *uuid; ++ ++ if (!iface->attrs) ++ { ++ iface->attrs = xmalloc( sizeof(*iface->attrs) ); ++ list_init( iface->attrs ); ++ } ++ ++ LIST_FOR_EACH_ENTRY(attr, iface->attrs, attr_t, entry) ++ if (attr->type == ATTR_UUID) break; ++ ++ if (&attr->entry == iface->attrs) ++ { ++ attr = xmalloc( sizeof(*attr) ); ++ attr->type = ATTR_UUID; ++ attr->u.pval = xmalloc( sizeof(GUID) ); ++ list_add_tail( iface->attrs, &attr->entry ); ++ } ++ ++ A_SHAInit(&sha_ctx); ++ A_SHAUpdate(&sha_ctx, wrt_pinterface_namespace, sizeof(wrt_pinterface_namespace)); ++ A_SHAUpdate(&sha_ctx, (const UCHAR *)iface->signature, strlen(iface->signature)); ++ A_SHAFinal(&sha_ctx, (ULONG *)hash); ++ ++ /* https://tools.ietf.org/html/rfc4122: ++ ++ * Set the four most significant bits (bits 12 through 15) of the ++ time_hi_and_version field to the appropriate 4-bit version number ++ from Section 4.1.3. ++ ++ * Set the two most significant bits (bits 6 and 7) of the ++ clock_seq_hi_and_reserved to zero and one, respectively. ++ */ ++ ++ hash[6] = ((hash[6] & 0x0f) | (version << 4)); ++ hash[8] = ((hash[8] & 0x3f) | 0x80); ++ ++ uuid = attr->u.pval; ++ uuid->Data1 = ((DWORD)hash[0] << 24)|((DWORD)hash[1] << 16)|((DWORD)hash[2] << 8)|(DWORD)hash[3]; ++ uuid->Data2 = ((WORD)hash[4] << 8)|(WORD)hash[5]; ++ uuid->Data3 = ((WORD)hash[6] << 8)|(WORD)hash[7]; ++ memcpy(&uuid->Data4, hash + 8, sizeof(*uuid) - offsetof(GUID, Data4)); ++} ++ + static type_t *replace_type_parameters_in_type(type_t *type, type_list_t *orig, type_list_t *repl); + + static type_list_t *replace_type_parameters_in_type_list(type_list_t *type_list, type_list_t *orig, type_list_t *repl) +@@ -913,6 +965,7 @@ type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *par + iface->signature = format_parameterized_type_signature(type, params); + iface->defined = TRUE; + } ++ compute_interface_signature_uuid(iface); + compute_method_indexes(iface); + return iface; + } +diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h +index b4257fe615f..46a223d50e3 100644 +--- a/tools/widl/typetree.h ++++ b/tools/widl/typetree.h +@@ -84,7 +84,7 @@ static inline const GUID *type_get_uuid(const type_t *type) + { + static const GUID empty; + attr_t *attr; +- LIST_FOR_EACH_ENTRY(attr, type->attrs, attr_t, entry) ++ if (type->attrs) LIST_FOR_EACH_ENTRY(attr, type->attrs, attr_t, entry) + if (attr->type == ATTR_UUID) return attr->u.pval; + error("type '%s' uuid not found\n", type->name); + return ∅ +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0027-widl-Generate-helper-macros-for-WinRT-implementation.patch b/patches/widl-winrt-support/0027-widl-Generate-helper-macros-for-WinRT-implementation.patch new file mode 100644 index 00000000..d2b51606 --- /dev/null +++ b/patches/widl-winrt-support/0027-widl-Generate-helper-macros-for-WinRT-implementation.patch @@ -0,0 +1,206 @@ +From d517b9b5856840f19b3a805b812153d5c0f6d0d9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Wed, 26 Aug 2020 22:46:02 +0200 +Subject: [PATCH 27/28] widl: Generate helper macros for WinRT implementation. + +This generates additional macros to help keeping implementation simple, +guarded with WIDL_USING ifdefs, like this: + + #ifdef WIDL_USING_WINDOWS_FOO_IFOO + #define IFooVtbl __x_ABI_CWindows_CFoo_CIFooVtbl + #define IFoo __x_ABI_CWindows_CFoo_CIFoo + #define IFoo_DoFoo __x_ABI_CWindows_CFoo_CIFoo_DoFoo + #endif /* WIDL_USING_WINDOWS_FOO_IFOO */ + +Implementation files can define the desired WIDL_USING preprocessor +macros before including the header, and then implement or use the +interface methods with the simple non-prefixed names instead. +--- + tools/widl/header.c | 71 ++++++++++++++++++++++++++++++++++++++++-- + tools/widl/typetree.c | 24 ++++++++++++++ + tools/widl/widltypes.h | 1 + + 3 files changed, 94 insertions(+), 2 deletions(-) + +diff --git a/tools/widl/header.c b/tools/widl/header.c +index 64faf89c36a..4aa6844ee99 100644 +--- a/tools/widl/header.c ++++ b/tools/widl/header.c +@@ -50,6 +50,8 @@ static void write_winrt_type_comments(FILE *header, const type_t *type); + static void write_apicontract_guard_start(FILE *header, const expr_t *expr); + static void write_apicontract_guard_end(FILE *header, const expr_t *expr); + ++static void write_widl_using_macros(FILE *header, type_t *iface); ++ + static void indent(FILE *h, int delta) + { + int c; +@@ -616,10 +618,11 @@ static void write_type_definition(FILE *f, type_t *t, int declonly) + t->written = save_written; + write_namespace_end(f, t->namespace); + fprintf(f, "extern \"C\" {\n"); +- fprintf(f, "#else\n"); ++ fprintf(f, "#else /* __cplusplus */\n"); + write_type_left(f, &ds, NAME_C, declonly, TRUE); + fprintf(f, ";\n"); +- fprintf(f, "#endif\n\n"); ++ if (winrt_mode) write_widl_using_macros(f, t); ++ fprintf(f, "#endif /* __cplusplus */\n\n"); + } + if (contract) write_apicontract_guard_end(f, contract); + } +@@ -1643,6 +1646,69 @@ static void write_com_interface_start(FILE *header, const type_t *iface) + fprintf(header,"#define __%s_%sINTERFACE_DEFINED__\n\n", iface->c_name, dispinterface ? "DISP" : ""); + } + ++static char *get_winrt_guard_macro(type_t *iface) ++{ ++ unsigned int len; ++ char *macro, *tmp = (char *)iface->c_name; ++ int i; ++ ++ if (!strncmp(tmp, "__x", 3)) tmp += 3; ++ if (!strncmp(tmp, "_ABI", 4)) tmp += 4; ++ macro = xstrdup(tmp); ++ ++ len = strlen(macro) + 1; ++ for (tmp = strstr(macro, "__F"); tmp; tmp = strstr(tmp, "__F")) ++ memmove(tmp + 1, tmp + 3, len - (tmp - macro) - 3); ++ for (tmp = strstr(macro, "__C"); tmp; tmp = strstr(tmp, "__C")) ++ memmove(tmp + 1, tmp + 3, len - (tmp - macro) - 3); ++ for (tmp = strstr(macro, "_C"); tmp; tmp = strstr(tmp, "_C")) ++ memmove(tmp + 1, tmp + 2, len - (tmp - macro) - 2); ++ ++ for (i = strlen(macro); i > 0; --i) macro[i - 1] = toupper(macro[i - 1]); ++ ++ return macro; ++} ++ ++static void write_widl_using_method_macros(FILE *header, const type_t *iface, const type_t *top_iface) ++{ ++ const statement_t *stmt; ++ const char *name = top_iface->short_name ? top_iface->short_name : top_iface->name; ++ ++ if (type_iface_get_inherit(iface)) write_widl_using_method_macros(header, type_iface_get_inherit(iface), top_iface); ++ ++ STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) ++ { ++ const var_t *func = stmt->u.var; ++ const char *func_name = get_name(func); ++ ++ if (is_override_method(iface, top_iface, func)) continue; ++ ++ if (!is_callas(func->attrs)) ++ fprintf(header, "#define %s_%s %s_%s\n", name, func_name, top_iface->c_name, func_name); ++ } ++} ++ ++static void write_widl_using_macros(FILE *header, type_t *iface) ++{ ++ const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); ++ const char *name = iface->short_name ? iface->short_name : iface->name; ++ char *macro; ++ ++ if (!strcmp(iface->name, iface->c_name)) return; ++ ++ macro = get_winrt_guard_macro(iface); ++ fprintf(header, "#ifdef WIDL_USING%s\n", macro); ++ ++ if (uuid) fprintf(header, "#define IID_%s IID_%s\n", name, iface->c_name); ++ if (iface->type_type == TYPE_INTERFACE) fprintf(header, "#define %sVtbl %sVtbl\n", name, iface->c_name); ++ fprintf(header, "#define %s %s\n", name, iface->c_name); ++ ++ if (iface->type_type == TYPE_INTERFACE) write_widl_using_method_macros(header, iface, iface); ++ ++ fprintf(header, "#endif /* WIDL_USING_%s */\n", macro); ++ free(macro); ++} ++ + static void write_com_interface_end(FILE *header, type_t *iface) + { + int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); +@@ -1715,6 +1781,7 @@ static void write_com_interface_end(FILE *header, type_t *iface) + fprintf(header, "#else\n"); + write_inline_wrappers(header, type, type, iface->c_name); + fprintf(header, "#endif\n"); ++ if (winrt_mode) write_widl_using_macros(header, iface); + fprintf(header, "#endif\n"); + fprintf(header, "\n"); + fprintf(header, "#endif\n"); +diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c +index 2d060363d8e..f62d0eb51dc 100644 +--- a/tools/widl/typetree.c ++++ b/tools/widl/typetree.c +@@ -51,6 +51,7 @@ type_t *make_type(enum type_type type) + t->attrs = NULL; + t->c_name = NULL; + t->signature = NULL; ++ t->short_name = NULL; + memset(&t->details, 0, sizeof(t->details)); + t->typestring_offset = 0; + t->ptrdesc = 0; +@@ -281,6 +282,19 @@ static int format_parameterized_type_signature_buffer(char *buf, size_t len, typ + return ret; + } + ++static int format_parameterized_type_short_name_buffer(char *buf, size_t len, type_t *type, type_list_t *params, const char *prefix) ++{ ++ type_list_t *entry; ++ int ret = 0; ++ append_buf(snprintf, "%s%s", prefix, type->name); ++ for (entry = params; entry; entry = entry->next) ++ { ++ for (type = entry->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {} ++ append_buf(snprintf, "_%s", type->name); ++ } ++ return ret; ++} ++ + #undef append_buf + + char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix) +@@ -340,6 +354,14 @@ static char *format_parameterized_type_signature(type_t *type, type_list_t *para + return buf; + } + ++static char *format_parameterized_type_short_name(type_t *type, type_list_t *params, const char *prefix) ++{ ++ int len = format_parameterized_type_short_name_buffer(NULL, 0, type, params, prefix); ++ char *buf = xmalloc(len + 1); ++ format_parameterized_type_short_name_buffer(buf, len + 1, type, params, prefix); ++ return buf; ++} ++ + type_t *type_new_function(var_list_t *args) + { + var_t *arg; +@@ -929,6 +951,7 @@ type_t *type_parameterized_type_specialize_declare(type_t *type, type_list_t *pa + new_type->name = format_parameterized_type_name(type, params); + reg_type(new_type, new_type->name, new_type->namespace, 0); + new_type->c_name = format_parameterized_type_c_name(type, params, ""); ++ new_type->short_name = format_parameterized_type_short_name(type, params, ""); + + if (new_type->type_type == TYPE_DELEGATE) + { +@@ -936,6 +959,7 @@ type_t *type_parameterized_type_specialize_declare(type_t *type, type_list_t *pa + compute_delegate_iface_name(new_type); + new_type->details.delegate.iface->namespace = new_type->namespace; + new_type->details.delegate.iface->c_name = format_parameterized_type_c_name(type, params, "I"); ++ new_type->details.delegate.iface->short_name = format_parameterized_type_short_name(type, params, "I"); + } + + return new_type; +diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h +index 58828a4f8e2..d80e9c04d51 100644 +--- a/tools/widl/widltypes.h ++++ b/tools/widl/widltypes.h +@@ -497,6 +497,7 @@ struct _type_t { + } details; + const char *c_name; + const char *signature; ++ const char *short_name; + unsigned int typestring_offset; + unsigned int ptrdesc; /* used for complex structs */ + int typelib_idx; +-- +2.28.0 + diff --git a/patches/widl-winrt-support/0028-include-Add-IVectorView-HSTRING-declaration-to-windo.patch b/patches/widl-winrt-support/0028-include-Add-IVectorView-HSTRING-declaration-to-windo.patch new file mode 100644 index 00000000..8175e912 --- /dev/null +++ b/patches/widl-winrt-support/0028-include-Add-IVectorView-HSTRING-declaration-to-windo.patch @@ -0,0 +1,29 @@ +From 5609ada48132040965e84cdbdd95cea9492a471d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Fri, 25 Sep 2020 17:05:17 +0200 +Subject: [PATCH 28/28] include: Add IVectorView declaration to + windows.foundation.idl. + +--- + include/windows.foundation.idl | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl +index 9583fa5bcc8..9b9b40897be 100644 +--- a/include/windows.foundation.idl ++++ b/include/windows.foundation.idl +@@ -157,3 +157,11 @@ namespace Windows { + #endif + } + } ++ ++namespace Windows { ++ namespace Foundation { ++ declare { ++ interface Windows.Foundation.Collections.IVectorView; ++ } ++ } ++} +-- +2.28.0 + diff --git a/patches/widl-winrt-support/definition b/patches/widl-winrt-support/definition new file mode 100644 index 00000000..4b45323d --- /dev/null +++ b/patches/widl-winrt-support/definition @@ -0,0 +1 @@ +Fixes: [68403] widl - Support WinRT idls diff --git a/patches/windows.globalization-dll/definition b/patches/windows.globalization-dll/definition index 58803f3b..2bd08acc 100644 --- a/patches/windows.globalization-dll/definition +++ b/patches/windows.globalization-dll/definition @@ -1,2 +1,3 @@ Fixes: [49740] windows.globalization: New DLL Depends: windows.media.speech.dll +Disabled: True diff --git a/patches/windows.networking.connectivity.dll/definition b/patches/windows.networking.connectivity.dll/definition index 4f248dd0..5e6b7a5b 100644 --- a/patches/windows.networking.connectivity.dll/definition +++ b/patches/windows.networking.connectivity.dll/definition @@ -1,2 +1,3 @@ Fixes: [46534] windows.networking.connectivity: New DLL Depends: windows.globalization-dll +Disabled: True