widl: Import Wine version 10.11 Signed-off-by: Jacek Caban <jacek@codeweavers.com>
diff --git a/mingw-w64-tools/widl/VERSION b/mingw-w64-tools/widl/VERSION index eaecc03..67f0d65 100644 --- a/mingw-w64-tools/widl/VERSION +++ b/mingw-w64-tools/widl/VERSION
@@ -1 +1 @@ -WIDL version 10.9 +WIDL version 10.11
diff --git a/mingw-w64-tools/widl/configure b/mingw-w64-tools/widl/configure index 8a670b8..b5651aa 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.9. +# Generated by GNU Autoconf 2.72 for widl 10.11. # # 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.9' -PACKAGE_STRING='widl 10.9' +PACKAGE_VERSION='10.11' +PACKAGE_STRING='widl 10.11' 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.9 to adapt to many kinds of systems. +'configure' configures widl 10.11 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.9:";; + short | recursive ) echo "Configuration of widl 10.11:";; 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.9 +widl configure 10.11 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.9, which was +It was created by widl $as_me 10.11, 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.9' + VERSION='10.11' 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.9, which was +This file was extended by widl $as_me 10.11, 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.9 +widl config.status 10.11 configured by $0, generated by GNU Autoconf 2.72, with options \\"\$ac_cs_config\\"
diff --git a/mingw-w64-tools/widl/include/minwinbase.h b/mingw-w64-tools/widl/include/minwinbase.h index 8693853..8971d4a 100644 --- a/mingw-w64-tools/widl/include/minwinbase.h +++ b/mingw-w64-tools/widl/include/minwinbase.h
@@ -143,6 +143,15 @@ #define PROCESS_HEAP_ENTRY_MOVEABLE 0x0010 #define PROCESS_HEAP_ENTRY_DDESHARE 0x0020 +typedef struct _HEAP_SUMMARY +{ + DWORD cb; + SIZE_T cbAllocated; + SIZE_T cbCommitted; + SIZE_T cbReserved; + SIZE_T cbMaxReserve; +} HEAP_SUMMARY, *PHEAP_SUMMARY, *LPHEAP_SUMMARY; + typedef enum _GET_FILEEX_INFO_LEVELS { GetFileExInfoStandard } GET_FILEEX_INFO_LEVELS;
diff --git a/mingw-w64-tools/widl/include/processthreadsapi.h b/mingw-w64-tools/widl/include/processthreadsapi.h index f255495..44cb251 100644 --- a/mingw-w64-tools/widl/include/processthreadsapi.h +++ b/mingw-w64-tools/widl/include/processthreadsapi.h
@@ -44,6 +44,7 @@ ULONG StateMask; } THREAD_POWER_THROTTLING_STATE; +WINBASEAPI VOID WINAPI GetCurrentThreadStackLimits(ULONG_PTR *, ULONG_PTR *); WINBASEAPI HRESULT WINAPI GetThreadDescription(HANDLE,PWSTR *); WINBASEAPI HRESULT WINAPI SetThreadDescription(HANDLE,PCWSTR); WINBASEAPI BOOL WINAPI SetThreadInformation(HANDLE,THREAD_INFORMATION_CLASS,LPVOID,DWORD);
diff --git a/mingw-w64-tools/widl/include/winbase.h b/mingw-w64-tools/widl/include/winbase.h index f75b750..4d23dd5 100644 --- a/mingw-w64-tools/widl/include/winbase.h +++ b/mingw-w64-tools/widl/include/winbase.h
@@ -113,6 +113,10 @@ #define SEM_NOALIGNMENTFAULTEXCEPT 0x0004 #define SEM_NOOPENFILEERRORBOX 0x8000 +/* RaiseFailFastException flags */ +#define FAIL_FAST_GENERATE_EXCEPTION_ADDRESS 0x0001 +#define FAIL_FAST_NO_HARD_ERROR_DLG 0x0002 + /* CopyFileEx flags */ #define COPY_FILE_FAIL_IF_EXISTS 0x00000001 #define COPY_FILE_RESTARTABLE 0x00000002 @@ -2086,6 +2090,7 @@ WINBASEAPI BOOL WINAPI HeapQueryInformation(HANDLE,HEAP_INFORMATION_CLASS,PVOID,SIZE_T,PSIZE_T); WINBASEAPI BOOL WINAPI HeapSetInformation(HANDLE,HEAP_INFORMATION_CLASS,PVOID,SIZE_T); WINBASEAPI SIZE_T WINAPI HeapSize(HANDLE,DWORD,LPCVOID); +WINBASEAPI BOOL WINAPI HeapSummary(HANDLE,DWORD,LPHEAP_SUMMARY); WINBASEAPI BOOL WINAPI HeapUnlock(HANDLE); WINBASEAPI BOOL WINAPI HeapValidate(HANDLE,DWORD,LPCVOID); WINBASEAPI BOOL WINAPI HeapWalk(HANDLE,LPPROCESS_HEAP_ENTRY);
diff --git a/mingw-w64-tools/widl/include/windef.h b/mingw-w64-tools/widl/include/windef.h index 12b3e5b..bb0722b 100644 --- a/mingw-w64-tools/widl/include/windef.h +++ b/mingw-w64-tools/widl/include/windef.h
@@ -158,6 +158,11 @@ typedef const RECTL *LPCRECTL; +typedef struct APP_LOCAL_DEVICE_ID +{ + BYTE value[32]; +} APP_LOCAL_DEVICE_ID; + /* DPI awareness */ typedef enum DPI_AWARENESS {
diff --git a/mingw-w64-tools/widl/src/header.c b/mingw-w64-tools/widl/src/header.c index 31b476d..e2ce883 100644 --- a/mingw-w64-tools/widl/src/header.c +++ b/mingw-w64-tools/widl/src/header.c
@@ -42,6 +42,7 @@ static void write_type_v(FILE *f, const decl_spec_t *t, int is_field, bool define, const char *name, enum name_type name_type); +static void write_apicontract( FILE *header, 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); @@ -559,11 +560,17 @@ static void write_type_definition(FILE *f, type_t *t, bool define) { 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 (t->written) return; + if (contract) write_apicontract_guard_start(f, contract); + if (winrt_mode && define && type_get_type( t ) == TYPE_ENUM) + { + fprintf( f, "#ifndef __%s_ENUM_DEFINED__\n", t->c_name ); + fprintf( f, "#define __%s_ENUM_DEFINED__\n", t->c_name ); + } if(in_namespace) { fprintf(f, "#ifdef __cplusplus\n"); fprintf(f, "} /* extern \"C\" */\n"); @@ -573,7 +580,7 @@ write_type_left(f, &ds, NAME_DEFAULT, define, TRUE); fprintf(f, ";\n"); if(in_namespace) { - t->written = save_written; + t->written = false; write_namespace_end(f, t->namespace); fprintf(f, "extern \"C\" {\n"); fprintf(f, "#else\n"); @@ -582,6 +589,8 @@ if (winrt_mode) write_widl_using_macros(f, t); fprintf(f, "#endif\n\n"); } + if (winrt_mode && define && type_get_type( t ) == TYPE_ENUM) + fprintf( f, "#endif /* __%s_ENUM_DEFINED__ */\n", t->c_name ); if (contract) write_apicontract_guard_end(f, contract); } @@ -816,6 +825,8 @@ static void write_typedef(FILE *header, type_t *type, bool define) { type_t *t = type_alias_get_aliasee_type(type), *root = type_pointer_get_root_type(t); + if (winrt_mode && !define && type_get_type( t ) == TYPE_ENUM) + write_type_definition( header, t, TRUE ); if (winrt_mode && root->namespace && !is_global_namespace(root->namespace)) { fprintf(header, "#ifndef __cplusplus\n"); @@ -1574,11 +1585,12 @@ static void write_apicontract_guard_start(FILE *header, const expr_t *expr) { - const type_t *type; + type_t *type; char *name; int ver; if (!winrt_mode) return; type = expr->u.tref.type; + write_apicontract( header, type ); ver = expr->ref->u.integer.value; name = format_apicontract_macro(type); fprintf(header, "#if %s_VERSION >= %#x\n", name, ver); @@ -1823,11 +1835,14 @@ static void write_apicontract(FILE *header, type_t *apicontract) { - char *name = format_apicontract_macro(apicontract); + char *name; + if (apicontract->written) return; + 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); + apicontract->written = true; } static void write_runtimeclass(FILE *header, type_t *runtimeclass)
diff --git a/mingw-w64-tools/widl/src/metadata.c b/mingw-w64-tools/widl/src/metadata.c index 4fd2039..348553e 100644 --- a/mingw-w64-tools/widl/src/metadata.c +++ b/mingw-w64-tools/widl/src/metadata.c
@@ -458,7 +458,7 @@ { const struct index *idx; UINT insert_idx, offset = tables[table].offset; - BOOL sort = (table != TABLE_PARAM && table != TABLE_FIELD); + BOOL sort = (table != TABLE_PARAM && table != TABLE_FIELD && table != TABLE_PROPERTY && table != TABLE_EVENT); if (sort && (idx = find_index( &tables_idx[table], &tables[table], row, row_size, FALSE, &insert_idx ))) return idx->offset / row_size + 1; @@ -479,6 +479,11 @@ buf->offset += size; } +static void serialize_byte( BYTE value ) +{ + add_bytes( &tables_disk, (const BYTE *)&value, sizeof(value) ); +} + static void serialize_ushort( USHORT value ) { add_bytes( &tables_disk, (const BYTE *)&value, sizeof(value) ); @@ -513,6 +518,18 @@ add_bytes( &tables_disk, (const BYTE *)&idx, size ); } +static enum table resolution_scope_to_table( UINT token ) +{ + switch (token & 0x3) + { + case 0: return TABLE_MODULE; + case 1: return TABLE_MODULEREF; + case 2: return TABLE_ASSEMBLYREF; + case 3: return TABLE_TYPEREF; + default: assert( 0 ); + } +} + static enum table typedef_or_ref_to_table( UINT token ) { switch (token & 0x3) @@ -524,6 +541,86 @@ } } +static enum table methoddef_or_ref_to_table( UINT token ) +{ + switch (token & 0x1) + { + case 0: return TABLE_METHODDEF; + case 1: return TABLE_MEMBERREF; + default: assert( 0 ); + } +} + +static enum table memberref_parent_to_table( UINT token ) +{ + switch (token & 0x7) + { + case 0: return TABLE_TYPEDEF; + case 1: return TABLE_TYPEREF; + case 2: return TABLE_MODULEREF; + case 3: return TABLE_METHODDEF; + case 4: return TABLE_TYPESPEC; + default: assert( 0 ); + } +} + +static enum table has_constant_to_table( UINT token ) +{ + switch (token & 0x3) + { + case 0: return TABLE_FIELD; + case 1: return TABLE_PARAM; + case 2: return TABLE_PROPERTY; + default: assert( 0 ); + } +} + +static enum table has_customattribute_to_table( UINT token ) +{ + switch (token & 0x1f) + { + case 0: return TABLE_METHODDEF; + case 1: return TABLE_FIELD; + case 2: return TABLE_TYPEREF; + case 3: return TABLE_TYPEDEF; + case 4: return TABLE_PARAM; + case 5: return TABLE_INTERFACEIMPL; + case 6: return TABLE_MEMBERREF; + case 7: return TABLE_MODULE; + case 9: return TABLE_PROPERTY; + case 10: return TABLE_EVENT; + case 11: return TABLE_STANDALONESIG; + case 12: return TABLE_MODULEREF; + case 13: return TABLE_TYPESPEC; + case 14: return TABLE_ASSEMBLY; + case 15: return TABLE_ASSEMBLYREF; + case 16: return TABLE_FILE; + case 17: return TABLE_EXPORTEDTYPE; + case 18: return TABLE_MANIFESTRESOURCE; + default: assert( 0 ); + } +} + +static enum table customattribute_type_to_table( UINT token ) +{ + switch (token & 0x7) + { + case 2: return TABLE_METHODDEF; + case 3: return TABLE_MEMBERREF; + default: assert( 0 ); + } +} + +static enum table has_semantics_to_table( UINT token ) +{ + switch (token & 0x1) + { + case 0: return TABLE_EVENT; + case 1: return TABLE_PROPERTY; + default: assert( 0 ); + } +} + struct module_row { USHORT generation; @@ -550,6 +647,33 @@ serialize_guid_idx( row->encbaseid ); } +struct typeref_row +{ + UINT scope; + UINT name; + UINT namespace; +}; + +static UINT add_typeref_row( UINT scope, UINT name, UINT namespace ) +{ + struct typeref_row row = { scope, name, namespace }; + return add_row( TABLE_TYPEREF, (const BYTE *)&row, sizeof(row) ); +} + +static void serialize_typeref_table( void ) +{ + const struct typeref_row *row = (const struct typeref_row *)tables[TABLE_TYPEREF].ptr; + UINT i; + + for (i = 0; i < tables[TABLE_TYPEREF].count; i++) + { + serialize_table_idx( row->scope, resolution_scope_to_table(row->scope) ); + serialize_string_idx( row->name ); + serialize_string_idx( row->namespace ); + row++; + } +} + struct typedef_row { UINT flags; @@ -587,6 +711,240 @@ } } +struct field_row +{ + USHORT flags; + UINT name; + UINT signature; +}; + +static UINT add_field_row( UINT flags, UINT name, UINT signature ) +{ + struct field_row row = { flags, name, signature }; + return add_row( TABLE_FIELD, (const BYTE *)&row, sizeof(row) ); +} + +static void serialize_field_table( void ) +{ + const struct field_row *row = (const struct field_row *)tables[TABLE_FIELD].ptr; + UINT i; + + for (i = 0; i < tables[TABLE_FIELD].count; i++) + { + serialize_ushort( row->flags ); + serialize_string_idx( row->name ); + serialize_blob_idx( row->signature ); + row++; + } +} + +struct methoddef_row +{ + UINT rva; + USHORT implflags; + USHORT flags; + UINT name; + UINT signature; + UINT paramlist; +}; + +static UINT add_methoddef_row( UINT implflags, UINT flags, UINT name, UINT signature, UINT paramlist ) +{ + struct methoddef_row row = { 0, implflags, flags, name, signature, paramlist }; + + if (!row.paramlist) row.paramlist = tables[TABLE_PARAM].count + 1; + return add_row( TABLE_METHODDEF, (const BYTE *)&row, sizeof(row) ); +} + +static void serialize_methoddef_table( void ) +{ + const struct methoddef_row *row = (const struct methoddef_row *)tables[TABLE_METHODDEF].ptr; + UINT i; + + for (i = 0; i < tables[TABLE_METHODDEF].count; i++) + { + serialize_uint( row->rva ); + serialize_ushort( row->implflags ); + serialize_ushort( row->flags ); + serialize_string_idx( row->name ); + serialize_blob_idx( row->signature ); + serialize_table_idx( row->paramlist, TABLE_PARAM ); + row++; + } +} + +struct param_row +{ + USHORT flags; + USHORT sequence; + UINT name; +}; + +static UINT add_param_row( USHORT flags, USHORT sequence, UINT name ) +{ + struct param_row row = { flags, sequence, name }; + return add_row( TABLE_PARAM, (const BYTE *)&row, sizeof(row) ); +} + +static void serialize_param_table( void ) +{ + const struct param_row *row = (const struct param_row *)tables[TABLE_PARAM].ptr; + UINT i; + + for (i = 0; i < tables[TABLE_PARAM].count; i++) + { + serialize_ushort( row->flags ); + serialize_ushort( row->sequence ); + serialize_string_idx( row->name ); + row++; + } +} + +struct interfaceimpl_row +{ + UINT class; + UINT interface; +}; + +static UINT add_interfaceimpl_row( UINT class, UINT interface ) +{ + struct interfaceimpl_row row = { class, interface }; + return add_row( TABLE_INTERFACEIMPL, (const BYTE *)&row, sizeof(row) ); +} + +static int cmp_interfaceimpl_row( const void *a, const void *b ) +{ + const struct interfaceimpl_row *row = a, *row2 = b; + if (row->class > row2->class) return 1; + if (row->class < row2->class) return -1; + if (row->interface > row2->interface) return 1; + if (row->interface < row2->interface) return -1; + return 0; +} + +/* sorted by class, interface */ +static void serialize_interfaceimpl_table( void ) +{ + const struct interfaceimpl_row *row = (const struct interfaceimpl_row *)tables[TABLE_INTERFACEIMPL].ptr; + UINT i; + + qsort( tables[TABLE_INTERFACEIMPL].ptr, tables[TABLE_INTERFACEIMPL].count, sizeof(*row), + cmp_interfaceimpl_row ); + + for (i = 0; i < tables_idx[TABLE_INTERFACEIMPL].count; i++) + { + serialize_table_idx( row->class, TABLE_TYPEDEF ); + serialize_table_idx( row->interface, typedef_or_ref_to_table(row->interface) ); + row++; + } +} + +struct memberref_row +{ + UINT class; + UINT name; + UINT signature; +}; + +static UINT add_memberref_row( UINT class, UINT name, UINT signature ) +{ + struct memberref_row row = { class, name, signature }; + return add_row( TABLE_MEMBERREF, (const BYTE *)&row, sizeof(row) ); +} + +static void serialize_memberref_table( void ) +{ + const struct memberref_row *row = (const struct memberref_row *)tables[TABLE_MEMBERREF].ptr; + UINT i; + + for (i = 0; i < tables[TABLE_MEMBERREF].count; i++) + { + serialize_table_idx( row->class, memberref_parent_to_table(row->class) ); + serialize_string_idx( row->name ); + serialize_blob_idx( row->signature ); + row++; + } +} + +struct constant_row +{ + BYTE type; + BYTE padding; + UINT parent; + UINT value; +}; + +static UINT add_constant_row( BYTE type, UINT parent, UINT value ) +{ + struct constant_row row = { type, 0, parent, value }; + return add_row( TABLE_CONSTANT, (const BYTE *)&row, sizeof(row) ); +} + +static int cmp_constant_row( const void *a, const void *b ) +{ + const struct constant_row *row = a, *row2 = b; + if (row->parent > row2->parent) return 1; + if (row->parent < row2->parent) return -1; + return 0; +} + +/* sorted by parent */ +static void serialize_constant_table( void ) +{ + const struct constant_row *row = (const struct constant_row *)tables[TABLE_CONSTANT].ptr; + UINT i; + + qsort( tables[TABLE_CONSTANT].ptr, tables[TABLE_CONSTANT].count, sizeof(*row), cmp_constant_row ); + + for (i = 0; i < tables_idx[TABLE_CONSTANT].count; i++) + { + serialize_byte( row->type ); + serialize_byte( row->padding ); + serialize_table_idx( row->parent, has_constant_to_table(row->parent) ); + serialize_blob_idx( row->value ); + row++; + } +} + +struct customattribute_row +{ + UINT parent; + UINT type; + UINT value; +}; + +static UINT add_customattribute_row( UINT parent, UINT type, UINT value ) +{ + struct customattribute_row row = { parent, type, value }; + return add_row( TABLE_CUSTOMATTRIBUTE, (const BYTE *)&row, sizeof(row) ); +} + +static int cmp_customattribute_row( const void *a, const void *b ) +{ + const struct customattribute_row *row = a, *row2 = b; + if (row->parent > row2->parent) return 1; + if (row->parent < row2->parent) return -1; + return 0; +} + +/* sorted by parent */ +static void serialize_customattribute_table( void ) +{ + const struct customattribute_row *row = (const struct customattribute_row *)tables[TABLE_CUSTOMATTRIBUTE].ptr; + UINT i; + + qsort( tables[TABLE_CUSTOMATTRIBUTE].ptr, tables[TABLE_CUSTOMATTRIBUTE].count, sizeof(*row), + cmp_customattribute_row ); + + for (i = 0; i < tables_idx[TABLE_CUSTOMATTRIBUTE].count; i++) + { + serialize_table_idx( row->parent, has_customattribute_to_table(row->parent) ); + serialize_table_idx( row->type, customattribute_type_to_table(row->type) ); + serialize_blob_idx( row->value ); + row++; + } +} + struct assembly_row { UINT hashalgid; @@ -660,6 +1018,450 @@ } } +struct propertymap_row +{ + UINT parent; + UINT proplist; +}; + +static UINT add_propertymap_row( UINT parent, UINT proplist ) +{ + struct propertymap_row row = { parent, proplist }; + return add_row( TABLE_PROPERTYMAP, (const BYTE *)&row, sizeof(row) ); +} + +static void serialize_propertymap_table( void ) +{ + const struct propertymap_row *row = (const struct propertymap_row *)tables[TABLE_PROPERTYMAP].ptr; + UINT i; + + for (i = 0; i < tables[TABLE_PROPERTYMAP].count; i++) + { + serialize_table_idx( row->parent, TABLE_TYPEDEF ); + serialize_table_idx( row->proplist, TABLE_PROPERTY ); + row++; + } +} + +struct property_row +{ + USHORT flags; + UINT name; + UINT type; +}; + +static UINT add_property_row( USHORT flags, UINT name, UINT type ) +{ + struct property_row row = { flags, name, type }; + return add_row( TABLE_PROPERTY, (const BYTE *)&row, sizeof(row) ); +} + +static void serialize_property_table( void ) +{ + const struct property_row *row = (const struct property_row *)tables[TABLE_PROPERTY].ptr; + UINT i; + + for (i = 0; i < tables[TABLE_PROPERTY].count; i++) + { + serialize_ushort( row->flags ); + serialize_string_idx( row->name ); + serialize_blob_idx( row->type ); + row++; + } +} + +struct eventmap_row +{ + UINT parent; + UINT eventlist; +}; + +static UINT add_eventmap_row( UINT parent, UINT eventlist ) +{ + struct eventmap_row row = { parent, eventlist }; + return add_row( TABLE_EVENTMAP, (const BYTE *)&row, sizeof(row) ); +} + +static void serialize_eventmap_table( void ) +{ + const struct eventmap_row *row = (const struct eventmap_row *)tables[TABLE_EVENTMAP].ptr; + UINT i; + + for (i = 0; i < tables[TABLE_EVENTMAP].count; i++) + { + serialize_table_idx( row->parent, TABLE_TYPEDEF ); + serialize_table_idx( row->eventlist, TABLE_EVENT ); + row++; + } +} + +struct event_row +{ + USHORT flags; + UINT name; + UINT type; +}; + +static UINT add_event_row( USHORT flags, UINT name, UINT type ) +{ + struct event_row row = { flags, name, type }; + return add_row( TABLE_EVENT, (const BYTE *)&row, sizeof(row) ); +} + +static void serialize_event_table( void ) +{ + const struct event_row *row = (const struct event_row *)tables[TABLE_EVENT].ptr; + UINT i; + + for (i = 0; i < tables[TABLE_EVENT].count; i++) + { + serialize_ushort( row->flags ); + serialize_string_idx( row->name ); + serialize_table_idx( row->type, typedef_or_ref_to_table(row->type) ); + row++; + } +} + +struct methodsemantics_row +{ + USHORT semantics; + UINT method; + UINT association; +}; + +static UINT add_methodsemantics_row( USHORT flags, UINT name, UINT type ) +{ + struct methodsemantics_row row = { flags, name, type }; + return add_row( TABLE_METHODSEMANTICS, (const BYTE *)&row, sizeof(row) ); +} + +static int cmp_methodsemantics_row( const void *a, const void *b ) +{ + const struct methodsemantics_row *row = a, *row2 = b; + if (row->association > row2->association) return 1; + if (row->association < row2->association) return -1; + return 0; +} + +/* sorted by association */ +static void serialize_methodsemantics_table( void ) +{ + const struct methodsemantics_row *row = (const struct methodsemantics_row *)tables[TABLE_METHODSEMANTICS].ptr; + UINT i; + + qsort( tables[TABLE_METHODSEMANTICS].ptr, tables[TABLE_METHODSEMANTICS].count, sizeof(*row), + cmp_methodsemantics_row ); + + for (i = 0; i < tables[TABLE_METHODSEMANTICS].count; i++) + { + serialize_ushort( row->semantics ); + serialize_table_idx( row->method, TABLE_METHODDEF ); + serialize_table_idx( row->association, has_semantics_to_table(row->association) ); + row++; + } +} + +struct methodimpl_row +{ + UINT class; + UINT body; + UINT declaration; +}; + +static UINT add_methodimpl_row( UINT class, UINT body, UINT declaration ) +{ + struct methodimpl_row row = { class, body, declaration }; + return add_row( TABLE_METHODIMPL, (const BYTE *)&row, sizeof(row) ); +} + +static void serialize_methodimpl_table( void ) +{ + const struct methodimpl_row *row = (const struct methodimpl_row *)tables[TABLE_METHODIMPL].ptr; + UINT i; + + for (i = 0; i < tables[TABLE_METHODIMPL].count; i++) + { + serialize_table_idx( row->class, row->class ); + serialize_table_idx( row->body, methoddef_or_ref_to_table(row->body) ); + serialize_table_idx( row->declaration, methoddef_or_ref_to_table(row->declaration) ); + row++; + } +} + +static UINT typedef_or_ref( enum table table, UINT row ) +{ + switch (table) + { + case TABLE_TYPEDEF: return row << 2; + case TABLE_TYPEREF: return row << 2 | 1; + case TABLE_TYPESPEC: return row << 2 | 2; + default: assert( 0 ); + } +} + +static UINT methoddef_or_ref( enum table table, UINT row ) +{ + switch (table) + { + case TABLE_METHODDEF: return row << 1; + case TABLE_MEMBERREF: return row << 1 | 1; + default: assert( 0 ); + } +} + +static UINT resolution_scope( enum table table, UINT row ) +{ + switch (table) + { + case TABLE_MODULE: return row << 2; + case TABLE_MODULEREF: return row << 2 | 1; + case TABLE_ASSEMBLYREF: return row << 2 | 2; + case TABLE_TYPEREF: return row << 2 | 3; + default: assert( 0 ); + } +} + +static UINT has_constant( enum table table, UINT row ) +{ + switch (table) + { + case TABLE_FIELD: return row << 2; + case TABLE_PARAM: return row << 2 | 1; + case TABLE_PROPERTY: return row << 2 | 2; + default: assert( 0 ); + } +} + +static UINT memberref_parent( enum table table, UINT row ) +{ + switch (table) + { + case TABLE_TYPEDEF: return row << 3; + case TABLE_TYPEREF: return row << 3 | 1; + case TABLE_MODULEREF: return row << 3 | 2; + case TABLE_METHODDEF: return row << 3 | 3; + case TABLE_TYPESPEC: return row << 3 | 4; + default: assert( 0 ); + } +} + +static UINT has_customattribute( enum table table, UINT row ) +{ + switch (table) + { + case TABLE_METHODDEF: return row << 5; + case TABLE_FIELD: return row << 5 | 1; + case TABLE_TYPEREF: return row << 5 | 2; + case TABLE_TYPEDEF: return row << 5 | 3; + case TABLE_PARAM: return row << 5 | 4; + case TABLE_INTERFACEIMPL: return row << 5 | 5; + case TABLE_MEMBERREF: return row << 5 | 6; + case TABLE_MODULE: return row << 5 | 7; + case TABLE_PROPERTY: return row << 5 | 9; + case TABLE_EVENT: return row << 5 | 10; + case TABLE_STANDALONESIG: return row << 5 | 11; + case TABLE_MODULEREF: return row << 5 | 12; + case TABLE_TYPESPEC: return row << 5 | 13; + case TABLE_ASSEMBLY: return row << 5 | 14; + case TABLE_ASSEMBLYREF: return row << 5 | 15; + case TABLE_FILE: return row << 5 | 16; + case TABLE_EXPORTEDTYPE: return row << 5 | 17; + case TABLE_MANIFESTRESOURCE: return row << 5 | 18; + default: assert( 0 ); + } +} + +static UINT customattribute_type( enum table table, UINT row ) +{ + switch (table) + { + case TABLE_METHODDEF: return row << 3 | 2; + case TABLE_MEMBERREF: return row << 3 | 3; + default: assert( 0 ); + } +} + +static UINT has_semantics( enum table table, UINT row ) +{ + switch (table) + { + case TABLE_EVENT: return row << 1; + case TABLE_PROPERTY: return row << 1 | 1; + default: assert( 0 ); + } +} + +enum element_type +{ + ELEMENT_TYPE_END = 0x00, + ELEMENT_TYPE_VOID = 0x01, + ELEMENT_TYPE_BOOLEAN = 0x02, + ELEMENT_TYPE_CHAR = 0x03, + ELEMENT_TYPE_I1 = 0x04, + ELEMENT_TYPE_U1 = 0x05, + ELEMENT_TYPE_I2 = 0x06, + ELEMENT_TYPE_U2 = 0x07, + ELEMENT_TYPE_I4 = 0x08, + ELEMENT_TYPE_U4 = 0x09, + ELEMENT_TYPE_I8 = 0x0a, + ELEMENT_TYPE_U8 = 0x0b, + ELEMENT_TYPE_R4 = 0x0c, + ELEMENT_TYPE_R8 = 0x0d, + ELEMENT_TYPE_STRING = 0x0e, + ELEMENT_TYPE_PTR = 0x0f, + ELEMENT_TYPE_BYREF = 0x10, + ELEMENT_TYPE_VALUETYPE = 0x11, + ELEMENT_TYPE_CLASS = 0x12, + ELEMENT_TYPE_VAR = 0x13, + ELEMENT_TYPE_ARRAY = 0x14, + ELEMENT_TYPE_GENERICINST = 0x15, + ELEMENT_TYPE_TYPEDBYREF = 0x16, + ELEMENT_TYPE_I = 0x18, + ELEMENT_TYPE_U = 0x19, + ELEMENT_TYPE_FNPTR = 0x1b, + ELEMENT_TYPE_OBJECT = 0x1c, + ELEMENT_TYPE_SZARRAY = 0x1d, + ELEMENT_TYPE_MVAR = 0x1e, + ELEMENT_TYPE_CMOD_REQD = 0x1f, + ELEMENT_TYPE_CMOD_OPT = 0x20, + ELEMENT_TYPE_INTERNAL = 0x21, + ELEMENT_TYPE_MODIFIER = 0x40, + ELEMENT_TYPE_SENTINEL = 0x41, + ELEMENT_TYPE_PINNED = 0x45 +}; + +enum +{ + TYPE_ATTR_PUBLIC = 0x000001, + TYPE_ATTR_NESTEDPUBLIC = 0x000002, + TYPE_ATTR_NESTEDPRIVATE = 0x000003, + TYPE_ATTR_NESTEDFAMILY = 0x000004, + TYPE_ATTR_NESTEDASSEMBLY = 0x000005, + TYPE_ATTR_NESTEDFAMANDASSEM = 0x000006, + TYPE_ATTR_NESTEDFAMORASSEM = 0x000007, + TYPE_ATTR_SEQUENTIALLAYOUT = 0x000008, + TYPE_ATTR_EXPLICITLAYOUT = 0x000010, + TYPE_ATTR_INTERFACE = 0x000020, + TYPE_ATTR_ABSTRACT = 0x000080, + TYPE_ATTR_SEALED = 0x000100, + TYPE_ATTR_SPECIALNAME = 0x000400, + TYPE_ATTR_RTSPECIALNAME = 0x000800, + TYPE_ATTR_IMPORT = 0x001000, + TYPE_ATTR_SERIALIZABLE = 0x002000, + TYPE_ATTR_UNKNOWN = 0x004000, + TYPE_ATTR_UNICODECLASS = 0x010000, + TYPE_ATTR_AUTOCLASS = 0x020000, + TYPE_ATTR_CUSTOMFORMATCLASS = 0x030000, + TYPE_ATTR_HASSECURITY = 0x040000, + TYPE_ATTR_BEFOREFIELDINIT = 0x100000 +}; + +enum +{ + FIELD_ATTR_PRIVATE = 0x0001, + FIELD_ATTR_FAMANDASSEM = 0x0002, + FIELD_ATTR_ASSEMBLY = 0x0003, + FIELD_ATTR_FAMILY = 0x0004, + FIELD_ATTR_FAMORASSEM = 0x0005, + FIELD_ATTR_PUBLIC = 0x0006, + FIELD_ATTR_STATIC = 0x0010, + FIELD_ATTR_INITONLY = 0x0020, + FIELD_ATTR_LITERAL = 0x0040, + FIELD_ATTR_NOTSERIALIZED = 0x0080, + FIELD_ATTR_HASFIELDRVA = 0x0100, + FIELD_ATTR_SPECIALNAME = 0x0200, + FIELD_ATTR_RTSPECIALNAME = 0x0400, + FIELD_ATTR_HASFIELDMARSHAL = 0x1000, + FIELD_ATTR_PINVOKEIMPL = 0x2000, + FIELD_ATTR_HASDEFAULT = 0x8000 +}; + +enum +{ + METHOD_ATTR_COMPILERCONTROLLED = 0x0000, + METHOD_ATTR_PRIVATE = 0x0001, + METHOD_ATTR_FAMANDASSEM = 0x0002, + METHOD_ATTR_ASSEM = 0x0003, + METHOD_ATTR_FAMILY = 0x0004, + METHOD_ATTR_FAMORASSEM = 0x0005, + METHOD_ATTR_PUBLIC = 0x0006, + METHOD_ATTR_STATIC = 0x0010, + METHOD_ATTR_FINAL = 0x0020, + METHOD_ATTR_VIRTUAL = 0x0040, + METHOD_ATTR_HIDEBYSIG = 0x0080, + METHOD_ATTR_NEWSLOT = 0x0100, + METHOD_ATTR_STRICT = 0x0200, + METHOD_ATTR_ABSTRACT = 0x0400, + METHOD_ATTR_SPECIALNAME = 0x0800, + METHOD_ATTR_RTSPECIALNAME = 0x1000, + METHOD_ATTR_PINVOKEIMPL = 0x2000 +}; + +enum +{ + METHOD_IMPL_IL = 0x0000, + METHOD_IMPL_NATIVE = 0x0001, + METHOD_IMPL_OPTIL = 0x0002, + METHOD_IMPL_RUNTIME = 0x0003, + METHOD_IMPL_UNMANAGED = 0x0004 +}; + +enum +{ + METHOD_SEM_SETTER = 0x0001, + METHOD_SEM_GETTER = 0x0002, + METHOD_SEM_OTHER = 0x0004, + METHOD_SEM_ADDON = 0x0008, + METHOD_SEM_REMOVEON = 0x0010 +}; + +enum +{ + PARAM_ATTR_IN = 0x0001, + PARAM_ATTR_OUT = 0x0002, + PARAM_ATTR_OPTIONAL = 0x0010 +}; + +enum +{ + SIG_TYPE_DEFAULT = 0x00, + SIG_TYPE_C = 0x01, + SIG_TYPE_STDCALL = 0x02, + SIG_TYPE_THISCALL = 0x03, + SIG_TYPE_FASTCALL = 0x04, + SIG_TYPE_VARARG = 0x05, + SIG_TYPE_FIELD = 0x06, + SIG_TYPE_LOCALSIG = 0x07, + SIG_TYPE_PROPERTY = 0x08, + SIG_TYPE_GENERIC = 0x10, + SIG_TYPE_HASTHIS = 0x20, + SIG_TYPE_EXPLICITTHIS = 0x40 +}; + +#define MODULE_ROW 1 +#define MSCORLIB_ROW 1 + +#define MAX_NAME 256 + +static UINT add_name( type_t *type, UINT *namespace ) +{ + UINT name = add_string( type->name ); + char *str = format_namespace( type->namespace, "", ".", NULL, NULL ); + *namespace = add_string( str ); + free( str ); + return name; +} + +static UINT make_field_value_sig( UINT token, BYTE *buf ) +{ + UINT len = 2; + + buf[0] = SIG_TYPE_FIELD; + buf[1] = ELEMENT_TYPE_VALUETYPE; + len += encode_int( token, buf + 2 ); + return len; +} + enum { LARGE_STRING_HEAP = 0x01, @@ -669,6 +1471,1324 @@ static char *assembly_name; +static enum element_type map_basic_type( enum type_basic_type type, int sign ) +{ + enum element_type elem_type; + + switch (type) + { + case TYPE_BASIC_CHAR: elem_type = ELEMENT_TYPE_BOOLEAN; break; + case TYPE_BASIC_INT16: elem_type = (sign > 0) ? ELEMENT_TYPE_U2 : ELEMENT_TYPE_I2; break; + case TYPE_BASIC_INT: + case TYPE_BASIC_INT32: + case TYPE_BASIC_LONG: elem_type = (sign > 0) ? ELEMENT_TYPE_U4 : ELEMENT_TYPE_I4; break; + case TYPE_BASIC_INT64: elem_type = (sign > 0) ? ELEMENT_TYPE_U8 : ELEMENT_TYPE_I8; break; + case TYPE_BASIC_BYTE: elem_type = ELEMENT_TYPE_U1; break; + case TYPE_BASIC_WCHAR: elem_type = ELEMENT_TYPE_CHAR; break; + case TYPE_BASIC_FLOAT: elem_type = ELEMENT_TYPE_R4; break; + case TYPE_BASIC_DOUBLE: elem_type = ELEMENT_TYPE_R8; break; + default: + fprintf( stderr, "Unhandled basic type %u.\n", type ); + exit( 1 ); + } + return elem_type; +} + +static UINT make_struct_field_sig( const var_t *var, BYTE *buf ) +{ + const type_t *type = var->declspec.type; + + if (type->name && !strcmp( type->name, "HSTRING" )) + { + buf[0] = SIG_TYPE_FIELD; + buf[1] = ELEMENT_TYPE_STRING; + return 2; + } + + if (type->name && !strcmp( type->name, "GUID" )) + { + UINT token = typedef_or_ref( TABLE_TYPEREF, type->md.ref ); + return make_field_value_sig( token, buf ); + } + + type = type_get_real_type( type ); + + if (type_get_type( type ) == TYPE_ENUM || type_get_type( type ) == TYPE_STRUCT) + { + UINT token = typedef_or_ref( TABLE_TYPEREF, type->md.ref ); + return make_field_value_sig( token, buf ); + } + + if (type_get_type( type ) != TYPE_BASIC) + { + fprintf( stderr, "Unhandled struct field type %u.\n", type_get_type( type ) ); + exit( 1 ); + } + + buf[0] = SIG_TYPE_FIELD; + buf[1] = map_basic_type( type_basic_get_type(type), type_basic_get_sign(type) ); + return 2; +} + +static UINT make_member_sig( UINT token, BYTE *buf ) +{ + UINT len = 4; + + buf[0] = SIG_TYPE_HASTHIS; + buf[1] = 2; + buf[2] = ELEMENT_TYPE_VOID; + buf[3] = ELEMENT_TYPE_CLASS; + len += encode_int( token, buf + 4 ); + buf[len++] = ELEMENT_TYPE_U4; + return len; +} + +static UINT make_member_sig2( UINT type, UINT token, BYTE *buf ) +{ + UINT len = 4; + + buf[0] = SIG_TYPE_HASTHIS; + buf[1] = 1; + buf[2] = ELEMENT_TYPE_VOID; + buf[3] = type; + len += encode_int( token, buf + 4 ); + return len; +} + +static UINT make_type_sig( const type_t *type, BYTE *buf ) +{ + UINT len = 0; + + type = type_get_real_type( type ); + + switch (type_get_type( type )) + { + case TYPE_POINTER: + { + const type_t *ref_type = type_pointer_get_ref_type( type ); + BOOL skip_byref = FALSE; + + switch (type_get_type( ref_type )) + { + case TYPE_DELEGATE: + case TYPE_INTERFACE: + case TYPE_RUNTIMECLASS: + skip_byref = TRUE; + break; + default: + break; + } + if (!skip_byref) buf[len++] = ELEMENT_TYPE_BYREF; + len += make_type_sig( ref_type, buf + len ); + break; + } + case TYPE_ARRAY: + buf[len++] = ELEMENT_TYPE_SZARRAY; + len += make_type_sig( type_array_get_element_type(type), buf + len ); + break; + + case TYPE_INTERFACE: + buf[len++] = ELEMENT_TYPE_OBJECT; + break; + + case TYPE_DELEGATE: + case TYPE_RUNTIMECLASS: + buf[len++] = ELEMENT_TYPE_CLASS; + len += encode_int( typedef_or_ref(TABLE_TYPEREF, type->md.ref), buf + 1 ); + break; + + case TYPE_ENUM: + case TYPE_STRUCT: + buf[len++] = ELEMENT_TYPE_VALUETYPE; + len += encode_int( typedef_or_ref(TABLE_TYPEREF, type->md.ref), buf + 1 ); + break; + + case TYPE_BASIC: + buf[len++] = map_basic_type( type_basic_get_type(type), type_basic_get_sign(type) ); + break; + + default: + fprintf( stderr, "Unhandled type %u.\n", type_get_type( type ) ); + exit( 1 ); + } + return len; +} + +static UINT make_method_sig( const var_t *method, BYTE *buf ) +{ + 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[1] = 0; + buf[2] = ELEMENT_TYPE_VOID; + + if (!arg_list) return 3; + + /* add return value first */ + LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry ) + { + const type_t *type; + + if (!is_attr( arg->attrs, ATTR_RETVAL )) continue; + type = type_pointer_get_ref_type( arg->declspec.type ); /* retval must be a pointer */ + len = make_type_sig( type, buf + 2 ) + 2; + } + + /* add remaining parameters */ + LIST_FOR_EACH_ENTRY( arg, arg_list, 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_property_sig( const var_t *method, BYTE *buf ) +{ + 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[1] = 0; + buf[2] = ELEMENT_TYPE_VOID; + + LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry ) + { + const type_t *type; + + if (!is_attr( arg->attrs, ATTR_RETVAL )) continue; + type = type_pointer_get_ref_type( arg->declspec.type ); /* retval must be a pointer */ + len = make_type_sig( type, buf + 2 ) + 2; + } + + return len; +} + +static UINT make_deprecated_sig( UINT token, BYTE *buf ) +{ + UINT len = 5; + + buf[0] = SIG_TYPE_HASTHIS; + buf[1] = 4; + buf[2] = ELEMENT_TYPE_VOID; + buf[3] = ELEMENT_TYPE_STRING; + buf[4] = ELEMENT_TYPE_VALUETYPE; + len += encode_int( token, buf + 5 ); + buf[len++] = ELEMENT_TYPE_U4; + buf[len++] = ELEMENT_TYPE_STRING; + + return len; +} + +static UINT make_contract_value( const type_t *type, BYTE *buf ) +{ + const expr_t *contract = get_attrp( type->attrs, ATTR_CONTRACT ); + 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 ); + + buf[0] = 1; + buf[1] = 0; + buf[2] = len; + memcpy( buf + 3, name, len ); + len += 3; + memcpy( buf + len, &version, sizeof(version) ); + len += sizeof(version); + buf[len++] = 0; + buf[len++] = 0; + + free( name ); + return len; +} + +static UINT make_version_value( const type_t *type, BYTE *buf ) +{ + UINT version = get_attrv( type->attrs, ATTR_VERSION ); + + buf[0] = 1; + buf[1] = 0; + buf[2] = is_attr( type->attrs, ATTR_VERSION ) ? 0 : 1; + buf[3] = 0; + memcpy( buf + 4, &version, sizeof(version) ); + return 8; +} + +static void add_contract_attr_step1( type_t *type ) +{ + UINT assemblyref, scope, typeref, typeref_type, class, sig_size; + BYTE sig[32]; + + if (!is_attr( type->attrs, ATTR_CONTRACT )) return; + + add_assemblyref_row( 0x200, 0, add_string("windowscontracts") ); + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + + scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); + typeref_type = add_typeref_row( scope, add_string("Type"), add_string("System") ); + + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref = add_typeref_row( scope, add_string("ContractVersionAttribute"), add_string("Windows.Foundation.Metadata") ); + + class = memberref_parent( TABLE_TYPEREF, typeref ); + sig_size = make_member_sig( typedef_or_ref(TABLE_TYPEREF, typeref_type), sig ); + type->md.member[MD_ATTR_CONTRACT] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) ); +} + +static void add_contract_attr_step2( type_t *type ) +{ + UINT parent, attr_type, value_size; + BYTE value[MAX_NAME + sizeof(UINT) + 5]; + + if (!is_attr( type->attrs, ATTR_CONTRACT )) return; + + parent = has_customattribute( TABLE_TYPEDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_CONTRACT] ); + value_size = make_contract_value( type, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); +} + +static void add_version_attr_step1( type_t *type ) +{ + static const BYTE sig[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4 }; + UINT assemblyref, scope, typeref, class; + + if (!is_attr( type->attrs, ATTR_VERSION ) && is_attr( type->attrs, ATTR_CONTRACT )) return; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + + typeref = add_typeref_row( scope, add_string("VersionAttribute"), add_string("Windows.Foundation.Metadata") ); + class = memberref_parent( TABLE_TYPEREF, typeref ); + type->md.member[MD_ATTR_VERSION] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) ); +} + +static void add_version_attr_step2( type_t *type ) +{ + UINT parent, attr_type, value_size; + BYTE value[8]; + + if (!is_attr( type->attrs, ATTR_VERSION ) && is_attr( type->attrs, ATTR_CONTRACT )) return; + + parent = has_customattribute( TABLE_TYPEDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_VERSION] ); + value_size = make_version_value( type, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); +} + +static void add_flags_attr_step1( type_t *type ) +{ + static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID }; + UINT scope, typeref, class; + + if (!is_attr( type->attrs, ATTR_FLAGS )) return; + + scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); + typeref = add_typeref_row( scope, add_string("FlagsAttribute"), add_string("System") ); + class = memberref_parent( TABLE_TYPEREF, typeref ); + type->md.member[MD_ATTR_FLAGS] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) ); +} + +static void add_flags_attr_step2( type_t *type ) +{ + static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 }; + UINT parent, attr_type; + + if (!is_attr( type->attrs, ATTR_FLAGS )) return; + + parent = has_customattribute( TABLE_TYPEDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_FLAGS] ); + add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) ); +} + +static void add_enum_type_step1( type_t *type ) +{ + UINT name, namespace, scope, typeref; + + name = add_name( type, &namespace ); + + scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); + typeref = add_typeref_row( scope, add_string("Enum"), add_string("System") ); + type->md.extends = typedef_or_ref( TABLE_TYPEREF, typeref ); + type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace ); + + add_version_attr_step1( type ); + add_contract_attr_step1( type ); + add_flags_attr_step1( type ); +} + +static void add_enum_type_step2( type_t *type ) +{ + BYTE sig_value[] = { SIG_TYPE_FIELD, ELEMENT_TYPE_I4 }; + UINT name, namespace, field, parent, sig_size; + BYTE sig_field[32]; + const var_t *var; + + if (is_attr( type->attrs, ATTR_FLAGS )) sig_value[1] = ELEMENT_TYPE_U4; + + name = add_name( type, &namespace ); + + field = add_field_row( FIELD_ATTR_PRIVATE | FIELD_ATTR_SPECIALNAME | FIELD_ATTR_RTSPECIALNAME, + add_string("value__"), add_blob(sig_value, sizeof(sig_value)) ); + + type->md.def = add_typedef_row( TYPE_ATTR_PUBLIC | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN, name, namespace, + type->md.extends, field, 1 ); + + sig_size = make_field_value_sig( typedef_or_ref(TABLE_TYPEREF, type->md.ref), sig_field ); + + LIST_FOR_EACH_ENTRY( var, type_enum_get_values(type), const var_t, entry ) + { + int val = var->eval->u.integer.value; + + field = add_field_row( FIELD_ATTR_PUBLIC | FIELD_ATTR_LITERAL | FIELD_ATTR_STATIC | FIELD_ATTR_HASDEFAULT, + add_string(var->name), add_blob(sig_field, sig_size) ); + parent = has_constant( TABLE_FIELD, field ); + add_constant_row( sig_value[1], parent, add_blob((const BYTE *)&val, sizeof(val)) ); + } + + add_version_attr_step2( type ); + add_contract_attr_step2( type ); + add_flags_attr_step2( type ); +} + +static void add_struct_type_step1( type_t *type ) +{ + UINT name, namespace, scope, typeref; + const var_t *var; + + name = add_name( type, &namespace ); + scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); + + LIST_FOR_EACH_ENTRY( var, type_struct_get_fields(type), const var_t, entry ) + { + type_t *field_type = var->declspec.type; + if (field_type->name && !strcmp( field_type->name, "GUID" )) + field_type->md.ref = add_typeref_row( scope, add_string("Guid"), add_string("System") ); + } + + typeref = add_typeref_row( scope, add_string("ValueType"), add_string("System") ); + type->md.extends = typedef_or_ref( TABLE_TYPEREF, typeref ); + type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace ); + + add_contract_attr_step1( type ); +} + +static void add_struct_type_step2( type_t *type ) +{ + UINT name, namespace, field, flags, sig_size, first_field = 0; + const var_t *var; + BYTE sig[32]; + + name = add_name( type, &namespace ); + + LIST_FOR_EACH_ENTRY( var, type_struct_get_fields(type), const var_t, entry ) + { + sig_size = make_struct_field_sig( var, sig ); + field = add_field_row( FIELD_ATTR_PUBLIC, add_string(var->name), add_blob(sig, sig_size) ); + if (!first_field) first_field = field; + } + + flags = TYPE_ATTR_PUBLIC | TYPE_ATTR_SEQUENTIALLAYOUT | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN; + type->md.def = add_typedef_row( flags, name, namespace, type->md.extends, first_field, 0 ); + + add_contract_attr_step2( type ); +} + +static void add_uuid_attr_step1( type_t *type ) +{ + static const BYTE sig[] = + { SIG_TYPE_HASTHIS, 11, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4, ELEMENT_TYPE_U2, ELEMENT_TYPE_U2, + ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, + ELEMENT_TYPE_U1, ELEMENT_TYPE_U1 }; + UINT assemblyref, scope, typeref, class; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref = add_typeref_row( scope, add_string("GuidAttribute"), add_string("Windows.Foundation.Metadata") ); + + class = memberref_parent( TABLE_TYPEREF, typeref ); + type->md.member[MD_ATTR_UUID] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) ); +} + +static void add_uuid_attr_step2( type_t *type ) +{ + static const BYTE default_uuid[] = + { 0xe7, 0x1f, 0xb5, 0x67, 0x6e, 0x38, 0x31, 0x5a, 0x8a, 0x1c, 0x89, 0x83, 0xc9, 0x49, 0x5c, 0x33 }; + const struct uuid *uuid = get_attrp( type->attrs, ATTR_UUID ); + BYTE value[sizeof(*uuid) + 4] = { 0x01 }; + UINT parent, attr_type; + + if (uuid) memcpy( value + 2, uuid, sizeof(*uuid) ); + else memcpy( value + 2, default_uuid, sizeof(default_uuid) ); + + parent = has_customattribute( TABLE_TYPEDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_UUID] ); + add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) ); +} + +static UINT make_exclusiveto_value( const type_t *type, BYTE *buf ) +{ + const type_t *attr = get_attrp( type->attrs, ATTR_EXCLUSIVETO ); + char *name = format_namespace( attr->namespace, "", ".", attr->name, NULL ); + UINT len = strlen( name ); + + buf[0] = 1; + buf[1] = 0; + buf[2] = len; + memcpy( buf + 3, name, len ); + len += 3; + buf[len++] = 0; + buf[len++] = 0; + + free( name ); + return len; +} + +static void add_exclusiveto_attr_step1( type_t *type ) +{ + UINT assemblyref, scope, typeref, typeref_type, class, sig_size; + BYTE sig[32]; + + if (!is_attr( type->attrs, ATTR_EXCLUSIVETO )) return; + + 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("ExclusiveToAttribute"), add_string("Windows.Foundation.Metadata") ); + + class = memberref_parent( TABLE_TYPEREF, typeref ); + sig_size = make_member_sig2( ELEMENT_TYPE_CLASS, typedef_or_ref(TABLE_TYPEREF, typeref_type), sig ); + type->md.member[MD_ATTR_EXCLUSIVETO] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) ); +} + +static void add_exclusiveto_attr_step2( type_t *type ) +{ + UINT parent, attr_type, value_size; + BYTE value[MAX_NAME + 5]; + + if (!is_attr( type->attrs, ATTR_EXCLUSIVETO )) return; + + parent = has_customattribute( TABLE_TYPEDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_EXCLUSIVETO] ); + value_size = make_exclusiveto_value( type, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); +} + +static UINT make_overload_value( const var_t *method, BYTE *buf ) +{ + UINT len = strlen( method->name ); + + buf[0] = 1; + buf[1] = 0; + buf[2] = len; + memcpy( buf + 3, method->name, len ); + len += 3; + buf[len++] = 0; + buf[len++] = 0; + + return len; +} + +static void add_overload_attr_step1( const var_t *method ) +{ + static const BYTE sig[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING }; + UINT assemblyref, scope, typeref, class; + type_t *type = method->declspec.type; + + if (!is_attr( method->attrs, ATTR_OVERLOAD )) return; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref = add_typeref_row( scope, add_string("OverloadAttribute"), add_string("Windows.Foundation.Metadata") ); + + class = memberref_parent( TABLE_TYPEREF, typeref ); + type->md.member[MD_ATTR_OVERLOAD] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) ); +} + +static void add_overload_attr_step2( const var_t *method ) +{ + const type_t *type = method->declspec.type; + UINT parent, attr_type, value_size; + BYTE value[MAX_NAME + 5]; + + if (!is_attr( method->attrs, ATTR_OVERLOAD )) return; + + parent = has_customattribute( TABLE_METHODDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_OVERLOAD] ); + value_size = make_overload_value( method, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); +} + +static void add_default_overload_attr_step1( const var_t *method ) +{ + static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID }; + UINT assemblyref, scope, typeref, class; + type_t *type = method->declspec.type; + + if (!is_attr( method->attrs, ATTR_DEFAULT_OVERLOAD ) || !is_attr( method->attrs, ATTR_OVERLOAD )) return; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref = add_typeref_row( scope, add_string("DefaultOverloadAttribute"), add_string("Windows.Foundation.Metadata") ); + + class = memberref_parent( TABLE_TYPEREF, typeref ); + type->md.member[MD_ATTR_DEFAULT_OVERLOAD] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) ); +} + +static void add_default_overload_attr_step2( const var_t *method ) +{ + static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 }; + const type_t *type = method->declspec.type; + UINT parent, attr_type; + + if (!is_attr( method->attrs, ATTR_DEFAULT_OVERLOAD ) || !is_attr( method->attrs, ATTR_OVERLOAD )) return; + + parent = has_customattribute( TABLE_METHODDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_DEFAULT_OVERLOAD] ); + add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) ); +} + +static UINT make_deprecated_value( const var_t *method, BYTE **ret_buf ) +{ + static const BYTE zero[] = { 0x00, 0x00, 0x00, 0x00 }, one[] = { 0x01, 0x00, 0x00, 0x00 }; + const expr_t *attr = get_attrp( method->attrs, ATTR_DEPRECATED ); + const char *text = attr->ref->u.sval; + const char *kind = attr->u.ext->u.sval; + BYTE encoded[4]; + UINT len, len_text = strlen( text ), len_encoded = encode_int( len_text, encoded ); + BYTE *buf = xmalloc( 2 + len_encoded + len_text + 6 + MAX_NAME + 5 ); + char *contract; + + buf[0] = 1; + buf[1] = 0; + memcpy( buf + 2, encoded, len_encoded ); + len = 2 + len_encoded; + memcpy( buf + len, text, len_text ); + len += len_text; + if (!strcmp( kind, "remove" )) memcpy( buf + len, one, sizeof(one) ); + else memcpy( buf + len, zero, sizeof(zero) ); + len += 4; + buf[len++] = 0; + buf[len++] = 0; + + buf[len++] = 1; + buf[len++] = 0; + contract = format_namespace( attr->ext2->u.tref.type->namespace, "", ".", attr->ext2->u.tref.type->name, NULL ); + len_text = strlen( contract ); + buf[len++] = len_text; + memcpy( buf + len, contract, len_text ); + free( contract ); + len += len_text; + buf[len++] = 0; + buf[len++] = 0; + + *ret_buf = buf; + return len; +} + +static void add_deprecated_attr_step1( const var_t *method ) +{ + UINT assemblyref, scope, typeref_type, typeref, class, sig_size; + type_t *type = method->declspec.type; + BYTE sig[32]; + + if (!is_attr( method->attrs, ATTR_DEPRECATED )) return; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref_type = add_typeref_row( scope, add_string("DeprecationType"), add_string("Windows.Foundation.Metadata") ); + typeref = add_typeref_row( scope, add_string("DeprecatedAttribute"), add_string("Windows.Foundation.Metadata") ); + + sig_size = make_deprecated_sig( typedef_or_ref(TABLE_TYPEREF, typeref_type), sig ); + class = memberref_parent( TABLE_TYPEREF, typeref ); + type->md.member[MD_ATTR_DEPRECATED] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) ); +} + +static void add_deprecated_attr_step2( const var_t *method ) +{ + const type_t *type = method->declspec.type; + UINT parent, attr_type, value_size; + BYTE *value; + + if (!is_attr( method->attrs, ATTR_DEPRECATED )) return; + + parent = has_customattribute( TABLE_METHODDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_DEPRECATED] ); + value_size = make_deprecated_value( method, &value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); + free( value ); +} + +static void add_method_params_step1( var_list_t *arg_list ) +{ + var_t *arg; + + if (!arg_list) return; + + LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry ) + { + type_t *type = arg->declspec.type; + + if (type_get_type( type ) == TYPE_POINTER) type = type_pointer_get_ref_type( type ); + if (type->name && !strcmp( type->name, "EventRegistrationToken" )) + { + UINT assemblyref, scope; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + type = type_get_real_type( type ); + type->md.ref = add_typeref_row( scope, add_string("EventRegistrationToken"), add_string("Windows.Foundation") ); + } + } +} + +static void add_interface_type_step1( type_t *type ) +{ + const statement_t *stmt; + UINT name, namespace; + + name = add_name( type, &namespace ); + + type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace ); + + 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) ) + { + const var_t *method = stmt->u.var; + + add_method_params_step1( type_function_get_args(method->declspec.type) ); + + add_overload_attr_step1( method ); + add_default_overload_attr_step1( method ); + add_deprecated_attr_step1( method ); + } +} + +static UINT get_param_attrs( const var_t *arg ) +{ + UINT attrs = 0; + + if (is_attr( arg->attrs, ATTR_IN )) attrs |= PARAM_ATTR_IN; + if (is_attr( arg->attrs, ATTR_OUT )) attrs |= PARAM_ATTR_OUT; + if (is_attr( arg->attrs, ATTR_OPTIONAL )) attrs |= PARAM_ATTR_OPTIONAL; + + return attrs ? attrs : PARAM_ATTR_IN; +} + +static UINT add_method_params_step2( var_list_t *arg_list ) +{ + UINT first = 0, row, seq = 1; + var_t *arg; + + if (!arg_list) return 0; + + LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry ) + { + if (is_attr( arg->attrs, ATTR_RETVAL )) + { + first = add_param_row( 0, 0, add_string(arg->name) ); + break; + } + } + + LIST_FOR_EACH_ENTRY( arg, arg_list, 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 (!first) first = row; + } + + return first; +} + +static char *get_method_name( const var_t *method ) +{ + const char *overload; + + if (is_attr( method->attrs, ATTR_PROPGET )) return strmake( "get_%s", method->name ); + else if (is_attr( method->attrs, ATTR_PROPPUT )) return strmake( "put_%s", method->name ); + else if (is_attr( method->attrs, ATTR_EVENTADD )) return strmake( "add_%s", method->name ); + else if (is_attr( method->attrs, ATTR_EVENTREMOVE )) return strmake( "remove_%s", method->name ); + + if ((overload = get_attrp( method->attrs, ATTR_OVERLOAD ))) return strmake( "%s", overload ); + return strmake( "%s", method->name ); +} + +static UINT get_method_attrs( BOOL abstract, BOOL special, UINT *flags ) +{ + UINT attrs = METHOD_ATTR_PUBLIC | METHOD_ATTR_VIRTUAL | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_NEWSLOT; + + if (abstract) + { + *flags = 0; + attrs |= METHOD_ATTR_ABSTRACT; + } + else + { + *flags = METHOD_IMPL_RUNTIME; + attrs |= METHOD_ATTR_FINAL; + } + + if (special) 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 ); + char *name = get_method_name( method ); + type_t *type = method->declspec.type; + BYTE sig[256]; + + if (class) property = type->md.class_property; + else property = type->md.iface_property; + + paramlist = add_method_params_step2( type_function_get_args(type) ); + sig_size = make_method_sig( method, sig ); + + 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) ); + free( name ); +} + +static const var_t *find_propget_method( const type_t *iface, const char *name ) +{ + const statement_t *stmt; + + STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) + { + const var_t *method = stmt->u.var; + if (is_attr( method->attrs, ATTR_PROPGET ) && !strcmp( method->name, name )) return method; + } + return NULL; +} + +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 ); + 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 ); + + type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); + free( name ); + + /* add propget method first if not already added */ + if (class) + { + if (!propget->declspec.type->md.class_property) add_propget_method( class, iface, propget ); + property = type->md.class_property = propget->declspec.type->md.class_property; + } + else + { + if (!propget->declspec.type->md.iface_property) add_propget_method( class, iface, propget ); + property = type->md.iface_property = propget->declspec.type->md.iface_property; + } + + add_methodsemantics_row( METHOD_SEM_SETTER, type->md.def, has_semantics(TABLE_PROPERTY, property) ); +} + +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 ); + char *name = get_method_name( method ); + type_t *type = method->declspec.type; + BYTE sig[256]; + + if (class) event = type->md.class_event; + else event = type->md.iface_event; + + paramlist = add_method_params_step2( type_function_get_args(type) ); + sig_size = make_method_sig( method, sig ); + + type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); + free( name ); + + add_methodsemantics_row( METHOD_SEM_ADDON, type->md.def, has_semantics(TABLE_EVENT, event) ); +} + +static const var_t *find_eventadd_method( const type_t *iface, const char *name ) +{ + const statement_t *stmt; + + STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) + { + const var_t *method = stmt->u.var; + if (is_attr( method->attrs, ATTR_EVENTADD ) && !strcmp( method->name, name )) return method; + } + return NULL; +} + +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 ); + 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 ); + + type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); + free( name ); + + /* add eventadd method first if not already added */ + if (class) + { + if (!eventadd->declspec.type->md.class_event) add_eventadd_method( class, iface, eventadd ); + event = type->md.class_event = eventadd->declspec.type->md.class_event; + } + else + { + if (!eventadd->declspec.type->md.iface_event) add_eventadd_method( class, iface, eventadd ); + event = type->md.iface_event = eventadd->declspec.type->md.iface_event; + } + + add_methodsemantics_row( METHOD_SEM_REMOVEON, type->md.def, has_semantics(TABLE_EVENT, event) ); +} + +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 ); + 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 ); + + type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist ); + free( name ); +} + +static void add_property( type_t *class, type_t *iface, const var_t *method ) +{ + UINT sig_size; + type_t *type = method->declspec.type; + BYTE sig[256]; + + if (!is_attr( method->attrs, ATTR_PROPGET )) return; + + sig_size = make_property_sig( method, sig ); + if (class) + { + type->md.class_property = add_property_row( 0, add_string(method->name), add_blob(sig, sig_size) ); + if (!class->md.propertymap) class->md.propertymap = add_propertymap_row( class->md.def, type->md.class_property ); + } + else + { + type->md.iface_property = add_property_row( 0, add_string(method->name), add_blob(sig, sig_size) ); + if (!iface->md.propertymap) iface->md.propertymap = add_propertymap_row( iface->md.def, type->md.iface_property ); + } +} + +static void add_event( type_t *class, type_t *iface, const var_t *method ) +{ + UINT event_type = 0; + type_t *type = method->declspec.type; + var_t *arg; + + if (!is_attr( method->attrs, ATTR_EVENTADD )) return; + + LIST_FOR_EACH_ENTRY( arg, type_function_get_args(type), var_t, entry ) + { + type_t *arg_type = arg->declspec.type; + + arg_type = type_pointer_get_ref_type( arg_type ); /* first arg must be a delegate pointer */ + event_type = typedef_or_ref( TABLE_TYPEREF, arg_type->md.ref ); + break; + } + + if (class) + { + type->md.class_event = add_event_row( 0, add_string(method->name), event_type ); + if (!class->md.eventmap) class->md.eventmap = add_eventmap_row( class->md.def, type->md.class_event ); + } + else + { + type->md.iface_event = add_event_row( 0, add_string(method->name), event_type ); + if (!iface->md.eventmap) iface->md.eventmap = add_eventmap_row( iface->md.def, type->md.iface_event ); + } +} + +static void add_method( type_t *class, type_t *iface, const var_t *method ) +{ + if (is_attr( method->attrs, ATTR_PROPGET )) add_propget_method( class, iface, method ); + else if (is_attr( method->attrs, ATTR_PROPPUT )) add_propput_method( class, iface, method ); + else if (is_attr( method->attrs, ATTR_EVENTADD )) add_eventadd_method( class, iface, method ); + else if (is_attr( method->attrs, ATTR_EVENTREMOVE )) add_eventremove_method( class, iface, method ); + else add_regular_method( class, iface, method ); +} + +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; + + name = add_name( type, &namespace ); + + if (!is_attr( type->attrs, ATTR_EXCLUSIVETO )) flags |= TYPE_ATTR_PUBLIC; + type->md.def = add_typedef_row( flags, name, namespace, 0, 0, 0 ); + + if (require_list) LIST_FOR_EACH_ENTRY( require, require_list, typeref_t, entry ) + { + interface = typedef_or_ref( TABLE_TYPEREF, require->type->md.ref ); + add_interfaceimpl_row( type->md.def, interface ); + } + + STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(type) ) + { + const var_t *method = stmt->u.var; + + add_property( NULL, type, method ); + add_event( NULL, type, method ); + add_method( NULL, type, method ); + + add_deprecated_attr_step2( method ); + add_default_overload_attr_step2( method ); + add_overload_attr_step2( method ); + } + + add_contract_attr_step2( type ); + add_uuid_attr_step2( type ); + add_exclusiveto_attr_step2( type ); +} + +static UINT make_contractversion_value( const type_t *type, BYTE *buf ) +{ + UINT version = get_attrv( type->attrs, ATTR_CONTRACTVERSION ), len = 2 + sizeof(version); + + buf[0] = 1; + buf[1] = 0; + memcpy( buf + 2, &version, sizeof(version) ); + buf[len++] = 0; + buf[len++] = 0; + return len; +} + +static void add_contractversion_attr_step1( type_t *type ) +{ + static const BYTE sig[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4 }; + UINT assemblyref, scope, typeref, class; + + if (!is_attr( type->attrs, ATTR_CONTRACTVERSION )) return; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref = add_typeref_row( scope, add_string("ContractVersionAttribute"), add_string("Windows.Foundation.Metadata") ); + + class = memberref_parent( TABLE_TYPEREF, typeref ); + type->md.member[MD_ATTR_CONTRACTVERSION] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) ); +} + +static void add_contractversion_attr_step2( type_t *type ) +{ + UINT parent, attr_type, value_size; + BYTE value[8]; + + if (!is_attr( type->attrs, ATTR_CONTRACTVERSION )) return; + + parent = has_customattribute( TABLE_TYPEDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_CONTRACTVERSION] ); + value_size = make_contractversion_value( type, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); +} + +static void add_apicontract_attr_step1( type_t *type ) +{ + static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID }; + UINT assemblyref, scope, typeref, class; + + assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") ); + scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref ); + typeref = add_typeref_row( scope, add_string("ApiContractAttribute"), add_string("Windows.Foundation.Metadata") ); + + class = memberref_parent( TABLE_TYPEREF, typeref ); + type->md.member[MD_ATTR_APICONTRACT] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) ); +} + +static void add_apicontract_attr_step2( type_t *type ) +{ + static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 }; + UINT parent, attr_type; + + parent = has_customattribute( TABLE_TYPEDEF, type->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_APICONTRACT] ); + add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) ); +} + +static void add_apicontract_type_step1( type_t *type ) +{ + UINT name, namespace, scope, typeref; + + name = add_name( type, &namespace ); + + scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); + typeref = add_typeref_row( scope, add_string("ValueType"), add_string("System") ); + type->md.extends = typedef_or_ref( TABLE_TYPEREF, typeref ); + type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace ); + + add_contractversion_attr_step1( type ); + add_apicontract_attr_step1( type ); +} + +static void add_apicontract_type_step2( type_t *type ) +{ + UINT name, namespace, flags = TYPE_ATTR_PUBLIC | TYPE_ATTR_SEQUENTIALLAYOUT | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN; + + name = add_name( type, &namespace ); + + type->md.def = add_typedef_row( flags, name, namespace, type->md.extends, 0, 1 ); + + add_contractversion_attr_step2( type ); + add_apicontract_attr_step2( type ); +} + +static void add_runtimeclass_type_step1( type_t *type ) +{ + UINT name, namespace; + + name = add_name( type, &namespace ); + + type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace ); +} + +static void add_method_impl( const type_t *class, const type_t *iface, const var_t *method ) +{ + UINT parent, memberref, body, decl, sig_size; + char *name = get_method_name( method ); + type_t *type = method->declspec.type; + BYTE sig[256]; + + parent = memberref_parent( TABLE_TYPEREF, iface->md.ref ); + sig_size = make_method_sig( method, sig ); + + memberref = add_memberref_row( parent, add_string(name), add_blob(sig, sig_size) ); + free( name ); + + body = methoddef_or_ref( TABLE_METHODDEF, type->md.def ); + decl = methoddef_or_ref( TABLE_MEMBERREF, memberref ); + + add_methodimpl_row( class->md.def, body, decl ); +} + +static void add_method_contract_attrs( const type_t *class, const type_t *iface, const type_t *method ) +{ + UINT parent, attr_type, value_size; + BYTE value[MAX_NAME + sizeof(UINT) + 5]; + + parent = has_customattribute( TABLE_METHODDEF, method->md.def ); + attr_type = customattribute_type( TABLE_MEMBERREF, iface->md.member[MD_ATTR_CONTRACT] ); + value_size = make_contract_value( class, value ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); + + if (method->md.class_property) + { + parent = has_customattribute( TABLE_PROPERTY, method->md.class_property ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); + } + + if (method->md.class_event) + { + parent = has_customattribute( TABLE_EVENT, method->md.class_event ); + add_customattribute_row( parent, attr_type, add_blob(value, value_size) ); + } +} + +static void add_runtimeclass_type_step2( type_t *type ) +{ + 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; + + name = add_name( type, &namespace ); + + scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); + typeref = add_typeref_row( scope, add_string("Object"), add_string("System") ); + + extends = typedef_or_ref( TABLE_TYPEREF, typeref ); + flags = TYPE_ATTR_PUBLIC | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN; + type->md.def = add_typedef_row( flags, name, namespace, extends, 0, 0 ); + + 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 ); + + /* 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 ); + } + + 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_contract_attr_step1( type ); + add_contract_attr_step2( type ); +} + +static void add_delegate_type_step1( type_t *type ) +{ + UINT name, namespace, scope, typeref; + + name = add_name( type, &namespace ); + + scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW ); + typeref = add_typeref_row( scope, add_string("MulticastDelegate"), add_string("System") ); + type->md.extends = typedef_or_ref( TABLE_TYPEREF, typeref ); + type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace ); + + add_version_attr_step1( type ); + add_contract_attr_step1( type ); + add_uuid_attr_step1( type ); +} + +static void add_delegate_type_step2( type_t *type ) +{ + static const BYTE sig_ctor[] = { SIG_TYPE_HASTHIS, 2, ELEMENT_TYPE_VOID, ELEMENT_TYPE_OBJECT, ELEMENT_TYPE_I }; + UINT name, namespace, methoddef, flags, paramlist; + const type_t *iface = type_delegate_get_iface( type ); + const statement_t *stmt; + + name = add_name( type, &namespace ); + + flags = METHOD_ATTR_RTSPECIALNAME | METHOD_ATTR_SPECIALNAME | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_PRIVATE; + methoddef = add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string(".ctor"), + add_blob(sig_ctor, sizeof(sig_ctor)), 0 ); + + add_param_row( 0, 1, add_string("object") ); + add_param_row( 0, 2, add_string("method") ); + + flags = METHOD_ATTR_SPECIALNAME | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_PUBLIC | METHOD_ATTR_VIRTUAL | + METHOD_ATTR_NEWSLOT; + + STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) + { + const var_t *method = stmt->u.var; + UINT sig_size; + BYTE sig[256]; + + sig_size = make_method_sig( method, sig ); + 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 ); + break; + } + type->md.def = add_typedef_row( TYPE_ATTR_PUBLIC | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN, name, namespace, + type->md.extends, 0, methoddef ); + + add_uuid_attr_step2( type ); + add_version_attr_step2( type ); + add_contract_attr_step2( type ); +} + +static void build_tables( const statement_list_t *stmt_list ) +{ + const statement_t *stmt; + + /* Adding a type involves two passes: the first creates various references and the second + uses those references to create the remaining rows. */ + + LIST_FOR_EACH_ENTRY( stmt, stmt_list, const statement_t, entry ) + { + type_t *type = stmt->u.type; + + if (stmt->type != STMT_TYPE) continue; + + switch (type->type_type) + { + case TYPE_ENUM: + add_enum_type_step1( type ); + break; + case TYPE_STRUCT: + add_struct_type_step1( type ); + break; + case TYPE_INTERFACE: + if (type->signature && !strncmp( type->signature, "pinterface", 10 )) + { + fprintf( stderr, "Ingoring supported %s parameterized interface.\n", type->name ); + break; + } + add_interface_type_step1( type ); + break; + case TYPE_APICONTRACT: + add_apicontract_type_step1( type ); + break; + case TYPE_RUNTIMECLASS: + add_runtimeclass_type_step1( type ); + break; + case TYPE_DELEGATE: + add_delegate_type_step1( type ); + break; + default: + fprintf( stderr, "Unhandled type %u name '%s'.\n", type->type_type, type->name ); + break; + } + } + + LIST_FOR_EACH_ENTRY( stmt, stmt_list, const statement_t, entry ) + { + type_t *type = stmt->u.type; + + if (stmt->type != STMT_TYPE) continue; + + switch (type->type_type) + { + case TYPE_ENUM: + add_enum_type_step2( type ); + break; + case TYPE_STRUCT: + add_struct_type_step2( type ); + break; + case TYPE_INTERFACE: + if (type->signature && !strncmp( type->signature, "pinterface", 10 )) + { + fprintf( stderr, "Ingoring supported %s parameterized interface.\n", type->name ); + break; + } + add_interface_type_step2( type ); + break; + case TYPE_APICONTRACT: + add_apicontract_type_step2( type ); + break; + case TYPE_RUNTIMECLASS: + add_runtimeclass_type_step2( type ); + break; + case TYPE_DELEGATE: + add_delegate_type_step2( type ); + break; + default: + break; + } + } +} + static void build_table_stream( const statement_list_t *stmts ) { static const GUID guid = { 0x9ddc04c6, 0x04ca, 0x04cc, { 0x52, 0x85, 0x4b, 0x50, 0xb2, 0x60, 0x1d, 0xa8 } }; @@ -690,6 +2810,8 @@ add_module_row( add_string(metadata_name), add_guid(&guid) ); add_assemblyref_row( 0, add_blob(token, sizeof(token)), add_string("mscorlib") ); + build_tables( stmts ); + for (i = 0; i < TABLE_MAX; i++) if (tables[i].count) tables_header.valid |= (1ull << i); if (strings.offset >> 16) tables_header.heap_sizes |= LARGE_STRING_HEAP; @@ -702,7 +2824,21 @@ if (tables[i].count) add_bytes( &tables_disk, (const BYTE *)&tables[i].count, sizeof(tables[i].count) ); serialize_module_table(); + serialize_typeref_table(); serialize_typedef_table(); + serialize_field_table(); + serialize_methoddef_table(); + serialize_param_table(); + serialize_interfaceimpl_table(); + serialize_memberref_table(); + serialize_constant_table(); + serialize_customattribute_table(); + serialize_eventmap_table(); + serialize_event_table(); + serialize_propertymap_table(); + serialize_property_table(); + serialize_methodsemantics_table(); + serialize_methodimpl_table(); serialize_assembly_table(); serialize_assemblyref_table(); }
diff --git a/mingw-w64-tools/widl/src/typegen.c b/mingw-w64-tools/widl/src/typegen.c index 9567b2d..6d7ccd3 100644 --- a/mingw-w64-tools/widl/src/typegen.c +++ b/mingw-w64-tools/widl/src/typegen.c
@@ -5031,12 +5031,20 @@ fprintf(file, "\n"); } +static void init_param_struct_declspec( decl_spec_t *dst, const decl_spec_t *src ) +{ + *dst = *src; + + if (!is_ptr( dst->type ) || type_is_alias( dst->type )) + dst->qualifier = 0; +} void write_func_param_struct( FILE *file, const type_t *iface, const type_t *func, const char *var_decl, int add_retval ) { var_t *retval = type_function_get_retval( func ); const var_list_t *args = type_function_get_args( func ); + decl_spec_t declspec; const var_t *arg; int needs_packing; unsigned int align = 0; @@ -5055,7 +5063,8 @@ if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) { print_file(file, 2, "%s", ""); - write_type_left( file, &arg->declspec, NAME_DEFAULT, false, TRUE ); + init_param_struct_declspec( &declspec, &arg->declspec ); + write_type_left( file, &declspec, NAME_DEFAULT, false, TRUE ); if (needs_space_after( arg->declspec.type )) fputc( ' ', file ); if (is_array( arg->declspec.type ) && !type_array_is_decl_as_ptr( arg->declspec.type )) fputc( '*', file ); @@ -5071,7 +5080,8 @@ if (add_retval && !is_void( retval->declspec.type )) { print_file(file, 2, "%s", ""); - write_type_left( file, &retval->declspec, NAME_DEFAULT, false, TRUE ); + init_param_struct_declspec( &declspec, &retval->declspec ); + write_type_left( file, &declspec, NAME_DEFAULT, false, TRUE ); if (needs_space_after( retval->declspec.type )) fputc( ' ', file ); if (!is_array( retval->declspec.type ) && !is_ptr( retval->declspec.type ) && type_memsize( retval->declspec.type ) != pointer_size) @@ -5239,9 +5249,7 @@ } else if (has_ret) print_file( file, 1, "%s", "CLIENT_CALL_RETURN _RetVal;\n\n" ); - len = fprintf( file, " %s%s( ", - has_ret ? "_RetVal = " : "", - interpreted_mode ? "NdrClientCall2" : "NdrClientCall" ); + len = fprintf( file, " %sNdrClientCall2( ", has_ret ? "_RetVal = " : "" ); fprintf( file, "&%s_StubDesc,", prefix ); fprintf( file, "\n%*s&__MIDL_ProcFormatString.Format[%u]", len, "", proc_offset ); if (needs_params)
diff --git a/mingw-w64-tools/widl/src/typetree.c b/mingw-w64-tools/widl/src/typetree.c index af41906..2f67545 100644 --- a/mingw-w64-tools/widl/src/typetree.c +++ b/mingw-w64-tools/widl/src/typetree.c
@@ -56,6 +56,7 @@ t->param_name = NULL; t->short_name = NULL; memset(&t->details, 0, sizeof(t->details)); + memset(&t->md, 0, sizeof(t->md)); t->typestring_offset = 0; t->ptrdesc = 0; t->ignore = (parse_only != 0);
diff --git a/mingw-w64-tools/widl/src/widltypes.h b/mingw-w64-tools/widl/src/widltypes.h index 5ee1323..f18c2a9 100644 --- a/mingw-w64-tools/widl/src/widltypes.h +++ b/mingw-w64-tools/widl/src/widltypes.h
@@ -496,6 +496,41 @@ TYPE_DELEGATE, }; +enum +{ + MD_ATTR_CONTRACT, + MD_ATTR_FLAGS, + MD_ATTR_APICONTRACT, + MD_ATTR_CONTRACTVERSION, + MD_ATTR_VERSION, + MD_ATTR_UUID, + MD_ATTR_EXCLUSIVETO, + MD_ATTR_STATIC, + MD_ATTR_ACTIVATABLE, + MD_ATTR_THREADING, + MD_ATTR_MARSHALINGBEHAVIOR, + MD_ATTR_OVERLOAD, + MD_ATTR_DEFAULT_OVERLOAD, + MD_ATTR_DEPRECATED, + MD_ATTR_MAX, +}; + +struct metadata +{ + unsigned int ref; + unsigned int def; + unsigned int extends; + unsigned int member[MD_ATTR_MAX]; + /* get/put methods */ + unsigned int class_property; + unsigned int iface_property; + unsigned int propertymap; + /* add/remove methods */ + unsigned int class_event; + unsigned int iface_event; + unsigned int eventmap; +}; + struct _type_t { const char *name; /* C++ name with parameters in brackets */ struct namespace *namespace; @@ -527,6 +562,7 @@ unsigned int typestring_offset; unsigned int ptrdesc; /* used for complex structs */ int typelib_idx; + struct metadata md; struct location where; unsigned int ignore : 1; unsigned int defined : 1; @@ -686,6 +722,11 @@ if (stmt->type == STMT_DECLARATION && stmt->u.var->declspec.stgclass == STG_NONE && \ type_get_type_detect_alias(stmt->u.var->declspec.type) == TYPE_FUNCTION) +#define STATEMENTS_FOR_EACH_FUNC_REV(stmt, stmts) \ + if (stmts) LIST_FOR_EACH_ENTRY_REV( stmt, stmts, statement_t, entry ) \ + if (stmt->type == STMT_DECLARATION && stmt->u.var->declspec.stgclass == STG_NONE && \ + type_get_type_detect_alias(stmt->u.var->declspec.type) == TYPE_FUNCTION) + static inline int statements_has_func(const statement_list_t *stmts) { const statement_t *stmt;