Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/tools/widl/metadata.c
8623 views
1
/*
2
* Copyright 2024, 2025 Hans Leidekker for CodeWeavers
3
*
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
8
*
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
13
*
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17
*/
18
19
#include "config.h"
20
#include <stdarg.h>
21
#include <stdio.h>
22
23
#include "widl.h"
24
#include "windef.h"
25
#include "winbase.h"
26
#include "wincrypt.h"
27
#include "winnt.h"
28
#include "utils.h"
29
#include "typetree.h"
30
31
static const IMAGE_DOS_HEADER dos_header =
32
{
33
.e_magic = IMAGE_DOS_SIGNATURE,
34
.e_lfanew = sizeof(dos_header),
35
};
36
37
#define FILE_ALIGNMENT 0x200
38
#define SECTION_ALIGNMENT 0x1000
39
static IMAGE_NT_HEADERS32 nt_header =
40
{
41
.Signature = IMAGE_NT_SIGNATURE,
42
.FileHeader =
43
{
44
.Machine = IMAGE_FILE_MACHINE_I386,
45
.NumberOfSections = 1,
46
.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER32),
47
.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_DLL
48
},
49
.OptionalHeader =
50
{
51
.Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC,
52
.MajorLinkerVersion = 11,
53
.ImageBase = 0x400000,
54
.SectionAlignment = SECTION_ALIGNMENT,
55
.FileAlignment = FILE_ALIGNMENT,
56
.MajorOperatingSystemVersion = 6,
57
.MinorOperatingSystemVersion = 2,
58
.MajorSubsystemVersion = 6,
59
.MinorSubsystemVersion = 2,
60
.SizeOfHeaders = FILE_ALIGNMENT,
61
.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI,
62
.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_NO_SEH | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE |
63
IMAGE_DLLCHARACTERISTICS_NX_COMPAT,
64
.SizeOfStackReserve = 0x100000,
65
.SizeOfHeapReserve = 0x1000,
66
.LoaderFlags = 0x100000,
67
.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES,
68
.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR] =
69
{ .VirtualAddress = SECTION_ALIGNMENT, .Size = sizeof(IMAGE_COR20_HEADER) }
70
}
71
};
72
73
static IMAGE_SECTION_HEADER section_header =
74
{
75
.Name = ".text",
76
.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ
77
};
78
79
static IMAGE_COR20_HEADER cor_header =
80
{
81
.cb = sizeof(IMAGE_COR20_HEADER),
82
.MajorRuntimeVersion = 2,
83
.MinorRuntimeVersion = 5,
84
.Flags = COMIMAGE_FLAGS_ILONLY
85
};
86
87
#define METADATA_MAGIC ('B' | ('S' << 8) | ('J' << 16) | ('B' << 24))
88
static struct
89
{
90
UINT signature;
91
USHORT major_version;
92
USHORT minor_version;
93
UINT reserved;
94
UINT length;
95
char version[20];
96
USHORT flags;
97
USHORT num_streams;
98
}
99
metadata_header =
100
{
101
METADATA_MAGIC,
102
1,
103
1,
104
0,
105
20,
106
"WindowsRuntime 1.4"
107
};
108
109
enum
110
{
111
WINMD_STREAM_TABLE,
112
WINMD_STREAM_STRING,
113
WINMD_STREAM_USERSTRING,
114
WINMD_STREAM_GUID,
115
WINMD_STREAM_BLOB,
116
WINMD_STREAM_MAX
117
};
118
119
static struct
120
{
121
UINT data_offset;
122
UINT data_size;
123
char name[12];
124
UINT header_size;
125
const BYTE *data;
126
}
127
streams[] =
128
{
129
{ 0, 0, "#~", 12 },
130
{ 0, 0, "#Strings", 20 },
131
{ 0, 0, "#US", 12 },
132
{ 0, 0, "#GUID", 16 },
133
{ 0, 0, "#Blob", 16 }
134
};
135
136
static void write_headers( UINT image_size )
137
{
138
static const BYTE pad[8];
139
UINT i, streams_size = 0;
140
USHORT num_streams = 0;
141
142
put_data( &dos_header, sizeof(dos_header) );
143
144
image_size += nt_header.OptionalHeader.SizeOfHeaders + sizeof(section_header);
145
nt_header.OptionalHeader.SizeOfImage = (image_size + 0x1fff) & ~0x1fff;
146
147
put_data( &nt_header, sizeof(nt_header) );
148
149
for (i = 0; i < WINMD_STREAM_MAX; i++)
150
{
151
if (!streams[i].data_size) continue;
152
streams_size += streams[i].header_size + streams[i].data_size;
153
num_streams++;
154
}
155
156
section_header.PointerToRawData = FILE_ALIGNMENT;
157
section_header.VirtualAddress = SECTION_ALIGNMENT;
158
section_header.Misc.VirtualSize = sizeof(cor_header) + sizeof(metadata_header) + streams_size + 8;
159
section_header.SizeOfRawData = (section_header.Misc.VirtualSize + FILE_ALIGNMENT - 1) & ~(FILE_ALIGNMENT - 1);
160
161
put_data( &section_header, sizeof(section_header) );
162
163
for (i = 0; i < FILE_ALIGNMENT - sizeof(dos_header) - sizeof(nt_header) - sizeof(section_header); i++)
164
put_data( pad, 1 );
165
166
cor_header.MetaData.VirtualAddress = section_header.VirtualAddress + sizeof(cor_header) + 8;
167
cor_header.MetaData.Size = sizeof(metadata_header) + streams_size;
168
169
put_data( &cor_header, sizeof(cor_header) );
170
put_data( pad, 8 );
171
172
metadata_header.num_streams = num_streams;
173
put_data( &metadata_header, sizeof(metadata_header) );
174
for (i = 0; i < WINMD_STREAM_MAX; i++)
175
{
176
if (!streams[i].data_size) continue;
177
put_data( &streams[i], streams[i].header_size );
178
}
179
}
180
181
enum table
182
{
183
TABLE_MODULE = 0x00,
184
TABLE_TYPEREF = 0x01,
185
TABLE_TYPEDEF = 0x02,
186
TABLE_FIELD = 0x04,
187
TABLE_METHODDEF = 0x06,
188
TABLE_PARAM = 0x08,
189
TABLE_INTERFACEIMPL = 0x09,
190
TABLE_MEMBERREF = 0x0a,
191
TABLE_CONSTANT = 0x0b,
192
TABLE_CUSTOMATTRIBUTE = 0x0c,
193
TABLE_FIELDMARSHAL = 0x0d,
194
TABLE_DECLSECURITY = 0x0e,
195
TABLE_CLASSLAYOUT = 0x0f,
196
TABLE_FIELDLAYOUT = 0x10,
197
TABLE_STANDALONESIG = 0x11,
198
TABLE_EVENTMAP = 0x12,
199
TABLE_EVENT = 0x14,
200
TABLE_PROPERTYMAP = 0x15,
201
TABLE_PROPERTY = 0x17,
202
TABLE_METHODSEMANTICS = 0x18,
203
TABLE_METHODIMPL = 0x19,
204
TABLE_MODULEREF = 0x1a,
205
TABLE_TYPESPEC = 0x1b,
206
TABLE_IMPLMAP = 0x1c,
207
TABLE_FIELDRVA = 0x1d,
208
TABLE_ASSEMBLY = 0x20,
209
TABLE_ASSEMBLYPROCESSOR = 0x21,
210
TABLE_ASSEMBLYOS = 0x22,
211
TABLE_ASSEMBLYREF = 0x23,
212
TABLE_ASSEMBLYREFPROCESSOR = 0x24,
213
TABLE_ASSEMBLYREFOS = 0x25,
214
TABLE_FILE = 0x26,
215
TABLE_EXPORTEDTYPE = 0x27,
216
TABLE_MANIFESTRESOURCE = 0x28,
217
TABLE_NESTEDCLASS = 0x29,
218
TABLE_GENERICPARAM = 0x2a,
219
TABLE_METHODSPEC = 0x2b,
220
TABLE_GENERICPARAMCONSTRAINT = 0x2c,
221
TABLE_MAX = 0x2d
222
};
223
224
#define SORTED_TABLES \
225
1ull << TABLE_INTERFACEIMPL |\
226
1ull << TABLE_CONSTANT |\
227
1ull << TABLE_CUSTOMATTRIBUTE |\
228
1ull << TABLE_FIELDMARSHAL |\
229
1ull << TABLE_DECLSECURITY |\
230
1ull << TABLE_CLASSLAYOUT |\
231
1ull << TABLE_FIELDLAYOUT |\
232
1ull << TABLE_EVENTMAP |\
233
1ull << TABLE_PROPERTYMAP |\
234
1ull << TABLE_METHODSEMANTICS |\
235
1ull << TABLE_METHODIMPL |\
236
1ull << TABLE_IMPLMAP |\
237
1ull << TABLE_FIELDRVA |\
238
1ull << TABLE_NESTEDCLASS |\
239
1ull << TABLE_GENERICPARAM |\
240
1ull << TABLE_GENERICPARAMCONSTRAINT
241
242
static struct
243
{
244
UINT reserved;
245
BYTE majorversion;
246
BYTE minor_version;
247
BYTE heap_sizes;
248
BYTE reserved2;
249
UINT64 valid;
250
UINT64 sorted;
251
}
252
tables_header = { 0, 2, 0, 0, 1, 0, SORTED_TABLES };
253
254
static struct buffer
255
{
256
UINT offset; /* write position */
257
UINT allocated; /* allocated size in bytes */
258
UINT count; /* number of entries written */
259
BYTE *ptr;
260
} strings, strings_idx, userstrings, userstrings_idx, blobs, blobs_idx, guids, tables[TABLE_MAX],
261
tables_idx[TABLE_MAX], tables_disk;
262
263
static void *grow_buffer( struct buffer *buf, UINT size )
264
{
265
UINT new_size;
266
267
if (buf->allocated - buf->offset >= size) return buf->ptr;
268
269
new_size = max( buf->offset + size, buf->allocated * 2 );
270
buf->ptr = xrealloc( buf->ptr, new_size );
271
buf->allocated = new_size;
272
return buf->ptr;
273
}
274
275
static UINT encode_int( UINT value, BYTE *encoded )
276
{
277
if (value < 0x80)
278
{
279
encoded[0] = value;
280
return 1;
281
}
282
if (value < 0x4000)
283
{
284
encoded[0] = value >> 8 | 0x80;
285
encoded[1] = value & 0xff;
286
return 2;
287
}
288
if (value < 0x20000000)
289
{
290
encoded[0] = value >> 24 | 0xc0;
291
encoded[1] = value >> 16 & 0xff;
292
encoded[2] = value >> 8 & 0xff;
293
encoded[3] = value & 0xff;
294
return 4;
295
}
296
fprintf( stderr, "Value too large to encode.\n" );
297
exit( 1 );
298
}
299
300
static UINT decode_int( const BYTE *encoded, UINT *len )
301
{
302
if (!(encoded[0] & 0x80))
303
{
304
*len = 1;
305
return encoded[0];
306
}
307
if (!(encoded[0] & 0x40))
308
{
309
*len = 2;
310
return ((encoded[0] & ~0xc0) << 8) + encoded[1];
311
}
312
if (!(encoded[0] & 0x20))
313
{
314
*len = 4;
315
return ((encoded[0] & ~0xe0) << 24) + (encoded[1] << 16) + (encoded[2] << 8) + encoded[3];
316
}
317
fprintf( stderr, "Invalid encoding.\n" );
318
exit( 1 );
319
}
320
321
struct index
322
{
323
UINT offset; /* offset into corresponding data buffer */
324
UINT size; /* size of data entry */
325
};
326
327
static inline int cmp_data( const BYTE *data, UINT size, const BYTE *data2, UINT size2 )
328
{
329
if (size < size2) return -1;
330
else if (size > size2) return 1;
331
return memcmp( data, data2, size );
332
}
333
334
/* return index struct if found, NULL and insert index if not found */
335
static const struct index *find_index( const struct buffer *buf_idx, const struct buffer *buf_data, const BYTE *data,
336
UINT data_size, BOOL is_blob, UINT *insert_idx )
337
{
338
int i, c, min = 0, max = buf_idx->count - 1;
339
const struct index *idx, *base = (const struct index *)buf_idx->ptr;
340
UINT size, len = 0;
341
342
while (min <= max)
343
{
344
i = (min + max) / 2;
345
idx = &base[i];
346
347
if (is_blob) size = decode_int( buf_data->ptr + idx->offset, &len );
348
else size = idx->size;
349
350
c = cmp_data( data, data_size, buf_data->ptr + idx->offset + len, size );
351
352
if (c < 0) max = i - 1;
353
else if (c > 0) min = i + 1;
354
else return idx;
355
}
356
357
if (insert_idx) *insert_idx = max + 1;
358
return NULL;
359
}
360
361
static void insert_index( struct buffer *buf_idx, UINT idx, UINT offset, UINT size )
362
{
363
struct index new = { offset, size }, *base = grow_buffer( buf_idx, sizeof(new) );
364
365
memmove( &base[idx] + 1, &base[idx], (buf_idx->count - idx) * sizeof(new) );
366
base[idx] = new;
367
buf_idx->offset += sizeof(new);
368
buf_idx->count++;
369
}
370
371
static UINT add_string( const char *str )
372
{
373
UINT insert_idx, size, offset = strings.offset;
374
const struct index *idx;
375
376
if (!str) return 0;
377
size = strlen( str ) + 1;
378
if ((idx = find_index( &strings_idx, &strings, (const BYTE *)str, size, FALSE, &insert_idx )))
379
return idx->offset;
380
381
grow_buffer( &strings, size );
382
memcpy( strings.ptr + offset, str, size );
383
strings.offset += size;
384
strings.count++;
385
386
insert_index( &strings_idx, insert_idx, offset, size );
387
return offset;
388
}
389
390
static inline int is_special_char( USHORT c )
391
{
392
return (c >= 0x100 || (c >= 0x01 && c <= 0x08) || (c >= 0x0e && c <= 0x1f) || c == 0x27 || c == 0x2d || c == 0x7f);
393
}
394
395
static UINT add_userstring( const USHORT *str, UINT size )
396
{
397
BYTE encoded[4], terminal = 0;
398
UINT i, insert_idx, offset = userstrings.offset, len = encode_int( size + (str ? 1 : 0), encoded );
399
const struct index *idx;
400
401
if (!str && offset) return 0;
402
403
if ((idx = find_index( &userstrings_idx, &userstrings, (const BYTE *)str, size, TRUE, &insert_idx )))
404
return idx->offset;
405
406
grow_buffer( &userstrings, len + size + 1 );
407
memcpy( userstrings.ptr + userstrings.offset, encoded, len );
408
userstrings.offset += len;
409
if (str)
410
{
411
for (i = 0; i < size / sizeof(USHORT); i++)
412
{
413
*(USHORT *)(userstrings.ptr + userstrings.offset) = str[i];
414
userstrings.offset += sizeof(USHORT);
415
if (is_special_char( str[i] )) terminal = 1;
416
}
417
userstrings.ptr[userstrings.offset++] = terminal;
418
}
419
userstrings.count++;
420
421
insert_index( &userstrings_idx, insert_idx, offset, size );
422
return offset;
423
}
424
425
static UINT add_blob( const BYTE *blob, UINT size )
426
{
427
BYTE encoded[4];
428
UINT insert_idx, offset = blobs.offset, len = encode_int( size, encoded );
429
const struct index *idx;
430
431
if (!blob && offset) return 0;
432
if ((idx = find_index( &blobs_idx, &blobs, blob, size, TRUE, &insert_idx ))) return idx->offset;
433
434
grow_buffer( &blobs, len + size );
435
memcpy( blobs.ptr + blobs.offset, encoded, len );
436
blobs.offset += len;
437
if (blob)
438
{
439
memcpy( blobs.ptr + blobs.offset, blob, size );
440
blobs.offset += size;
441
}
442
blobs.count++;
443
444
insert_index( &blobs_idx, insert_idx, offset, size );
445
return offset;
446
}
447
448
static UINT add_guid( const GUID *guid )
449
{
450
grow_buffer( &guids, sizeof(*guid) );
451
memcpy( guids.ptr + guids.offset, guid, sizeof(*guid) );
452
guids.offset += sizeof(*guid);
453
return ++guids.count;
454
}
455
456
/* returns row number */
457
static UINT add_row( enum table table, const BYTE *row, UINT row_size )
458
{
459
const struct index *idx;
460
UINT insert_idx, offset = tables[table].offset;
461
BOOL sort = (table != TABLE_PARAM && table != TABLE_FIELD && table != TABLE_PROPERTY && table != TABLE_EVENT);
462
463
if (sort && (idx = find_index( &tables_idx[table], &tables[table], row, row_size, FALSE, &insert_idx )))
464
return idx->offset / row_size + 1;
465
466
grow_buffer( &tables[table], row_size );
467
memcpy( tables[table].ptr + offset, row, row_size );
468
tables[table].offset += row_size;
469
tables[table].count++;
470
471
if (sort) insert_index( &tables_idx[table], insert_idx, offset, row_size );
472
return tables[table].count;
473
}
474
475
static void add_bytes( struct buffer *buf, const BYTE *data, UINT size )
476
{
477
grow_buffer( buf, size );
478
memcpy( buf->ptr + buf->offset, data, size );
479
buf->offset += size;
480
}
481
482
static void serialize_byte( UINT value )
483
{
484
assert( !(value >> 24) );
485
add_bytes( &tables_disk, (const BYTE *)&value, sizeof(BYTE) );
486
}
487
488
static void serialize_ushort( UINT value )
489
{
490
assert( !(value >> 16) );
491
add_bytes( &tables_disk, (const BYTE *)&value, sizeof(USHORT) );
492
}
493
494
static void serialize_uint( UINT value )
495
{
496
add_bytes( &tables_disk, (const BYTE *)&value, sizeof(value) );
497
}
498
499
static void serialize_string_idx( UINT idx )
500
{
501
UINT size = strings.offset >> 16 ? sizeof(UINT) : sizeof(USHORT);
502
add_bytes( &tables_disk, (const BYTE *)&idx, size );
503
}
504
505
static void serialize_guid_idx( UINT idx )
506
{
507
UINT size = guids.offset >> 16 ? sizeof(UINT) : sizeof(USHORT);
508
add_bytes( &tables_disk, (const BYTE *)&idx, size );
509
}
510
511
static void serialize_blob_idx( UINT idx )
512
{
513
UINT size = blobs.offset >> 16 ? sizeof(UINT) : sizeof(USHORT);
514
add_bytes( &tables_disk, (const BYTE *)&idx, size );
515
}
516
517
static void serialize_table_idx( UINT idx, enum table target )
518
{
519
UINT size = tables[target].count >> 16 ? sizeof(UINT) : sizeof(USHORT);
520
add_bytes( &tables_disk, (const BYTE *)&idx, size );
521
}
522
523
static enum table resolution_scope_to_table( UINT token )
524
{
525
switch (token & 0x3)
526
{
527
case 0: return TABLE_MODULE;
528
case 1: return TABLE_MODULEREF;
529
case 2: return TABLE_ASSEMBLYREF;
530
case 3: return TABLE_TYPEREF;
531
default: assert( 0 );
532
}
533
}
534
535
static enum table typedef_or_ref_to_table( UINT token )
536
{
537
switch (token & 0x3)
538
{
539
case 0: return TABLE_TYPEDEF;
540
case 1: return TABLE_TYPEREF;
541
case 2: return TABLE_TYPESPEC;
542
default: assert( 0 );
543
}
544
}
545
546
static enum table methoddef_or_ref_to_table( UINT token )
547
{
548
switch (token & 0x1)
549
{
550
case 0: return TABLE_METHODDEF;
551
case 1: return TABLE_MEMBERREF;
552
default: assert( 0 );
553
}
554
}
555
556
static enum table memberref_parent_to_table( UINT token )
557
{
558
switch (token & 0x7)
559
{
560
case 0: return TABLE_TYPEDEF;
561
case 1: return TABLE_TYPEREF;
562
case 2: return TABLE_MODULEREF;
563
case 3: return TABLE_METHODDEF;
564
case 4: return TABLE_TYPESPEC;
565
default: assert( 0 );
566
}
567
}
568
569
static enum table has_constant_to_table( UINT token )
570
{
571
switch (token & 0x3)
572
{
573
case 0: return TABLE_FIELD;
574
case 1: return TABLE_PARAM;
575
case 2: return TABLE_PROPERTY;
576
default: assert( 0 );
577
}
578
}
579
580
static enum table has_customattribute_to_table( UINT token )
581
{
582
switch (token & 0x1f)
583
{
584
case 0: return TABLE_METHODDEF;
585
case 1: return TABLE_FIELD;
586
case 2: return TABLE_TYPEREF;
587
case 3: return TABLE_TYPEDEF;
588
case 4: return TABLE_PARAM;
589
case 5: return TABLE_INTERFACEIMPL;
590
case 6: return TABLE_MEMBERREF;
591
case 7: return TABLE_MODULE;
592
case 9: return TABLE_PROPERTY;
593
case 10: return TABLE_EVENT;
594
case 11: return TABLE_STANDALONESIG;
595
case 12: return TABLE_MODULEREF;
596
case 13: return TABLE_TYPESPEC;
597
case 14: return TABLE_ASSEMBLY;
598
case 15: return TABLE_ASSEMBLYREF;
599
case 16: return TABLE_FILE;
600
case 17: return TABLE_EXPORTEDTYPE;
601
case 18: return TABLE_MANIFESTRESOURCE;
602
default: assert( 0 );
603
}
604
}
605
606
static enum table customattribute_type_to_table( UINT token )
607
{
608
switch (token & 0x7)
609
{
610
case 2: return TABLE_METHODDEF;
611
case 3: return TABLE_MEMBERREF;
612
default: assert( 0 );
613
}
614
}
615
616
static enum table has_semantics_to_table( UINT token )
617
{
618
switch (token & 0x1)
619
{
620
case 0: return TABLE_EVENT;
621
case 1: return TABLE_PROPERTY;
622
default: assert( 0 );
623
}
624
}
625
626
struct module_row
627
{
628
UINT generation;
629
UINT name;
630
UINT mvid;
631
UINT encid;
632
UINT encbaseid;
633
};
634
635
static UINT add_module_row( UINT name, UINT mvid )
636
{
637
struct module_row row = { 0, name, mvid, 0, 0 };
638
return add_row( TABLE_MODULE, (const BYTE *)&row, sizeof(row) );
639
}
640
641
static void serialize_module_table( void )
642
{
643
const struct module_row *row = (const struct module_row *)tables[TABLE_MODULE].ptr;
644
645
serialize_ushort( row->generation );
646
serialize_string_idx( row->name );
647
serialize_guid_idx( row->mvid );
648
serialize_guid_idx( row->encid );
649
serialize_guid_idx( row->encbaseid );
650
}
651
652
struct typeref_row
653
{
654
UINT scope;
655
UINT name;
656
UINT namespace;
657
};
658
659
static UINT add_typeref_row( UINT scope, UINT name, UINT namespace )
660
{
661
struct typeref_row row = { scope, name, namespace };
662
return add_row( TABLE_TYPEREF, (const BYTE *)&row, sizeof(row) );
663
}
664
665
static void serialize_typeref_table( void )
666
{
667
const struct typeref_row *row = (const struct typeref_row *)tables[TABLE_TYPEREF].ptr;
668
UINT i;
669
670
for (i = 0; i < tables[TABLE_TYPEREF].count; i++)
671
{
672
serialize_table_idx( row->scope, resolution_scope_to_table(row->scope) );
673
serialize_string_idx( row->name );
674
serialize_string_idx( row->namespace );
675
row++;
676
}
677
}
678
679
struct typedef_row
680
{
681
UINT flags;
682
UINT name;
683
UINT namespace;
684
UINT extends;
685
UINT fieldlist;
686
UINT methodlist;
687
};
688
689
static UINT add_typedef_row( UINT flags, UINT name, UINT namespace, UINT extends, UINT fieldlist, UINT methodlist )
690
{
691
struct typedef_row row = { flags, name, namespace, extends, fieldlist, methodlist };
692
693
if (!row.fieldlist) row.fieldlist = tables[TABLE_FIELD].count + 1;
694
if (!row.methodlist) row.methodlist = tables[TABLE_METHODDEF].count + 1;
695
return add_row( TABLE_TYPEDEF, (const BYTE *)&row, sizeof(row) );
696
}
697
698
/* FIXME: enclosing classes should come before enclosed classes */
699
static void serialize_typedef_table( void )
700
{
701
const struct typedef_row *row = (const struct typedef_row *)tables[TABLE_TYPEDEF].ptr;
702
UINT i;
703
704
for (i = 0; i < tables[TABLE_TYPEDEF].count; i++)
705
{
706
serialize_uint( row->flags );
707
serialize_string_idx( row->name );
708
serialize_string_idx( row->namespace );
709
serialize_table_idx( row->extends, typedef_or_ref_to_table(row->extends) );
710
serialize_table_idx( row->fieldlist, TABLE_FIELD );
711
serialize_table_idx( row->methodlist, TABLE_METHODDEF );
712
row++;
713
}
714
}
715
716
struct field_row
717
{
718
UINT flags;
719
UINT name;
720
UINT signature;
721
};
722
723
static UINT add_field_row( UINT flags, UINT name, UINT signature )
724
{
725
struct field_row row = { flags, name, signature };
726
return add_row( TABLE_FIELD, (const BYTE *)&row, sizeof(row) );
727
}
728
729
static void serialize_field_table( void )
730
{
731
const struct field_row *row = (const struct field_row *)tables[TABLE_FIELD].ptr;
732
UINT i;
733
734
for (i = 0; i < tables[TABLE_FIELD].count; i++)
735
{
736
serialize_ushort( row->flags );
737
serialize_string_idx( row->name );
738
serialize_blob_idx( row->signature );
739
row++;
740
}
741
}
742
743
struct methoddef_row
744
{
745
UINT rva;
746
UINT implflags;
747
UINT flags;
748
UINT name;
749
UINT signature;
750
UINT paramlist;
751
};
752
753
static UINT add_methoddef_row( UINT implflags, UINT flags, UINT name, UINT signature, UINT paramlist )
754
{
755
struct methoddef_row row = { 0, implflags, flags, name, signature, paramlist };
756
757
if (!row.paramlist) row.paramlist = tables[TABLE_PARAM].count + 1;
758
return add_row( TABLE_METHODDEF, (const BYTE *)&row, sizeof(row) );
759
}
760
761
static void serialize_methoddef_table( void )
762
{
763
const struct methoddef_row *row = (const struct methoddef_row *)tables[TABLE_METHODDEF].ptr;
764
UINT i;
765
766
for (i = 0; i < tables[TABLE_METHODDEF].count; i++)
767
{
768
serialize_uint( row->rva );
769
serialize_ushort( row->implflags );
770
serialize_ushort( row->flags );
771
serialize_string_idx( row->name );
772
serialize_blob_idx( row->signature );
773
serialize_table_idx( row->paramlist, TABLE_PARAM );
774
row++;
775
}
776
}
777
778
struct param_row
779
{
780
UINT flags;
781
UINT sequence;
782
UINT name;
783
};
784
785
static UINT add_param_row( USHORT flags, USHORT sequence, UINT name )
786
{
787
struct param_row row = { flags, sequence, name };
788
return add_row( TABLE_PARAM, (const BYTE *)&row, sizeof(row) );
789
}
790
791
static void serialize_param_table( void )
792
{
793
const struct param_row *row = (const struct param_row *)tables[TABLE_PARAM].ptr;
794
UINT i;
795
796
for (i = 0; i < tables[TABLE_PARAM].count; i++)
797
{
798
serialize_ushort( row->flags );
799
serialize_ushort( row->sequence );
800
serialize_string_idx( row->name );
801
row++;
802
}
803
}
804
805
struct interfaceimpl_row
806
{
807
UINT class;
808
UINT interface;
809
};
810
811
static UINT add_interfaceimpl_row( UINT class, UINT interface )
812
{
813
struct interfaceimpl_row row = { class, interface };
814
return add_row( TABLE_INTERFACEIMPL, (const BYTE *)&row, sizeof(row) );
815
}
816
817
static int cmp_interfaceimpl_row( const void *a, const void *b )
818
{
819
const struct interfaceimpl_row *row = a, *row2 = b;
820
if (row->class > row2->class) return 1;
821
if (row->class < row2->class) return -1;
822
if (row->interface > row2->interface) return 1;
823
if (row->interface < row2->interface) return -1;
824
return 0;
825
}
826
827
/* sorted by class, interface */
828
static void serialize_interfaceimpl_table( void )
829
{
830
const struct interfaceimpl_row *row = (const struct interfaceimpl_row *)tables[TABLE_INTERFACEIMPL].ptr;
831
UINT i;
832
833
qsort( tables[TABLE_INTERFACEIMPL].ptr, tables[TABLE_INTERFACEIMPL].count, sizeof(*row),
834
cmp_interfaceimpl_row );
835
836
for (i = 0; i < tables_idx[TABLE_INTERFACEIMPL].count; i++)
837
{
838
serialize_table_idx( row->class, TABLE_TYPEDEF );
839
serialize_table_idx( row->interface, typedef_or_ref_to_table(row->interface) );
840
row++;
841
}
842
}
843
844
struct memberref_row
845
{
846
UINT class;
847
UINT name;
848
UINT signature;
849
};
850
851
static UINT add_memberref_row( UINT class, UINT name, UINT signature )
852
{
853
struct memberref_row row = { class, name, signature };
854
return add_row( TABLE_MEMBERREF, (const BYTE *)&row, sizeof(row) );
855
}
856
857
static void serialize_memberref_table( void )
858
{
859
const struct memberref_row *row = (const struct memberref_row *)tables[TABLE_MEMBERREF].ptr;
860
UINT i;
861
862
for (i = 0; i < tables[TABLE_MEMBERREF].count; i++)
863
{
864
serialize_table_idx( row->class, memberref_parent_to_table(row->class) );
865
serialize_string_idx( row->name );
866
serialize_blob_idx( row->signature );
867
row++;
868
}
869
}
870
871
struct constant_row
872
{
873
UINT type;
874
UINT padding;
875
UINT parent;
876
UINT value;
877
};
878
879
static UINT add_constant_row( BYTE type, UINT parent, UINT value )
880
{
881
struct constant_row row = { type, 0, parent, value };
882
return add_row( TABLE_CONSTANT, (const BYTE *)&row, sizeof(row) );
883
}
884
885
static int cmp_constant_row( const void *a, const void *b )
886
{
887
const struct constant_row *row = a, *row2 = b;
888
if (row->parent > row2->parent) return 1;
889
if (row->parent < row2->parent) return -1;
890
return 0;
891
}
892
893
/* sorted by parent */
894
static void serialize_constant_table( void )
895
{
896
const struct constant_row *row = (const struct constant_row *)tables[TABLE_CONSTANT].ptr;
897
UINT i;
898
899
qsort( tables[TABLE_CONSTANT].ptr, tables[TABLE_CONSTANT].count, sizeof(*row), cmp_constant_row );
900
901
for (i = 0; i < tables_idx[TABLE_CONSTANT].count; i++)
902
{
903
serialize_byte( row->type );
904
serialize_byte( row->padding );
905
serialize_table_idx( row->parent, has_constant_to_table(row->parent) );
906
serialize_blob_idx( row->value );
907
row++;
908
}
909
}
910
911
struct customattribute_row
912
{
913
UINT parent;
914
UINT type;
915
UINT value;
916
};
917
918
static UINT add_customattribute_row( UINT parent, UINT type, UINT value )
919
{
920
struct customattribute_row row = { parent, type, value };
921
return add_row( TABLE_CUSTOMATTRIBUTE, (const BYTE *)&row, sizeof(row) );
922
}
923
924
static int cmp_customattribute_row( const void *a, const void *b )
925
{
926
const struct customattribute_row *row = a, *row2 = b;
927
if (row->parent > row2->parent) return 1;
928
if (row->parent < row2->parent) return -1;
929
return 0;
930
}
931
932
/* sorted by parent */
933
static void serialize_customattribute_table( void )
934
{
935
const struct customattribute_row *row = (const struct customattribute_row *)tables[TABLE_CUSTOMATTRIBUTE].ptr;
936
UINT i;
937
938
qsort( tables[TABLE_CUSTOMATTRIBUTE].ptr, tables[TABLE_CUSTOMATTRIBUTE].count, sizeof(*row),
939
cmp_customattribute_row );
940
941
for (i = 0; i < tables_idx[TABLE_CUSTOMATTRIBUTE].count; i++)
942
{
943
serialize_table_idx( row->parent, has_customattribute_to_table(row->parent) );
944
serialize_table_idx( row->type, customattribute_type_to_table(row->type) );
945
serialize_blob_idx( row->value );
946
row++;
947
}
948
}
949
950
struct assembly_row
951
{
952
UINT hashalgid;
953
UINT majorversion;
954
UINT minorversion;
955
UINT buildnumber;
956
UINT revisionnumber;
957
UINT flags;
958
UINT publickey;
959
UINT name;
960
UINT culture;
961
};
962
963
static UINT add_assembly_row( UINT name )
964
{
965
struct assembly_row row = { CALG_SHA, 255, 255, 255, 255, 0x200, 0, name, 0 };
966
return add_row( TABLE_ASSEMBLY, (const BYTE *)&row, sizeof(row) );
967
}
968
969
static void serialize_assembly_table( void )
970
{
971
const struct assembly_row *row = (const struct assembly_row *)tables[TABLE_ASSEMBLY].ptr;
972
973
serialize_uint( row->hashalgid );
974
serialize_ushort( row->majorversion );
975
serialize_ushort( row->minorversion );
976
serialize_ushort( row->buildnumber );
977
serialize_ushort( row->revisionnumber );
978
serialize_uint( row->flags );
979
serialize_blob_idx( row->publickey );
980
serialize_string_idx( row->name );
981
serialize_string_idx( row->culture );
982
}
983
984
struct assemblyref_row
985
{
986
UINT majorversion;
987
UINT minorversion;
988
UINT buildnumber;
989
UINT revisionnumber;
990
UINT flags;
991
UINT publickey;
992
UINT name;
993
UINT culture;
994
UINT hashvalue;
995
};
996
997
static UINT add_assemblyref_row( UINT flags, UINT publickey, UINT name )
998
{
999
struct assemblyref_row row = { 255, 255, 255, 255, flags, publickey, name, 0, 0 };
1000
return add_row( TABLE_ASSEMBLYREF, (const BYTE *)&row, sizeof(row) );
1001
}
1002
1003
static void serialize_assemblyref_table( void )
1004
{
1005
const struct assemblyref_row *row = (const struct assemblyref_row *)tables[TABLE_ASSEMBLYREF].ptr;
1006
UINT i;
1007
1008
for (i = 0; i < tables[TABLE_ASSEMBLYREF].count; i++)
1009
{
1010
serialize_ushort( row->majorversion );
1011
serialize_ushort( row->minorversion );
1012
serialize_ushort( row->buildnumber );
1013
serialize_ushort( row->revisionnumber );
1014
serialize_uint( row->flags );
1015
serialize_blob_idx( row->publickey );
1016
serialize_string_idx( row->name );
1017
serialize_string_idx( row->culture );
1018
serialize_blob_idx( row->hashvalue );
1019
row++;
1020
}
1021
}
1022
1023
struct propertymap_row
1024
{
1025
UINT parent;
1026
UINT proplist;
1027
};
1028
1029
static UINT add_propertymap_row( UINT parent, UINT proplist )
1030
{
1031
struct propertymap_row row = { parent, proplist };
1032
return add_row( TABLE_PROPERTYMAP, (const BYTE *)&row, sizeof(row) );
1033
}
1034
1035
static void serialize_propertymap_table( void )
1036
{
1037
const struct propertymap_row *row = (const struct propertymap_row *)tables[TABLE_PROPERTYMAP].ptr;
1038
UINT i;
1039
1040
for (i = 0; i < tables[TABLE_PROPERTYMAP].count; i++)
1041
{
1042
serialize_table_idx( row->parent, TABLE_TYPEDEF );
1043
serialize_table_idx( row->proplist, TABLE_PROPERTY );
1044
row++;
1045
}
1046
}
1047
1048
struct property_row
1049
{
1050
UINT flags;
1051
UINT name;
1052
UINT type;
1053
};
1054
1055
static UINT add_property_row( USHORT flags, UINT name, UINT type )
1056
{
1057
struct property_row row = { flags, name, type };
1058
return add_row( TABLE_PROPERTY, (const BYTE *)&row, sizeof(row) );
1059
}
1060
1061
static void serialize_property_table( void )
1062
{
1063
const struct property_row *row = (const struct property_row *)tables[TABLE_PROPERTY].ptr;
1064
UINT i;
1065
1066
for (i = 0; i < tables[TABLE_PROPERTY].count; i++)
1067
{
1068
serialize_ushort( row->flags );
1069
serialize_string_idx( row->name );
1070
serialize_blob_idx( row->type );
1071
row++;
1072
}
1073
}
1074
1075
struct eventmap_row
1076
{
1077
UINT parent;
1078
UINT eventlist;
1079
};
1080
1081
static UINT add_eventmap_row( UINT parent, UINT eventlist )
1082
{
1083
struct eventmap_row row = { parent, eventlist };
1084
return add_row( TABLE_EVENTMAP, (const BYTE *)&row, sizeof(row) );
1085
}
1086
1087
static void serialize_eventmap_table( void )
1088
{
1089
const struct eventmap_row *row = (const struct eventmap_row *)tables[TABLE_EVENTMAP].ptr;
1090
UINT i;
1091
1092
for (i = 0; i < tables[TABLE_EVENTMAP].count; i++)
1093
{
1094
serialize_table_idx( row->parent, TABLE_TYPEDEF );
1095
serialize_table_idx( row->eventlist, TABLE_EVENT );
1096
row++;
1097
}
1098
}
1099
1100
struct event_row
1101
{
1102
UINT flags;
1103
UINT name;
1104
UINT type;
1105
};
1106
1107
static UINT add_event_row( USHORT flags, UINT name, UINT type )
1108
{
1109
struct event_row row = { flags, name, type };
1110
return add_row( TABLE_EVENT, (const BYTE *)&row, sizeof(row) );
1111
}
1112
1113
static void serialize_event_table( void )
1114
{
1115
const struct event_row *row = (const struct event_row *)tables[TABLE_EVENT].ptr;
1116
UINT i;
1117
1118
for (i = 0; i < tables[TABLE_EVENT].count; i++)
1119
{
1120
serialize_ushort( row->flags );
1121
serialize_string_idx( row->name );
1122
serialize_table_idx( row->type, typedef_or_ref_to_table(row->type) );
1123
row++;
1124
}
1125
}
1126
1127
struct methodsemantics_row
1128
{
1129
UINT semantics;
1130
UINT method;
1131
UINT association;
1132
};
1133
1134
static UINT add_methodsemantics_row( USHORT flags, UINT name, UINT type )
1135
{
1136
struct methodsemantics_row row = { flags, name, type };
1137
return add_row( TABLE_METHODSEMANTICS, (const BYTE *)&row, sizeof(row) );
1138
}
1139
1140
static int cmp_methodsemantics_row( const void *a, const void *b )
1141
{
1142
const struct methodsemantics_row *row = a, *row2 = b;
1143
if (row->association > row2->association) return 1;
1144
if (row->association < row2->association) return -1;
1145
return 0;
1146
}
1147
1148
/* sorted by association */
1149
static void serialize_methodsemantics_table( void )
1150
{
1151
const struct methodsemantics_row *row = (const struct methodsemantics_row *)tables[TABLE_METHODSEMANTICS].ptr;
1152
UINT i;
1153
1154
qsort( tables[TABLE_METHODSEMANTICS].ptr, tables[TABLE_METHODSEMANTICS].count, sizeof(*row),
1155
cmp_methodsemantics_row );
1156
1157
for (i = 0; i < tables[TABLE_METHODSEMANTICS].count; i++)
1158
{
1159
serialize_ushort( row->semantics );
1160
serialize_table_idx( row->method, TABLE_METHODDEF );
1161
serialize_table_idx( row->association, has_semantics_to_table(row->association) );
1162
row++;
1163
}
1164
}
1165
1166
struct methodimpl_row
1167
{
1168
UINT class;
1169
UINT body;
1170
UINT declaration;
1171
};
1172
1173
static UINT add_methodimpl_row( UINT class, UINT body, UINT declaration )
1174
{
1175
struct methodimpl_row row = { class, body, declaration };
1176
return add_row( TABLE_METHODIMPL, (const BYTE *)&row, sizeof(row) );
1177
}
1178
1179
static void serialize_methodimpl_table( void )
1180
{
1181
const struct methodimpl_row *row = (const struct methodimpl_row *)tables[TABLE_METHODIMPL].ptr;
1182
UINT i;
1183
1184
for (i = 0; i < tables[TABLE_METHODIMPL].count; i++)
1185
{
1186
serialize_table_idx( row->class, row->class );
1187
serialize_table_idx( row->body, methoddef_or_ref_to_table(row->body) );
1188
serialize_table_idx( row->declaration, methoddef_or_ref_to_table(row->declaration) );
1189
row++;
1190
}
1191
}
1192
1193
static UINT typedef_or_ref( enum table table, UINT row )
1194
{
1195
switch (table)
1196
{
1197
case TABLE_TYPEDEF: return row << 2;
1198
case TABLE_TYPEREF: return row << 2 | 1;
1199
case TABLE_TYPESPEC: return row << 2 | 2;
1200
default: assert( 0 );
1201
}
1202
}
1203
1204
static UINT methoddef_or_ref( enum table table, UINT row )
1205
{
1206
switch (table)
1207
{
1208
case TABLE_METHODDEF: return row << 1;
1209
case TABLE_MEMBERREF: return row << 1 | 1;
1210
default: assert( 0 );
1211
}
1212
}
1213
1214
static UINT resolution_scope( enum table table, UINT row )
1215
{
1216
switch (table)
1217
{
1218
case TABLE_MODULE: return row << 2;
1219
case TABLE_MODULEREF: return row << 2 | 1;
1220
case TABLE_ASSEMBLYREF: return row << 2 | 2;
1221
case TABLE_TYPEREF: return row << 2 | 3;
1222
default: assert( 0 );
1223
}
1224
}
1225
1226
static UINT has_constant( enum table table, UINT row )
1227
{
1228
switch (table)
1229
{
1230
case TABLE_FIELD: return row << 2;
1231
case TABLE_PARAM: return row << 2 | 1;
1232
case TABLE_PROPERTY: return row << 2 | 2;
1233
default: assert( 0 );
1234
}
1235
}
1236
1237
static UINT memberref_parent( enum table table, UINT row )
1238
{
1239
switch (table)
1240
{
1241
case TABLE_TYPEDEF: return row << 3;
1242
case TABLE_TYPEREF: return row << 3 | 1;
1243
case TABLE_MODULEREF: return row << 3 | 2;
1244
case TABLE_METHODDEF: return row << 3 | 3;
1245
case TABLE_TYPESPEC: return row << 3 | 4;
1246
default: assert( 0 );
1247
}
1248
}
1249
1250
static UINT has_customattribute( enum table table, UINT row )
1251
{
1252
switch (table)
1253
{
1254
case TABLE_METHODDEF: return row << 5;
1255
case TABLE_FIELD: return row << 5 | 1;
1256
case TABLE_TYPEREF: return row << 5 | 2;
1257
case TABLE_TYPEDEF: return row << 5 | 3;
1258
case TABLE_PARAM: return row << 5 | 4;
1259
case TABLE_INTERFACEIMPL: return row << 5 | 5;
1260
case TABLE_MEMBERREF: return row << 5 | 6;
1261
case TABLE_MODULE: return row << 5 | 7;
1262
case TABLE_PROPERTY: return row << 5 | 9;
1263
case TABLE_EVENT: return row << 5 | 10;
1264
case TABLE_STANDALONESIG: return row << 5 | 11;
1265
case TABLE_MODULEREF: return row << 5 | 12;
1266
case TABLE_TYPESPEC: return row << 5 | 13;
1267
case TABLE_ASSEMBLY: return row << 5 | 14;
1268
case TABLE_ASSEMBLYREF: return row << 5 | 15;
1269
case TABLE_FILE: return row << 5 | 16;
1270
case TABLE_EXPORTEDTYPE: return row << 5 | 17;
1271
case TABLE_MANIFESTRESOURCE: return row << 5 | 18;
1272
default: assert( 0 );
1273
}
1274
}
1275
1276
static UINT customattribute_type( enum table table, UINT row )
1277
{
1278
switch (table)
1279
{
1280
case TABLE_METHODDEF: return row << 3 | 2;
1281
case TABLE_MEMBERREF: return row << 3 | 3;
1282
default: assert( 0 );
1283
}
1284
}
1285
1286
static UINT has_semantics( enum table table, UINT row )
1287
{
1288
switch (table)
1289
{
1290
case TABLE_EVENT: return row << 1;
1291
case TABLE_PROPERTY: return row << 1 | 1;
1292
default: assert( 0 );
1293
}
1294
}
1295
1296
enum element_type
1297
{
1298
ELEMENT_TYPE_END = 0x00,
1299
ELEMENT_TYPE_VOID = 0x01,
1300
ELEMENT_TYPE_BOOLEAN = 0x02,
1301
ELEMENT_TYPE_CHAR = 0x03,
1302
ELEMENT_TYPE_I1 = 0x04,
1303
ELEMENT_TYPE_U1 = 0x05,
1304
ELEMENT_TYPE_I2 = 0x06,
1305
ELEMENT_TYPE_U2 = 0x07,
1306
ELEMENT_TYPE_I4 = 0x08,
1307
ELEMENT_TYPE_U4 = 0x09,
1308
ELEMENT_TYPE_I8 = 0x0a,
1309
ELEMENT_TYPE_U8 = 0x0b,
1310
ELEMENT_TYPE_R4 = 0x0c,
1311
ELEMENT_TYPE_R8 = 0x0d,
1312
ELEMENT_TYPE_STRING = 0x0e,
1313
ELEMENT_TYPE_PTR = 0x0f,
1314
ELEMENT_TYPE_BYREF = 0x10,
1315
ELEMENT_TYPE_VALUETYPE = 0x11,
1316
ELEMENT_TYPE_CLASS = 0x12,
1317
ELEMENT_TYPE_VAR = 0x13,
1318
ELEMENT_TYPE_ARRAY = 0x14,
1319
ELEMENT_TYPE_GENERICINST = 0x15,
1320
ELEMENT_TYPE_TYPEDBYREF = 0x16,
1321
ELEMENT_TYPE_I = 0x18,
1322
ELEMENT_TYPE_U = 0x19,
1323
ELEMENT_TYPE_FNPTR = 0x1b,
1324
ELEMENT_TYPE_OBJECT = 0x1c,
1325
ELEMENT_TYPE_SZARRAY = 0x1d,
1326
ELEMENT_TYPE_MVAR = 0x1e,
1327
ELEMENT_TYPE_CMOD_REQD = 0x1f,
1328
ELEMENT_TYPE_CMOD_OPT = 0x20,
1329
ELEMENT_TYPE_INTERNAL = 0x21,
1330
ELEMENT_TYPE_MODIFIER = 0x40,
1331
ELEMENT_TYPE_SENTINEL = 0x41,
1332
ELEMENT_TYPE_PINNED = 0x45
1333
};
1334
1335
enum
1336
{
1337
TYPE_ATTR_PUBLIC = 0x000001,
1338
TYPE_ATTR_NESTEDPUBLIC = 0x000002,
1339
TYPE_ATTR_NESTEDPRIVATE = 0x000003,
1340
TYPE_ATTR_NESTEDFAMILY = 0x000004,
1341
TYPE_ATTR_NESTEDASSEMBLY = 0x000005,
1342
TYPE_ATTR_NESTEDFAMANDASSEM = 0x000006,
1343
TYPE_ATTR_NESTEDFAMORASSEM = 0x000007,
1344
TYPE_ATTR_SEQUENTIALLAYOUT = 0x000008,
1345
TYPE_ATTR_EXPLICITLAYOUT = 0x000010,
1346
TYPE_ATTR_INTERFACE = 0x000020,
1347
TYPE_ATTR_ABSTRACT = 0x000080,
1348
TYPE_ATTR_SEALED = 0x000100,
1349
TYPE_ATTR_SPECIALNAME = 0x000400,
1350
TYPE_ATTR_RTSPECIALNAME = 0x000800,
1351
TYPE_ATTR_IMPORT = 0x001000,
1352
TYPE_ATTR_SERIALIZABLE = 0x002000,
1353
TYPE_ATTR_UNKNOWN = 0x004000,
1354
TYPE_ATTR_UNICODECLASS = 0x010000,
1355
TYPE_ATTR_AUTOCLASS = 0x020000,
1356
TYPE_ATTR_CUSTOMFORMATCLASS = 0x030000,
1357
TYPE_ATTR_HASSECURITY = 0x040000,
1358
TYPE_ATTR_BEFOREFIELDINIT = 0x100000
1359
};
1360
1361
enum
1362
{
1363
FIELD_ATTR_PRIVATE = 0x0001,
1364
FIELD_ATTR_FAMANDASSEM = 0x0002,
1365
FIELD_ATTR_ASSEMBLY = 0x0003,
1366
FIELD_ATTR_FAMILY = 0x0004,
1367
FIELD_ATTR_FAMORASSEM = 0x0005,
1368
FIELD_ATTR_PUBLIC = 0x0006,
1369
FIELD_ATTR_STATIC = 0x0010,
1370
FIELD_ATTR_INITONLY = 0x0020,
1371
FIELD_ATTR_LITERAL = 0x0040,
1372
FIELD_ATTR_NOTSERIALIZED = 0x0080,
1373
FIELD_ATTR_HASFIELDRVA = 0x0100,
1374
FIELD_ATTR_SPECIALNAME = 0x0200,
1375
FIELD_ATTR_RTSPECIALNAME = 0x0400,
1376
FIELD_ATTR_HASFIELDMARSHAL = 0x1000,
1377
FIELD_ATTR_PINVOKEIMPL = 0x2000,
1378
FIELD_ATTR_HASDEFAULT = 0x8000
1379
};
1380
1381
enum
1382
{
1383
METHOD_ATTR_COMPILERCONTROLLED = 0x0000,
1384
METHOD_ATTR_PRIVATE = 0x0001,
1385
METHOD_ATTR_FAMANDASSEM = 0x0002,
1386
METHOD_ATTR_ASSEM = 0x0003,
1387
METHOD_ATTR_FAMILY = 0x0004,
1388
METHOD_ATTR_FAMORASSEM = 0x0005,
1389
METHOD_ATTR_PUBLIC = 0x0006,
1390
METHOD_ATTR_STATIC = 0x0010,
1391
METHOD_ATTR_FINAL = 0x0020,
1392
METHOD_ATTR_VIRTUAL = 0x0040,
1393
METHOD_ATTR_HIDEBYSIG = 0x0080,
1394
METHOD_ATTR_NEWSLOT = 0x0100,
1395
METHOD_ATTR_STRICT = 0x0200,
1396
METHOD_ATTR_ABSTRACT = 0x0400,
1397
METHOD_ATTR_SPECIALNAME = 0x0800,
1398
METHOD_ATTR_RTSPECIALNAME = 0x1000,
1399
METHOD_ATTR_PINVOKEIMPL = 0x2000
1400
};
1401
1402
enum
1403
{
1404
METHOD_IMPL_IL = 0x0000,
1405
METHOD_IMPL_NATIVE = 0x0001,
1406
METHOD_IMPL_OPTIL = 0x0002,
1407
METHOD_IMPL_RUNTIME = 0x0003,
1408
METHOD_IMPL_UNMANAGED = 0x0004
1409
};
1410
1411
enum
1412
{
1413
METHOD_SEM_SETTER = 0x0001,
1414
METHOD_SEM_GETTER = 0x0002,
1415
METHOD_SEM_OTHER = 0x0004,
1416
METHOD_SEM_ADDON = 0x0008,
1417
METHOD_SEM_REMOVEON = 0x0010
1418
};
1419
1420
enum
1421
{
1422
PARAM_ATTR_IN = 0x0001,
1423
PARAM_ATTR_OUT = 0x0002,
1424
PARAM_ATTR_OPTIONAL = 0x0010
1425
};
1426
1427
enum
1428
{
1429
SIG_TYPE_DEFAULT = 0x00,
1430
SIG_TYPE_C = 0x01,
1431
SIG_TYPE_STDCALL = 0x02,
1432
SIG_TYPE_THISCALL = 0x03,
1433
SIG_TYPE_FASTCALL = 0x04,
1434
SIG_TYPE_VARARG = 0x05,
1435
SIG_TYPE_FIELD = 0x06,
1436
SIG_TYPE_LOCALSIG = 0x07,
1437
SIG_TYPE_PROPERTY = 0x08,
1438
SIG_TYPE_GENERIC = 0x10,
1439
SIG_TYPE_HASTHIS = 0x20,
1440
SIG_TYPE_EXPLICITTHIS = 0x40
1441
};
1442
1443
static char *assembly_name; /* current module */
1444
static char **assembly_imports;
1445
static UINT num_assembly_imports;
1446
1447
static void append_assembly_import( const char *import )
1448
{
1449
char *ptr, *name = xstrdup( import );
1450
1451
if ((ptr = strrchr( name, '.' ))) *ptr = 0;
1452
assembly_imports = xrealloc( assembly_imports, (num_assembly_imports + 1) * sizeof(*assembly_imports) );
1453
assembly_imports[num_assembly_imports++] = name;
1454
}
1455
1456
static const char *get_assembly_import( const char *name )
1457
{
1458
UINT i;
1459
for (i = 0; i < num_assembly_imports; i++)
1460
{
1461
if (!strcasecmp( name, assembly_imports[i] )) return assembly_imports[i];
1462
}
1463
return NULL;
1464
}
1465
1466
#define MODULE_ROW 1
1467
#define MSCORLIB_ROW 1
1468
1469
#define MAX_NAME 256
1470
1471
/* create a type reference if needed and store it in the base type */
1472
static void create_typeref( type_t *type )
1473
{
1474
UINT namespace, assemblyref, scope;
1475
char *namespace_str;
1476
const char *import_name;
1477
type_t *base_type;
1478
1479
while (type_get_type( type ) == TYPE_POINTER) type = type_pointer_get_ref_type( type );
1480
base_type = type_get_real_type( type );
1481
1482
if (base_type->md.ref) return;
1483
1484
/* basic types don't get a reference */
1485
if (!base_type->name) return;
1486
1487
/* HSTRING is treated as a fundamental type */
1488
if (type->name && !strcmp( type->name, "HSTRING__" )) return;
1489
1490
/* IInspectable is treated as a fundamental type */
1491
if (type->name && !strcmp( base_type->name, "IInspectable" )) return;
1492
1493
/* GUID is imported from mscorlib */
1494
if (type->name && !strcmp( type->name, "GUID" ))
1495
{
1496
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
1497
base_type->md.ref = add_typeref_row( scope, add_string("Guid"), add_string("System") );
1498
return;
1499
}
1500
1501
if (base_type->winmd_short_name)
1502
base_type->md.name = add_string( base_type->winmd_short_name );
1503
else
1504
base_type->md.name = add_string( base_type->name );
1505
1506
namespace_str = format_namespace( base_type->namespace, "", ".", NULL, NULL );
1507
base_type->md.namespace = add_string( namespace_str );
1508
1509
if (base_type->md.namespace && (import_name = get_assembly_import( namespace_str )))
1510
{
1511
assemblyref = add_assemblyref_row( 0x200, 0, add_string(import_name) );
1512
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
1513
base_type->md.ref = add_typeref_row( scope, base_type->md.name, base_type->md.namespace );
1514
}
1515
else if (!base_type->md.namespace) /* types without namespace are imported from Windows.Foundation */
1516
{
1517
namespace = add_string( "Windows.Foundation" );
1518
assemblyref = add_assemblyref_row( 0x200, 0, namespace );
1519
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
1520
base_type->md.ref = add_typeref_row( scope, base_type->md.name, namespace );
1521
}
1522
else
1523
{
1524
scope = resolution_scope( TABLE_MODULE, MODULE_ROW );
1525
base_type->md.ref = add_typeref_row( scope, base_type->md.name, base_type->md.namespace );
1526
}
1527
1528
free( namespace_str );
1529
}
1530
1531
static UINT make_field_value_sig( UINT token, BYTE *buf )
1532
{
1533
UINT len = 2;
1534
1535
buf[0] = SIG_TYPE_FIELD;
1536
buf[1] = ELEMENT_TYPE_VALUETYPE;
1537
len += encode_int( token, buf + 2 );
1538
return len;
1539
}
1540
1541
enum
1542
{
1543
LARGE_STRING_HEAP = 0x01,
1544
LARGE_GUID_HEAP = 0x02,
1545
LARGE_BLOB_HEAP = 0x04
1546
};
1547
1548
static enum element_type map_basic_type( enum type_basic_type type, int sign )
1549
{
1550
enum element_type elem_type;
1551
1552
switch (type)
1553
{
1554
case TYPE_BASIC_CHAR: elem_type = ELEMENT_TYPE_BOOLEAN; break;
1555
case TYPE_BASIC_INT16: elem_type = (sign > 0) ? ELEMENT_TYPE_U2 : ELEMENT_TYPE_I2; break;
1556
case TYPE_BASIC_INT:
1557
case TYPE_BASIC_INT32:
1558
case TYPE_BASIC_LONG: elem_type = (sign > 0) ? ELEMENT_TYPE_U4 : ELEMENT_TYPE_I4; break;
1559
case TYPE_BASIC_INT64: elem_type = (sign > 0) ? ELEMENT_TYPE_U8 : ELEMENT_TYPE_I8; break;
1560
case TYPE_BASIC_BYTE: elem_type = ELEMENT_TYPE_U1; break;
1561
case TYPE_BASIC_WCHAR: elem_type = ELEMENT_TYPE_CHAR; break;
1562
case TYPE_BASIC_FLOAT: elem_type = ELEMENT_TYPE_R4; break;
1563
case TYPE_BASIC_DOUBLE: elem_type = ELEMENT_TYPE_R8; break;
1564
default:
1565
fprintf( stderr, "Unhandled basic type %u.\n", type );
1566
exit( 1 );
1567
}
1568
return elem_type;
1569
}
1570
1571
static UINT make_struct_field_sig( const var_t *var, BYTE *buf )
1572
{
1573
const type_t *type = var->declspec.type;
1574
1575
if (type->name && !strcmp( type->name, "HSTRING" ))
1576
{
1577
buf[0] = SIG_TYPE_FIELD;
1578
buf[1] = ELEMENT_TYPE_STRING;
1579
return 2;
1580
}
1581
1582
if (type->name && !strcmp( type->name, "GUID" ))
1583
{
1584
UINT token = typedef_or_ref( TABLE_TYPEREF, type_get_real_type(type)->md.ref );
1585
return make_field_value_sig( token, buf );
1586
}
1587
1588
type = type_get_real_type( type );
1589
1590
if (type_get_type( type ) == TYPE_ENUM || type_get_type( type ) == TYPE_STRUCT)
1591
{
1592
UINT token = typedef_or_ref( TABLE_TYPEREF, type->md.ref );
1593
return make_field_value_sig( token, buf );
1594
}
1595
1596
if (type_get_type( type ) != TYPE_BASIC)
1597
{
1598
fprintf( stderr, "Unhandled struct field type %u.\n", type_get_type( type ) );
1599
exit( 1 );
1600
}
1601
1602
buf[0] = SIG_TYPE_FIELD;
1603
buf[1] = map_basic_type( type_basic_get_type(type), type_basic_get_sign(type) );
1604
return 2;
1605
}
1606
1607
static UINT make_member_sig( UINT token, BYTE *buf )
1608
{
1609
UINT len = 4;
1610
1611
buf[0] = SIG_TYPE_HASTHIS;
1612
buf[1] = 2;
1613
buf[2] = ELEMENT_TYPE_VOID;
1614
buf[3] = ELEMENT_TYPE_CLASS;
1615
len += encode_int( token, buf + 4 );
1616
buf[len++] = ELEMENT_TYPE_U4;
1617
return len;
1618
}
1619
1620
static UINT make_member_sig2( UINT type, UINT token, BYTE *buf )
1621
{
1622
UINT len = 4;
1623
1624
buf[0] = SIG_TYPE_HASTHIS;
1625
buf[1] = 1;
1626
buf[2] = ELEMENT_TYPE_VOID;
1627
buf[3] = type;
1628
len += encode_int( token, buf + 4 );
1629
return len;
1630
}
1631
1632
static UINT make_member_sig3( UINT token, BYTE *buf )
1633
{
1634
UINT len = 4;
1635
1636
buf[0] = SIG_TYPE_HASTHIS;
1637
buf[1] = 3;
1638
buf[2] = ELEMENT_TYPE_VOID;
1639
buf[3] = ELEMENT_TYPE_CLASS;
1640
len += encode_int( token, buf + 4 );
1641
buf[len++] = ELEMENT_TYPE_U4;
1642
buf[len++] = ELEMENT_TYPE_STRING;
1643
return len;
1644
}
1645
1646
static UINT make_member_sig4( UINT token, UINT token2, BYTE *buf )
1647
{
1648
UINT len = 4;
1649
1650
buf[0] = SIG_TYPE_HASTHIS;
1651
buf[1] = 4;
1652
buf[2] = ELEMENT_TYPE_VOID;
1653
buf[3] = ELEMENT_TYPE_CLASS;
1654
len += encode_int( token, buf + 4 );
1655
buf[len++] = ELEMENT_TYPE_VALUETYPE;
1656
len += encode_int( token2, buf + len );
1657
buf[len++] = ELEMENT_TYPE_U4;
1658
buf[len++] = ELEMENT_TYPE_STRING;
1659
return len;
1660
}
1661
1662
static UINT make_type_sig( const type_t *type, BYTE *buf )
1663
{
1664
UINT len = 0;
1665
1666
if (type->name && !strcmp( type->name, "HSTRING" ))
1667
{
1668
buf[0] = ELEMENT_TYPE_STRING;
1669
return 1;
1670
}
1671
1672
type = type_get_real_type( type );
1673
1674
switch (type_get_type( type ))
1675
{
1676
case TYPE_POINTER:
1677
{
1678
const type_t *ref_type = type_pointer_get_ref_type( type );
1679
BOOL skip_byref = FALSE;
1680
1681
switch (type_get_type( ref_type ))
1682
{
1683
case TYPE_DELEGATE:
1684
case TYPE_INTERFACE:
1685
case TYPE_RUNTIMECLASS:
1686
skip_byref = TRUE;
1687
break;
1688
default:
1689
break;
1690
}
1691
if (!skip_byref) buf[len++] = ELEMENT_TYPE_BYREF;
1692
len += make_type_sig( ref_type, buf + len );
1693
break;
1694
}
1695
case TYPE_ARRAY:
1696
buf[len++] = ELEMENT_TYPE_SZARRAY;
1697
len += make_type_sig( type_array_get_element_type(type), buf + len );
1698
break;
1699
1700
case TYPE_INTERFACE:
1701
buf[len++] = ELEMENT_TYPE_OBJECT;
1702
break;
1703
1704
case TYPE_DELEGATE:
1705
case TYPE_RUNTIMECLASS:
1706
buf[len++] = ELEMENT_TYPE_CLASS;
1707
len += encode_int( typedef_or_ref(TABLE_TYPEREF, type->md.ref), buf + 1 );
1708
break;
1709
1710
case TYPE_ENUM:
1711
case TYPE_STRUCT:
1712
buf[len++] = ELEMENT_TYPE_VALUETYPE;
1713
len += encode_int( typedef_or_ref(TABLE_TYPEREF, type->md.ref), buf + 1 );
1714
break;
1715
1716
case TYPE_BASIC:
1717
buf[len++] = map_basic_type( type_basic_get_type(type), type_basic_get_sign(type) );
1718
break;
1719
1720
default:
1721
fprintf( stderr, "Unhandled type %u.\n", type_get_type( type ) );
1722
exit( 1 );
1723
}
1724
return len;
1725
}
1726
1727
static BOOL is_retval( const var_t *arg )
1728
{
1729
const type_t *type = arg->declspec.type;
1730
1731
/* array return values are encoded as out parameters even if the retval attribute is present */
1732
if (!is_attr( arg->attrs, ATTR_RETVAL ) || type_get_type( type ) == TYPE_ARRAY) return FALSE;
1733
return TRUE;
1734
}
1735
1736
static UINT make_method_sig( const var_t *method, BYTE *buf, BOOL is_static )
1737
{
1738
const var_t *arg;
1739
const var_list_t *arg_list = type_function_get_args( method->declspec.type );
1740
UINT len = 3;
1741
1742
buf[0] = is_static ? SIG_TYPE_DEFAULT : SIG_TYPE_HASTHIS;
1743
buf[1] = 0;
1744
buf[2] = ELEMENT_TYPE_VOID;
1745
1746
if (!arg_list) return 3;
1747
1748
/* add return value first */
1749
LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry )
1750
{
1751
const type_t *type;
1752
1753
if (!is_retval( arg )) continue;
1754
type = type_pointer_get_ref_type( arg->declspec.type ); /* retval must be a pointer */
1755
len = make_type_sig( type, buf + 2 ) + 2;
1756
}
1757
1758
/* add remaining parameters */
1759
LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry )
1760
{
1761
if (is_size_param( arg, arg_list ) || is_retval( arg ) ) continue;
1762
len += make_type_sig( arg->declspec.type, buf + len );
1763
buf[1]++;
1764
}
1765
return len;
1766
}
1767
1768
static UINT make_property_sig( const var_t *method, BYTE *buf, BOOL is_static )
1769
{
1770
const var_t *arg;
1771
const var_list_t *arg_list = type_function_get_args( method->declspec.type );
1772
UINT len = 3;
1773
1774
buf[0] = is_static ? SIG_TYPE_PROPERTY : SIG_TYPE_HASTHIS | SIG_TYPE_PROPERTY;
1775
buf[1] = 0;
1776
buf[2] = ELEMENT_TYPE_VOID;
1777
1778
LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry )
1779
{
1780
const type_t *type;
1781
1782
if (!is_retval( arg )) continue;
1783
type = type_pointer_get_ref_type( arg->declspec.type ); /* retval must be a pointer */
1784
len = make_type_sig( type, buf + 2 ) + 2;
1785
}
1786
1787
return len;
1788
}
1789
1790
static UINT make_activation_sig( const var_t *method, BYTE *buf )
1791
{
1792
const var_t *arg;
1793
UINT len = 3;
1794
1795
buf[0] = SIG_TYPE_HASTHIS;
1796
buf[1] = 0;
1797
buf[2] = ELEMENT_TYPE_VOID;
1798
1799
if (method) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry )
1800
{
1801
if (is_retval( arg )) continue;
1802
len += make_type_sig( arg->declspec.type, buf + len );
1803
buf[1]++;
1804
}
1805
1806
return len;
1807
}
1808
1809
static UINT make_composition_sig( const var_t *method, BYTE *buf )
1810
{
1811
const var_t *arg;
1812
UINT len = 3, count = 0;
1813
1814
buf[0] = SIG_TYPE_HASTHIS;
1815
buf[1] = 0;
1816
buf[2] = ELEMENT_TYPE_VOID;
1817
1818
if (method) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry ) count++;
1819
1820
if (method) assert( count >= 3 );
1821
1822
if (count > 3) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry )
1823
{
1824
if (--count < 3) break; /* omit last 3 standard composition args */
1825
len += make_type_sig( arg->declspec.type, buf + len );
1826
buf[1]++;
1827
}
1828
1829
return len;
1830
}
1831
1832
static UINT make_deprecated_sig( UINT token, BYTE *buf )
1833
{
1834
UINT len = 5;
1835
1836
buf[0] = SIG_TYPE_HASTHIS;
1837
buf[1] = 4;
1838
buf[2] = ELEMENT_TYPE_VOID;
1839
buf[3] = ELEMENT_TYPE_STRING;
1840
buf[4] = ELEMENT_TYPE_VALUETYPE;
1841
len += encode_int( token, buf + 5 );
1842
buf[len++] = ELEMENT_TYPE_U4;
1843
buf[len++] = ELEMENT_TYPE_STRING;
1844
1845
return len;
1846
}
1847
1848
static UINT make_contract_value( const attr_t *attr, BYTE *buf )
1849
{
1850
const expr_t *expr = attr->u.pval;
1851
const type_t *contract = expr->u.var->declspec.type;
1852
char *name = format_namespace( contract->namespace, "", ".", contract->name, NULL );
1853
UINT version = expr->ref->u.integer.value, len = strlen( name );
1854
1855
buf[0] = 1;
1856
buf[1] = 0;
1857
buf[2] = len;
1858
memcpy( buf + 3, name, len );
1859
len += 3;
1860
memcpy( buf + len, &version, sizeof(version) );
1861
len += sizeof(version);
1862
buf[len++] = 0;
1863
buf[len++] = 0;
1864
1865
free( name );
1866
return len;
1867
}
1868
1869
static UINT make_version_value( const attr_t *attr, BYTE *buf )
1870
{
1871
const version_t *version;
1872
UINT value;
1873
1874
if (attr && (version = attr->u.pval)) value = (version->major << 16) | version->minor;
1875
else value = 1;
1876
1877
buf[0] = 1;
1878
buf[1] = 0;
1879
memcpy( buf + 2, &value, sizeof(value) );
1880
buf[6] = buf[7] = 0;
1881
return 8;
1882
}
1883
1884
static attr_t *get_attr( const attr_list_t *list, enum attr_type attr_type )
1885
{
1886
attr_t *attr;
1887
if (list) LIST_FOR_EACH_ENTRY( attr, list, attr_t, entry )
1888
{
1889
if (attr->type == attr_type ) return attr;
1890
}
1891
return NULL;
1892
}
1893
1894
static void add_contract_attr_step1( const type_t *type )
1895
{
1896
UINT assemblyref, scope, typeref, typeref_type, class, sig_size;
1897
BYTE sig[32];
1898
attr_t *attr;
1899
1900
if (!(attr = get_attr( type->attrs, ATTR_CONTRACT ))) return;
1901
1902
add_assemblyref_row( 0x200, 0, add_string("windowscontracts") );
1903
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
1904
1905
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
1906
typeref_type = add_typeref_row( scope, add_string("Type"), add_string("System") );
1907
1908
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
1909
typeref = add_typeref_row( scope, add_string("ContractVersionAttribute"), add_string("Windows.Foundation.Metadata") );
1910
1911
class = memberref_parent( TABLE_TYPEREF, typeref );
1912
sig_size = make_member_sig( typedef_or_ref(TABLE_TYPEREF, typeref_type), sig );
1913
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
1914
}
1915
1916
static void add_contract_attr_step2( const type_t *type )
1917
{
1918
UINT parent, attr_type, value_size;
1919
BYTE value[MAX_NAME + sizeof(UINT) + 5];
1920
const attr_t *attr;
1921
1922
if (!(attr = get_attr( type->attrs, ATTR_CONTRACT ))) return;
1923
1924
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
1925
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
1926
value_size = make_contract_value( attr, value );
1927
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
1928
}
1929
1930
static void add_version_attr_step1( const type_t *type )
1931
{
1932
static const BYTE sig[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4 };
1933
UINT assemblyref, scope, typeref, class;
1934
attr_t *attr;
1935
1936
if (!(attr = get_attr( type->attrs, ATTR_VERSION )) && is_attr( type->attrs, ATTR_CONTRACT )) return;
1937
1938
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
1939
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
1940
1941
typeref = add_typeref_row( scope, add_string("VersionAttribute"), add_string("Windows.Foundation.Metadata") );
1942
class = memberref_parent( TABLE_TYPEREF, typeref );
1943
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
1944
}
1945
1946
static void add_version_attr_step2( const type_t *type )
1947
{
1948
UINT parent, attr_type, value_size;
1949
BYTE value[8];
1950
const attr_t *attr;
1951
1952
if (!(attr = get_attr( type->attrs, ATTR_VERSION )) && is_attr( type->attrs, ATTR_CONTRACT )) return;
1953
1954
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
1955
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
1956
value_size = make_version_value( attr, value );
1957
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
1958
}
1959
1960
static void add_flags_attr_step1( const type_t *type )
1961
{
1962
static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID };
1963
UINT scope, typeref, class;
1964
attr_t *attr;
1965
1966
if (!(attr = get_attr( type->attrs, ATTR_FLAGS ))) return;
1967
1968
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
1969
typeref = add_typeref_row( scope, add_string("FlagsAttribute"), add_string("System") );
1970
class = memberref_parent( TABLE_TYPEREF, typeref );
1971
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
1972
}
1973
1974
static void add_flags_attr_step2( const type_t *type )
1975
{
1976
static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 };
1977
UINT parent, attr_type;
1978
const attr_t *attr;
1979
1980
if (!(attr = get_attr( type->attrs, ATTR_FLAGS ))) return;
1981
1982
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
1983
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
1984
add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) );
1985
}
1986
1987
static void add_enum_type_step1( type_t *type )
1988
{
1989
UINT scope, typeref;
1990
1991
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
1992
typeref = add_typeref_row( scope, add_string("Enum"), add_string("System") );
1993
type->md.extends = typedef_or_ref( TABLE_TYPEREF, typeref );
1994
1995
create_typeref( type );
1996
1997
add_version_attr_step1( type );
1998
add_contract_attr_step1( type );
1999
add_flags_attr_step1( type );
2000
}
2001
2002
static void add_enum_type_step2( type_t *type )
2003
{
2004
BYTE sig_value[] = { SIG_TYPE_FIELD, ELEMENT_TYPE_I4 };
2005
UINT field, parent, sig_size;
2006
BYTE sig_field[32];
2007
const var_t *var;
2008
2009
if (is_attr( type->attrs, ATTR_FLAGS )) sig_value[1] = ELEMENT_TYPE_U4;
2010
2011
field = add_field_row( FIELD_ATTR_PRIVATE | FIELD_ATTR_SPECIALNAME | FIELD_ATTR_RTSPECIALNAME,
2012
add_string("value__"), add_blob(sig_value, sizeof(sig_value)) );
2013
2014
type->md.def = add_typedef_row( TYPE_ATTR_PUBLIC | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN, type->md.name,
2015
type->md.namespace, type->md.extends, field, 0 );
2016
2017
sig_size = make_field_value_sig( typedef_or_ref(TABLE_TYPEREF, type->md.ref), sig_field );
2018
2019
LIST_FOR_EACH_ENTRY( var, type_enum_get_values(type), const var_t, entry )
2020
{
2021
int val = var->eval->u.integer.value;
2022
2023
field = add_field_row( FIELD_ATTR_PUBLIC | FIELD_ATTR_LITERAL | FIELD_ATTR_STATIC | FIELD_ATTR_HASDEFAULT,
2024
add_string(var->name), add_blob(sig_field, sig_size) );
2025
parent = has_constant( TABLE_FIELD, field );
2026
add_constant_row( sig_value[1], parent, add_blob((const BYTE *)&val, sizeof(val)) );
2027
}
2028
2029
add_version_attr_step2( type );
2030
add_contract_attr_step2( type );
2031
add_flags_attr_step2( type );
2032
}
2033
2034
static void add_struct_type_step1( type_t *type )
2035
{
2036
UINT scope, typeref;
2037
const var_t *var;
2038
2039
LIST_FOR_EACH_ENTRY( var, type_struct_get_fields(type), const var_t, entry )
2040
{
2041
create_typeref( var->declspec.type );
2042
}
2043
2044
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
2045
typeref = add_typeref_row( scope, add_string("ValueType"), add_string("System") );
2046
type->md.extends = typedef_or_ref( TABLE_TYPEREF, typeref );
2047
2048
create_typeref( type );
2049
2050
add_contract_attr_step1( type );
2051
}
2052
2053
static void add_struct_type_step2( type_t *type )
2054
{
2055
UINT field, flags, sig_size, first_field = 0;
2056
const var_t *var;
2057
BYTE sig[32];
2058
2059
LIST_FOR_EACH_ENTRY( var, type_struct_get_fields(type), const var_t, entry )
2060
{
2061
sig_size = make_struct_field_sig( var, sig );
2062
field = add_field_row( FIELD_ATTR_PUBLIC, add_string(var->name), add_blob(sig, sig_size) );
2063
if (!first_field) first_field = field;
2064
}
2065
2066
flags = TYPE_ATTR_PUBLIC | TYPE_ATTR_SEQUENTIALLAYOUT | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN;
2067
type->md.def = add_typedef_row( flags, type->md.name, type->md.namespace, type->md.extends, first_field, 0 );
2068
2069
add_contract_attr_step2( type );
2070
}
2071
2072
static void add_uuid_attr_step1( const type_t *type )
2073
{
2074
static const BYTE sig[] =
2075
{ SIG_TYPE_HASTHIS, 11, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4, ELEMENT_TYPE_U2, ELEMENT_TYPE_U2,
2076
ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1,
2077
ELEMENT_TYPE_U1, ELEMENT_TYPE_U1 };
2078
UINT assemblyref, scope, typeref, class;
2079
attr_t *attr;
2080
2081
if (!(attr = get_attr( type->attrs, ATTR_UUID ))) return;
2082
2083
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2084
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2085
typeref = add_typeref_row( scope, add_string("GuidAttribute"), add_string("Windows.Foundation.Metadata") );
2086
2087
class = memberref_parent( TABLE_TYPEREF, typeref );
2088
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
2089
}
2090
2091
static void add_uuid_attr_step2( const type_t *type )
2092
{
2093
const struct uuid *uuid;
2094
BYTE value[sizeof(*uuid) + 4] = { 0x01 };
2095
UINT parent, attr_type;
2096
const attr_t *attr;
2097
2098
if (!(attr = get_attr( type->attrs, ATTR_UUID ))) return;
2099
2100
uuid = attr->u.pval;
2101
memcpy( value + 2, uuid, sizeof(*uuid) );
2102
2103
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
2104
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2105
add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) );
2106
}
2107
2108
static UINT make_exclusiveto_value( const attr_t *attr, BYTE *buf )
2109
{
2110
const type_t *type = attr->u.pval;
2111
char *name = format_namespace( type->namespace, "", ".", type->name, NULL );
2112
UINT len = strlen( name );
2113
2114
buf[0] = 1;
2115
buf[1] = 0;
2116
buf[2] = len;
2117
memcpy( buf + 3, name, len );
2118
len += 3;
2119
buf[len++] = 0;
2120
buf[len++] = 0;
2121
2122
free( name );
2123
return len;
2124
}
2125
2126
static void add_exclusiveto_attr_step1( const type_t *type )
2127
{
2128
UINT assemblyref, scope, typeref, typeref_type, class, sig_size;
2129
BYTE sig[32];
2130
attr_t *attr;
2131
2132
if (!(attr = get_attr( type->attrs, ATTR_EXCLUSIVETO ))) return;
2133
2134
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
2135
typeref_type = add_typeref_row( scope, add_string("Type"), add_string("System") );
2136
2137
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2138
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2139
typeref = add_typeref_row( scope, add_string("ExclusiveToAttribute"), add_string("Windows.Foundation.Metadata") );
2140
2141
class = memberref_parent( TABLE_TYPEREF, typeref );
2142
sig_size = make_member_sig2( ELEMENT_TYPE_CLASS, typedef_or_ref(TABLE_TYPEREF, typeref_type), sig );
2143
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
2144
}
2145
2146
static void add_exclusiveto_attr_step2( const type_t *type )
2147
{
2148
UINT parent, attr_type, value_size;
2149
BYTE value[MAX_NAME + 5];
2150
const attr_t *attr;
2151
2152
if (!(attr = get_attr( type->attrs, ATTR_EXCLUSIVETO ))) return;
2153
2154
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
2155
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2156
value_size = make_exclusiveto_value( attr, value );
2157
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2158
}
2159
2160
static UINT make_overload_value( const char *name, BYTE *buf )
2161
{
2162
UINT len = strlen( name );
2163
2164
buf[0] = 1;
2165
buf[1] = 0;
2166
buf[2] = len;
2167
memcpy( buf + 3, name, len );
2168
len += 3;
2169
buf[len++] = 0;
2170
buf[len++] = 0;
2171
2172
return len;
2173
}
2174
2175
static void add_overload_attr_step1( const var_t *method )
2176
{
2177
static const BYTE sig[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING };
2178
UINT assemblyref, scope, typeref, class;
2179
attr_t *attr;
2180
2181
if (!(attr = get_attr( method->attrs, ATTR_OVERLOAD ))) return;
2182
2183
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2184
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2185
typeref = add_typeref_row( scope, add_string("OverloadAttribute"), add_string("Windows.Foundation.Metadata") );
2186
2187
class = memberref_parent( TABLE_TYPEREF, typeref );
2188
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
2189
}
2190
2191
static void add_overload_attr_step2( const var_t *method )
2192
{
2193
const type_t *type = method->declspec.type;
2194
UINT parent, attr_type, value_size;
2195
BYTE value[MAX_NAME + 5];
2196
const attr_t *attr;
2197
2198
if (!(attr = get_attr( method->attrs, ATTR_OVERLOAD ))) return;
2199
2200
parent = has_customattribute( TABLE_METHODDEF, type->md.def );
2201
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2202
value_size = make_overload_value( method->name, value );
2203
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2204
}
2205
2206
static void add_default_overload_attr_step1( const var_t *method )
2207
{
2208
static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID };
2209
UINT assemblyref, scope, typeref, class;
2210
attr_t *attr;
2211
2212
if (!(attr = get_attr( method->attrs, ATTR_DEFAULT_OVERLOAD )) || !is_attr( method->attrs, ATTR_OVERLOAD )) return;
2213
2214
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2215
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2216
typeref = add_typeref_row( scope, add_string("DefaultOverloadAttribute"), add_string("Windows.Foundation.Metadata") );
2217
2218
class = memberref_parent( TABLE_TYPEREF, typeref );
2219
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
2220
}
2221
2222
static void add_default_overload_attr_step2( const var_t *method )
2223
{
2224
static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 };
2225
const type_t *type = method->declspec.type;
2226
UINT parent, attr_type;
2227
const attr_t *attr;
2228
2229
if (!(attr = get_attr( method->attrs, ATTR_DEFAULT_OVERLOAD )) || !is_attr( method->attrs, ATTR_OVERLOAD )) return;
2230
2231
parent = has_customattribute( TABLE_METHODDEF, type->md.def );
2232
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2233
add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) );
2234
}
2235
2236
static UINT make_deprecated_value( const attr_t *attr, BYTE **ret_buf )
2237
{
2238
static const BYTE zero[] = { 0x00, 0x00, 0x00, 0x00 }, one[] = { 0x01, 0x00, 0x00, 0x00 };
2239
const expr_t *expr = attr->u.pval;
2240
const type_t *type = expr->ext2->u.var->declspec.type;
2241
const char *text = expr->ref->u.sval;
2242
const char *kind = expr->u.ext->u.sval;
2243
BYTE encoded[4];
2244
UINT len, version, len_text = strlen( text ), len_encoded = encode_int( len_text, encoded );
2245
BYTE *buf = xmalloc( 2 + len_encoded + len_text + 6 + MAX_NAME + 5 );
2246
char *contract;
2247
2248
buf[0] = 1;
2249
buf[1] = 0;
2250
memcpy( buf + 2, encoded, len_encoded );
2251
len = 2 + len_encoded;
2252
memcpy( buf + len, text, len_text );
2253
len += len_text;
2254
if (!strcmp( kind, "remove" )) memcpy( buf + len, one, sizeof(one) );
2255
else memcpy( buf + len, zero, sizeof(zero) );
2256
len += 4;
2257
2258
version = expr->ext2->ref->u.integer.value;
2259
memcpy( buf + len, &version, sizeof(version) );
2260
len += sizeof(version);
2261
2262
contract = format_namespace( type->namespace, "", ".", type->name, NULL );
2263
len_text = strlen( contract );
2264
buf[len++] = len_text;
2265
memcpy( buf + len, contract, len_text );
2266
free( contract );
2267
len += len_text;
2268
buf[len++] = 0;
2269
buf[len++] = 0;
2270
2271
*ret_buf = buf;
2272
return len;
2273
}
2274
2275
static void add_deprecated_attr_step1( const var_t *method )
2276
{
2277
UINT assemblyref, scope, typeref_type, typeref, class, sig_size;
2278
BYTE sig[32];
2279
attr_t *attr;
2280
2281
if (!(attr = get_attr( method->attrs, ATTR_DEPRECATED ))) return;
2282
2283
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2284
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2285
typeref_type = add_typeref_row( scope, add_string("DeprecationType"), add_string("Windows.Foundation.Metadata") );
2286
typeref = add_typeref_row( scope, add_string("DeprecatedAttribute"), add_string("Windows.Foundation.Metadata") );
2287
2288
sig_size = make_deprecated_sig( typedef_or_ref(TABLE_TYPEREF, typeref_type), sig );
2289
class = memberref_parent( TABLE_TYPEREF, typeref );
2290
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
2291
}
2292
2293
static void add_deprecated_attr_step2( const var_t *method )
2294
{
2295
const type_t *type = method->declspec.type;
2296
UINT parent, attr_type, value_size;
2297
BYTE *value;
2298
const attr_t *attr;
2299
2300
if (!(attr = get_attr( method->attrs, ATTR_DEPRECATED ))) return;
2301
2302
parent = has_customattribute( TABLE_METHODDEF, type->md.def );
2303
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2304
value_size = make_deprecated_value( attr, &value );
2305
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2306
free( value );
2307
}
2308
2309
static void add_method_params_step1( const var_t *method )
2310
{
2311
const var_list_t *arg_list = type_function_get_args( method->declspec.type );
2312
const var_t *arg;
2313
2314
if (arg_list) LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry )
2315
{
2316
if (is_size_param( arg, arg_list )) continue;
2317
create_typeref( arg->declspec.type );
2318
}
2319
}
2320
2321
static void add_runtimeclass_type_step1( type_t * );
2322
2323
static void add_interface_type_step1( type_t *type )
2324
{
2325
const statement_t *stmt;
2326
type_t *class;
2327
2328
create_typeref( type );
2329
2330
if ((class = type->details.iface->runtime_class)) add_runtimeclass_type_step1( class );
2331
2332
add_contract_attr_step1( type );
2333
add_uuid_attr_step1( type );
2334
add_exclusiveto_attr_step1( type );
2335
2336
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(type) )
2337
{
2338
const var_t *method = stmt->u.var;
2339
2340
add_method_params_step1( method );
2341
2342
add_overload_attr_step1( method );
2343
add_default_overload_attr_step1( method );
2344
add_deprecated_attr_step1( method );
2345
}
2346
}
2347
2348
static UINT get_param_attrs( const var_t *arg )
2349
{
2350
UINT attrs = 0;
2351
2352
if (is_attr( arg->attrs, ATTR_IN )) attrs |= PARAM_ATTR_IN;
2353
if (is_attr( arg->attrs, ATTR_OUT )) attrs |= PARAM_ATTR_OUT;
2354
if (is_attr( arg->attrs, ATTR_OPTIONAL )) attrs |= PARAM_ATTR_OPTIONAL;
2355
2356
return attrs ? attrs : PARAM_ATTR_IN;
2357
}
2358
2359
static UINT add_method_params_step2( var_list_t *arg_list )
2360
{
2361
UINT first = 0, row, seq = 1;
2362
var_t *arg;
2363
2364
if (!arg_list) return 0;
2365
2366
LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry )
2367
{
2368
if (is_retval( arg ))
2369
{
2370
first = add_param_row( 0, 0, add_string(arg->name) );
2371
break;
2372
}
2373
}
2374
2375
LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry )
2376
{
2377
if (is_size_param( arg, arg_list) || is_retval( arg )) continue;
2378
row = add_param_row( get_param_attrs(arg), seq++, add_string(arg->name) );
2379
if (!first) first = row;
2380
}
2381
2382
return first;
2383
}
2384
2385
static char *get_method_name( const var_t *method )
2386
{
2387
const char *overload;
2388
2389
if (is_attr( method->attrs, ATTR_PROPGET )) return strmake( "get_%s", method->name );
2390
else if (is_attr( method->attrs, ATTR_PROPPUT )) return strmake( "put_%s", method->name );
2391
else if (is_attr( method->attrs, ATTR_EVENTADD )) return strmake( "add_%s", method->name );
2392
else if (is_attr( method->attrs, ATTR_EVENTREMOVE )) return strmake( "remove_%s", method->name );
2393
2394
if ((overload = get_attrp( method->attrs, ATTR_OVERLOAD ))) return strmake( "%s", overload );
2395
return strmake( "%s", method->name );
2396
}
2397
2398
static BOOL is_special_method( const var_t *method )
2399
{
2400
if (is_attr( method->attrs, ATTR_PROPGET ) || is_attr( method->attrs, ATTR_PROPPUT ) ||
2401
is_attr( method->attrs, ATTR_EVENTADD ) || is_attr( method->attrs, ATTR_EVENTREMOVE )) return TRUE;
2402
return FALSE;
2403
}
2404
2405
static BOOL is_static_iface( const type_t *class, const type_t *iface )
2406
{
2407
const attr_t *attr;
2408
2409
if (!class || !class->attrs) return FALSE;
2410
2411
LIST_FOR_EACH_ENTRY( attr, class->attrs, const attr_t, entry )
2412
{
2413
const expr_t *value = attr->u.pval;
2414
2415
if (attr->type != ATTR_STATIC) continue;
2416
if (value->u.var->declspec.type == iface) return TRUE;
2417
}
2418
2419
return FALSE;
2420
}
2421
2422
static UINT get_method_attrs( const type_t *class, const type_t *iface, const var_t *method, UINT *flags )
2423
{
2424
UINT attrs = METHOD_ATTR_PUBLIC | METHOD_ATTR_HIDEBYSIG;
2425
2426
if (!class)
2427
{
2428
*flags = 0;
2429
attrs |= METHOD_ATTR_ABSTRACT | METHOD_ATTR_VIRTUAL | METHOD_ATTR_NEWSLOT;
2430
}
2431
else
2432
{
2433
*flags = METHOD_IMPL_RUNTIME;
2434
if (is_static_iface( class, iface )) attrs |= METHOD_ATTR_STATIC;
2435
else attrs |= METHOD_ATTR_VIRTUAL | METHOD_ATTR_NEWSLOT | METHOD_ATTR_FINAL;
2436
}
2437
2438
if (is_special_method( method )) attrs |= METHOD_ATTR_SPECIALNAME;
2439
return attrs;
2440
}
2441
2442
static void add_propget_method( const type_t *class, const type_t *iface, const var_t *method )
2443
{
2444
UINT sig_size, property, paramlist, flags, attrs = get_method_attrs( class, iface, method, &flags );
2445
char *name = get_method_name( method );
2446
type_t *type = method->declspec.type;
2447
BYTE sig[256];
2448
2449
if (class) property = type->md.class_property;
2450
else property = type->md.iface_property;
2451
2452
paramlist = add_method_params_step2( type_function_get_args(type) );
2453
sig_size = make_method_sig( method, sig, is_static_iface(class, iface) );
2454
2455
type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist );
2456
add_methodsemantics_row( METHOD_SEM_GETTER, type->md.def, has_semantics(TABLE_PROPERTY, property) );
2457
free( name );
2458
}
2459
2460
static const var_t *find_propget_method( const type_t *iface, const char *name )
2461
{
2462
const statement_t *stmt;
2463
2464
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
2465
{
2466
const var_t *method = stmt->u.var;
2467
if (is_attr( method->attrs, ATTR_PROPGET ) && !strcmp( method->name, name )) return method;
2468
}
2469
return NULL;
2470
}
2471
2472
static void add_propput_method( const type_t *class, const type_t *iface, const var_t *method )
2473
{
2474
const var_t *propget = find_propget_method( iface, method->name );
2475
UINT sig_size, paramlist, property, flags, attrs = get_method_attrs( class, iface, method, &flags );
2476
char *name = get_method_name( method );
2477
type_t *type = method->declspec.type;
2478
BYTE sig[256];
2479
2480
paramlist = add_method_params_step2( type_function_get_args(method->declspec.type) );
2481
sig_size = make_method_sig( method, sig, is_static_iface(class, iface) );
2482
2483
type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist );
2484
free( name );
2485
2486
/* add propget method first if not already added */
2487
if (class)
2488
{
2489
if (!propget->declspec.type->md.class_property) add_propget_method( class, iface, propget );
2490
property = type->md.class_property = propget->declspec.type->md.class_property;
2491
}
2492
else
2493
{
2494
if (!propget->declspec.type->md.iface_property) add_propget_method( class, iface, propget );
2495
property = type->md.iface_property = propget->declspec.type->md.iface_property;
2496
}
2497
2498
add_methodsemantics_row( METHOD_SEM_SETTER, type->md.def, has_semantics(TABLE_PROPERTY, property) );
2499
}
2500
2501
static void add_eventadd_method( const type_t *class, const type_t *iface, const var_t *method )
2502
{
2503
UINT event, sig_size, paramlist, flags, attrs = get_method_attrs( class, iface, method, &flags );
2504
char *name = get_method_name( method );
2505
type_t *type = method->declspec.type;
2506
BYTE sig[256];
2507
2508
if (class) event = type->md.class_event;
2509
else event = type->md.iface_event;
2510
2511
paramlist = add_method_params_step2( type_function_get_args(type) );
2512
sig_size = make_method_sig( method, sig, is_static_iface(class, iface) );
2513
2514
type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist );
2515
free( name );
2516
2517
add_methodsemantics_row( METHOD_SEM_ADDON, type->md.def, has_semantics(TABLE_EVENT, event) );
2518
}
2519
2520
static const var_t *find_eventadd_method( const type_t *iface, const char *name )
2521
{
2522
const statement_t *stmt;
2523
2524
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
2525
{
2526
const var_t *method = stmt->u.var;
2527
if (is_attr( method->attrs, ATTR_EVENTADD ) && !strcmp( method->name, name )) return method;
2528
}
2529
return NULL;
2530
}
2531
2532
static void add_eventremove_method( const type_t *class, const type_t *iface, const var_t *method )
2533
{
2534
const var_t *eventadd = find_eventadd_method( iface, method->name );
2535
UINT event, sig_size, paramlist, flags, attrs = get_method_attrs( class, iface, method, &flags );
2536
char *name = get_method_name( method );
2537
type_t *type = method->declspec.type;
2538
BYTE sig[256];
2539
2540
paramlist = add_method_params_step2( type_function_get_args(type) );
2541
sig_size = make_method_sig( method, sig, is_static_iface(class, iface) );
2542
2543
type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist );
2544
free( name );
2545
2546
/* add eventadd method first if not already added */
2547
if (class)
2548
{
2549
if (!eventadd->declspec.type->md.class_event) add_eventadd_method( class, iface, eventadd );
2550
event = type->md.class_event = eventadd->declspec.type->md.class_event;
2551
}
2552
else
2553
{
2554
if (!eventadd->declspec.type->md.iface_event) add_eventadd_method( class, iface, eventadd );
2555
event = type->md.iface_event = eventadd->declspec.type->md.iface_event;
2556
}
2557
2558
add_methodsemantics_row( METHOD_SEM_REMOVEON, type->md.def, has_semantics(TABLE_EVENT, event) );
2559
}
2560
2561
static void add_regular_method( const type_t *class, const type_t *iface, const var_t *method )
2562
{
2563
UINT paramlist, sig_size, flags, attrs = get_method_attrs( class, iface, method, &flags );
2564
char *name = get_method_name( method );
2565
type_t *type = method->declspec.type;
2566
BYTE sig[256];
2567
2568
paramlist = add_method_params_step2( type_function_get_args(type) );
2569
sig_size = make_method_sig( method, sig, is_static_iface(class, iface) );
2570
2571
type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist );
2572
free( name );
2573
}
2574
2575
static void add_property( type_t *class, type_t *iface, const var_t *method )
2576
{
2577
UINT sig_size;
2578
type_t *type = method->declspec.type;
2579
BYTE sig[256];
2580
2581
if (!is_attr( method->attrs, ATTR_PROPGET )) return;
2582
2583
sig_size = make_property_sig( method, sig, is_static_iface(class, iface) );
2584
if (class)
2585
{
2586
type->md.class_property = add_property_row( 0, add_string(method->name), add_blob(sig, sig_size) );
2587
if (!class->md.propertymap) class->md.propertymap = add_propertymap_row( class->md.def, type->md.class_property );
2588
}
2589
else
2590
{
2591
type->md.iface_property = add_property_row( 0, add_string(method->name), add_blob(sig, sig_size) );
2592
if (!iface->md.propertymap) iface->md.propertymap = add_propertymap_row( iface->md.def, type->md.iface_property );
2593
}
2594
}
2595
2596
static void add_event( type_t *class, type_t *iface, const var_t *method )
2597
{
2598
UINT event_type = 0;
2599
type_t *type = method->declspec.type;
2600
var_t *arg;
2601
2602
if (!is_attr( method->attrs, ATTR_EVENTADD )) return;
2603
2604
LIST_FOR_EACH_ENTRY( arg, type_function_get_args(type), var_t, entry )
2605
{
2606
type_t *arg_type = arg->declspec.type;
2607
2608
arg_type = type_pointer_get_ref_type( arg_type ); /* first arg must be a delegate pointer */
2609
event_type = typedef_or_ref( TABLE_TYPEREF, arg_type->md.ref );
2610
break;
2611
}
2612
2613
if (class)
2614
{
2615
type->md.class_event = add_event_row( 0, add_string(method->name), event_type );
2616
if (!class->md.eventmap) class->md.eventmap = add_eventmap_row( class->md.def, type->md.class_event );
2617
}
2618
else
2619
{
2620
type->md.iface_event = add_event_row( 0, add_string(method->name), event_type );
2621
if (!iface->md.eventmap) iface->md.eventmap = add_eventmap_row( iface->md.def, type->md.iface_event );
2622
}
2623
}
2624
2625
static void add_method( type_t *class, type_t *iface, const var_t *method )
2626
{
2627
if (is_attr( method->attrs, ATTR_PROPGET )) add_propget_method( class, iface, method );
2628
else if (is_attr( method->attrs, ATTR_PROPPUT )) add_propput_method( class, iface, method );
2629
else if (is_attr( method->attrs, ATTR_EVENTADD )) add_eventadd_method( class, iface, method );
2630
else if (is_attr( method->attrs, ATTR_EVENTREMOVE )) add_eventremove_method( class, iface, method );
2631
else add_regular_method( class, iface, method );
2632
}
2633
2634
static void add_runtimeclass_type_step2( type_t *type );
2635
2636
static void add_interface_type_step2( type_t *type )
2637
{
2638
UINT interface, flags = TYPE_ATTR_INTERFACE | TYPE_ATTR_ABSTRACT | TYPE_ATTR_UNKNOWN;
2639
const typeref_list_t *require_list = type_iface_get_requires( type );
2640
const typeref_t *require;
2641
const statement_t *stmt;
2642
type_t *class;
2643
2644
if (!is_attr( type->attrs, ATTR_EXCLUSIVETO )) flags |= TYPE_ATTR_PUBLIC;
2645
type->md.def = add_typedef_row( flags, type->md.name, type->md.namespace, 0, 0, 0 );
2646
2647
if (require_list) LIST_FOR_EACH_ENTRY( require, require_list, typeref_t, entry )
2648
{
2649
interface = typedef_or_ref( TABLE_TYPEREF, require->type->md.ref );
2650
add_interfaceimpl_row( type->md.def, interface );
2651
}
2652
2653
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(type) )
2654
{
2655
const var_t *method = stmt->u.var;
2656
2657
add_property( NULL, type, method );
2658
add_event( NULL, type, method );
2659
add_method( NULL, type, method );
2660
2661
add_deprecated_attr_step2( method );
2662
add_default_overload_attr_step2( method );
2663
add_overload_attr_step2( method );
2664
}
2665
2666
if ((class = type->details.iface->runtime_class)) add_runtimeclass_type_step2( class );
2667
2668
add_contract_attr_step2( type );
2669
add_uuid_attr_step2( type );
2670
add_exclusiveto_attr_step2( type );
2671
}
2672
2673
static void add_contractversion_attr_step1( const type_t *type )
2674
{
2675
static const BYTE sig[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4 };
2676
UINT assemblyref, scope, typeref, class;
2677
attr_t *attr;
2678
2679
if (!(attr = get_attr( type->attrs, ATTR_CONTRACTVERSION ))) return;
2680
2681
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2682
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2683
typeref = add_typeref_row( scope, add_string("ContractVersionAttribute"), add_string("Windows.Foundation.Metadata") );
2684
2685
class = memberref_parent( TABLE_TYPEREF, typeref );
2686
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
2687
}
2688
2689
static void add_contractversion_attr_step2( const type_t *type )
2690
{
2691
UINT parent, attr_type, value_size;
2692
BYTE value[8];
2693
const attr_t *attr;
2694
2695
if (!(attr = get_attr( type->attrs, ATTR_CONTRACTVERSION ))) return;
2696
2697
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
2698
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2699
value_size = make_version_value( attr, value );
2700
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2701
}
2702
2703
static void add_apicontract_attr_step1( const type_t *type )
2704
{
2705
static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID };
2706
UINT assemblyref, scope, typeref, class;
2707
attr_t *attr;
2708
2709
if (!(attr = get_attr( type->attrs, ATTR_APICONTRACT ))) return;
2710
2711
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2712
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2713
typeref = add_typeref_row( scope, add_string("ApiContractAttribute"), add_string("Windows.Foundation.Metadata") );
2714
2715
class = memberref_parent( TABLE_TYPEREF, typeref );
2716
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
2717
}
2718
2719
static void add_apicontract_attr_step2( const type_t *type )
2720
{
2721
static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 };
2722
UINT parent, attr_type;
2723
const attr_t *attr;
2724
2725
if (!(attr = get_attr( type->attrs, ATTR_APICONTRACT ))) return;
2726
2727
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
2728
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2729
add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) );
2730
}
2731
2732
static void add_apicontract_type_step1( type_t *type )
2733
{
2734
UINT scope, typeref;
2735
2736
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
2737
typeref = add_typeref_row( scope, add_string("ValueType"), add_string("System") );
2738
type->md.extends = typedef_or_ref( TABLE_TYPEREF, typeref );
2739
2740
create_typeref( type );
2741
2742
add_contractversion_attr_step1( type );
2743
add_apicontract_attr_step1( type );
2744
}
2745
2746
static void add_apicontract_type_step2( type_t *type )
2747
{
2748
UINT flags = TYPE_ATTR_PUBLIC | TYPE_ATTR_SEQUENTIALLAYOUT | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN;
2749
2750
type->md.def = add_typedef_row( flags, type->md.name, type->md.namespace, type->md.extends, 0, 0 );
2751
2752
add_contractversion_attr_step2( type );
2753
add_apicontract_attr_step2( type );
2754
}
2755
2756
static void add_runtimeclass_type_step1( type_t *type )
2757
{
2758
const typeref_list_t *iface_list = type_runtimeclass_get_ifaces( type );
2759
const typeref_t *iface;
2760
UINT scope, typeref;
2761
2762
create_typeref( type );
2763
2764
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
2765
typeref = add_typeref_row( scope, add_string("Object"), add_string("System") );
2766
type->md.extends = typedef_or_ref( TABLE_TYPEREF, typeref );
2767
2768
if (iface_list) LIST_FOR_EACH_ENTRY( iface, iface_list, typeref_t, entry )
2769
{
2770
add_interface_type_step1( iface->type );
2771
}
2772
}
2773
2774
static void add_default_attr( UINT interfaceimpl_ref )
2775
{
2776
static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID };
2777
static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 };
2778
UINT assemblyref, scope, typeref, class, memberref, parent, attr_type;
2779
2780
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2781
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2782
typeref = add_typeref_row( scope, add_string("DefaultAttribute"), add_string("Windows.Foundation.Metadata") );
2783
class = memberref_parent( TABLE_TYPEREF, typeref );
2784
memberref = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
2785
2786
parent = has_customattribute( TABLE_INTERFACEIMPL, interfaceimpl_ref );
2787
attr_type = customattribute_type( TABLE_MEMBERREF, memberref );
2788
add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) );
2789
}
2790
2791
static void add_method_impl( const type_t *class, const type_t *iface, const var_t *method )
2792
{
2793
UINT parent, memberref, body, decl, sig_size;
2794
char *name = get_method_name( method );
2795
type_t *type = method->declspec.type;
2796
BYTE sig[256];
2797
2798
parent = memberref_parent( TABLE_TYPEREF, iface->md.ref );
2799
sig_size = make_method_sig( method, sig, FALSE );
2800
2801
memberref = add_memberref_row( parent, add_string(name), add_blob(sig, sig_size) );
2802
free( name );
2803
2804
body = methoddef_or_ref( TABLE_METHODDEF, type->md.def );
2805
decl = methoddef_or_ref( TABLE_MEMBERREF, memberref );
2806
2807
add_methodimpl_row( class->md.def, body, decl );
2808
}
2809
2810
static void add_method_contract_attrs( const type_t *class, const type_t *iface, const type_t *method )
2811
{
2812
UINT parent, attr_type, value_size;
2813
BYTE value[MAX_NAME + sizeof(UINT) + 5];
2814
const attr_t *attr = get_attr( iface->attrs, ATTR_CONTRACT );
2815
2816
parent = has_customattribute( TABLE_METHODDEF, method->md.def );
2817
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2818
value_size = make_contract_value( get_attr(class->attrs, ATTR_CONTRACT), value );
2819
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2820
2821
if (method->md.class_property)
2822
{
2823
parent = has_customattribute( TABLE_PROPERTY, method->md.class_property );
2824
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2825
}
2826
2827
if (method->md.class_event)
2828
{
2829
parent = has_customattribute( TABLE_EVENT, method->md.class_event );
2830
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2831
}
2832
}
2833
2834
static UINT make_static_value( const expr_t *attr, BYTE *buf )
2835
{
2836
const expr_t *contract = attr->ref;
2837
const type_t *type_iface = attr->u.var->declspec.type, *type_contract = contract->u.var->declspec.type;
2838
char *name_iface = format_namespace( type_iface->namespace, "", ".", type_iface->name, NULL );
2839
char *name_contract = format_namespace( type_contract->namespace, "", ".", type_contract->name, NULL );
2840
UINT len_iface = strlen( name_iface ), len_contract = strlen( name_contract );
2841
BYTE *ptr = buf;
2842
2843
ptr[0] = 1;
2844
ptr[1] = 0;
2845
ptr[2] = len_iface;
2846
memcpy( ptr + 3, name_iface, len_iface );
2847
ptr += len_iface + 3;
2848
ptr[0] = ptr[1] = 0;
2849
2850
ptr += 2;
2851
ptr[0] = 1;
2852
ptr[1] = 0;
2853
ptr[2] = len_contract;
2854
memcpy( ptr + 3, name_contract, len_contract );
2855
ptr += len_contract + 3;
2856
ptr[0] = ptr[1] = 0;
2857
2858
free( name_iface );
2859
free( name_contract );
2860
return len_iface + len_contract + 10;
2861
}
2862
2863
static void add_static_attr_step1( const type_t *type )
2864
{
2865
UINT assemblyref, scope, typeref, typeref_type, class, sig_size;
2866
BYTE sig[32];
2867
attr_t *attr;
2868
2869
if (!(attr = get_attr( type->attrs, ATTR_STATIC ))) return;
2870
2871
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2872
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2873
typeref = add_typeref_row( scope, add_string("StaticAttribute"), add_string("Windows.Foundation.Metadata") );
2874
2875
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
2876
typeref_type = add_typeref_row( scope, add_string("Type"), add_string("System") );
2877
2878
class = memberref_parent( TABLE_TYPEREF, typeref );
2879
sig_size = make_member_sig3( typedef_or_ref(TABLE_TYPEREF, typeref_type), sig );
2880
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
2881
}
2882
2883
static void add_static_attr_step2( const type_t *type )
2884
{
2885
const attr_t *attr;
2886
2887
if (type->attrs) LIST_FOR_EACH_ENTRY_REV( attr, type->attrs, const attr_t, entry )
2888
{
2889
UINT parent, attr_type, value_size;
2890
BYTE value[MAX_NAME * 2 + 10];
2891
2892
if (attr->type != ATTR_STATIC) continue;
2893
2894
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
2895
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2896
value_size = make_static_value( attr->u.pval, value );
2897
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2898
}
2899
}
2900
2901
static UINT make_activatable_value( const expr_t *attr, BYTE *buf )
2902
{
2903
char *name_iface = NULL, *name_contract;
2904
const type_t *type_iface, *type_contract;
2905
UINT version, len_iface = 0, len_contract, len_extra = 5;
2906
BYTE *ptr = buf;
2907
2908
if (attr->type == EXPR_MEMBER)
2909
{
2910
type_iface = attr->u.var->declspec.type;
2911
name_iface = format_namespace( type_iface->namespace, "", ".", type_iface->name, NULL );
2912
len_iface = strlen( name_iface );
2913
2914
type_contract = attr->ref->u.var->declspec.type;
2915
version = attr->ref->ref->u.integer.value;
2916
}
2917
else
2918
{
2919
type_contract = attr->u.var->declspec.type;
2920
version = attr->ref->u.integer.value;
2921
}
2922
2923
name_contract = format_namespace( type_contract->namespace, "", ".", type_contract->name, NULL );
2924
len_contract = strlen( name_contract );
2925
2926
if (len_iface)
2927
{
2928
ptr[0] = 1;
2929
ptr[1] = 0;
2930
ptr[2] = len_iface;
2931
memcpy( ptr + 3, name_iface, len_iface );
2932
ptr += len_iface + 3;
2933
ptr[0] = ptr[1] = 0;
2934
ptr += 2;
2935
len_extra += 5;
2936
}
2937
2938
ptr[0] = 1;
2939
ptr[1] = 0;
2940
memcpy( ptr + 2, &version, sizeof(version) );
2941
ptr += sizeof(version) + 2;
2942
2943
ptr[0] = len_contract;
2944
memcpy( ptr + 1, name_contract, len_contract );
2945
ptr += len_contract + 1;
2946
ptr[0] = ptr[1] = 0;
2947
2948
free( name_iface );
2949
free( name_contract );
2950
return len_iface + sizeof(version) + len_contract + len_extra;
2951
}
2952
2953
static void add_activatable_attr_step1( const type_t *type )
2954
{
2955
static const BYTE sig_default[] = { SIG_TYPE_HASTHIS, 2, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4, ELEMENT_TYPE_STRING };
2956
attr_t *attr;
2957
2958
if (type->attrs) LIST_FOR_EACH_ENTRY_REV( attr, type->attrs, attr_t, entry )
2959
{
2960
UINT assemblyref, scope, typeref, typeref_type, class, sig_size;
2961
const expr_t *value = attr->u.pval;
2962
BYTE sig[32];
2963
2964
if (attr->type != ATTR_ACTIVATABLE) continue;
2965
2966
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2967
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2968
typeref = add_typeref_row( scope, add_string("ActivatableAttribute"), add_string("Windows.Foundation.Metadata") );
2969
2970
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
2971
typeref_type = add_typeref_row( scope, add_string("Type"), add_string("System") );
2972
2973
class = memberref_parent( TABLE_TYPEREF, typeref );
2974
2975
if (value->type == EXPR_MEMBER)
2976
sig_size = make_member_sig3( typedef_or_ref(TABLE_TYPEREF, typeref_type), sig );
2977
else
2978
{
2979
memcpy( sig, sig_default, sizeof(sig_default) );
2980
sig_size = sizeof(sig_default);
2981
}
2982
2983
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
2984
}
2985
}
2986
2987
static void add_activatable_attr_step2( const type_t *type )
2988
{
2989
const attr_t *attr;
2990
2991
if (type->attrs) LIST_FOR_EACH_ENTRY_REV( attr, type->attrs, const attr_t, entry )
2992
{
2993
UINT parent, attr_type, value_size;
2994
BYTE value[MAX_NAME * 2 + sizeof(UINT) + 10];
2995
2996
if (attr->type != ATTR_ACTIVATABLE) continue;
2997
2998
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
2999
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
3000
value_size = make_activatable_value( attr->u.pval, value );
3001
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
3002
}
3003
}
3004
3005
static UINT make_threading_value( const attr_t *attr, BYTE *buf )
3006
{
3007
UINT value, model = attr->u.ival;
3008
3009
switch (model)
3010
{
3011
case THREADING_SINGLE:
3012
value = 1;
3013
break;
3014
case THREADING_FREE:
3015
value = 2;
3016
break;
3017
case THREADING_BOTH:
3018
value = 3;
3019
break;
3020
default:
3021
fprintf( stderr, "Unhandled model %u.\n", model );
3022
return 0;
3023
}
3024
3025
buf[0] = 1;
3026
buf[1] = 0;
3027
memcpy( buf + 2, &value, sizeof(value) );
3028
buf[6] = buf[7] = 0;
3029
return 8;
3030
}
3031
3032
static void add_threading_attr_step1( const type_t *type )
3033
{
3034
UINT assemblyref, scope, typeref, typeref_attr, class, sig_size;
3035
BYTE sig[32];
3036
attr_t *attr;
3037
3038
if (!(attr = get_attr( type->attrs, ATTR_THREADING ))) return;
3039
3040
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
3041
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
3042
typeref = add_typeref_row( scope, add_string("ThreadingModel"), add_string("Windows.Foundation.Metadata") );
3043
3044
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
3045
typeref_attr = add_typeref_row( scope, add_string("ThreadingAttribute"), add_string("Windows.Foundation.Metadata") );
3046
3047
class = memberref_parent( TABLE_TYPEREF, typeref_attr );
3048
sig_size = make_member_sig2( ELEMENT_TYPE_VALUETYPE, typedef_or_ref(TABLE_TYPEREF, typeref), sig );
3049
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
3050
}
3051
3052
static void add_threading_attr_step2( const type_t *type )
3053
{
3054
UINT parent, attr_type, value_size;
3055
BYTE value[8];
3056
const attr_t *attr;
3057
3058
if (!(attr = get_attr( type->attrs, ATTR_THREADING ))) return;
3059
3060
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
3061
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
3062
value_size = make_threading_value( attr, value );
3063
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
3064
}
3065
3066
static UINT make_marshalingbehavior_value( const attr_t *attr, BYTE *buf )
3067
{
3068
UINT marshaling = attr->u.ival;
3069
3070
buf[0] = 1;
3071
buf[1] = 0;
3072
memcpy( buf + 2, &marshaling, sizeof(marshaling) );
3073
buf[6] = buf[7] = 0;
3074
return 8;
3075
}
3076
3077
static void add_marshalingbehavior_attr_step1( const type_t *type )
3078
{
3079
UINT assemblyref, scope, typeref, typeref_attr, class, sig_size;
3080
BYTE sig[32];
3081
attr_t *attr;
3082
3083
if (!(attr = get_attr( type->attrs, ATTR_MARSHALING_BEHAVIOR ))) return;
3084
3085
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
3086
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
3087
typeref = add_typeref_row( scope, add_string("MarshalingType"), add_string("Windows.Foundation.Metadata") );
3088
3089
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
3090
typeref_attr = add_typeref_row( scope, add_string("MarshalingBehaviorAttribute"), add_string("Windows.Foundation.Metadata") );
3091
3092
class = memberref_parent( TABLE_TYPEREF, typeref_attr );
3093
sig_size = make_member_sig2( ELEMENT_TYPE_VALUETYPE, typedef_or_ref(TABLE_TYPEREF, typeref), sig );
3094
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
3095
}
3096
3097
static void add_marshalingbehavior_attr_step2( const type_t *type )
3098
{
3099
UINT parent, attr_type, value_size;
3100
BYTE value[8];
3101
const attr_t *attr;
3102
3103
if (!(attr = get_attr( type->attrs, ATTR_MARSHALING_BEHAVIOR ))) return;
3104
3105
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
3106
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
3107
value_size = make_marshalingbehavior_value( attr, value );
3108
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
3109
}
3110
3111
static UINT make_composable_value( const expr_t *attr, BYTE *buf )
3112
{
3113
char *name_iface, *name_contract;
3114
const expr_t *contract = attr->ref;
3115
const type_t *type_iface = attr->u.var->declspec.type;
3116
const type_t *type_contract = contract->u.var->declspec.type;
3117
UINT access_type = 1, contract_version = contract->ref->u.integer.value;
3118
UINT len_iface, len_contract;
3119
BYTE *ptr = buf;
3120
3121
name_iface = format_namespace( type_iface->namespace, "", ".", type_iface->name, NULL );
3122
len_iface = strlen( name_iface );
3123
3124
name_contract = format_namespace( type_contract->namespace, "", ".", type_contract->name, NULL );
3125
len_contract = strlen( name_contract );
3126
3127
ptr[0] = 1;
3128
ptr[1] = 0;
3129
ptr[2] = len_iface;
3130
memcpy( ptr + 3, name_iface, len_iface );
3131
ptr += len_iface + 3;
3132
3133
if (is_attr( attr->u.var->attrs, ATTR_PUBLIC)) access_type = 2;
3134
memcpy( ptr, &access_type, sizeof(access_type) );
3135
ptr += sizeof(access_type);
3136
3137
memcpy( ptr, &contract_version, sizeof(contract_version) );
3138
ptr += sizeof(contract_version);
3139
3140
ptr[0] = len_contract;
3141
memcpy( ptr + 1, name_contract, len_contract );
3142
ptr += len_contract + 1;
3143
ptr[0] = ptr[1] = 0;
3144
3145
free( name_iface );
3146
free( name_contract );
3147
return len_iface + sizeof(access_type) + sizeof(contract_version) + len_contract + 6;
3148
}
3149
3150
static void add_composable_attr_step1( const type_t *type )
3151
{
3152
attr_t *attr;
3153
3154
if (type->attrs) LIST_FOR_EACH_ENTRY( attr, type->attrs, attr_t, entry )
3155
{
3156
UINT assemblyref, scope, typeref, typeref_attr, typeref_type, class, sig_size;
3157
BYTE sig[64];
3158
3159
if (attr->type != ATTR_COMPOSABLE) continue;
3160
3161
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
3162
typeref_type = add_typeref_row( scope, add_string("Type"), add_string("System") );
3163
3164
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
3165
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
3166
typeref = add_typeref_row( scope, add_string("CompositionType"), add_string("Windows.Foundation.Metadata") );
3167
typeref_attr = add_typeref_row( scope, add_string("ComposableAttribute"), add_string("Windows.Foundation.Metadata") );
3168
3169
class = memberref_parent( TABLE_TYPEREF, typeref_attr );
3170
sig_size = make_member_sig4( typedef_or_ref(TABLE_TYPEREF, typeref_type), typedef_or_ref(TABLE_TYPEREF, typeref), sig );
3171
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
3172
}
3173
}
3174
3175
static void add_composable_attr_step2( const type_t *type )
3176
{
3177
const attr_t *attr;
3178
3179
if (type->attrs) LIST_FOR_EACH_ENTRY( attr, type->attrs, const attr_t, entry )
3180
{
3181
UINT parent, attr_type, value_size;
3182
BYTE value[MAX_NAME + sizeof(UINT) * 2 + 6];
3183
3184
if (attr->type != ATTR_COMPOSABLE) continue;
3185
3186
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
3187
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
3188
value_size = make_composable_value( attr->u.pval, value );
3189
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
3190
}
3191
}
3192
3193
static void add_member_interfaces( type_t *class )
3194
{
3195
const typeref_list_t *iface_list = type_runtimeclass_get_ifaces( class );
3196
const typeref_t *iface;
3197
3198
if (iface_list) LIST_FOR_EACH_ENTRY( iface, iface_list, typeref_t, entry )
3199
{
3200
UINT interface, interfaceimpl_ref;
3201
const statement_t *stmt;
3202
3203
create_typeref( iface->type );
3204
3205
interface = typedef_or_ref( TABLE_TYPEREF, iface->type->md.ref );
3206
interfaceimpl_ref = add_interfaceimpl_row( class->md.def, interface );
3207
3208
if (is_attr( iface->attrs, ATTR_DEFAULT )) add_default_attr( interfaceimpl_ref );
3209
3210
/* add properties in reverse order like midlrt */
3211
STATEMENTS_FOR_EACH_FUNC_REV( stmt, type_iface_get_stmts(iface->type) )
3212
{
3213
const var_t *method = stmt->u.var;
3214
3215
add_property( class, iface->type, method );
3216
}
3217
3218
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface->type) )
3219
{
3220
const var_t *method = stmt->u.var;
3221
3222
add_event( class, iface->type, method );
3223
add_method( class, iface->type, method );
3224
add_method_impl( class, iface->type, method );
3225
add_method_contract_attrs( class, iface->type, method->declspec.type );
3226
}
3227
}
3228
}
3229
3230
static void add_static_interfaces( type_t *class )
3231
{
3232
const attr_t *attr;
3233
3234
if (class->attrs) LIST_FOR_EACH_ENTRY( attr, class->attrs, const attr_t, entry )
3235
{
3236
const expr_t *value = attr->u.pval;
3237
const statement_t *stmt;
3238
type_t *iface;
3239
3240
if (attr->type != ATTR_STATIC) continue;
3241
3242
iface = value->u.var->declspec.type;
3243
3244
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
3245
{
3246
const var_t *method = stmt->u.var;
3247
3248
add_property( class, iface, method );
3249
add_event( class, iface, method );
3250
add_method( class, iface, method );
3251
add_method_contract_attrs( class, iface, method->declspec.type );
3252
}
3253
}
3254
}
3255
3256
static void add_activation_interfaces( const type_t *class )
3257
{
3258
UINT flags = METHOD_ATTR_PUBLIC | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_SPECIALNAME | METHOD_ATTR_RTSPECIALNAME;
3259
const attr_t *attr, *contract_attr = get_attr( class->attrs, ATTR_CONTRACT );
3260
3261
if (class->attrs) LIST_FOR_EACH_ENTRY_REV( attr, class->attrs, const attr_t, entry )
3262
{
3263
UINT methoddef, parent, attr_type, value_size, paramlist = 0, sig_size;
3264
BYTE value[MAX_NAME + sizeof(UINT) + 5], sig[256];
3265
const expr_t *activatable = attr->u.pval;
3266
const type_t *iface = NULL;
3267
const var_t *method = NULL, *arg;
3268
const statement_t *stmt;
3269
3270
if (attr->type != ATTR_ACTIVATABLE) continue;
3271
3272
/* interface is optional */
3273
if (activatable->type == EXPR_MEMBER) iface = activatable->u.var->declspec.type;
3274
3275
if (iface) STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
3276
{
3277
UINT seq = 1, row;
3278
3279
method = stmt->u.var;
3280
3281
LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry )
3282
{
3283
if (is_retval( arg )) continue;
3284
row = add_param_row( get_param_attrs(arg), seq++, add_string(arg->name) );
3285
if (!paramlist) paramlist = row;
3286
}
3287
break;
3288
}
3289
3290
sig_size = make_activation_sig( method, sig );
3291
methoddef = add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string(".ctor"), add_blob(sig, sig_size), paramlist );
3292
3293
parent = has_customattribute( TABLE_METHODDEF, methoddef );
3294
attr_type = customattribute_type( TABLE_MEMBERREF, contract_attr->md_member );
3295
value_size = make_contract_value( contract_attr, value );
3296
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
3297
}
3298
}
3299
3300
static void add_composition_interfaces( const type_t *class )
3301
{
3302
UINT flags = METHOD_ATTR_FAMILY | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_SPECIALNAME | METHOD_ATTR_RTSPECIALNAME;
3303
const attr_t *attr, *contract_attr = get_attr( class->attrs, ATTR_CONTRACT );
3304
3305
if (class->attrs) LIST_FOR_EACH_ENTRY_REV( attr, class->attrs, const attr_t, entry )
3306
{
3307
UINT methoddef, parent, attr_type, value_size, paramlist = 0, sig_size;
3308
BYTE value[MAX_NAME + sizeof(UINT) + 5], sig[256];
3309
const expr_t *composable = attr->u.pval;
3310
const var_t *method = NULL, *arg;
3311
const statement_t *stmt;
3312
const type_t *iface;
3313
3314
if (attr->type != ATTR_COMPOSABLE) continue;
3315
3316
iface = composable->u.var->declspec.type;
3317
3318
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
3319
{
3320
UINT seq = 1, row, count = 0;
3321
3322
method = stmt->u.var;
3323
3324
LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry ) count++;
3325
3326
if (count > 3) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry )
3327
{
3328
if (--count < 3) break; /* omit last 3 standard composition args */
3329
row = add_param_row( get_param_attrs(arg), seq++, add_string(arg->name) );
3330
if (!paramlist) paramlist = row;
3331
}
3332
break;
3333
}
3334
3335
sig_size = make_composition_sig( method, sig );
3336
methoddef = add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string(".ctor"), add_blob(sig, sig_size), paramlist );
3337
3338
parent = has_customattribute( TABLE_METHODDEF, methoddef );
3339
attr_type = customattribute_type( TABLE_MEMBERREF, contract_attr->md_member );
3340
value_size = make_contract_value( contract_attr, value );
3341
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
3342
}
3343
}
3344
3345
static void add_constructor_overload( const type_t *type )
3346
{
3347
static const BYTE sig_default[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID };
3348
static const BYTE sig_overload[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING };
3349
UINT name, namespace;
3350
const attr_t *attr;
3351
3352
if (type->attrs) LIST_FOR_EACH_ENTRY_REV( attr, type->attrs, const attr_t, entry )
3353
{
3354
const expr_t *value = attr->u.pval;
3355
3356
if (attr->type == ATTR_COMPOSABLE || (attr->type == ATTR_ACTIVATABLE && value->type == EXPR_MEMBER))
3357
{
3358
UINT assemblyref, scope, typeref_default, typeref_overload, class;
3359
3360
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
3361
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
3362
3363
name = add_string( "DefaultOverloadAttribute" );
3364
namespace = add_string( "Windows.Foundation.Metadata" );
3365
typeref_default = add_typeref_row( scope, name, namespace );
3366
3367
class = memberref_parent( TABLE_TYPEREF, typeref_default );
3368
add_memberref_row( class, add_string(".ctor"), add_blob(sig_default, sizeof(sig_default)) );
3369
3370
name = add_string( "OverloadAttribute" );
3371
typeref_overload = add_typeref_row( scope, name, namespace );
3372
3373
class = memberref_parent( TABLE_TYPEREF, typeref_overload );
3374
add_memberref_row( class, add_string(".ctor"), add_blob(sig_overload, sizeof(sig_overload)) );
3375
break;
3376
}
3377
}
3378
}
3379
3380
static void add_runtimeclass_type_step2( type_t *type )
3381
{
3382
const typeref_list_t *iface_list = type_runtimeclass_get_ifaces( type );
3383
UINT flags;
3384
3385
if (type->md.def) return;
3386
3387
add_constructor_overload( type );
3388
3389
flags = TYPE_ATTR_PUBLIC | TYPE_ATTR_UNKNOWN;
3390
if (!is_attr( type->attrs, ATTR_COMPOSABLE )) flags |= TYPE_ATTR_SEALED;
3391
if (!iface_list) flags |= TYPE_ATTR_ABSTRACT;
3392
3393
type->md.def = add_typedef_row( flags, type->md.name, type->md.namespace, type->md.extends, 0, 0 );
3394
3395
/* add contract first so activation/composition constructors can inherit it */
3396
add_contract_attr_step1( type );
3397
3398
add_activation_interfaces( type );
3399
add_composition_interfaces( type );
3400
add_member_interfaces( type );
3401
add_static_interfaces( type );
3402
3403
add_composable_attr_step1( type );
3404
add_static_attr_step1( type );
3405
add_activatable_attr_step1( type );
3406
add_threading_attr_step1( type );
3407
add_marshalingbehavior_attr_step1( type );
3408
3409
add_contract_attr_step2( type );
3410
add_composable_attr_step2( type );
3411
add_static_attr_step2( type );
3412
add_activatable_attr_step2( type );
3413
add_threading_attr_step2( type );
3414
add_marshalingbehavior_attr_step2( type );
3415
}
3416
3417
static void add_delegate_type_step1( type_t *type )
3418
{
3419
const type_t *iface = type_delegate_get_iface( type );
3420
UINT scope, typeref;
3421
const statement_t *stmt;
3422
3423
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
3424
typeref = add_typeref_row( scope, add_string("MulticastDelegate"), add_string("System") );
3425
type->md.extends = typedef_or_ref( TABLE_TYPEREF, typeref );
3426
3427
create_typeref( type );
3428
3429
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
3430
{
3431
add_method_params_step1( stmt->u.var );
3432
}
3433
3434
add_version_attr_step1( type );
3435
add_contract_attr_step1( type );
3436
add_uuid_attr_step1( type );
3437
}
3438
3439
static void add_delegate_type_step2( type_t *type )
3440
{
3441
static const BYTE sig_ctor[] = { SIG_TYPE_HASTHIS, 2, ELEMENT_TYPE_VOID, ELEMENT_TYPE_OBJECT, ELEMENT_TYPE_I };
3442
UINT methoddef, flags, paramlist;
3443
const type_t *iface = type_delegate_get_iface( type );
3444
const statement_t *stmt;
3445
3446
flags = METHOD_ATTR_RTSPECIALNAME | METHOD_ATTR_SPECIALNAME | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_PRIVATE;
3447
methoddef = add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string(".ctor"),
3448
add_blob(sig_ctor, sizeof(sig_ctor)), 0 );
3449
3450
add_param_row( 0, 1, add_string("object") );
3451
add_param_row( 0, 2, add_string("method") );
3452
3453
flags = METHOD_ATTR_SPECIALNAME | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_PUBLIC | METHOD_ATTR_VIRTUAL |
3454
METHOD_ATTR_NEWSLOT;
3455
3456
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
3457
{
3458
const var_t *method = stmt->u.var;
3459
UINT sig_size;
3460
BYTE sig[256];
3461
3462
sig_size = make_method_sig( method, sig, FALSE );
3463
paramlist = add_method_params_step2( type_function_get_args(method->declspec.type) );
3464
3465
add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string("Invoke"), add_blob(sig, sig_size), paramlist );
3466
break;
3467
}
3468
type->md.def = add_typedef_row( TYPE_ATTR_PUBLIC | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN, type->md.name,
3469
type->md.namespace, type->md.extends, 0, methoddef );
3470
3471
add_uuid_attr_step2( type );
3472
add_version_attr_step2( type );
3473
add_contract_attr_step2( type );
3474
}
3475
3476
static void build_tables( const statement_list_t *stmt_list )
3477
{
3478
const statement_t *stmt;
3479
3480
/* Adding a type involves two passes: the first creates various references and the second
3481
uses those references to create the remaining rows. */
3482
3483
LIST_FOR_EACH_ENTRY( stmt, stmt_list, const statement_t, entry )
3484
{
3485
type_t *type = stmt->u.type;
3486
3487
if (stmt->type == STMT_IMPORT) append_assembly_import( stmt->u.str );
3488
3489
if (stmt->type != STMT_TYPE) continue;
3490
3491
switch (type->type_type)
3492
{
3493
case TYPE_ENUM:
3494
add_enum_type_step1( type );
3495
break;
3496
case TYPE_STRUCT:
3497
add_struct_type_step1( type );
3498
break;
3499
case TYPE_INTERFACE:
3500
if (type->signature && !strncmp( type->signature, "pinterface", 10 ))
3501
{
3502
/* fprintf( stderr, "Ignoring supported %s parameterized interface.\n", type->name ); */
3503
break;
3504
}
3505
add_interface_type_step1( type );
3506
break;
3507
case TYPE_APICONTRACT:
3508
add_apicontract_type_step1( type );
3509
break;
3510
case TYPE_RUNTIMECLASS:
3511
add_runtimeclass_type_step1( type );
3512
break;
3513
case TYPE_DELEGATE:
3514
add_delegate_type_step1( type );
3515
break;
3516
default:
3517
fprintf( stderr, "Unhandled type %u name '%s'.\n", type->type_type, type->name );
3518
break;
3519
}
3520
}
3521
3522
LIST_FOR_EACH_ENTRY( stmt, stmt_list, const statement_t, entry )
3523
{
3524
type_t *type = stmt->u.type;
3525
3526
if (stmt->type != STMT_TYPE) continue;
3527
3528
switch (type->type_type)
3529
{
3530
case TYPE_ENUM:
3531
add_enum_type_step2( type );
3532
break;
3533
case TYPE_STRUCT:
3534
add_struct_type_step2( type );
3535
break;
3536
case TYPE_INTERFACE:
3537
if (type->signature && !strncmp( type->signature, "pinterface", 10 ))
3538
{
3539
/* fprintf( stderr, "Ignoring supported %s parameterized interface.\n", type->name ); */
3540
break;
3541
}
3542
add_interface_type_step2( type );
3543
break;
3544
case TYPE_APICONTRACT:
3545
add_apicontract_type_step2( type );
3546
break;
3547
case TYPE_RUNTIMECLASS:
3548
add_runtimeclass_type_step2( type );
3549
break;
3550
case TYPE_DELEGATE:
3551
add_delegate_type_step2( type );
3552
break;
3553
default:
3554
break;
3555
}
3556
}
3557
}
3558
3559
static void build_table_stream( const statement_list_t *stmts )
3560
{
3561
static const GUID guid = { 0x9ddc04c6, 0x04ca, 0x04cc, { 0x52, 0x85, 0x4b, 0x50, 0xb2, 0x60, 0x1d, 0xa8 } };
3562
static const BYTE token[] = { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 };
3563
static const USHORT space = 0x20;
3564
char *ptr;
3565
UINT i;
3566
3567
add_string( "" );
3568
add_userstring( NULL, 0 );
3569
add_userstring( &space, sizeof(space) );
3570
add_blob( NULL, 0 );
3571
3572
assembly_name = xstrdup( metadata_name );
3573
if ((ptr = strrchr( assembly_name, '.' ))) *ptr = 0;
3574
3575
add_typedef_row( 0, add_string("<Module>"), 0, 0, 1, 1 );
3576
add_assembly_row( add_string(assembly_name) );
3577
add_module_row( add_string(metadata_name), add_guid(&guid) );
3578
add_assemblyref_row( 0, add_blob(token, sizeof(token)), add_string("mscorlib") );
3579
3580
build_tables( stmts );
3581
3582
for (i = 0; i < TABLE_MAX; i++) if (tables[i].count) tables_header.valid |= (1ull << i);
3583
3584
if (strings.offset >> 16) tables_header.heap_sizes |= LARGE_STRING_HEAP;
3585
if (guids.offset >> 16) tables_header.heap_sizes |= LARGE_GUID_HEAP;
3586
if (blobs.offset >> 16) tables_header.heap_sizes |= LARGE_BLOB_HEAP;
3587
3588
add_bytes( &tables_disk, (const BYTE *)&tables_header, sizeof(tables_header) );
3589
3590
for (i = 0; i < TABLE_MAX; i++)
3591
if (tables[i].count) add_bytes( &tables_disk, (const BYTE *)&tables[i].count, sizeof(tables[i].count) );
3592
3593
serialize_module_table();
3594
serialize_typeref_table();
3595
serialize_typedef_table();
3596
serialize_field_table();
3597
serialize_methoddef_table();
3598
serialize_param_table();
3599
serialize_interfaceimpl_table();
3600
serialize_memberref_table();
3601
serialize_constant_table();
3602
serialize_customattribute_table();
3603
serialize_eventmap_table();
3604
serialize_event_table();
3605
serialize_propertymap_table();
3606
serialize_property_table();
3607
serialize_methodsemantics_table();
3608
serialize_methodimpl_table();
3609
serialize_assembly_table();
3610
serialize_assemblyref_table();
3611
}
3612
3613
static void build_streams( const statement_list_t *stmts )
3614
{
3615
static const BYTE pad[4];
3616
UINT i, len, offset = sizeof(metadata_header);
3617
3618
build_table_stream( stmts );
3619
3620
len = (tables_disk.offset + 3) & ~3;
3621
add_bytes( &tables_disk, pad, len - tables_disk.offset );
3622
3623
streams[WINMD_STREAM_TABLE].data_size = tables_disk.offset;
3624
streams[WINMD_STREAM_TABLE].data = tables_disk.ptr;
3625
3626
len = (strings.offset + 3) & ~3;
3627
add_bytes( &strings, pad, len - strings.offset );
3628
3629
streams[WINMD_STREAM_STRING].data_size = strings.offset;
3630
streams[WINMD_STREAM_STRING].data = strings.ptr;
3631
3632
len = (userstrings.offset + 3) & ~3;
3633
add_bytes( &userstrings, pad, len - userstrings.offset );
3634
3635
streams[WINMD_STREAM_USERSTRING].data_size = userstrings.offset;
3636
streams[WINMD_STREAM_USERSTRING].data = userstrings.ptr;
3637
3638
len = (blobs.offset + 3) & ~3;
3639
add_bytes( &blobs, pad, len - blobs.offset );
3640
3641
streams[WINMD_STREAM_BLOB].data_size = blobs.offset;
3642
streams[WINMD_STREAM_BLOB].data = blobs.ptr;
3643
3644
streams[WINMD_STREAM_GUID].data_size = guids.offset;
3645
streams[WINMD_STREAM_GUID].data = guids.ptr;
3646
3647
for (i = 0; i < WINMD_STREAM_MAX; i++)
3648
{
3649
if (!streams[i].data_size) continue;
3650
offset += streams[i].header_size;
3651
}
3652
for (i = 0; i < WINMD_STREAM_MAX; i++)
3653
{
3654
if (!streams[i].data_size) continue;
3655
streams[i].data_offset = offset;
3656
offset += streams[i].data_size;
3657
}
3658
}
3659
3660
static void write_streams( void )
3661
{
3662
UINT i;
3663
for (i = 0; i < WINMD_STREAM_MAX; i++)
3664
{
3665
if (!streams[i].data_size) continue;
3666
put_data( streams[i].data, streams[i].data_size );
3667
}
3668
}
3669
3670
void write_metadata( const statement_list_t *stmts )
3671
{
3672
static const BYTE pad[FILE_ALIGNMENT];
3673
UINT image_size, file_size, i;
3674
3675
if (!do_metadata || !winrt_mode) return;
3676
3677
build_streams( stmts );
3678
3679
image_size = FILE_ALIGNMENT + sizeof(cor_header) + 8 + sizeof(metadata_header);
3680
for (i = 0; i < WINMD_STREAM_MAX; i++) image_size += streams[i].header_size + streams[i].data_size;
3681
3682
init_output_buffer();
3683
3684
write_headers( image_size );
3685
write_streams( );
3686
3687
file_size = (image_size + FILE_ALIGNMENT - 1) & ~(FILE_ALIGNMENT - 1);
3688
put_data( pad, file_size - image_size );
3689
3690
flush_output_buffer( metadata_name );
3691
}
3692
3693