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;