widl: Import Wine version 10.12 Signed-off-by: Jacek Caban <jacek@codeweavers.com>
diff --git a/mingw-w64-tools/widl/VERSION b/mingw-w64-tools/widl/VERSION index 67f0d65..7a0caa1 100644 --- a/mingw-w64-tools/widl/VERSION +++ b/mingw-w64-tools/widl/VERSION
@@ -1 +1 @@ -WIDL version 10.11 +WIDL version 10.12
diff --git a/mingw-w64-tools/widl/configure b/mingw-w64-tools/widl/configure index b5651aa..0e191c7 100755 --- a/mingw-w64-tools/widl/configure +++ b/mingw-w64-tools/widl/configure
@@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.72 for widl 10.11. +# Generated by GNU Autoconf 2.72 for widl 10.12. # # Report bugs to <mingw-w64-public@lists.sourceforge.net>. # @@ -603,8 +603,8 @@ # Identity of this package. PACKAGE_NAME='widl' PACKAGE_TARNAME='widl' -PACKAGE_VERSION='10.11' -PACKAGE_STRING='widl 10.11' +PACKAGE_VERSION='10.12' +PACKAGE_STRING='widl 10.12' PACKAGE_BUGREPORT='mingw-w64-public@lists.sourceforge.net' PACKAGE_URL='' @@ -1311,7 +1311,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -'configure' configures widl 10.11 to adapt to many kinds of systems. +'configure' configures widl 10.12 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1383,7 +1383,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of widl 10.11:";; + short | recursive ) echo "Configuration of widl 10.12:";; esac cat <<\_ACEOF @@ -1485,7 +1485,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -widl configure 10.11 +widl configure 10.12 generated by GNU Autoconf 2.72 Copyright (C) 2023 Free Software Foundation, Inc. @@ -1910,7 +1910,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by widl $as_me 10.11, which was +It was created by widl $as_me 10.12, which was generated by GNU Autoconf 2.72. Invocation command line was $ $0$ac_configure_args_raw @@ -3327,7 +3327,7 @@ # Define the identity of the package. PACKAGE='widl' - VERSION='10.11' + VERSION='10.12' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -5797,7 +5797,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by widl $as_me 10.11, which was +This file was extended by widl $as_me 10.12, which was generated by GNU Autoconf 2.72. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5865,7 +5865,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -widl config.status 10.11 +widl config.status 10.12 configured by $0, generated by GNU Autoconf 2.72, with options \\"\$ac_cs_config\\"
diff --git a/mingw-w64-tools/widl/include/basetsd.h b/mingw-w64-tools/widl/include/basetsd.h index 6eb7656..b3587da 100644 --- a/mingw-w64-tools/widl/include/basetsd.h +++ b/mingw-w64-tools/widl/include/basetsd.h
@@ -95,18 +95,23 @@ typedef unsigned int DWORD32, *PDWORD32; #ifdef _MSC_VER -typedef signed __int64 INT64, *PINT64; -typedef unsigned __int64 UINT64, *PUINT64; -typedef signed __int64 LONG64, *PLONG64; -typedef unsigned __int64 ULONG64, *PULONG64; -typedef unsigned __int64 DWORD64, *PDWORD64; +typedef signed __int64 INT64; +typedef unsigned __int64 UINT64; +typedef signed __int64 LONG64; +typedef unsigned __int64 ULONG64; +typedef unsigned __int64 DWORD64; #else -typedef signed __int64 DECLSPEC_ALIGN(8) INT64, *PINT64; -typedef unsigned __int64 DECLSPEC_ALIGN(8) UINT64, *PUINT64; -typedef signed __int64 DECLSPEC_ALIGN(8) LONG64, *PLONG64; -typedef unsigned __int64 DECLSPEC_ALIGN(8) ULONG64, *PULONG64; -typedef unsigned __int64 DECLSPEC_ALIGN(8) DWORD64, *PDWORD64; +typedef signed __int64 DECLSPEC_ALIGN(8) INT64; +typedef unsigned __int64 DECLSPEC_ALIGN(8) UINT64; +typedef signed __int64 DECLSPEC_ALIGN(8) LONG64; +typedef unsigned __int64 DECLSPEC_ALIGN(8) ULONG64; +typedef unsigned __int64 DECLSPEC_ALIGN(8) DWORD64; #endif +typedef INT64 *PINT64; +typedef UINT64 *PUINT64; +typedef LONG64 *PLONG64; +typedef ULONG64 *PULONG64; +typedef DWORD64 *PDWORD64; /* Basic pointer-sized integer types */
diff --git a/mingw-w64-tools/widl/include/sysinfoapi.h b/mingw-w64-tools/widl/include/sysinfoapi.h index cf40a18..d6712c5 100644 --- a/mingw-w64-tools/widl/include/sysinfoapi.h +++ b/mingw-w64-tools/widl/include/sysinfoapi.h
@@ -50,13 +50,13 @@ typedef struct tagMEMORYSTATUSEX { DWORD dwLength; DWORD dwMemoryLoad; - DWORDLONG DECLSPEC_ALIGN(8) ullTotalPhys; - DWORDLONG DECLSPEC_ALIGN(8) ullAvailPhys; - DWORDLONG DECLSPEC_ALIGN(8) ullTotalPageFile; - DWORDLONG DECLSPEC_ALIGN(8) ullAvailPageFile; - DWORDLONG DECLSPEC_ALIGN(8) ullTotalVirtual; - DWORDLONG DECLSPEC_ALIGN(8) ullAvailVirtual; - DWORDLONG DECLSPEC_ALIGN(8) ullAvailExtendedVirtual; + DWORDLONG ullTotalPhys; + DWORDLONG ullAvailPhys; + DWORDLONG ullTotalPageFile; + DWORDLONG ullAvailPageFile; + DWORDLONG ullTotalVirtual; + DWORDLONG ullAvailVirtual; + DWORDLONG ullAvailExtendedVirtual; } MEMORYSTATUSEX, *LPMEMORYSTATUSEX; #pragma pack(pop)
diff --git a/mingw-w64-tools/widl/include/winbase.h b/mingw-w64-tools/widl/include/winbase.h index 4d23dd5..29a3ea8 100644 --- a/mingw-w64-tools/widl/include/winbase.h +++ b/mingw-w64-tools/widl/include/winbase.h
@@ -1574,6 +1574,9 @@ WINBASEAPI HANDLE WINAPI CreateActCtxA(PCACTCTXA); WINBASEAPI HANDLE WINAPI CreateActCtxW(PCACTCTXW); #define CreateActCtx WINELIB_NAME_AW(CreateActCtx) +WINBASEAPI HANDLE WINAPI CreateBoundaryDescriptorA(LPCSTR,ULONG); + /* CreateBoundaryDescriptorW is in namespaceapi.h */ +#define CreateBoundaryDescriptor WINELIB_NAME_AW(CreateBoundaryDescriptor) WINBASEAPI BOOL WINAPI CreateDirectoryA(LPCSTR,LPSECURITY_ATTRIBUTES); WINBASEAPI BOOL WINAPI CreateDirectoryW(LPCWSTR,LPSECURITY_ATTRIBUTES); #define CreateDirectory WINELIB_NAME_AW(CreateDirectory)
diff --git a/mingw-w64-tools/widl/include/winnt.h b/mingw-w64-tools/widl/include/winnt.h index c5bd89d..f0ab49e 100644 --- a/mingw-w64-tools/widl/include/winnt.h +++ b/mingw-w64-tools/widl/include/winnt.h
@@ -494,21 +494,19 @@ #ifndef _ULONGLONG_ # define _ULONGLONG_ # ifdef _MSC_VER -typedef signed __int64 LONGLONG, *PLONGLONG; -typedef unsigned __int64 ULONGLONG, *PULONGLONG; +typedef signed __int64 LONGLONG; +typedef unsigned __int64 ULONGLONG; # else -typedef signed __int64 DECLSPEC_ALIGN(8) LONGLONG, *PLONGLONG; -typedef unsigned __int64 DECLSPEC_ALIGN(8) ULONGLONG, *PULONGLONG; +typedef signed __int64 DECLSPEC_ALIGN(8) LONGLONG; +typedef unsigned __int64 DECLSPEC_ALIGN(8) ULONGLONG; # endif +typedef LONGLONG *PLONGLONG; +typedef ULONGLONG *PULONGLONG; #endif #ifndef _DWORDLONG_ # define _DWORDLONG_ -# ifdef _MSC_VER typedef ULONGLONG DWORDLONG, *PDWORDLONG; -# else -typedef ULONGLONG DECLSPEC_ALIGN(8) DWORDLONG, *PDWORDLONG; -# endif #endif /* ANSI string types */ @@ -6231,12 +6229,12 @@ #pragma pack(push,8) typedef struct _IO_COUNTERS { - ULONGLONG DECLSPEC_ALIGN(8) ReadOperationCount; - ULONGLONG DECLSPEC_ALIGN(8) WriteOperationCount; - ULONGLONG DECLSPEC_ALIGN(8) OtherOperationCount; - ULONGLONG DECLSPEC_ALIGN(8) ReadTransferCount; - ULONGLONG DECLSPEC_ALIGN(8) WriteTransferCount; - ULONGLONG DECLSPEC_ALIGN(8) OtherTransferCount; + ULONGLONG ReadOperationCount; + ULONGLONG WriteOperationCount; + ULONGLONG OtherOperationCount; + ULONGLONG ReadTransferCount; + ULONGLONG WriteTransferCount; + ULONGLONG OtherTransferCount; } IO_COUNTERS, *PIO_COUNTERS; #pragma pack(pop)
diff --git a/mingw-w64-tools/widl/src/expr.c b/mingw-w64-tools/widl/src/expr.c index be818de..6d16209 100644 --- a/mingw-w64-tools/widl/src/expr.c +++ b/mingw-w64-tools/widl/src/expr.c
@@ -198,7 +198,7 @@ e = xmalloc(sizeof(expr_t)); e->type = type; e->ref = expr; - e->u.tref = var->declspec; + e->u.var = var; e->is_const = FALSE; if (type == EXPR_SIZEOF) { @@ -240,7 +240,6 @@ e->cval = expr->cval; } } - free(var); return e; } @@ -581,7 +580,7 @@ break; case EXPR_CAST: result = resolve_expression(expr_loc, cont_type, e->ref); - result.type = e->u.tref.type; + result.type = e->u.var->declspec.type; break; case EXPR_SIZEOF: result.is_temporary = FALSE; @@ -752,13 +751,13 @@ break; case EXPR_CAST: fprintf(h, "("); - write_type_decl(h, &e->u.tref, NULL); + write_type_decl(h, &e->u.var->declspec, NULL); fprintf(h, ")"); write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); break; case EXPR_SIZEOF: fprintf(h, "sizeof("); - write_type_decl(h, &e->u.tref, NULL); + write_type_decl(h, &e->u.var->declspec, NULL); fprintf(h, ")"); break; case EXPR_SHL: @@ -909,7 +908,7 @@ return ret; return compare_expr(a->u.ext, b->u.ext); case EXPR_CAST: - ret = compare_type(a->u.tref.type, b->u.tref.type); + ret = compare_type(a->u.var->declspec.type, b->u.var->declspec.type); if (ret != 0) return ret; /* Fall through. */ @@ -921,7 +920,7 @@ case EXPR_POS: return compare_expr(a->ref, b->ref); case EXPR_SIZEOF: - return compare_type(a->u.tref.type, b->u.tref.type); + return compare_type(a->u.var->declspec.type, b->u.var->declspec.type); case EXPR_VOID: return 0; }
diff --git a/mingw-w64-tools/widl/src/header.c b/mingw-w64-tools/widl/src/header.c index e2ce883..81a789a 100644 --- a/mingw-w64-tools/widl/src/header.c +++ b/mingw-w64-tools/widl/src/header.c
@@ -1589,7 +1589,7 @@ char *name; int ver; if (!winrt_mode) return; - type = expr->u.tref.type; + type = expr->u.var->declspec.type; write_apicontract( header, type ); ver = expr->ref->u.integer.value; name = format_apicontract_macro(type); @@ -1603,7 +1603,7 @@ char *name; int ver; if (!winrt_mode) return; - type = expr->u.tref.type; + type = expr->u.var->declspec.type; ver = expr->ref->u.integer.value; name = format_apicontract_macro(type); fprintf(header, "#endif /* %s_VERSION >= %#x */\n", name, ver); @@ -1977,6 +1977,26 @@ } } +static void write_header_stmts( FILE *header, const statement_list_t *stmts, const type_t *iface, int ignore_funcs ); + +static void write_header_com_interface( FILE *header, type_t *iface, const type_t *ref_iface ) +{ + type_t *inherit_from; + + if (iface->written) return; + + /* ensure declaration of inherited interface exists before ours (C++ requires this) */ + inherit_from = type_iface_get_inherit( iface ); + if (inherit_from && !inherit_from->ignore) + write_header_com_interface( header, inherit_from, inherit_from ); + + write_com_interface_start( header, iface ); + write_header_stmts( header, type_iface_get_stmts(iface), ref_iface, TRUE ); + write_com_interface_end( header, iface ); + + iface->written = true; +} + static void write_header_stmts(FILE *header, const statement_list_t *stmts, const type_t *iface, int ignore_funcs) { const statement_t *stmt; @@ -1993,9 +2013,7 @@ if (is_object(iface)) is_object_interface++; if (is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE) || is_object(stmt->u.type)) { - write_com_interface_start(header, iface); - write_header_stmts(header, type_iface_get_stmts(iface), stmt->u.type, TRUE); - write_com_interface_end(header, iface); + write_header_com_interface(header, iface, stmt->u.type); if (async_iface) { write_com_interface_start(header, async_iface); @@ -2028,7 +2046,7 @@ case STMT_TYPEREF: /* FIXME: shouldn't write out forward declarations for undefined * interfaces but a number of our IDL files depend on this */ - if (type_get_type(stmt->u.type) == TYPE_INTERFACE && !stmt->u.type->written) + if (type_get_type(stmt->u.type) == TYPE_INTERFACE) write_forward(header, stmt->u.type); break; case STMT_IMPORTLIB:
diff --git a/mingw-w64-tools/widl/src/metadata.c b/mingw-w64-tools/widl/src/metadata.c index 348553e..bd953c5 100644 --- a/mingw-w64-tools/widl/src/metadata.c +++ b/mingw-w64-tools/widl/src/metadata.c
@@ -108,12 +108,12 @@ enum { - STREAM_TABLE, - STREAM_STRING, - STREAM_USERSTRING, - STREAM_GUID, - STREAM_BLOB, - STREAM_MAX + WINMD_STREAM_TABLE, + WINMD_STREAM_STRING, + WINMD_STREAM_USERSTRING, + WINMD_STREAM_GUID, + WINMD_STREAM_BLOB, + WINMD_STREAM_MAX }; static struct @@ -146,7 +146,7 @@ put_data( &nt_header, sizeof(nt_header) ); - for (i = 0; i < STREAM_MAX; i++) + for (i = 0; i < WINMD_STREAM_MAX; i++) { if (!streams[i].data_size) continue; streams_size += streams[i].header_size + streams[i].data_size; @@ -171,7 +171,7 @@ metadata_header.num_streams = num_streams; put_data( &metadata_header, sizeof(metadata_header) ); - for (i = 0; i < STREAM_MAX; i++) + for (i = 0; i < WINMD_STREAM_MAX; i++) { if (!streams[i].data_size) continue; put_data( &streams[i], streams[i].header_size ); @@ -1555,6 +1555,36 @@ return len; } +static UINT make_member_sig3( UINT token, BYTE *buf ) +{ + UINT len = 4; + + buf[0] = SIG_TYPE_HASTHIS; + buf[1] = 3; + buf[2] = ELEMENT_TYPE_VOID; + buf[3] = ELEMENT_TYPE_CLASS; + len += encode_int( token, buf + 4 ); + buf[len++] = ELEMENT_TYPE_U4; + buf[len++] = ELEMENT_TYPE_STRING; + return len; +} + +static UINT make_member_sig4( UINT token, UINT token2, BYTE *buf ) +{ + UINT len = 4; + + buf[0] = SIG_TYPE_HASTHIS; + buf[1] = 4; + buf[2] = ELEMENT_TYPE_VOID; + buf[3] = ELEMENT_TYPE_CLASS; + len += encode_int( token, buf + 4 ); + buf[len++] = ELEMENT_TYPE_VALUETYPE; + len += encode_int( token2, buf + len ); + buf[len++] = ELEMENT_TYPE_U4; + buf[len++] = ELEMENT_TYPE_STRING; + return len; +} + static UINT make_type_sig( const type_t *type, BYTE *buf ) { UINT len = 0; @@ -1614,13 +1644,13 @@ return len; } -static UINT make_method_sig( const var_t *method, BYTE *buf ) +static UINT make_method_sig( const var_t *method, BYTE *buf, BOOL is_static ) { const var_t *arg; const var_list_t *arg_list = type_function_get_args( method->declspec.type ); UINT len = 3; - buf[0] = SIG_TYPE_HASTHIS; + buf[0] = is_static ? SIG_TYPE_DEFAULT : SIG_TYPE_HASTHIS; buf[1] = 0; buf[2] = ELEMENT_TYPE_VOID; @@ -1646,13 +1676,13 @@ return len; } -static UINT make_property_sig( const var_t *method, BYTE *buf ) +static UINT make_property_sig( const var_t *method, BYTE *buf, BOOL is_static ) { const var_t *arg; const var_list_t *arg_list = type_function_get_args( method->declspec.type ); UINT len = 3; - buf[0] = SIG_TYPE_HASTHIS | SIG_TYPE_PROPERTY; + buf[0] = is_static ? SIG_TYPE_PROPERTY : SIG_TYPE_HASTHIS | SIG_TYPE_PROPERTY; buf[1] = 0; buf[2] = ELEMENT_TYPE_VOID; @@ -1668,6 +1698,48 @@ return len; } +static UINT make_activation_sig( const var_t *method, BYTE *buf ) +{ + const var_t *arg; + UINT len = 3; + + buf[0] = SIG_TYPE_HASTHIS; + buf[1] = 0; + buf[2] = ELEMENT_TYPE_VOID; + + if (method) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry ) + { + if (is_attr( arg->attrs, ATTR_RETVAL )) continue; + len += make_type_sig( arg->declspec.type, buf + len ); + buf[1]++; + } + + return len; +} + +static UINT make_composition_sig( const var_t *method, BYTE *buf ) +{ + const var_t *arg; + UINT len = 3, count = 0; + + buf[0] = SIG_TYPE_HASTHIS; + buf[1] = 0; + buf[2] = ELEMENT_TYPE_VOID; + + if (method) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry ) count++; + + if (method) assert( count >= 3 ); + + if (count > 3) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry ) + { + if (--count < 3) break; /* omit last 3 standard composition args */ + len += make_type_sig( arg->declspec.type, buf + len ); + buf[1]++; + } + + return len; +} + static UINT make_deprecated_sig( UINT token, BYTE *buf ) { UINT len = 5; @@ -1686,9 +1758,10 @@ static UINT make_contract_value( const type_t *type, BYTE *buf ) { - const expr_t *contract = get_attrp( type->attrs, ATTR_CONTRACT ); - char *name = format_namespace( contract->u.tref.type->namespace, "", ".", contract->u.tref.type->name, NULL ); - UINT version = contract->ref->u.integer.value, len = strlen( name ); + const expr_t *attr = get_attrp( type->attrs, ATTR_CONTRACT ); + const type_t *contract = attr->u.var->declspec.type; + char *name = format_namespace( contract->namespace, "", ".", contract->name, NULL ); + UINT version = attr->ref->u.integer.value, len = strlen( name ); buf[0] = 1; buf[1] = 0; @@ -2056,6 +2129,7 @@ { static const BYTE zero[] = { 0x00, 0x00, 0x00, 0x00 }, one[] = { 0x01, 0x00, 0x00, 0x00 }; const expr_t *attr = get_attrp( method->attrs, ATTR_DEPRECATED ); + const type_t *type = attr->ext2->u.var->declspec.type; const char *text = attr->ref->u.sval; const char *kind = attr->u.ext->u.sval; BYTE encoded[4]; @@ -2077,7 +2151,7 @@ buf[len++] = 1; buf[len++] = 0; - contract = format_namespace( attr->ext2->u.tref.type->namespace, "", ".", attr->ext2->u.tref.type->name, NULL ); + contract = format_namespace( type->namespace, "", ".", type->name, NULL ); len_text = strlen( contract ); buf[len++] = len_text; memcpy( buf + len, contract, len_text ); @@ -2146,18 +2220,24 @@ } } +static void add_runtimeclass_type_step1( type_t * ); + static void add_interface_type_step1( type_t *type ) { const statement_t *stmt; UINT name, namespace; + type_t *class; name = add_name( type, &namespace ); type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace ); + add_exclusiveto_attr_step1( type ); + + if ((class = type->details.iface->runtime_class)) add_runtimeclass_type_step1( class ); + add_contract_attr_step1( type ); add_uuid_attr_step1( type ); - add_exclusiveto_attr_step1( type ); STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(type) ) { @@ -2221,28 +2301,53 @@ return strmake( "%s", method->name ); } -static UINT get_method_attrs( BOOL abstract, BOOL special, UINT *flags ) +static BOOL is_special_method( const var_t *method ) { - UINT attrs = METHOD_ATTR_PUBLIC | METHOD_ATTR_VIRTUAL | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_NEWSLOT; + if (is_attr( method->attrs, ATTR_PROPGET ) || is_attr( method->attrs, ATTR_PROPPUT ) || + is_attr( method->attrs, ATTR_EVENTADD ) || is_attr( method->attrs, ATTR_EVENTREMOVE )) return TRUE; + return FALSE; +} - if (abstract) +static BOOL is_static_iface( const type_t *class, const type_t *iface ) +{ + const attr_t *attr; + + if (!class || !class->attrs) return FALSE; + + LIST_FOR_EACH_ENTRY( attr, class->attrs, const attr_t, entry ) + { + const expr_t *value = attr->u.pval; + + if (attr->type != ATTR_STATIC) continue; + if (value->u.var->declspec.type == iface) return TRUE; + } + + return FALSE; +} + +static UINT get_method_attrs( const type_t *class, const type_t *iface, const var_t *method, UINT *flags ) +{ + UINT attrs = METHOD_ATTR_PUBLIC | METHOD_ATTR_HIDEBYSIG; + + if (!class) { *flags = 0; - attrs |= METHOD_ATTR_ABSTRACT; + attrs |= METHOD_ATTR_ABSTRACT | METHOD_ATTR_VIRTUAL | METHOD_ATTR_NEWSLOT; } else { *flags = METHOD_IMPL_RUNTIME; - attrs |= METHOD_ATTR_FINAL; + if (is_static_iface( class, iface )) attrs |= METHOD_ATTR_STATIC; + else attrs |= METHOD_ATTR_VIRTUAL | METHOD_ATTR_NEWSLOT | METHOD_ATTR_FINAL; } - if (special) attrs |= METHOD_ATTR_SPECIALNAME; + if (is_special_method( method )) attrs |= METHOD_ATTR_SPECIALNAME; return attrs; } static void add_propget_method( const type_t *class, const type_t *iface, const var_t *method ) { - UINT sig_size, property, paramlist, flags, attrs = get_method_attrs( class == NULL, TRUE, &flags ); + UINT sig_size, property, paramlist, flags, attrs = get_method_attrs( class, iface, method, &flags ); char *name = get_method_name( method ); type_t *type = method->declspec.type; BYTE sig[256]; @@ -2251,7 +2356,7 @@ else property = type->md.iface_property; paramlist = add_method_params_step2( type_function_get_args(type) ); - sig_size = make_method_sig( method, sig ); + sig_size = make_method_sig( method, sig, is_static_iface(class, iface) ); type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); add_methodsemantics_row( METHOD_SEM_GETTER, type->md.def, has_semantics(TABLE_PROPERTY, property) ); @@ -2273,13 +2378,13 @@ static void add_propput_method( const type_t *class, const type_t *iface, const var_t *method ) { const var_t *propget = find_propget_method( iface, method->name ); - UINT sig_size, paramlist, property, flags, attrs = get_method_attrs( class == NULL, TRUE, &flags ); + UINT sig_size, paramlist, property, flags, attrs = get_method_attrs( class, iface, method, &flags ); char *name = get_method_name( method ); type_t *type = method->declspec.type; BYTE sig[256]; paramlist = add_method_params_step2( type_function_get_args(method->declspec.type) ); - sig_size = make_method_sig( method, sig ); + sig_size = make_method_sig( method, sig, is_static_iface(class, iface) ); type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); free( name ); @@ -2301,7 +2406,7 @@ static void add_eventadd_method( const type_t *class, const type_t *iface, const var_t *method ) { - UINT event, sig_size, paramlist, flags, attrs = get_method_attrs( class == NULL, TRUE, &flags ); + UINT event, sig_size, paramlist, flags, attrs = get_method_attrs( class, iface, method, &flags ); char *name = get_method_name( method ); type_t *type = method->declspec.type; BYTE sig[256]; @@ -2310,7 +2415,7 @@ else event = type->md.iface_event; paramlist = add_method_params_step2( type_function_get_args(type) ); - sig_size = make_method_sig( method, sig ); + sig_size = make_method_sig( method, sig, is_static_iface(class, iface) ); type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); free( name ); @@ -2333,13 +2438,13 @@ static void add_eventremove_method( const type_t *class, const type_t *iface, const var_t *method ) { const var_t *eventadd = find_eventadd_method( iface, method->name ); - UINT event, sig_size, paramlist, flags, attrs = get_method_attrs( class == NULL, TRUE, &flags ); + UINT event, sig_size, paramlist, flags, attrs = get_method_attrs( class, iface, method, &flags ); char *name = get_method_name( method ); type_t *type = method->declspec.type; BYTE sig[256]; paramlist = add_method_params_step2( type_function_get_args(type) ); - sig_size = make_method_sig( method, sig ); + sig_size = make_method_sig( method, sig, is_static_iface(class, iface) ); type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); free( name ); @@ -2361,13 +2466,13 @@ static void add_regular_method( const type_t *class, const type_t *iface, const var_t *method ) { - UINT paramlist, sig_size, flags, attrs = get_method_attrs( class == NULL, FALSE, &flags ); + UINT paramlist, sig_size, flags, attrs = get_method_attrs( class, iface, method, &flags ); char *name = get_method_name( method ); type_t *type = method->declspec.type; BYTE sig[256]; paramlist = add_method_params_step2( type_function_get_args(type) ); - sig_size = make_method_sig( method, sig ); + sig_size = make_method_sig( method, sig, is_static_iface(class, iface) ); type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); free( name ); @@ -2381,7 +2486,7 @@ if (!is_attr( method->attrs, ATTR_PROPGET )) return; - sig_size = make_property_sig( method, sig ); + sig_size = make_property_sig( method, sig, is_static_iface(class, iface) ); if (class) { type->md.class_property = add_property_row( 0, add_string(method->name), add_blob(sig, sig_size) ); @@ -2432,12 +2537,15 @@ else add_regular_method( class, iface, method ); } +static void add_runtimeclass_type_step2( type_t *type ); + static void add_interface_type_step2( type_t *type ) { UINT name, namespace, interface, flags = TYPE_ATTR_INTERFACE | TYPE_ATTR_ABSTRACT | TYPE_ATTR_UNKNOWN; const typeref_list_t *require_list = type_iface_get_requires( type ); const typeref_t *require; const statement_t *stmt; + type_t *class; name = add_name( type, &namespace ); @@ -2463,6 +2571,8 @@ add_overload_attr_step2( method ); } + if ((class = type->details.iface->runtime_class)) add_runtimeclass_type_step2( class ); + add_contract_attr_step2( type ); add_uuid_attr_step2( type ); add_exclusiveto_attr_step2( type ); @@ -2562,11 +2672,29 @@ { UINT name, namespace; - name = add_name( type, &namespace ); + if (type->md.ref) return; + name = add_name( type, &namespace ); type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace ); } +static void add_default_attr( const type_t *type, UINT interfaceimpl_ref ) +{ + static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID }; + static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 }; + UINT assemblyref, scope, typeref, class, memberref, parent, attr_type; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref = add_typeref_row( scope, add_string("DefaultAttribute"), add_string("Windows.Foundation.Metadata") ); + class = memberref_parent( TABLE_TYPEREF, typeref ); + memberref = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) ); + + parent = has_customattribute( TABLE_INTERFACEIMPL, interfaceimpl_ref ); + attr_type = customattribute_type( TABLE_MEMBERREF, memberref ); + add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) ); +} + static void add_method_impl( const type_t *class, const type_t *iface, const var_t *method ) { UINT parent, memberref, body, decl, sig_size; @@ -2575,7 +2703,7 @@ BYTE sig[256]; parent = memberref_parent( TABLE_TYPEREF, iface->md.ref ); - sig_size = make_method_sig( method, sig ); + sig_size = make_method_sig( method, sig, FALSE ); memberref = add_memberref_row( parent, add_string(name), add_blob(sig, sig_size) ); free( name ); @@ -2609,48 +2737,584 @@ } } -static void add_runtimeclass_type_step2( type_t *type ) +static UINT make_static_value( const expr_t *attr, BYTE *buf ) { - UINT name, namespace, scope, extends, typeref, interface, flags; - typeref_list_t *iface_list = type_runtimeclass_get_ifaces( type ); - typeref_t *iface; - const statement_t *stmt; + const expr_t *contract = attr->ref; + const type_t *type_iface = attr->u.var->declspec.type, *type_contract = contract->u.var->declspec.type; + char *name_iface = format_namespace( type_iface->namespace, "", ".", type_iface->name, NULL ); + char *name_contract = format_namespace( type_contract->namespace, "", ".", type_contract->name, NULL ); + UINT len_iface = strlen( name_iface ), len_contract = strlen( name_contract ); + BYTE *ptr = buf; - name = add_name( type, &namespace ); + ptr[0] = 1; + ptr[1] = 0; + ptr[2] = len_iface; + memcpy( ptr + 3, name_iface, len_iface ); + ptr += len_iface + 3; + ptr[0] = ptr[1] = 0; + + ptr += 2; + ptr[0] = 1; + ptr[1] = 0; + ptr[2] = len_contract; + memcpy( ptr + 3, name_contract, len_contract ); + ptr += len_contract + 3; + ptr[0] = ptr[1] = 0; + + free( name_iface ); + free( name_contract ); + return len_iface + len_contract + 10; +} + +static void add_static_attr_step1( type_t *type ) +{ + UINT assemblyref, scope, typeref, typeref_type, class, sig_size; + BYTE sig[32]; + + if (!is_attr( type->attrs, ATTR_STATIC )) return; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref = add_typeref_row( scope, add_string("StaticAttribute"), add_string("Windows.Foundation.Metadata") ); scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); - typeref = add_typeref_row( scope, add_string("Object"), add_string("System") ); + typeref_type = add_typeref_row( scope, add_string("Type"), add_string("System") ); - extends = typedef_or_ref( TABLE_TYPEREF, typeref ); - flags = TYPE_ATTR_PUBLIC | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN; - type->md.def = add_typedef_row( flags, name, namespace, extends, 0, 0 ); + class = memberref_parent( TABLE_TYPEREF, typeref ); + sig_size = make_member_sig3( typedef_or_ref(TABLE_TYPEREF, typeref_type), sig ); + type->md.member[MD_ATTR_STATIC] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) ); +} + +static void add_static_attr_step2( type_t *type ) +{ + const attr_t *attr; + + if (type->attrs) LIST_FOR_EACH_ENTRY_REV( attr, type->attrs, const attr_t, entry ) + { + UINT parent, attr_type, value_size; + BYTE value[MAX_NAME * 2 + 10]; + + if (attr->type != ATTR_STATIC) continue; + + parent = has_customattribute( TABLE_TYPEDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_STATIC] ); + value_size = make_static_value( attr->u.pval, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); + } +} + +static UINT make_activatable_value( const expr_t *attr, BYTE *buf ) +{ + char *name_iface = NULL, *name_contract; + const type_t *type_iface, *type_contract; + UINT version, len_iface = 0, len_contract, len_extra = 5; + BYTE *ptr = buf; + + if (attr->type == EXPR_MEMBER) + { + type_iface = attr->u.var->declspec.type; + name_iface = format_namespace( type_iface->namespace, "", ".", type_iface->name, NULL ); + len_iface = strlen( name_iface ); + + type_contract = attr->ref->u.var->declspec.type; + version = attr->ref->ref->u.integer.value; + } + else + { + type_contract = attr->u.var->declspec.type; + version = attr->ref->u.integer.value; + } + + name_contract = format_namespace( type_contract->namespace, "", ".", type_contract->name, NULL ); + len_contract = strlen( name_contract ); + + if (len_iface) + { + ptr[0] = 1; + ptr[1] = 0; + ptr[2] = len_iface; + memcpy( ptr + 3, name_iface, len_iface ); + ptr += len_iface + 3; + ptr[0] = ptr[1] = 0; + ptr += 2; + len_extra += 5; + } + + ptr[0] = 1; + ptr[1] = 0; + memcpy( ptr + 2, &version, sizeof(version) ); + ptr += sizeof(version) + 2; + + ptr[0] = len_contract; + memcpy( ptr + 1, name_contract, len_contract ); + ptr += len_contract + 1; + ptr[0] = ptr[1] = 0; + + free( name_iface ); + free( name_contract ); + return len_iface + sizeof(version) + len_contract + len_extra; +} + +static void add_activatable_attr_step1( type_t *type ) +{ + static const BYTE sig_default[] = { SIG_TYPE_HASTHIS, 2, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4, ELEMENT_TYPE_STRING }; + attr_t *attr; + + if (type->attrs) LIST_FOR_EACH_ENTRY_REV( attr, type->attrs, attr_t, entry ) + { + UINT assemblyref, scope, typeref, typeref_type, class, sig_size; + const expr_t *value = attr->u.pval; + BYTE sig[32]; + + if (attr->type != ATTR_ACTIVATABLE) continue; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref = add_typeref_row( scope, add_string("ActivatableAttribute"), add_string("Windows.Foundation.Metadata") ); + + scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); + typeref_type = add_typeref_row( scope, add_string("Type"), add_string("System") ); + + class = memberref_parent( TABLE_TYPEREF, typeref ); + + if (value->type == EXPR_MEMBER) + sig_size = make_member_sig3( typedef_or_ref(TABLE_TYPEREF, typeref_type), sig ); + else + { + memcpy( sig, sig_default, sizeof(sig_default) ); + sig_size = sizeof(sig_default); + } + + attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) ); + } +} + +static void add_activatable_attr_step2( type_t *type ) +{ + const attr_t *attr; + + if (type->attrs) LIST_FOR_EACH_ENTRY_REV( attr, type->attrs, const attr_t, entry ) + { + UINT parent, attr_type, value_size; + BYTE value[MAX_NAME * 2 + sizeof(UINT) + 10]; + + if (attr->type != ATTR_ACTIVATABLE) continue; + + parent = has_customattribute( TABLE_TYPEDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member ); + value_size = make_activatable_value( attr->u.pval, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); + } +} + +static UINT make_threading_value( const type_t *type, BYTE *buf ) +{ + UINT value, model = get_attrv( type->attrs, ATTR_THREADING ); + + switch (model) + { + case THREADING_SINGLE: + value = 1; + break; + case THREADING_FREE: + value = 2; + break; + case THREADING_BOTH: + value = 3; + break; + default: + fprintf( stderr, "Unhandled model %u.\n", model ); + return 0; + } + + buf[0] = 1; + buf[1] = 0; + memcpy( buf + 2, &value, sizeof(value) ); + buf[6] = buf[7] = 0; + return 8; +} + +static void add_threading_attr_step1( type_t *type ) +{ + UINT assemblyref, scope, typeref, typeref_attr, class, sig_size; + BYTE sig[32]; + + if (!is_attr( type->attrs, ATTR_THREADING )) return; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref = add_typeref_row( scope, add_string("ThreadingModel"), add_string("Windows.Foundation.Metadata") ); + + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref_attr = add_typeref_row( scope, add_string("ThreadingAttribute"), add_string("Windows.Foundation.Metadata") ); + + class = memberref_parent( TABLE_TYPEREF, typeref_attr ); + sig_size = make_member_sig2( ELEMENT_TYPE_VALUETYPE, typedef_or_ref(TABLE_TYPEREF, typeref), sig ); + type->md.member[MD_ATTR_THREADING] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) ); +} + +static void add_threading_attr_step2( type_t *type ) +{ + UINT parent, attr_type, value_size; + BYTE value[8]; + + if (!is_attr( type->attrs, ATTR_THREADING )) return; + + parent = has_customattribute( TABLE_TYPEDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_THREADING] ); + value_size = make_threading_value( type, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); +} + +static UINT make_marshalingbehavior_value( const type_t *type, BYTE *buf ) +{ + UINT marshaling = get_attrv( type->attrs, ATTR_MARSHALING_BEHAVIOR ); + + buf[0] = 1; + buf[1] = 0; + memcpy( buf + 2, &marshaling, sizeof(marshaling) ); + buf[6] = buf[7] = 0; + return 8; +} + +static void add_marshalingbehavior_attr_step1( type_t *type ) +{ + UINT assemblyref, scope, typeref, typeref_attr, class, sig_size; + BYTE sig[32]; + + if (!is_attr( type->attrs, ATTR_MARSHALING_BEHAVIOR )) return; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref = add_typeref_row( scope, add_string("MarshalingType"), add_string("Windows.Foundation.Metadata") ); + + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref_attr = add_typeref_row( scope, add_string("MarshalingBehaviorAttribute"), add_string("Windows.Foundation.Metadata") ); + + class = memberref_parent( TABLE_TYPEREF, typeref_attr ); + sig_size = make_member_sig2( ELEMENT_TYPE_VALUETYPE, typedef_or_ref(TABLE_TYPEREF, typeref), sig ); + type->md.member[MD_ATTR_MARSHALINGBEHAVIOR] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) ); +} + +static void add_marshalingbehavior_attr_step2( type_t *type ) +{ + UINT parent, attr_type, value_size; + BYTE value[8]; + + if (!is_attr( type->attrs, ATTR_MARSHALING_BEHAVIOR )) return; + + parent = has_customattribute( TABLE_TYPEDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_MARSHALINGBEHAVIOR] ); + value_size = make_marshalingbehavior_value( type, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); +} + +static UINT make_composable_value( const expr_t *attr, BYTE *buf ) +{ + char *name_iface, *name_contract; + const expr_t *contract = attr->ref; + const type_t *type_iface = attr->u.var->declspec.type; + const type_t *type_contract = contract->u.var->declspec.type; + UINT access_type = 1, contract_version = contract->ref->u.integer.value; + UINT len_iface, len_contract; + BYTE *ptr = buf; + + name_iface = format_namespace( type_iface->namespace, "", ".", type_iface->name, NULL ); + len_iface = strlen( name_iface ); + + name_contract = format_namespace( type_contract->namespace, "", ".", type_contract->name, NULL ); + len_contract = strlen( name_contract ); + + ptr[0] = 1; + ptr[1] = 0; + ptr[2] = len_iface; + memcpy( ptr + 3, name_iface, len_iface ); + ptr += len_iface + 3; + + if (is_attr( attr->u.var->attrs, ATTR_PUBLIC)) access_type = 2; + memcpy( ptr, &access_type, sizeof(access_type) ); + ptr += sizeof(access_type); + + memcpy( ptr, &contract_version, sizeof(contract_version) ); + ptr += sizeof(contract_version); + + ptr[0] = len_contract; + memcpy( ptr + 1, name_contract, len_contract ); + ptr += len_contract + 1; + ptr[0] = ptr[1] = 0; + + free( name_iface ); + free( name_contract ); + return len_iface + sizeof(access_type) + sizeof(contract_version) + len_contract + 6; +} + +static void add_composable_attr_step1( type_t *type ) +{ + attr_t *attr; + + if (type->attrs) LIST_FOR_EACH_ENTRY( attr, type->attrs, attr_t, entry ) + { + UINT assemblyref, scope, typeref, typeref_attr, typeref_type, class, sig_size; + BYTE sig[64]; + + if (attr->type != ATTR_COMPOSABLE) continue; + + scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); + typeref_type = add_typeref_row( scope, add_string("Type"), add_string("System") ); + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref = add_typeref_row( scope, add_string("CompositionType"), add_string("Windows.Foundation.Metadata") ); + typeref_attr = add_typeref_row( scope, add_string("ComposableAttribute"), add_string("Windows.Foundation.Metadata") ); + + class = memberref_parent( TABLE_TYPEREF, typeref_attr ); + sig_size = make_member_sig4( typedef_or_ref(TABLE_TYPEREF, typeref_type), typedef_or_ref(TABLE_TYPEREF, typeref), sig ); + attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) ); + } +} + +static void add_composable_attr_step2( type_t *type ) +{ + const attr_t *attr; + + if (type->attrs) LIST_FOR_EACH_ENTRY( attr, type->attrs, const attr_t, entry ) + { + UINT parent, attr_type, value_size; + BYTE value[MAX_NAME + sizeof(UINT) * 2 + 6]; + + if (attr->type != ATTR_COMPOSABLE) continue; + + parent = has_customattribute( TABLE_TYPEDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member ); + value_size = make_composable_value( attr->u.pval, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); + } +} + +static void add_member_interfaces( type_t *class ) +{ + const typeref_list_t *iface_list = type_runtimeclass_get_ifaces( class ); + const typeref_t *iface; if (iface_list) LIST_FOR_EACH_ENTRY( iface, iface_list, typeref_t, entry ) { - interface = typedef_or_ref( TABLE_TYPEREF, iface->type->md.ref ); - add_interfaceimpl_row( type->md.def, interface ); + UINT interface = typedef_or_ref( TABLE_TYPEREF, iface->type->md.ref ); + UINT interfaceimpl_ref = add_interfaceimpl_row( class->md.def, interface ); + const statement_t *stmt; + + if (is_attr( iface->attrs, ATTR_DEFAULT )) add_default_attr( class, interfaceimpl_ref ); /* add properties in reverse order like midlrt */ STATEMENTS_FOR_EACH_FUNC_REV( stmt, type_iface_get_stmts(iface->type) ) { const var_t *method = stmt->u.var; - add_property( type, iface->type, method ); + add_property( class, iface->type, method ); } STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface->type) ) { const var_t *method = stmt->u.var; - add_event( type, iface->type, method ); - add_method( type, iface->type, method ); - add_method_impl( type, iface->type, method ); - add_method_contract_attrs( type, iface->type, method->declspec.type ); + add_event( class, iface->type, method ); + add_method( class, iface->type, method ); + add_method_impl( class, iface->type, method ); + add_method_contract_attrs( class, iface->type, method->declspec.type ); } } +} +static void add_static_interfaces( type_t *class ) +{ + const attr_t *attr; + + if (class->attrs) LIST_FOR_EACH_ENTRY( attr, class->attrs, const attr_t, entry ) + { + const expr_t *value = attr->u.pval; + const statement_t *stmt; + type_t *iface; + + if (attr->type != ATTR_STATIC) continue; + + iface = value->u.var->declspec.type; + + STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) + { + const var_t *method = stmt->u.var; + + add_property( class, iface, method ); + add_event( class, iface, method ); + add_method( class, iface, method ); + add_method_contract_attrs( class, iface, method->declspec.type ); + } + } +} + +static void add_activation_interfaces( const type_t *class ) +{ + UINT flags = METHOD_ATTR_PUBLIC | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_SPECIALNAME | METHOD_ATTR_RTSPECIALNAME; + const attr_t *attr; + + if (class->attrs) LIST_FOR_EACH_ENTRY_REV( attr, class->attrs, const attr_t, entry ) + { + UINT methoddef, parent, attr_type, value_size, paramlist = 0, sig_size; + BYTE value[MAX_NAME + sizeof(UINT) + 5], sig[256]; + const expr_t *activatable = attr->u.pval; + const type_t *iface = NULL; + const var_t *method = NULL, *arg; + const statement_t *stmt; + + if (attr->type != ATTR_ACTIVATABLE) continue; + + /* interface is optional */ + if (activatable->type == EXPR_MEMBER) iface = activatable->u.var->declspec.type; + + if (iface) STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) + { + UINT seq = 1, row; + + method = stmt->u.var; + + LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry ) + { + if (is_attr( arg->attrs, ATTR_RETVAL )) continue; + row = add_param_row( get_param_attrs(arg), seq++, add_string(arg->name) ); + if (!paramlist) paramlist = row; + } + break; + } + + sig_size = make_activation_sig( method, sig ); + methoddef = add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string(".ctor"), add_blob(sig, sig_size), paramlist ); + + parent = has_customattribute( TABLE_METHODDEF, methoddef ); + attr_type = customattribute_type( TABLE_MEMBERREF, class->md.member[MD_ATTR_CONTRACT] ); + value_size = make_contract_value( class, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); + } +} + +static void add_composition_interfaces( const type_t *class ) +{ + UINT flags = METHOD_ATTR_FAMILY | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_SPECIALNAME | METHOD_ATTR_RTSPECIALNAME; + const attr_t *attr; + + if (class->attrs) LIST_FOR_EACH_ENTRY_REV( attr, class->attrs, const attr_t, entry ) + { + UINT methoddef, parent, attr_type, value_size, paramlist = 0, sig_size; + BYTE value[MAX_NAME + sizeof(UINT) + 5], sig[256]; + const expr_t *composable = attr->u.pval; + const var_t *method = NULL, *arg; + const statement_t *stmt; + const type_t *iface; + + if (attr->type != ATTR_COMPOSABLE) continue; + + iface = composable->u.var->declspec.type; + + STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) + { + UINT seq = 1, row, count = 0; + + method = stmt->u.var; + + LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry ) count++; + + if (count > 3) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry ) + { + if (--count < 3) break; /* omit last 3 standard composition args */ + row = add_param_row( get_param_attrs(arg), seq++, add_string(arg->name) ); + if (!paramlist) paramlist = row; + } + break; + } + + sig_size = make_composition_sig( method, sig ); + methoddef = add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string(".ctor"), add_blob(sig, sig_size), paramlist ); + + parent = has_customattribute( TABLE_METHODDEF, methoddef ); + attr_type = customattribute_type( TABLE_MEMBERREF, class->md.member[MD_ATTR_CONTRACT] ); + value_size = make_contract_value( class, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); + } +} + +static void add_constructor_overload( const type_t *type ) +{ + static const BYTE sig_default[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID }; + static const BYTE sig_overload[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING }; + UINT name, namespace; + const attr_t *attr; + + if (type->attrs) LIST_FOR_EACH_ENTRY_REV( attr, type->attrs, const attr_t, entry ) + { + const expr_t *value = attr->u.pval; + + if (attr->type == ATTR_COMPOSABLE || (attr->type == ATTR_ACTIVATABLE && value->type == EXPR_MEMBER)) + { + UINT assemblyref, scope, typeref_default, typeref_overload, class; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + + name = add_string( "DefaultOverloadAttribute" ); + namespace = add_string( "Windows.Foundation.Metadata" ); + typeref_default = add_typeref_row( scope, name, namespace ); + + class = memberref_parent( TABLE_TYPEREF, typeref_default ); + add_memberref_row( class, add_string(".ctor"), add_blob(sig_default, sizeof(sig_default)) ); + + name = add_string( "OverloadAttribute" ); + typeref_overload = add_typeref_row( scope, name, namespace ); + + class = memberref_parent( TABLE_TYPEREF, typeref_overload ); + add_memberref_row( class, add_string(".ctor"), add_blob(sig_overload, sizeof(sig_overload)) ); + break; + } + } +} + +static void add_runtimeclass_type_step2( type_t *type ) +{ + const typeref_list_t *iface_list = type_runtimeclass_get_ifaces( type ); + UINT name, namespace, scope, extends, typeref, flags; + + if (type->md.def) return; + + name = add_name( type, &namespace ); + + add_constructor_overload( type ); + + scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); + typeref = add_typeref_row( scope, add_string("Object"), add_string("System") ); + extends = typedef_or_ref( TABLE_TYPEREF, typeref ); + + flags = TYPE_ATTR_PUBLIC | TYPE_ATTR_UNKNOWN; + if (!is_attr( type->attrs, ATTR_COMPOSABLE )) flags |= TYPE_ATTR_SEALED; + if (!iface_list) flags |= TYPE_ATTR_ABSTRACT; + + type->md.def = add_typedef_row( flags, name, namespace, extends, 0, 0 ); + + /* add contract first so activation/composition constructors can inherit it */ add_contract_attr_step1( type ); + + add_activation_interfaces( type ); + add_composition_interfaces( type ); + add_member_interfaces( type ); + add_static_interfaces( type ); + + add_composable_attr_step1( type ); + add_static_attr_step1( type ); + add_activatable_attr_step1( type ); + add_threading_attr_step1( type ); + add_marshalingbehavior_attr_step1( type ); + add_contract_attr_step2( type ); + add_composable_attr_step2( type ); + add_static_attr_step2( type ); + add_activatable_attr_step2( type ); + add_threading_attr_step2( type ); + add_marshalingbehavior_attr_step2( type ); } static void add_delegate_type_step1( type_t *type ) @@ -2694,7 +3358,7 @@ UINT sig_size; BYTE sig[256]; - sig_size = make_method_sig( method, sig ); + sig_size = make_method_sig( method, sig, FALSE ); paramlist = add_method_params_step2( type_function_get_args(method->declspec.type) ); add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string("Invoke"), add_blob(sig, sig_size), paramlist ); @@ -2853,36 +3517,36 @@ len = (tables_disk.offset + 3) & ~3; add_bytes( &tables_disk, pad, len - tables_disk.offset ); - streams[STREAM_TABLE].data_size = tables_disk.offset; - streams[STREAM_TABLE].data = tables_disk.ptr; + streams[WINMD_STREAM_TABLE].data_size = tables_disk.offset; + streams[WINMD_STREAM_TABLE].data = tables_disk.ptr; len = (strings.offset + 3) & ~3; add_bytes( &strings, pad, len - strings.offset ); - streams[STREAM_STRING].data_size = strings.offset; - streams[STREAM_STRING].data = strings.ptr; + streams[WINMD_STREAM_STRING].data_size = strings.offset; + streams[WINMD_STREAM_STRING].data = strings.ptr; len = (userstrings.offset + 3) & ~3; add_bytes( &userstrings, pad, len - userstrings.offset ); - streams[STREAM_USERSTRING].data_size = userstrings.offset; - streams[STREAM_USERSTRING].data = userstrings.ptr; + streams[WINMD_STREAM_USERSTRING].data_size = userstrings.offset; + streams[WINMD_STREAM_USERSTRING].data = userstrings.ptr; len = (blobs.offset + 3) & ~3; add_bytes( &blobs, pad, len - blobs.offset ); - streams[STREAM_BLOB].data_size = blobs.offset; - streams[STREAM_BLOB].data = blobs.ptr; + streams[WINMD_STREAM_BLOB].data_size = blobs.offset; + streams[WINMD_STREAM_BLOB].data = blobs.ptr; - streams[STREAM_GUID].data_size = guids.offset; - streams[STREAM_GUID].data = guids.ptr; + streams[WINMD_STREAM_GUID].data_size = guids.offset; + streams[WINMD_STREAM_GUID].data = guids.ptr; - for (i = 0; i < STREAM_MAX; i++) + for (i = 0; i < WINMD_STREAM_MAX; i++) { if (!streams[i].data_size) continue; offset += streams[i].header_size; } - for (i = 0; i < STREAM_MAX; i++) + for (i = 0; i < WINMD_STREAM_MAX; i++) { if (!streams[i].data_size) continue; streams[i].data_offset = offset; @@ -2893,7 +3557,7 @@ static void write_streams( void ) { UINT i; - for (i = 0; i < STREAM_MAX; i++) + for (i = 0; i < WINMD_STREAM_MAX; i++) { if (!streams[i].data_size) continue; put_data( streams[i].data, streams[i].data_size ); @@ -2905,12 +3569,12 @@ static const BYTE pad[FILE_ALIGNMENT]; UINT image_size, file_size, i; - if (!do_metadata) return; + if (!do_metadata || !winrt_mode) return; build_streams( stmts ); image_size = FILE_ALIGNMENT + sizeof(cor_header) + 8 + sizeof(metadata_header); - for (i = 0; i < STREAM_MAX; i++) image_size += streams[i].header_size + streams[i].data_size; + for (i = 0; i < WINMD_STREAM_MAX; i++) image_size += streams[i].header_size + streams[i].data_size; init_output_buffer();
diff --git a/mingw-w64-tools/widl/src/parser.tab.c b/mingw-w64-tools/widl/src/parser.tab.c index 92bf76b..d521169 100644 --- a/mingw-w64-tools/widl/src/parser.tab.c +++ b/mingw-w64-tools/widl/src/parser.tab.c
@@ -8115,6 +8115,11 @@ !is_local(stmt->u.type->attrs)) { const statement_t *stmt_func; + const type_t *type = stmt->u.type; + if (type->details.iface && type->details.iface->inherit && !type_is_complete(type->details.iface->inherit)) + error_at(&type->where, "interface %s can't inherit from incomplete interface %s\n", + type->name, type->details.iface->inherit->name); + STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(stmt->u.type)) { const var_t *func = stmt_func->u.var; if (type_function_get_args(func->declspec.type))
diff --git a/mingw-w64-tools/widl/src/parser.y b/mingw-w64-tools/widl/src/parser.y index 54b1436..5185615 100644 --- a/mingw-w64-tools/widl/src/parser.y +++ b/mingw-w64-tools/widl/src/parser.y
@@ -2826,6 +2826,11 @@ !is_local(stmt->u.type->attrs)) { const statement_t *stmt_func; + const type_t *type = stmt->u.type; + if (type->details.iface && type->details.iface->inherit && !type_is_complete(type->details.iface->inherit)) + error_at(&type->where, "interface %s can't inherit from incomplete interface %s\n", + type->name, type->details.iface->inherit->name); + STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(stmt->u.type)) { const var_t *func = stmt_func->u.var; if (type_function_get_args(func->declspec.type))
diff --git a/mingw-w64-tools/widl/src/typetree.c b/mingw-w64-tools/widl/src/typetree.c index 2f67545..441b6cd 100644 --- a/mingw-w64-tools/widl/src/typetree.c +++ b/mingw-w64-tools/widl/src/typetree.c
@@ -748,6 +748,7 @@ iface->details.iface->inherit = inherit; iface->details.iface->disp_inherit = NULL; iface->details.iface->async_iface = NULL; + iface->details.iface->runtime_class = NULL; iface->details.iface->requires = requires; define_type(iface, where); compute_method_indexes(iface); @@ -845,6 +846,24 @@ return type; } +static void set_constructor_runtimeclass(type_t *runtimeclass, attr_list_t *attrs) +{ + const attr_t *attr; + if (!attrs) return; + LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) + { + if (attr->type == ATTR_ACTIVATABLE || attr->type == ATTR_COMPOSABLE) + { + const expr_t *value = attr->u.pval; + if (value->type == EXPR_MEMBER && value->u.var->declspec.type->type_type == TYPE_INTERFACE && + value->u.var->declspec.type->details.iface) + { + value->u.var->declspec.type->details.iface->runtime_class = runtimeclass; + } + } + } +} + type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, typeref_list_t *ifaces, const struct location *where) { @@ -853,10 +872,10 @@ runtimeclass->attrs = check_runtimeclass_attrs(runtimeclass->name, attrs); runtimeclass->details.runtimeclass.ifaces = ifaces; + set_constructor_runtimeclass(runtimeclass, attrs); define_type(runtimeclass, where); - if (!type_runtimeclass_get_default_iface(runtimeclass, FALSE) && - !get_attrp(runtimeclass->attrs, ATTR_STATIC)) - error_loc("runtimeclass %s must have a default interface or static factory\n", runtimeclass->name); + if (!type_runtimeclass_get_ifaces(runtimeclass) && !get_attrp(runtimeclass->attrs, ATTR_STATIC)) + error_loc("runtimeclass %s must have at least one interface or static factory\n", runtimeclass->name); if (ifaces) LIST_FOR_EACH_ENTRY(ref, ifaces, typeref_t, entry) {
diff --git a/mingw-w64-tools/widl/src/widltypes.h b/mingw-w64-tools/widl/src/widltypes.h index f18c2a9..1706f39 100644 --- a/mingw-w64-tools/widl/src/widltypes.h +++ b/mingw-w64-tools/widl/src/widltypes.h
@@ -346,6 +346,7 @@ /* parser-internal */ struct list entry; struct location where; + unsigned int md_member; }; struct integer @@ -364,7 +365,7 @@ double dval; const char *sval; const expr_t *ext; - decl_spec_t tref; + var_t *var; } u; const expr_t *ext2; int is_const; @@ -402,6 +403,7 @@ struct _type_t *inherit; struct _type_t *disp_inherit; struct _type_t *async_iface; + struct _type_t *runtime_class; typeref_list_t *requires; }; @@ -506,7 +508,6 @@ MD_ATTR_UUID, MD_ATTR_EXCLUSIVETO, MD_ATTR_STATIC, - MD_ATTR_ACTIVATABLE, MD_ATTR_THREADING, MD_ATTR_MARSHALINGBEHAVIOR, MD_ATTR_OVERLOAD,