Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/tools/widl/metadata.c
4388 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
#define MODULE_ROW 1
1444
#define MSCORLIB_ROW 1
1445
1446
#define MAX_NAME 256
1447
1448
static UINT add_name( type_t *type, UINT *namespace )
1449
{
1450
UINT name = add_string( type->name );
1451
char *str = format_namespace( type->namespace, "", ".", NULL, NULL );
1452
*namespace = add_string( str );
1453
free( str );
1454
return name;
1455
}
1456
1457
static UINT make_field_value_sig( UINT token, BYTE *buf )
1458
{
1459
UINT len = 2;
1460
1461
buf[0] = SIG_TYPE_FIELD;
1462
buf[1] = ELEMENT_TYPE_VALUETYPE;
1463
len += encode_int( token, buf + 2 );
1464
return len;
1465
}
1466
1467
enum
1468
{
1469
LARGE_STRING_HEAP = 0x01,
1470
LARGE_GUID_HEAP = 0x02,
1471
LARGE_BLOB_HEAP = 0x04
1472
};
1473
1474
static char *assembly_name;
1475
1476
static enum element_type map_basic_type( enum type_basic_type type, int sign )
1477
{
1478
enum element_type elem_type;
1479
1480
switch (type)
1481
{
1482
case TYPE_BASIC_CHAR: elem_type = ELEMENT_TYPE_BOOLEAN; break;
1483
case TYPE_BASIC_INT16: elem_type = (sign > 0) ? ELEMENT_TYPE_U2 : ELEMENT_TYPE_I2; break;
1484
case TYPE_BASIC_INT:
1485
case TYPE_BASIC_INT32:
1486
case TYPE_BASIC_LONG: elem_type = (sign > 0) ? ELEMENT_TYPE_U4 : ELEMENT_TYPE_I4; break;
1487
case TYPE_BASIC_INT64: elem_type = (sign > 0) ? ELEMENT_TYPE_U8 : ELEMENT_TYPE_I8; break;
1488
case TYPE_BASIC_BYTE: elem_type = ELEMENT_TYPE_U1; break;
1489
case TYPE_BASIC_WCHAR: elem_type = ELEMENT_TYPE_CHAR; break;
1490
case TYPE_BASIC_FLOAT: elem_type = ELEMENT_TYPE_R4; break;
1491
case TYPE_BASIC_DOUBLE: elem_type = ELEMENT_TYPE_R8; break;
1492
default:
1493
fprintf( stderr, "Unhandled basic type %u.\n", type );
1494
exit( 1 );
1495
}
1496
return elem_type;
1497
}
1498
1499
static UINT make_struct_field_sig( const var_t *var, BYTE *buf )
1500
{
1501
const type_t *type = var->declspec.type;
1502
1503
if (type->name && !strcmp( type->name, "HSTRING" ))
1504
{
1505
buf[0] = SIG_TYPE_FIELD;
1506
buf[1] = ELEMENT_TYPE_STRING;
1507
return 2;
1508
}
1509
1510
if (type->name && !strcmp( type->name, "GUID" ))
1511
{
1512
UINT token = typedef_or_ref( TABLE_TYPEREF, type->md.ref );
1513
return make_field_value_sig( token, buf );
1514
}
1515
1516
type = type_get_real_type( type );
1517
1518
if (type_get_type( type ) == TYPE_ENUM || type_get_type( type ) == TYPE_STRUCT)
1519
{
1520
UINT token = typedef_or_ref( TABLE_TYPEREF, type->md.ref );
1521
return make_field_value_sig( token, buf );
1522
}
1523
1524
if (type_get_type( type ) != TYPE_BASIC)
1525
{
1526
fprintf( stderr, "Unhandled struct field type %u.\n", type_get_type( type ) );
1527
exit( 1 );
1528
}
1529
1530
buf[0] = SIG_TYPE_FIELD;
1531
buf[1] = map_basic_type( type_basic_get_type(type), type_basic_get_sign(type) );
1532
return 2;
1533
}
1534
1535
static UINT make_member_sig( UINT token, BYTE *buf )
1536
{
1537
UINT len = 4;
1538
1539
buf[0] = SIG_TYPE_HASTHIS;
1540
buf[1] = 2;
1541
buf[2] = ELEMENT_TYPE_VOID;
1542
buf[3] = ELEMENT_TYPE_CLASS;
1543
len += encode_int( token, buf + 4 );
1544
buf[len++] = ELEMENT_TYPE_U4;
1545
return len;
1546
}
1547
1548
static UINT make_member_sig2( UINT type, UINT token, BYTE *buf )
1549
{
1550
UINT len = 4;
1551
1552
buf[0] = SIG_TYPE_HASTHIS;
1553
buf[1] = 1;
1554
buf[2] = ELEMENT_TYPE_VOID;
1555
buf[3] = type;
1556
len += encode_int( token, buf + 4 );
1557
return len;
1558
}
1559
1560
static UINT make_member_sig3( UINT token, BYTE *buf )
1561
{
1562
UINT len = 4;
1563
1564
buf[0] = SIG_TYPE_HASTHIS;
1565
buf[1] = 3;
1566
buf[2] = ELEMENT_TYPE_VOID;
1567
buf[3] = ELEMENT_TYPE_CLASS;
1568
len += encode_int( token, buf + 4 );
1569
buf[len++] = ELEMENT_TYPE_U4;
1570
buf[len++] = ELEMENT_TYPE_STRING;
1571
return len;
1572
}
1573
1574
static UINT make_member_sig4( UINT token, UINT token2, BYTE *buf )
1575
{
1576
UINT len = 4;
1577
1578
buf[0] = SIG_TYPE_HASTHIS;
1579
buf[1] = 4;
1580
buf[2] = ELEMENT_TYPE_VOID;
1581
buf[3] = ELEMENT_TYPE_CLASS;
1582
len += encode_int( token, buf + 4 );
1583
buf[len++] = ELEMENT_TYPE_VALUETYPE;
1584
len += encode_int( token2, buf + len );
1585
buf[len++] = ELEMENT_TYPE_U4;
1586
buf[len++] = ELEMENT_TYPE_STRING;
1587
return len;
1588
}
1589
1590
static UINT make_type_sig( const type_t *type, BYTE *buf )
1591
{
1592
UINT len = 0;
1593
1594
type = type_get_real_type( type );
1595
1596
switch (type_get_type( type ))
1597
{
1598
case TYPE_POINTER:
1599
{
1600
const type_t *ref_type = type_pointer_get_ref_type( type );
1601
BOOL skip_byref = FALSE;
1602
1603
switch (type_get_type( ref_type ))
1604
{
1605
case TYPE_DELEGATE:
1606
case TYPE_INTERFACE:
1607
case TYPE_RUNTIMECLASS:
1608
skip_byref = TRUE;
1609
break;
1610
default:
1611
break;
1612
}
1613
if (!skip_byref) buf[len++] = ELEMENT_TYPE_BYREF;
1614
len += make_type_sig( ref_type, buf + len );
1615
break;
1616
}
1617
case TYPE_ARRAY:
1618
buf[len++] = ELEMENT_TYPE_SZARRAY;
1619
len += make_type_sig( type_array_get_element_type(type), buf + len );
1620
break;
1621
1622
case TYPE_INTERFACE:
1623
buf[len++] = ELEMENT_TYPE_OBJECT;
1624
break;
1625
1626
case TYPE_DELEGATE:
1627
case TYPE_RUNTIMECLASS:
1628
buf[len++] = ELEMENT_TYPE_CLASS;
1629
len += encode_int( typedef_or_ref(TABLE_TYPEREF, type->md.ref), buf + 1 );
1630
break;
1631
1632
case TYPE_ENUM:
1633
case TYPE_STRUCT:
1634
buf[len++] = ELEMENT_TYPE_VALUETYPE;
1635
len += encode_int( typedef_or_ref(TABLE_TYPEREF, type->md.ref), buf + 1 );
1636
break;
1637
1638
case TYPE_BASIC:
1639
buf[len++] = map_basic_type( type_basic_get_type(type), type_basic_get_sign(type) );
1640
break;
1641
1642
default:
1643
fprintf( stderr, "Unhandled type %u.\n", type_get_type( type ) );
1644
exit( 1 );
1645
}
1646
return len;
1647
}
1648
1649
static BOOL is_retval( const var_t *arg )
1650
{
1651
const type_t *type = arg->declspec.type;
1652
1653
/* array return values are encoded as out parameters even if the retval attribute is present */
1654
if (!is_attr( arg->attrs, ATTR_RETVAL ) || type_get_type( type ) == TYPE_ARRAY) return FALSE;
1655
return TRUE;
1656
}
1657
1658
static UINT make_method_sig( const var_t *method, BYTE *buf, BOOL is_static )
1659
{
1660
const var_t *arg;
1661
const var_list_t *arg_list = type_function_get_args( method->declspec.type );
1662
UINT len = 3;
1663
1664
buf[0] = is_static ? SIG_TYPE_DEFAULT : SIG_TYPE_HASTHIS;
1665
buf[1] = 0;
1666
buf[2] = ELEMENT_TYPE_VOID;
1667
1668
if (!arg_list) return 3;
1669
1670
/* add return value first */
1671
LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry )
1672
{
1673
const type_t *type;
1674
1675
if (!is_retval( arg )) continue;
1676
type = type_pointer_get_ref_type( arg->declspec.type ); /* retval must be a pointer */
1677
len = make_type_sig( type, buf + 2 ) + 2;
1678
}
1679
1680
/* add remaining parameters */
1681
LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry )
1682
{
1683
if (is_size_param( arg, arg_list ) || is_retval( arg ) ) continue;
1684
len += make_type_sig( arg->declspec.type, buf + len );
1685
buf[1]++;
1686
}
1687
return len;
1688
}
1689
1690
static UINT make_property_sig( const var_t *method, BYTE *buf, BOOL is_static )
1691
{
1692
const var_t *arg;
1693
const var_list_t *arg_list = type_function_get_args( method->declspec.type );
1694
UINT len = 3;
1695
1696
buf[0] = is_static ? SIG_TYPE_PROPERTY : SIG_TYPE_HASTHIS | SIG_TYPE_PROPERTY;
1697
buf[1] = 0;
1698
buf[2] = ELEMENT_TYPE_VOID;
1699
1700
LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry )
1701
{
1702
const type_t *type;
1703
1704
if (!is_retval( arg )) continue;
1705
type = type_pointer_get_ref_type( arg->declspec.type ); /* retval must be a pointer */
1706
len = make_type_sig( type, buf + 2 ) + 2;
1707
}
1708
1709
return len;
1710
}
1711
1712
static UINT make_activation_sig( const var_t *method, BYTE *buf )
1713
{
1714
const var_t *arg;
1715
UINT len = 3;
1716
1717
buf[0] = SIG_TYPE_HASTHIS;
1718
buf[1] = 0;
1719
buf[2] = ELEMENT_TYPE_VOID;
1720
1721
if (method) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry )
1722
{
1723
if (is_retval( arg )) continue;
1724
len += make_type_sig( arg->declspec.type, buf + len );
1725
buf[1]++;
1726
}
1727
1728
return len;
1729
}
1730
1731
static UINT make_composition_sig( const var_t *method, BYTE *buf )
1732
{
1733
const var_t *arg;
1734
UINT len = 3, count = 0;
1735
1736
buf[0] = SIG_TYPE_HASTHIS;
1737
buf[1] = 0;
1738
buf[2] = ELEMENT_TYPE_VOID;
1739
1740
if (method) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry ) count++;
1741
1742
if (method) assert( count >= 3 );
1743
1744
if (count > 3) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry )
1745
{
1746
if (--count < 3) break; /* omit last 3 standard composition args */
1747
len += make_type_sig( arg->declspec.type, buf + len );
1748
buf[1]++;
1749
}
1750
1751
return len;
1752
}
1753
1754
static UINT make_deprecated_sig( UINT token, BYTE *buf )
1755
{
1756
UINT len = 5;
1757
1758
buf[0] = SIG_TYPE_HASTHIS;
1759
buf[1] = 4;
1760
buf[2] = ELEMENT_TYPE_VOID;
1761
buf[3] = ELEMENT_TYPE_STRING;
1762
buf[4] = ELEMENT_TYPE_VALUETYPE;
1763
len += encode_int( token, buf + 5 );
1764
buf[len++] = ELEMENT_TYPE_U4;
1765
buf[len++] = ELEMENT_TYPE_STRING;
1766
1767
return len;
1768
}
1769
1770
static UINT make_contract_value( const attr_t *attr, BYTE *buf )
1771
{
1772
const expr_t *expr = attr->u.pval;
1773
const type_t *contract = expr->u.var->declspec.type;
1774
char *name = format_namespace( contract->namespace, "", ".", contract->name, NULL );
1775
UINT version = expr->ref->u.integer.value, len = strlen( name );
1776
1777
buf[0] = 1;
1778
buf[1] = 0;
1779
buf[2] = len;
1780
memcpy( buf + 3, name, len );
1781
len += 3;
1782
memcpy( buf + len, &version, sizeof(version) );
1783
len += sizeof(version);
1784
buf[len++] = 0;
1785
buf[len++] = 0;
1786
1787
free( name );
1788
return len;
1789
}
1790
1791
static UINT make_version_value( const attr_t *attr, BYTE *buf )
1792
{
1793
const version_t *version;
1794
UINT value;
1795
1796
if (attr && (version = attr->u.pval)) value = (version->major << 16) | version->minor;
1797
else value = 1;
1798
1799
buf[0] = 1;
1800
buf[1] = 0;
1801
memcpy( buf + 2, &value, sizeof(value) );
1802
buf[6] = buf[7] = 0;
1803
return 8;
1804
}
1805
1806
static attr_t *get_attr( const attr_list_t *list, enum attr_type attr_type )
1807
{
1808
attr_t *attr;
1809
if (list) LIST_FOR_EACH_ENTRY( attr, list, attr_t, entry )
1810
{
1811
if (attr->type == attr_type ) return attr;
1812
}
1813
return NULL;
1814
}
1815
1816
static void add_contract_attr_step1( const type_t *type )
1817
{
1818
UINT assemblyref, scope, typeref, typeref_type, class, sig_size;
1819
BYTE sig[32];
1820
attr_t *attr;
1821
1822
if (!(attr = get_attr( type->attrs, ATTR_CONTRACT ))) return;
1823
1824
add_assemblyref_row( 0x200, 0, add_string("windowscontracts") );
1825
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
1826
1827
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
1828
typeref_type = add_typeref_row( scope, add_string("Type"), add_string("System") );
1829
1830
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
1831
typeref = add_typeref_row( scope, add_string("ContractVersionAttribute"), add_string("Windows.Foundation.Metadata") );
1832
1833
class = memberref_parent( TABLE_TYPEREF, typeref );
1834
sig_size = make_member_sig( typedef_or_ref(TABLE_TYPEREF, typeref_type), sig );
1835
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
1836
}
1837
1838
static void add_contract_attr_step2( const type_t *type )
1839
{
1840
UINT parent, attr_type, value_size;
1841
BYTE value[MAX_NAME + sizeof(UINT) + 5];
1842
const attr_t *attr;
1843
1844
if (!(attr = get_attr( type->attrs, ATTR_CONTRACT ))) return;
1845
1846
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
1847
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
1848
value_size = make_contract_value( attr, value );
1849
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
1850
}
1851
1852
static void add_version_attr_step1( const type_t *type )
1853
{
1854
static const BYTE sig[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4 };
1855
UINT assemblyref, scope, typeref, class;
1856
attr_t *attr;
1857
1858
if (!(attr = get_attr( type->attrs, ATTR_VERSION )) && is_attr( type->attrs, ATTR_CONTRACT )) return;
1859
1860
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
1861
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
1862
1863
typeref = add_typeref_row( scope, add_string("VersionAttribute"), add_string("Windows.Foundation.Metadata") );
1864
class = memberref_parent( TABLE_TYPEREF, typeref );
1865
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
1866
}
1867
1868
static void add_version_attr_step2( const type_t *type )
1869
{
1870
UINT parent, attr_type, value_size;
1871
BYTE value[8];
1872
const attr_t *attr;
1873
1874
if (!(attr = get_attr( type->attrs, ATTR_VERSION )) && is_attr( type->attrs, ATTR_CONTRACT )) return;
1875
1876
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
1877
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
1878
value_size = make_version_value( attr, value );
1879
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
1880
}
1881
1882
static void add_flags_attr_step1( const type_t *type )
1883
{
1884
static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID };
1885
UINT scope, typeref, class;
1886
attr_t *attr;
1887
1888
if (!(attr = get_attr( type->attrs, ATTR_FLAGS ))) return;
1889
1890
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
1891
typeref = add_typeref_row( scope, add_string("FlagsAttribute"), add_string("System") );
1892
class = memberref_parent( TABLE_TYPEREF, typeref );
1893
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
1894
}
1895
1896
static void add_flags_attr_step2( const type_t *type )
1897
{
1898
static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 };
1899
UINT parent, attr_type;
1900
const attr_t *attr;
1901
1902
if (!(attr = get_attr( type->attrs, ATTR_FLAGS ))) return;
1903
1904
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
1905
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
1906
add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) );
1907
}
1908
1909
static void add_enum_type_step1( type_t *type )
1910
{
1911
UINT name, namespace, scope, typeref;
1912
1913
name = add_name( type, &namespace );
1914
1915
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
1916
typeref = add_typeref_row( scope, add_string("Enum"), add_string("System") );
1917
type->md.extends = typedef_or_ref( TABLE_TYPEREF, typeref );
1918
type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace );
1919
1920
add_version_attr_step1( type );
1921
add_contract_attr_step1( type );
1922
add_flags_attr_step1( type );
1923
}
1924
1925
static void add_enum_type_step2( type_t *type )
1926
{
1927
BYTE sig_value[] = { SIG_TYPE_FIELD, ELEMENT_TYPE_I4 };
1928
UINT name, namespace, field, parent, sig_size;
1929
BYTE sig_field[32];
1930
const var_t *var;
1931
1932
if (is_attr( type->attrs, ATTR_FLAGS )) sig_value[1] = ELEMENT_TYPE_U4;
1933
1934
name = add_name( type, &namespace );
1935
1936
field = add_field_row( FIELD_ATTR_PRIVATE | FIELD_ATTR_SPECIALNAME | FIELD_ATTR_RTSPECIALNAME,
1937
add_string("value__"), add_blob(sig_value, sizeof(sig_value)) );
1938
1939
type->md.def = add_typedef_row( TYPE_ATTR_PUBLIC | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN, name, namespace,
1940
type->md.extends, field, 1 );
1941
1942
sig_size = make_field_value_sig( typedef_or_ref(TABLE_TYPEREF, type->md.ref), sig_field );
1943
1944
LIST_FOR_EACH_ENTRY( var, type_enum_get_values(type), const var_t, entry )
1945
{
1946
int val = var->eval->u.integer.value;
1947
1948
field = add_field_row( FIELD_ATTR_PUBLIC | FIELD_ATTR_LITERAL | FIELD_ATTR_STATIC | FIELD_ATTR_HASDEFAULT,
1949
add_string(var->name), add_blob(sig_field, sig_size) );
1950
parent = has_constant( TABLE_FIELD, field );
1951
add_constant_row( sig_value[1], parent, add_blob((const BYTE *)&val, sizeof(val)) );
1952
}
1953
1954
add_version_attr_step2( type );
1955
add_contract_attr_step2( type );
1956
add_flags_attr_step2( type );
1957
}
1958
1959
static void add_struct_type_step1( type_t *type )
1960
{
1961
UINT name, namespace, scope, typeref;
1962
const var_t *var;
1963
1964
name = add_name( type, &namespace );
1965
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
1966
1967
LIST_FOR_EACH_ENTRY( var, type_struct_get_fields(type), const var_t, entry )
1968
{
1969
type_t *field_type = var->declspec.type;
1970
if (field_type->name && !strcmp( field_type->name, "GUID" ))
1971
field_type->md.ref = add_typeref_row( scope, add_string("Guid"), add_string("System") );
1972
}
1973
1974
typeref = add_typeref_row( scope, add_string("ValueType"), add_string("System") );
1975
type->md.extends = typedef_or_ref( TABLE_TYPEREF, typeref );
1976
type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace );
1977
1978
add_contract_attr_step1( type );
1979
}
1980
1981
static void add_struct_type_step2( type_t *type )
1982
{
1983
UINT name, namespace, field, flags, sig_size, first_field = 0;
1984
const var_t *var;
1985
BYTE sig[32];
1986
1987
name = add_name( type, &namespace );
1988
1989
LIST_FOR_EACH_ENTRY( var, type_struct_get_fields(type), const var_t, entry )
1990
{
1991
sig_size = make_struct_field_sig( var, sig );
1992
field = add_field_row( FIELD_ATTR_PUBLIC, add_string(var->name), add_blob(sig, sig_size) );
1993
if (!first_field) first_field = field;
1994
}
1995
1996
flags = TYPE_ATTR_PUBLIC | TYPE_ATTR_SEQUENTIALLAYOUT | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN;
1997
type->md.def = add_typedef_row( flags, name, namespace, type->md.extends, first_field, 0 );
1998
1999
add_contract_attr_step2( type );
2000
}
2001
2002
static void add_uuid_attr_step1( const type_t *type )
2003
{
2004
static const BYTE sig[] =
2005
{ SIG_TYPE_HASTHIS, 11, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4, ELEMENT_TYPE_U2, ELEMENT_TYPE_U2,
2006
ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1,
2007
ELEMENT_TYPE_U1, ELEMENT_TYPE_U1 };
2008
UINT assemblyref, scope, typeref, class;
2009
attr_t *attr;
2010
2011
if (!(attr = get_attr( type->attrs, ATTR_UUID ))) return;
2012
2013
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2014
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2015
typeref = add_typeref_row( scope, add_string("GuidAttribute"), add_string("Windows.Foundation.Metadata") );
2016
2017
class = memberref_parent( TABLE_TYPEREF, typeref );
2018
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
2019
}
2020
2021
static void add_uuid_attr_step2( const type_t *type )
2022
{
2023
const struct uuid *uuid;
2024
BYTE value[sizeof(*uuid) + 4] = { 0x01 };
2025
UINT parent, attr_type;
2026
const attr_t *attr;
2027
2028
if (!(attr = get_attr( type->attrs, ATTR_UUID ))) return;
2029
2030
uuid = attr->u.pval;
2031
memcpy( value + 2, uuid, sizeof(*uuid) );
2032
2033
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
2034
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2035
add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) );
2036
}
2037
2038
static UINT make_exclusiveto_value( const attr_t *attr, BYTE *buf )
2039
{
2040
const type_t *type = attr->u.pval;
2041
char *name = format_namespace( type->namespace, "", ".", type->name, NULL );
2042
UINT len = strlen( name );
2043
2044
buf[0] = 1;
2045
buf[1] = 0;
2046
buf[2] = len;
2047
memcpy( buf + 3, name, len );
2048
len += 3;
2049
buf[len++] = 0;
2050
buf[len++] = 0;
2051
2052
free( name );
2053
return len;
2054
}
2055
2056
static void add_exclusiveto_attr_step1( const type_t *type )
2057
{
2058
UINT assemblyref, scope, typeref, typeref_type, class, sig_size;
2059
BYTE sig[32];
2060
attr_t *attr;
2061
2062
if (!(attr = get_attr( type->attrs, ATTR_EXCLUSIVETO ))) return;
2063
2064
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
2065
typeref_type = add_typeref_row( scope, add_string("Type"), add_string("System") );
2066
2067
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2068
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2069
typeref = add_typeref_row( scope, add_string("ExclusiveToAttribute"), add_string("Windows.Foundation.Metadata") );
2070
2071
class = memberref_parent( TABLE_TYPEREF, typeref );
2072
sig_size = make_member_sig2( ELEMENT_TYPE_CLASS, typedef_or_ref(TABLE_TYPEREF, typeref_type), sig );
2073
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
2074
}
2075
2076
static void add_exclusiveto_attr_step2( const type_t *type )
2077
{
2078
UINT parent, attr_type, value_size;
2079
BYTE value[MAX_NAME + 5];
2080
const attr_t *attr;
2081
2082
if (!(attr = get_attr( type->attrs, ATTR_EXCLUSIVETO ))) return;
2083
2084
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
2085
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2086
value_size = make_exclusiveto_value( attr, value );
2087
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2088
}
2089
2090
static UINT make_overload_value( const char *name, BYTE *buf )
2091
{
2092
UINT len = strlen( name );
2093
2094
buf[0] = 1;
2095
buf[1] = 0;
2096
buf[2] = len;
2097
memcpy( buf + 3, name, len );
2098
len += 3;
2099
buf[len++] = 0;
2100
buf[len++] = 0;
2101
2102
return len;
2103
}
2104
2105
static void add_overload_attr_step1( const var_t *method )
2106
{
2107
static const BYTE sig[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING };
2108
UINT assemblyref, scope, typeref, class;
2109
attr_t *attr;
2110
2111
if (!(attr = get_attr( method->attrs, ATTR_OVERLOAD ))) return;
2112
2113
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2114
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2115
typeref = add_typeref_row( scope, add_string("OverloadAttribute"), add_string("Windows.Foundation.Metadata") );
2116
2117
class = memberref_parent( TABLE_TYPEREF, typeref );
2118
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
2119
}
2120
2121
static void add_overload_attr_step2( const var_t *method )
2122
{
2123
const type_t *type = method->declspec.type;
2124
UINT parent, attr_type, value_size;
2125
BYTE value[MAX_NAME + 5];
2126
const attr_t *attr;
2127
2128
if (!(attr = get_attr( method->attrs, ATTR_OVERLOAD ))) return;
2129
2130
parent = has_customattribute( TABLE_METHODDEF, type->md.def );
2131
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2132
value_size = make_overload_value( method->name, value );
2133
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2134
}
2135
2136
static void add_default_overload_attr_step1( const var_t *method )
2137
{
2138
static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID };
2139
UINT assemblyref, scope, typeref, class;
2140
attr_t *attr;
2141
2142
if (!(attr = get_attr( method->attrs, ATTR_DEFAULT_OVERLOAD )) || !is_attr( method->attrs, ATTR_OVERLOAD )) return;
2143
2144
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2145
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2146
typeref = add_typeref_row( scope, add_string("DefaultOverloadAttribute"), add_string("Windows.Foundation.Metadata") );
2147
2148
class = memberref_parent( TABLE_TYPEREF, typeref );
2149
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
2150
}
2151
2152
static void add_default_overload_attr_step2( const var_t *method )
2153
{
2154
static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 };
2155
const type_t *type = method->declspec.type;
2156
UINT parent, attr_type;
2157
const attr_t *attr;
2158
2159
if (!(attr = get_attr( method->attrs, ATTR_DEFAULT_OVERLOAD )) || !is_attr( method->attrs, ATTR_OVERLOAD )) return;
2160
2161
parent = has_customattribute( TABLE_METHODDEF, type->md.def );
2162
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2163
add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) );
2164
}
2165
2166
static UINT make_deprecated_value( const attr_t *attr, BYTE **ret_buf )
2167
{
2168
static const BYTE zero[] = { 0x00, 0x00, 0x00, 0x00 }, one[] = { 0x01, 0x00, 0x00, 0x00 };
2169
const expr_t *expr = attr->u.pval;
2170
const type_t *type = expr->ext2->u.var->declspec.type;
2171
const char *text = expr->ref->u.sval;
2172
const char *kind = expr->u.ext->u.sval;
2173
BYTE encoded[4];
2174
UINT len, version, len_text = strlen( text ), len_encoded = encode_int( len_text, encoded );
2175
BYTE *buf = xmalloc( 2 + len_encoded + len_text + 6 + MAX_NAME + 5 );
2176
char *contract;
2177
2178
buf[0] = 1;
2179
buf[1] = 0;
2180
memcpy( buf + 2, encoded, len_encoded );
2181
len = 2 + len_encoded;
2182
memcpy( buf + len, text, len_text );
2183
len += len_text;
2184
if (!strcmp( kind, "remove" )) memcpy( buf + len, one, sizeof(one) );
2185
else memcpy( buf + len, zero, sizeof(zero) );
2186
len += 4;
2187
2188
version = expr->ext2->ref->u.integer.value;
2189
memcpy( buf + len, &version, sizeof(version) );
2190
len += sizeof(version);
2191
2192
contract = format_namespace( type->namespace, "", ".", type->name, NULL );
2193
len_text = strlen( contract );
2194
buf[len++] = len_text;
2195
memcpy( buf + len, contract, len_text );
2196
free( contract );
2197
len += len_text;
2198
buf[len++] = 0;
2199
buf[len++] = 0;
2200
2201
*ret_buf = buf;
2202
return len;
2203
}
2204
2205
static void add_deprecated_attr_step1( const var_t *method )
2206
{
2207
UINT assemblyref, scope, typeref_type, typeref, class, sig_size;
2208
BYTE sig[32];
2209
attr_t *attr;
2210
2211
if (!(attr = get_attr( method->attrs, ATTR_DEPRECATED ))) return;
2212
2213
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2214
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2215
typeref_type = add_typeref_row( scope, add_string("DeprecationType"), add_string("Windows.Foundation.Metadata") );
2216
typeref = add_typeref_row( scope, add_string("DeprecatedAttribute"), add_string("Windows.Foundation.Metadata") );
2217
2218
sig_size = make_deprecated_sig( typedef_or_ref(TABLE_TYPEREF, typeref_type), sig );
2219
class = memberref_parent( TABLE_TYPEREF, typeref );
2220
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
2221
}
2222
2223
static void add_deprecated_attr_step2( const var_t *method )
2224
{
2225
const type_t *type = method->declspec.type;
2226
UINT parent, attr_type, value_size;
2227
BYTE *value;
2228
const attr_t *attr;
2229
2230
if (!(attr = get_attr( method->attrs, ATTR_DEPRECATED ))) return;
2231
2232
parent = has_customattribute( TABLE_METHODDEF, type->md.def );
2233
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2234
value_size = make_deprecated_value( attr, &value );
2235
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2236
free( value );
2237
}
2238
2239
static void add_method_params_step1( var_list_t *arg_list )
2240
{
2241
var_t *arg;
2242
2243
if (!arg_list) return;
2244
2245
LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry )
2246
{
2247
type_t *type = arg->declspec.type;
2248
2249
if (is_size_param( arg, arg_list )) continue;
2250
if (type_get_type( type ) == TYPE_POINTER) type = type_pointer_get_ref_type( type );
2251
if (type->name && !strcmp( type->name, "EventRegistrationToken" ))
2252
{
2253
UINT assemblyref, scope;
2254
2255
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2256
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2257
type = type_get_real_type( type );
2258
type->md.ref = add_typeref_row( scope, add_string("EventRegistrationToken"), add_string("Windows.Foundation") );
2259
}
2260
}
2261
}
2262
2263
static void add_runtimeclass_type_step1( type_t * );
2264
2265
static void add_interface_type_step1( type_t *type )
2266
{
2267
const statement_t *stmt;
2268
UINT name, namespace;
2269
type_t *class;
2270
2271
name = add_name( type, &namespace );
2272
2273
type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace );
2274
2275
add_exclusiveto_attr_step1( type );
2276
2277
if ((class = type->details.iface->runtime_class)) add_runtimeclass_type_step1( class );
2278
2279
add_contract_attr_step1( type );
2280
add_uuid_attr_step1( type );
2281
2282
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(type) )
2283
{
2284
const var_t *method = stmt->u.var;
2285
2286
add_method_params_step1( type_function_get_args(method->declspec.type) );
2287
2288
add_overload_attr_step1( method );
2289
add_default_overload_attr_step1( method );
2290
add_deprecated_attr_step1( method );
2291
}
2292
}
2293
2294
static UINT get_param_attrs( const var_t *arg )
2295
{
2296
UINT attrs = 0;
2297
2298
if (is_attr( arg->attrs, ATTR_IN )) attrs |= PARAM_ATTR_IN;
2299
if (is_attr( arg->attrs, ATTR_OUT )) attrs |= PARAM_ATTR_OUT;
2300
if (is_attr( arg->attrs, ATTR_OPTIONAL )) attrs |= PARAM_ATTR_OPTIONAL;
2301
2302
return attrs ? attrs : PARAM_ATTR_IN;
2303
}
2304
2305
static UINT add_method_params_step2( var_list_t *arg_list )
2306
{
2307
UINT first = 0, row, seq = 1;
2308
var_t *arg;
2309
2310
if (!arg_list) return 0;
2311
2312
LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry )
2313
{
2314
if (is_retval( arg ))
2315
{
2316
first = add_param_row( 0, 0, add_string(arg->name) );
2317
break;
2318
}
2319
}
2320
2321
LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry )
2322
{
2323
if (is_size_param( arg, arg_list) || is_retval( arg )) continue;
2324
row = add_param_row( get_param_attrs(arg), seq++, add_string(arg->name) );
2325
if (!first) first = row;
2326
}
2327
2328
return first;
2329
}
2330
2331
static char *get_method_name( const var_t *method )
2332
{
2333
const char *overload;
2334
2335
if (is_attr( method->attrs, ATTR_PROPGET )) return strmake( "get_%s", method->name );
2336
else if (is_attr( method->attrs, ATTR_PROPPUT )) return strmake( "put_%s", method->name );
2337
else if (is_attr( method->attrs, ATTR_EVENTADD )) return strmake( "add_%s", method->name );
2338
else if (is_attr( method->attrs, ATTR_EVENTREMOVE )) return strmake( "remove_%s", method->name );
2339
2340
if ((overload = get_attrp( method->attrs, ATTR_OVERLOAD ))) return strmake( "%s", overload );
2341
return strmake( "%s", method->name );
2342
}
2343
2344
static BOOL is_special_method( const var_t *method )
2345
{
2346
if (is_attr( method->attrs, ATTR_PROPGET ) || is_attr( method->attrs, ATTR_PROPPUT ) ||
2347
is_attr( method->attrs, ATTR_EVENTADD ) || is_attr( method->attrs, ATTR_EVENTREMOVE )) return TRUE;
2348
return FALSE;
2349
}
2350
2351
static BOOL is_static_iface( const type_t *class, const type_t *iface )
2352
{
2353
const attr_t *attr;
2354
2355
if (!class || !class->attrs) return FALSE;
2356
2357
LIST_FOR_EACH_ENTRY( attr, class->attrs, const attr_t, entry )
2358
{
2359
const expr_t *value = attr->u.pval;
2360
2361
if (attr->type != ATTR_STATIC) continue;
2362
if (value->u.var->declspec.type == iface) return TRUE;
2363
}
2364
2365
return FALSE;
2366
}
2367
2368
static UINT get_method_attrs( const type_t *class, const type_t *iface, const var_t *method, UINT *flags )
2369
{
2370
UINT attrs = METHOD_ATTR_PUBLIC | METHOD_ATTR_HIDEBYSIG;
2371
2372
if (!class)
2373
{
2374
*flags = 0;
2375
attrs |= METHOD_ATTR_ABSTRACT | METHOD_ATTR_VIRTUAL | METHOD_ATTR_NEWSLOT;
2376
}
2377
else
2378
{
2379
*flags = METHOD_IMPL_RUNTIME;
2380
if (is_static_iface( class, iface )) attrs |= METHOD_ATTR_STATIC;
2381
else attrs |= METHOD_ATTR_VIRTUAL | METHOD_ATTR_NEWSLOT | METHOD_ATTR_FINAL;
2382
}
2383
2384
if (is_special_method( method )) attrs |= METHOD_ATTR_SPECIALNAME;
2385
return attrs;
2386
}
2387
2388
static void add_propget_method( const type_t *class, const type_t *iface, const var_t *method )
2389
{
2390
UINT sig_size, property, paramlist, flags, attrs = get_method_attrs( class, iface, method, &flags );
2391
char *name = get_method_name( method );
2392
type_t *type = method->declspec.type;
2393
BYTE sig[256];
2394
2395
if (class) property = type->md.class_property;
2396
else property = type->md.iface_property;
2397
2398
paramlist = add_method_params_step2( type_function_get_args(type) );
2399
sig_size = make_method_sig( method, sig, is_static_iface(class, iface) );
2400
2401
type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist );
2402
add_methodsemantics_row( METHOD_SEM_GETTER, type->md.def, has_semantics(TABLE_PROPERTY, property) );
2403
free( name );
2404
}
2405
2406
static const var_t *find_propget_method( const type_t *iface, const char *name )
2407
{
2408
const statement_t *stmt;
2409
2410
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
2411
{
2412
const var_t *method = stmt->u.var;
2413
if (is_attr( method->attrs, ATTR_PROPGET ) && !strcmp( method->name, name )) return method;
2414
}
2415
return NULL;
2416
}
2417
2418
static void add_propput_method( const type_t *class, const type_t *iface, const var_t *method )
2419
{
2420
const var_t *propget = find_propget_method( iface, method->name );
2421
UINT sig_size, paramlist, property, flags, attrs = get_method_attrs( class, iface, method, &flags );
2422
char *name = get_method_name( method );
2423
type_t *type = method->declspec.type;
2424
BYTE sig[256];
2425
2426
paramlist = add_method_params_step2( type_function_get_args(method->declspec.type) );
2427
sig_size = make_method_sig( method, sig, is_static_iface(class, iface) );
2428
2429
type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist );
2430
free( name );
2431
2432
/* add propget method first if not already added */
2433
if (class)
2434
{
2435
if (!propget->declspec.type->md.class_property) add_propget_method( class, iface, propget );
2436
property = type->md.class_property = propget->declspec.type->md.class_property;
2437
}
2438
else
2439
{
2440
if (!propget->declspec.type->md.iface_property) add_propget_method( class, iface, propget );
2441
property = type->md.iface_property = propget->declspec.type->md.iface_property;
2442
}
2443
2444
add_methodsemantics_row( METHOD_SEM_SETTER, type->md.def, has_semantics(TABLE_PROPERTY, property) );
2445
}
2446
2447
static void add_eventadd_method( const type_t *class, const type_t *iface, const var_t *method )
2448
{
2449
UINT event, sig_size, paramlist, flags, attrs = get_method_attrs( class, iface, method, &flags );
2450
char *name = get_method_name( method );
2451
type_t *type = method->declspec.type;
2452
BYTE sig[256];
2453
2454
if (class) event = type->md.class_event;
2455
else event = type->md.iface_event;
2456
2457
paramlist = add_method_params_step2( type_function_get_args(type) );
2458
sig_size = make_method_sig( method, sig, is_static_iface(class, iface) );
2459
2460
type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist );
2461
free( name );
2462
2463
add_methodsemantics_row( METHOD_SEM_ADDON, type->md.def, has_semantics(TABLE_EVENT, event) );
2464
}
2465
2466
static const var_t *find_eventadd_method( const type_t *iface, const char *name )
2467
{
2468
const statement_t *stmt;
2469
2470
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
2471
{
2472
const var_t *method = stmt->u.var;
2473
if (is_attr( method->attrs, ATTR_EVENTADD ) && !strcmp( method->name, name )) return method;
2474
}
2475
return NULL;
2476
}
2477
2478
static void add_eventremove_method( const type_t *class, const type_t *iface, const var_t *method )
2479
{
2480
const var_t *eventadd = find_eventadd_method( iface, method->name );
2481
UINT event, sig_size, paramlist, flags, attrs = get_method_attrs( class, iface, method, &flags );
2482
char *name = get_method_name( method );
2483
type_t *type = method->declspec.type;
2484
BYTE sig[256];
2485
2486
paramlist = add_method_params_step2( type_function_get_args(type) );
2487
sig_size = make_method_sig( method, sig, is_static_iface(class, iface) );
2488
2489
type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist );
2490
free( name );
2491
2492
/* add eventadd method first if not already added */
2493
if (class)
2494
{
2495
if (!eventadd->declspec.type->md.class_event) add_eventadd_method( class, iface, eventadd );
2496
event = type->md.class_event = eventadd->declspec.type->md.class_event;
2497
}
2498
else
2499
{
2500
if (!eventadd->declspec.type->md.iface_event) add_eventadd_method( class, iface, eventadd );
2501
event = type->md.iface_event = eventadd->declspec.type->md.iface_event;
2502
}
2503
2504
add_methodsemantics_row( METHOD_SEM_REMOVEON, type->md.def, has_semantics(TABLE_EVENT, event) );
2505
}
2506
2507
static void add_regular_method( const type_t *class, const type_t *iface, const var_t *method )
2508
{
2509
UINT paramlist, sig_size, flags, attrs = get_method_attrs( class, iface, method, &flags );
2510
char *name = get_method_name( method );
2511
type_t *type = method->declspec.type;
2512
BYTE sig[256];
2513
2514
paramlist = add_method_params_step2( type_function_get_args(type) );
2515
sig_size = make_method_sig( method, sig, is_static_iface(class, iface) );
2516
2517
type->md.def = add_methoddef_row( flags, attrs, add_string(name), add_blob(sig, sig_size), paramlist );
2518
free( name );
2519
}
2520
2521
static void add_property( type_t *class, type_t *iface, const var_t *method )
2522
{
2523
UINT sig_size;
2524
type_t *type = method->declspec.type;
2525
BYTE sig[256];
2526
2527
if (!is_attr( method->attrs, ATTR_PROPGET )) return;
2528
2529
sig_size = make_property_sig( method, sig, is_static_iface(class, iface) );
2530
if (class)
2531
{
2532
type->md.class_property = add_property_row( 0, add_string(method->name), add_blob(sig, sig_size) );
2533
if (!class->md.propertymap) class->md.propertymap = add_propertymap_row( class->md.def, type->md.class_property );
2534
}
2535
else
2536
{
2537
type->md.iface_property = add_property_row( 0, add_string(method->name), add_blob(sig, sig_size) );
2538
if (!iface->md.propertymap) iface->md.propertymap = add_propertymap_row( iface->md.def, type->md.iface_property );
2539
}
2540
}
2541
2542
static void add_event( type_t *class, type_t *iface, const var_t *method )
2543
{
2544
UINT event_type = 0;
2545
type_t *type = method->declspec.type;
2546
var_t *arg;
2547
2548
if (!is_attr( method->attrs, ATTR_EVENTADD )) return;
2549
2550
LIST_FOR_EACH_ENTRY( arg, type_function_get_args(type), var_t, entry )
2551
{
2552
type_t *arg_type = arg->declspec.type;
2553
2554
arg_type = type_pointer_get_ref_type( arg_type ); /* first arg must be a delegate pointer */
2555
event_type = typedef_or_ref( TABLE_TYPEREF, arg_type->md.ref );
2556
break;
2557
}
2558
2559
if (class)
2560
{
2561
type->md.class_event = add_event_row( 0, add_string(method->name), event_type );
2562
if (!class->md.eventmap) class->md.eventmap = add_eventmap_row( class->md.def, type->md.class_event );
2563
}
2564
else
2565
{
2566
type->md.iface_event = add_event_row( 0, add_string(method->name), event_type );
2567
if (!iface->md.eventmap) iface->md.eventmap = add_eventmap_row( iface->md.def, type->md.iface_event );
2568
}
2569
}
2570
2571
static void add_method( type_t *class, type_t *iface, const var_t *method )
2572
{
2573
if (is_attr( method->attrs, ATTR_PROPGET )) add_propget_method( class, iface, method );
2574
else if (is_attr( method->attrs, ATTR_PROPPUT )) add_propput_method( class, iface, method );
2575
else if (is_attr( method->attrs, ATTR_EVENTADD )) add_eventadd_method( class, iface, method );
2576
else if (is_attr( method->attrs, ATTR_EVENTREMOVE )) add_eventremove_method( class, iface, method );
2577
else add_regular_method( class, iface, method );
2578
}
2579
2580
static void add_runtimeclass_type_step2( type_t *type );
2581
2582
static void add_interface_type_step2( type_t *type )
2583
{
2584
UINT name, namespace, interface, flags = TYPE_ATTR_INTERFACE | TYPE_ATTR_ABSTRACT | TYPE_ATTR_UNKNOWN;
2585
const typeref_list_t *require_list = type_iface_get_requires( type );
2586
const typeref_t *require;
2587
const statement_t *stmt;
2588
type_t *class;
2589
2590
name = add_name( type, &namespace );
2591
2592
if (!is_attr( type->attrs, ATTR_EXCLUSIVETO )) flags |= TYPE_ATTR_PUBLIC;
2593
type->md.def = add_typedef_row( flags, name, namespace, 0, 0, 0 );
2594
2595
if (require_list) LIST_FOR_EACH_ENTRY( require, require_list, typeref_t, entry )
2596
{
2597
interface = typedef_or_ref( TABLE_TYPEREF, require->type->md.ref );
2598
add_interfaceimpl_row( type->md.def, interface );
2599
}
2600
2601
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(type) )
2602
{
2603
const var_t *method = stmt->u.var;
2604
2605
add_property( NULL, type, method );
2606
add_event( NULL, type, method );
2607
add_method( NULL, type, method );
2608
2609
add_deprecated_attr_step2( method );
2610
add_default_overload_attr_step2( method );
2611
add_overload_attr_step2( method );
2612
}
2613
2614
if ((class = type->details.iface->runtime_class)) add_runtimeclass_type_step2( class );
2615
2616
add_contract_attr_step2( type );
2617
add_uuid_attr_step2( type );
2618
add_exclusiveto_attr_step2( type );
2619
}
2620
2621
static void add_contractversion_attr_step1( const type_t *type )
2622
{
2623
static const BYTE sig[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4 };
2624
UINT assemblyref, scope, typeref, class;
2625
attr_t *attr;
2626
2627
if (!(attr = get_attr( type->attrs, ATTR_CONTRACTVERSION ))) return;
2628
2629
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2630
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2631
typeref = add_typeref_row( scope, add_string("ContractVersionAttribute"), add_string("Windows.Foundation.Metadata") );
2632
2633
class = memberref_parent( TABLE_TYPEREF, typeref );
2634
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
2635
}
2636
2637
static void add_contractversion_attr_step2( const type_t *type )
2638
{
2639
UINT parent, attr_type, value_size;
2640
BYTE value[8];
2641
const attr_t *attr;
2642
2643
if (!(attr = get_attr( type->attrs, ATTR_CONTRACTVERSION ))) return;
2644
2645
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
2646
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2647
value_size = make_version_value( attr, value );
2648
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2649
}
2650
2651
static void add_apicontract_attr_step1( const type_t *type )
2652
{
2653
static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID };
2654
UINT assemblyref, scope, typeref, class;
2655
attr_t *attr;
2656
2657
if (!(attr = get_attr( type->attrs, ATTR_APICONTRACT ))) return;
2658
2659
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2660
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2661
typeref = add_typeref_row( scope, add_string("ApiContractAttribute"), add_string("Windows.Foundation.Metadata") );
2662
2663
class = memberref_parent( TABLE_TYPEREF, typeref );
2664
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
2665
}
2666
2667
static void add_apicontract_attr_step2( const type_t *type )
2668
{
2669
static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 };
2670
UINT parent, attr_type;
2671
const attr_t *attr;
2672
2673
if (!(attr = get_attr( type->attrs, ATTR_APICONTRACT ))) return;
2674
2675
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
2676
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2677
add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) );
2678
}
2679
2680
static void add_apicontract_type_step1( type_t *type )
2681
{
2682
UINT name, namespace, scope, typeref;
2683
2684
name = add_name( type, &namespace );
2685
2686
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
2687
typeref = add_typeref_row( scope, add_string("ValueType"), add_string("System") );
2688
type->md.extends = typedef_or_ref( TABLE_TYPEREF, typeref );
2689
type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace );
2690
2691
add_contractversion_attr_step1( type );
2692
add_apicontract_attr_step1( type );
2693
}
2694
2695
static void add_apicontract_type_step2( type_t *type )
2696
{
2697
UINT name, namespace, flags = TYPE_ATTR_PUBLIC | TYPE_ATTR_SEQUENTIALLAYOUT | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN;
2698
2699
name = add_name( type, &namespace );
2700
2701
type->md.def = add_typedef_row( flags, name, namespace, type->md.extends, 0, 1 );
2702
2703
add_contractversion_attr_step2( type );
2704
add_apicontract_attr_step2( type );
2705
}
2706
2707
static void add_runtimeclass_type_step1( type_t *type )
2708
{
2709
UINT name, namespace;
2710
2711
if (type->md.ref) return;
2712
2713
name = add_name( type, &namespace );
2714
type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace );
2715
}
2716
2717
static void add_default_attr( UINT interfaceimpl_ref )
2718
{
2719
static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID };
2720
static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 };
2721
UINT assemblyref, scope, typeref, class, memberref, parent, attr_type;
2722
2723
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2724
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2725
typeref = add_typeref_row( scope, add_string("DefaultAttribute"), add_string("Windows.Foundation.Metadata") );
2726
class = memberref_parent( TABLE_TYPEREF, typeref );
2727
memberref = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
2728
2729
parent = has_customattribute( TABLE_INTERFACEIMPL, interfaceimpl_ref );
2730
attr_type = customattribute_type( TABLE_MEMBERREF, memberref );
2731
add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) );
2732
}
2733
2734
static void add_method_impl( const type_t *class, const type_t *iface, const var_t *method )
2735
{
2736
UINT parent, memberref, body, decl, sig_size;
2737
char *name = get_method_name( method );
2738
type_t *type = method->declspec.type;
2739
BYTE sig[256];
2740
2741
parent = memberref_parent( TABLE_TYPEREF, iface->md.ref );
2742
sig_size = make_method_sig( method, sig, FALSE );
2743
2744
memberref = add_memberref_row( parent, add_string(name), add_blob(sig, sig_size) );
2745
free( name );
2746
2747
body = methoddef_or_ref( TABLE_METHODDEF, type->md.def );
2748
decl = methoddef_or_ref( TABLE_MEMBERREF, memberref );
2749
2750
add_methodimpl_row( class->md.def, body, decl );
2751
}
2752
2753
static void add_method_contract_attrs( const type_t *class, const type_t *iface, const type_t *method )
2754
{
2755
UINT parent, attr_type, value_size;
2756
BYTE value[MAX_NAME + sizeof(UINT) + 5];
2757
const attr_t *attr = get_attr( iface->attrs, ATTR_CONTRACT );
2758
2759
parent = has_customattribute( TABLE_METHODDEF, method->md.def );
2760
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2761
value_size = make_contract_value( get_attr(class->attrs, ATTR_CONTRACT), value );
2762
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2763
2764
if (method->md.class_property)
2765
{
2766
parent = has_customattribute( TABLE_PROPERTY, method->md.class_property );
2767
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2768
}
2769
2770
if (method->md.class_event)
2771
{
2772
parent = has_customattribute( TABLE_EVENT, method->md.class_event );
2773
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2774
}
2775
}
2776
2777
static UINT make_static_value( const expr_t *attr, BYTE *buf )
2778
{
2779
const expr_t *contract = attr->ref;
2780
const type_t *type_iface = attr->u.var->declspec.type, *type_contract = contract->u.var->declspec.type;
2781
char *name_iface = format_namespace( type_iface->namespace, "", ".", type_iface->name, NULL );
2782
char *name_contract = format_namespace( type_contract->namespace, "", ".", type_contract->name, NULL );
2783
UINT len_iface = strlen( name_iface ), len_contract = strlen( name_contract );
2784
BYTE *ptr = buf;
2785
2786
ptr[0] = 1;
2787
ptr[1] = 0;
2788
ptr[2] = len_iface;
2789
memcpy( ptr + 3, name_iface, len_iface );
2790
ptr += len_iface + 3;
2791
ptr[0] = ptr[1] = 0;
2792
2793
ptr += 2;
2794
ptr[0] = 1;
2795
ptr[1] = 0;
2796
ptr[2] = len_contract;
2797
memcpy( ptr + 3, name_contract, len_contract );
2798
ptr += len_contract + 3;
2799
ptr[0] = ptr[1] = 0;
2800
2801
free( name_iface );
2802
free( name_contract );
2803
return len_iface + len_contract + 10;
2804
}
2805
2806
static void add_static_attr_step1( const type_t *type )
2807
{
2808
UINT assemblyref, scope, typeref, typeref_type, class, sig_size;
2809
BYTE sig[32];
2810
attr_t *attr;
2811
2812
if (!(attr = get_attr( type->attrs, ATTR_STATIC ))) return;
2813
2814
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2815
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2816
typeref = add_typeref_row( scope, add_string("StaticAttribute"), add_string("Windows.Foundation.Metadata") );
2817
2818
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
2819
typeref_type = add_typeref_row( scope, add_string("Type"), add_string("System") );
2820
2821
class = memberref_parent( TABLE_TYPEREF, typeref );
2822
sig_size = make_member_sig3( typedef_or_ref(TABLE_TYPEREF, typeref_type), sig );
2823
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
2824
}
2825
2826
static void add_static_attr_step2( const type_t *type )
2827
{
2828
const attr_t *attr;
2829
2830
if (type->attrs) LIST_FOR_EACH_ENTRY_REV( attr, type->attrs, const attr_t, entry )
2831
{
2832
UINT parent, attr_type, value_size;
2833
BYTE value[MAX_NAME * 2 + 10];
2834
2835
if (attr->type != ATTR_STATIC) continue;
2836
2837
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
2838
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2839
value_size = make_static_value( attr->u.pval, value );
2840
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2841
}
2842
}
2843
2844
static UINT make_activatable_value( const expr_t *attr, BYTE *buf )
2845
{
2846
char *name_iface = NULL, *name_contract;
2847
const type_t *type_iface, *type_contract;
2848
UINT version, len_iface = 0, len_contract, len_extra = 5;
2849
BYTE *ptr = buf;
2850
2851
if (attr->type == EXPR_MEMBER)
2852
{
2853
type_iface = attr->u.var->declspec.type;
2854
name_iface = format_namespace( type_iface->namespace, "", ".", type_iface->name, NULL );
2855
len_iface = strlen( name_iface );
2856
2857
type_contract = attr->ref->u.var->declspec.type;
2858
version = attr->ref->ref->u.integer.value;
2859
}
2860
else
2861
{
2862
type_contract = attr->u.var->declspec.type;
2863
version = attr->ref->u.integer.value;
2864
}
2865
2866
name_contract = format_namespace( type_contract->namespace, "", ".", type_contract->name, NULL );
2867
len_contract = strlen( name_contract );
2868
2869
if (len_iface)
2870
{
2871
ptr[0] = 1;
2872
ptr[1] = 0;
2873
ptr[2] = len_iface;
2874
memcpy( ptr + 3, name_iface, len_iface );
2875
ptr += len_iface + 3;
2876
ptr[0] = ptr[1] = 0;
2877
ptr += 2;
2878
len_extra += 5;
2879
}
2880
2881
ptr[0] = 1;
2882
ptr[1] = 0;
2883
memcpy( ptr + 2, &version, sizeof(version) );
2884
ptr += sizeof(version) + 2;
2885
2886
ptr[0] = len_contract;
2887
memcpy( ptr + 1, name_contract, len_contract );
2888
ptr += len_contract + 1;
2889
ptr[0] = ptr[1] = 0;
2890
2891
free( name_iface );
2892
free( name_contract );
2893
return len_iface + sizeof(version) + len_contract + len_extra;
2894
}
2895
2896
static void add_activatable_attr_step1( const type_t *type )
2897
{
2898
static const BYTE sig_default[] = { SIG_TYPE_HASTHIS, 2, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4, ELEMENT_TYPE_STRING };
2899
attr_t *attr;
2900
2901
if (type->attrs) LIST_FOR_EACH_ENTRY_REV( attr, type->attrs, attr_t, entry )
2902
{
2903
UINT assemblyref, scope, typeref, typeref_type, class, sig_size;
2904
const expr_t *value = attr->u.pval;
2905
BYTE sig[32];
2906
2907
if (attr->type != ATTR_ACTIVATABLE) continue;
2908
2909
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2910
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2911
typeref = add_typeref_row( scope, add_string("ActivatableAttribute"), add_string("Windows.Foundation.Metadata") );
2912
2913
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
2914
typeref_type = add_typeref_row( scope, add_string("Type"), add_string("System") );
2915
2916
class = memberref_parent( TABLE_TYPEREF, typeref );
2917
2918
if (value->type == EXPR_MEMBER)
2919
sig_size = make_member_sig3( typedef_or_ref(TABLE_TYPEREF, typeref_type), sig );
2920
else
2921
{
2922
memcpy( sig, sig_default, sizeof(sig_default) );
2923
sig_size = sizeof(sig_default);
2924
}
2925
2926
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
2927
}
2928
}
2929
2930
static void add_activatable_attr_step2( const type_t *type )
2931
{
2932
const attr_t *attr;
2933
2934
if (type->attrs) LIST_FOR_EACH_ENTRY_REV( attr, type->attrs, const attr_t, entry )
2935
{
2936
UINT parent, attr_type, value_size;
2937
BYTE value[MAX_NAME * 2 + sizeof(UINT) + 10];
2938
2939
if (attr->type != ATTR_ACTIVATABLE) continue;
2940
2941
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
2942
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
2943
value_size = make_activatable_value( attr->u.pval, value );
2944
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
2945
}
2946
}
2947
2948
static UINT make_threading_value( const attr_t *attr, BYTE *buf )
2949
{
2950
UINT value, model = attr->u.ival;
2951
2952
switch (model)
2953
{
2954
case THREADING_SINGLE:
2955
value = 1;
2956
break;
2957
case THREADING_FREE:
2958
value = 2;
2959
break;
2960
case THREADING_BOTH:
2961
value = 3;
2962
break;
2963
default:
2964
fprintf( stderr, "Unhandled model %u.\n", model );
2965
return 0;
2966
}
2967
2968
buf[0] = 1;
2969
buf[1] = 0;
2970
memcpy( buf + 2, &value, sizeof(value) );
2971
buf[6] = buf[7] = 0;
2972
return 8;
2973
}
2974
2975
static void add_threading_attr_step1( const type_t *type )
2976
{
2977
UINT assemblyref, scope, typeref, typeref_attr, class, sig_size;
2978
BYTE sig[32];
2979
attr_t *attr;
2980
2981
if (!(attr = get_attr( type->attrs, ATTR_THREADING ))) return;
2982
2983
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
2984
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2985
typeref = add_typeref_row( scope, add_string("ThreadingModel"), add_string("Windows.Foundation.Metadata") );
2986
2987
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
2988
typeref_attr = add_typeref_row( scope, add_string("ThreadingAttribute"), add_string("Windows.Foundation.Metadata") );
2989
2990
class = memberref_parent( TABLE_TYPEREF, typeref_attr );
2991
sig_size = make_member_sig2( ELEMENT_TYPE_VALUETYPE, typedef_or_ref(TABLE_TYPEREF, typeref), sig );
2992
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
2993
}
2994
2995
static void add_threading_attr_step2( const type_t *type )
2996
{
2997
UINT parent, attr_type, value_size;
2998
BYTE value[8];
2999
const attr_t *attr;
3000
3001
if (!(attr = get_attr( type->attrs, ATTR_THREADING ))) return;
3002
3003
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
3004
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
3005
value_size = make_threading_value( attr, value );
3006
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
3007
}
3008
3009
static UINT make_marshalingbehavior_value( const attr_t *attr, BYTE *buf )
3010
{
3011
UINT marshaling = attr->u.ival;
3012
3013
buf[0] = 1;
3014
buf[1] = 0;
3015
memcpy( buf + 2, &marshaling, sizeof(marshaling) );
3016
buf[6] = buf[7] = 0;
3017
return 8;
3018
}
3019
3020
static void add_marshalingbehavior_attr_step1( const type_t *type )
3021
{
3022
UINT assemblyref, scope, typeref, typeref_attr, class, sig_size;
3023
BYTE sig[32];
3024
attr_t *attr;
3025
3026
if (!(attr = get_attr( type->attrs, ATTR_MARSHALING_BEHAVIOR ))) return;
3027
3028
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
3029
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
3030
typeref = add_typeref_row( scope, add_string("MarshalingType"), add_string("Windows.Foundation.Metadata") );
3031
3032
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
3033
typeref_attr = add_typeref_row( scope, add_string("MarshalingBehaviorAttribute"), add_string("Windows.Foundation.Metadata") );
3034
3035
class = memberref_parent( TABLE_TYPEREF, typeref_attr );
3036
sig_size = make_member_sig2( ELEMENT_TYPE_VALUETYPE, typedef_or_ref(TABLE_TYPEREF, typeref), sig );
3037
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
3038
}
3039
3040
static void add_marshalingbehavior_attr_step2( const type_t *type )
3041
{
3042
UINT parent, attr_type, value_size;
3043
BYTE value[8];
3044
const attr_t *attr;
3045
3046
if (!(attr = get_attr( type->attrs, ATTR_MARSHALING_BEHAVIOR ))) return;
3047
3048
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
3049
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
3050
value_size = make_marshalingbehavior_value( attr, value );
3051
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
3052
}
3053
3054
static UINT make_composable_value( const expr_t *attr, BYTE *buf )
3055
{
3056
char *name_iface, *name_contract;
3057
const expr_t *contract = attr->ref;
3058
const type_t *type_iface = attr->u.var->declspec.type;
3059
const type_t *type_contract = contract->u.var->declspec.type;
3060
UINT access_type = 1, contract_version = contract->ref->u.integer.value;
3061
UINT len_iface, len_contract;
3062
BYTE *ptr = buf;
3063
3064
name_iface = format_namespace( type_iface->namespace, "", ".", type_iface->name, NULL );
3065
len_iface = strlen( name_iface );
3066
3067
name_contract = format_namespace( type_contract->namespace, "", ".", type_contract->name, NULL );
3068
len_contract = strlen( name_contract );
3069
3070
ptr[0] = 1;
3071
ptr[1] = 0;
3072
ptr[2] = len_iface;
3073
memcpy( ptr + 3, name_iface, len_iface );
3074
ptr += len_iface + 3;
3075
3076
if (is_attr( attr->u.var->attrs, ATTR_PUBLIC)) access_type = 2;
3077
memcpy( ptr, &access_type, sizeof(access_type) );
3078
ptr += sizeof(access_type);
3079
3080
memcpy( ptr, &contract_version, sizeof(contract_version) );
3081
ptr += sizeof(contract_version);
3082
3083
ptr[0] = len_contract;
3084
memcpy( ptr + 1, name_contract, len_contract );
3085
ptr += len_contract + 1;
3086
ptr[0] = ptr[1] = 0;
3087
3088
free( name_iface );
3089
free( name_contract );
3090
return len_iface + sizeof(access_type) + sizeof(contract_version) + len_contract + 6;
3091
}
3092
3093
static void add_composable_attr_step1( const type_t *type )
3094
{
3095
attr_t *attr;
3096
3097
if (type->attrs) LIST_FOR_EACH_ENTRY( attr, type->attrs, attr_t, entry )
3098
{
3099
UINT assemblyref, scope, typeref, typeref_attr, typeref_type, class, sig_size;
3100
BYTE sig[64];
3101
3102
if (attr->type != ATTR_COMPOSABLE) continue;
3103
3104
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
3105
typeref_type = add_typeref_row( scope, add_string("Type"), add_string("System") );
3106
3107
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
3108
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
3109
typeref = add_typeref_row( scope, add_string("CompositionType"), add_string("Windows.Foundation.Metadata") );
3110
typeref_attr = add_typeref_row( scope, add_string("ComposableAttribute"), add_string("Windows.Foundation.Metadata") );
3111
3112
class = memberref_parent( TABLE_TYPEREF, typeref_attr );
3113
sig_size = make_member_sig4( typedef_or_ref(TABLE_TYPEREF, typeref_type), typedef_or_ref(TABLE_TYPEREF, typeref), sig );
3114
attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
3115
}
3116
}
3117
3118
static void add_composable_attr_step2( const type_t *type )
3119
{
3120
const attr_t *attr;
3121
3122
if (type->attrs) LIST_FOR_EACH_ENTRY( attr, type->attrs, const attr_t, entry )
3123
{
3124
UINT parent, attr_type, value_size;
3125
BYTE value[MAX_NAME + sizeof(UINT) * 2 + 6];
3126
3127
if (attr->type != ATTR_COMPOSABLE) continue;
3128
3129
parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
3130
attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
3131
value_size = make_composable_value( attr->u.pval, value );
3132
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
3133
}
3134
}
3135
3136
static void add_member_interfaces( type_t *class )
3137
{
3138
const typeref_list_t *iface_list = type_runtimeclass_get_ifaces( class );
3139
const typeref_t *iface;
3140
3141
if (iface_list) LIST_FOR_EACH_ENTRY( iface, iface_list, typeref_t, entry )
3142
{
3143
UINT interface = typedef_or_ref( TABLE_TYPEREF, iface->type->md.ref );
3144
UINT interfaceimpl_ref = add_interfaceimpl_row( class->md.def, interface );
3145
const statement_t *stmt;
3146
3147
if (is_attr( iface->attrs, ATTR_DEFAULT )) add_default_attr( interfaceimpl_ref );
3148
3149
/* add properties in reverse order like midlrt */
3150
STATEMENTS_FOR_EACH_FUNC_REV( stmt, type_iface_get_stmts(iface->type) )
3151
{
3152
const var_t *method = stmt->u.var;
3153
3154
add_property( class, iface->type, method );
3155
}
3156
3157
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface->type) )
3158
{
3159
const var_t *method = stmt->u.var;
3160
3161
add_event( class, iface->type, method );
3162
add_method( class, iface->type, method );
3163
add_method_impl( class, iface->type, method );
3164
add_method_contract_attrs( class, iface->type, method->declspec.type );
3165
}
3166
}
3167
}
3168
3169
static void add_static_interfaces( type_t *class )
3170
{
3171
const attr_t *attr;
3172
3173
if (class->attrs) LIST_FOR_EACH_ENTRY( attr, class->attrs, const attr_t, entry )
3174
{
3175
const expr_t *value = attr->u.pval;
3176
const statement_t *stmt;
3177
type_t *iface;
3178
3179
if (attr->type != ATTR_STATIC) continue;
3180
3181
iface = value->u.var->declspec.type;
3182
3183
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
3184
{
3185
const var_t *method = stmt->u.var;
3186
3187
add_property( class, iface, method );
3188
add_event( class, iface, method );
3189
add_method( class, iface, method );
3190
add_method_contract_attrs( class, iface, method->declspec.type );
3191
}
3192
}
3193
}
3194
3195
static void add_activation_interfaces( const type_t *class )
3196
{
3197
UINT flags = METHOD_ATTR_PUBLIC | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_SPECIALNAME | METHOD_ATTR_RTSPECIALNAME;
3198
const attr_t *attr, *contract_attr = get_attr( class->attrs, ATTR_CONTRACT );
3199
3200
if (class->attrs) LIST_FOR_EACH_ENTRY_REV( attr, class->attrs, const attr_t, entry )
3201
{
3202
UINT methoddef, parent, attr_type, value_size, paramlist = 0, sig_size;
3203
BYTE value[MAX_NAME + sizeof(UINT) + 5], sig[256];
3204
const expr_t *activatable = attr->u.pval;
3205
const type_t *iface = NULL;
3206
const var_t *method = NULL, *arg;
3207
const statement_t *stmt;
3208
3209
if (attr->type != ATTR_ACTIVATABLE) continue;
3210
3211
/* interface is optional */
3212
if (activatable->type == EXPR_MEMBER) iface = activatable->u.var->declspec.type;
3213
3214
if (iface) STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
3215
{
3216
UINT seq = 1, row;
3217
3218
method = stmt->u.var;
3219
3220
LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry )
3221
{
3222
if (is_retval( arg )) continue;
3223
row = add_param_row( get_param_attrs(arg), seq++, add_string(arg->name) );
3224
if (!paramlist) paramlist = row;
3225
}
3226
break;
3227
}
3228
3229
sig_size = make_activation_sig( method, sig );
3230
methoddef = add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string(".ctor"), add_blob(sig, sig_size), paramlist );
3231
3232
parent = has_customattribute( TABLE_METHODDEF, methoddef );
3233
attr_type = customattribute_type( TABLE_MEMBERREF, contract_attr->md_member );
3234
value_size = make_contract_value( contract_attr, value );
3235
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
3236
}
3237
}
3238
3239
static void add_composition_interfaces( const type_t *class )
3240
{
3241
UINT flags = METHOD_ATTR_FAMILY | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_SPECIALNAME | METHOD_ATTR_RTSPECIALNAME;
3242
const attr_t *attr, *contract_attr = get_attr( class->attrs, ATTR_CONTRACT );
3243
3244
if (class->attrs) LIST_FOR_EACH_ENTRY_REV( attr, class->attrs, const attr_t, entry )
3245
{
3246
UINT methoddef, parent, attr_type, value_size, paramlist = 0, sig_size;
3247
BYTE value[MAX_NAME + sizeof(UINT) + 5], sig[256];
3248
const expr_t *composable = attr->u.pval;
3249
const var_t *method = NULL, *arg;
3250
const statement_t *stmt;
3251
const type_t *iface;
3252
3253
if (attr->type != ATTR_COMPOSABLE) continue;
3254
3255
iface = composable->u.var->declspec.type;
3256
3257
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
3258
{
3259
UINT seq = 1, row, count = 0;
3260
3261
method = stmt->u.var;
3262
3263
LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry ) count++;
3264
3265
if (count > 3) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry )
3266
{
3267
if (--count < 3) break; /* omit last 3 standard composition args */
3268
row = add_param_row( get_param_attrs(arg), seq++, add_string(arg->name) );
3269
if (!paramlist) paramlist = row;
3270
}
3271
break;
3272
}
3273
3274
sig_size = make_composition_sig( method, sig );
3275
methoddef = add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string(".ctor"), add_blob(sig, sig_size), paramlist );
3276
3277
parent = has_customattribute( TABLE_METHODDEF, methoddef );
3278
attr_type = customattribute_type( TABLE_MEMBERREF, contract_attr->md_member );
3279
value_size = make_contract_value( contract_attr, value );
3280
add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
3281
}
3282
}
3283
3284
static void add_constructor_overload( const type_t *type )
3285
{
3286
static const BYTE sig_default[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID };
3287
static const BYTE sig_overload[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING };
3288
UINT name, namespace;
3289
const attr_t *attr;
3290
3291
if (type->attrs) LIST_FOR_EACH_ENTRY_REV( attr, type->attrs, const attr_t, entry )
3292
{
3293
const expr_t *value = attr->u.pval;
3294
3295
if (attr->type == ATTR_COMPOSABLE || (attr->type == ATTR_ACTIVATABLE && value->type == EXPR_MEMBER))
3296
{
3297
UINT assemblyref, scope, typeref_default, typeref_overload, class;
3298
3299
assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
3300
scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
3301
3302
name = add_string( "DefaultOverloadAttribute" );
3303
namespace = add_string( "Windows.Foundation.Metadata" );
3304
typeref_default = add_typeref_row( scope, name, namespace );
3305
3306
class = memberref_parent( TABLE_TYPEREF, typeref_default );
3307
add_memberref_row( class, add_string(".ctor"), add_blob(sig_default, sizeof(sig_default)) );
3308
3309
name = add_string( "OverloadAttribute" );
3310
typeref_overload = add_typeref_row( scope, name, namespace );
3311
3312
class = memberref_parent( TABLE_TYPEREF, typeref_overload );
3313
add_memberref_row( class, add_string(".ctor"), add_blob(sig_overload, sizeof(sig_overload)) );
3314
break;
3315
}
3316
}
3317
}
3318
3319
static void add_runtimeclass_type_step2( type_t *type )
3320
{
3321
const typeref_list_t *iface_list = type_runtimeclass_get_ifaces( type );
3322
UINT name, namespace, scope, extends, typeref, flags;
3323
3324
if (type->md.def) return;
3325
3326
name = add_name( type, &namespace );
3327
3328
add_constructor_overload( type );
3329
3330
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
3331
typeref = add_typeref_row( scope, add_string("Object"), add_string("System") );
3332
extends = typedef_or_ref( TABLE_TYPEREF, typeref );
3333
3334
flags = TYPE_ATTR_PUBLIC | TYPE_ATTR_UNKNOWN;
3335
if (!is_attr( type->attrs, ATTR_COMPOSABLE )) flags |= TYPE_ATTR_SEALED;
3336
if (!iface_list) flags |= TYPE_ATTR_ABSTRACT;
3337
3338
type->md.def = add_typedef_row( flags, name, namespace, extends, 0, 0 );
3339
3340
/* add contract first so activation/composition constructors can inherit it */
3341
add_contract_attr_step1( type );
3342
3343
add_activation_interfaces( type );
3344
add_composition_interfaces( type );
3345
add_member_interfaces( type );
3346
add_static_interfaces( type );
3347
3348
add_composable_attr_step1( type );
3349
add_static_attr_step1( type );
3350
add_activatable_attr_step1( type );
3351
add_threading_attr_step1( type );
3352
add_marshalingbehavior_attr_step1( type );
3353
3354
add_contract_attr_step2( type );
3355
add_composable_attr_step2( type );
3356
add_static_attr_step2( type );
3357
add_activatable_attr_step2( type );
3358
add_threading_attr_step2( type );
3359
add_marshalingbehavior_attr_step2( type );
3360
}
3361
3362
static void add_delegate_type_step1( type_t *type )
3363
{
3364
UINT name, namespace, scope, typeref;
3365
3366
name = add_name( type, &namespace );
3367
3368
scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
3369
typeref = add_typeref_row( scope, add_string("MulticastDelegate"), add_string("System") );
3370
type->md.extends = typedef_or_ref( TABLE_TYPEREF, typeref );
3371
type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace );
3372
3373
add_version_attr_step1( type );
3374
add_contract_attr_step1( type );
3375
add_uuid_attr_step1( type );
3376
}
3377
3378
static void add_delegate_type_step2( type_t *type )
3379
{
3380
static const BYTE sig_ctor[] = { SIG_TYPE_HASTHIS, 2, ELEMENT_TYPE_VOID, ELEMENT_TYPE_OBJECT, ELEMENT_TYPE_I };
3381
UINT name, namespace, methoddef, flags, paramlist;
3382
const type_t *iface = type_delegate_get_iface( type );
3383
const statement_t *stmt;
3384
3385
name = add_name( type, &namespace );
3386
3387
flags = METHOD_ATTR_RTSPECIALNAME | METHOD_ATTR_SPECIALNAME | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_PRIVATE;
3388
methoddef = add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string(".ctor"),
3389
add_blob(sig_ctor, sizeof(sig_ctor)), 0 );
3390
3391
add_param_row( 0, 1, add_string("object") );
3392
add_param_row( 0, 2, add_string("method") );
3393
3394
flags = METHOD_ATTR_SPECIALNAME | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_PUBLIC | METHOD_ATTR_VIRTUAL |
3395
METHOD_ATTR_NEWSLOT;
3396
3397
STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
3398
{
3399
const var_t *method = stmt->u.var;
3400
UINT sig_size;
3401
BYTE sig[256];
3402
3403
sig_size = make_method_sig( method, sig, FALSE );
3404
paramlist = add_method_params_step2( type_function_get_args(method->declspec.type) );
3405
3406
add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string("Invoke"), add_blob(sig, sig_size), paramlist );
3407
break;
3408
}
3409
type->md.def = add_typedef_row( TYPE_ATTR_PUBLIC | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN, name, namespace,
3410
type->md.extends, 0, methoddef );
3411
3412
add_uuid_attr_step2( type );
3413
add_version_attr_step2( type );
3414
add_contract_attr_step2( type );
3415
}
3416
3417
static void build_tables( const statement_list_t *stmt_list )
3418
{
3419
const statement_t *stmt;
3420
3421
/* Adding a type involves two passes: the first creates various references and the second
3422
uses those references to create the remaining rows. */
3423
3424
LIST_FOR_EACH_ENTRY( stmt, stmt_list, const statement_t, entry )
3425
{
3426
type_t *type = stmt->u.type;
3427
3428
if (stmt->type != STMT_TYPE) continue;
3429
3430
switch (type->type_type)
3431
{
3432
case TYPE_ENUM:
3433
add_enum_type_step1( type );
3434
break;
3435
case TYPE_STRUCT:
3436
add_struct_type_step1( type );
3437
break;
3438
case TYPE_INTERFACE:
3439
if (type->signature && !strncmp( type->signature, "pinterface", 10 ))
3440
{
3441
fprintf( stderr, "Ingoring supported %s parameterized interface.\n", type->name );
3442
break;
3443
}
3444
add_interface_type_step1( type );
3445
break;
3446
case TYPE_APICONTRACT:
3447
add_apicontract_type_step1( type );
3448
break;
3449
case TYPE_RUNTIMECLASS:
3450
add_runtimeclass_type_step1( type );
3451
break;
3452
case TYPE_DELEGATE:
3453
add_delegate_type_step1( type );
3454
break;
3455
default:
3456
fprintf( stderr, "Unhandled type %u name '%s'.\n", type->type_type, type->name );
3457
break;
3458
}
3459
}
3460
3461
LIST_FOR_EACH_ENTRY( stmt, stmt_list, const statement_t, entry )
3462
{
3463
type_t *type = stmt->u.type;
3464
3465
if (stmt->type != STMT_TYPE) continue;
3466
3467
switch (type->type_type)
3468
{
3469
case TYPE_ENUM:
3470
add_enum_type_step2( type );
3471
break;
3472
case TYPE_STRUCT:
3473
add_struct_type_step2( type );
3474
break;
3475
case TYPE_INTERFACE:
3476
if (type->signature && !strncmp( type->signature, "pinterface", 10 ))
3477
{
3478
fprintf( stderr, "Ingoring supported %s parameterized interface.\n", type->name );
3479
break;
3480
}
3481
add_interface_type_step2( type );
3482
break;
3483
case TYPE_APICONTRACT:
3484
add_apicontract_type_step2( type );
3485
break;
3486
case TYPE_RUNTIMECLASS:
3487
add_runtimeclass_type_step2( type );
3488
break;
3489
case TYPE_DELEGATE:
3490
add_delegate_type_step2( type );
3491
break;
3492
default:
3493
break;
3494
}
3495
}
3496
}
3497
3498
static void build_table_stream( const statement_list_t *stmts )
3499
{
3500
static const GUID guid = { 0x9ddc04c6, 0x04ca, 0x04cc, { 0x52, 0x85, 0x4b, 0x50, 0xb2, 0x60, 0x1d, 0xa8 } };
3501
static const BYTE token[] = { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 };
3502
static const USHORT space = 0x20;
3503
char *ptr;
3504
UINT i;
3505
3506
add_string( "" );
3507
add_userstring( NULL, 0 );
3508
add_userstring( &space, sizeof(space) );
3509
add_blob( NULL, 0 );
3510
3511
assembly_name = xstrdup( metadata_name );
3512
if ((ptr = strrchr( assembly_name, '.' ))) *ptr = 0;
3513
3514
add_typedef_row( 0, add_string("<Module>"), 0, 0, 1, 1 );
3515
add_assembly_row( add_string(assembly_name) );
3516
add_module_row( add_string(metadata_name), add_guid(&guid) );
3517
add_assemblyref_row( 0, add_blob(token, sizeof(token)), add_string("mscorlib") );
3518
3519
build_tables( stmts );
3520
3521
for (i = 0; i < TABLE_MAX; i++) if (tables[i].count) tables_header.valid |= (1ull << i);
3522
3523
if (strings.offset >> 16) tables_header.heap_sizes |= LARGE_STRING_HEAP;
3524
if (guids.offset >> 16) tables_header.heap_sizes |= LARGE_GUID_HEAP;
3525
if (blobs.offset >> 16) tables_header.heap_sizes |= LARGE_BLOB_HEAP;
3526
3527
add_bytes( &tables_disk, (const BYTE *)&tables_header, sizeof(tables_header) );
3528
3529
for (i = 0; i < TABLE_MAX; i++)
3530
if (tables[i].count) add_bytes( &tables_disk, (const BYTE *)&tables[i].count, sizeof(tables[i].count) );
3531
3532
serialize_module_table();
3533
serialize_typeref_table();
3534
serialize_typedef_table();
3535
serialize_field_table();
3536
serialize_methoddef_table();
3537
serialize_param_table();
3538
serialize_interfaceimpl_table();
3539
serialize_memberref_table();
3540
serialize_constant_table();
3541
serialize_customattribute_table();
3542
serialize_eventmap_table();
3543
serialize_event_table();
3544
serialize_propertymap_table();
3545
serialize_property_table();
3546
serialize_methodsemantics_table();
3547
serialize_methodimpl_table();
3548
serialize_assembly_table();
3549
serialize_assemblyref_table();
3550
}
3551
3552
static void build_streams( const statement_list_t *stmts )
3553
{
3554
static const BYTE pad[4];
3555
UINT i, len, offset = sizeof(metadata_header);
3556
3557
build_table_stream( stmts );
3558
3559
len = (tables_disk.offset + 3) & ~3;
3560
add_bytes( &tables_disk, pad, len - tables_disk.offset );
3561
3562
streams[WINMD_STREAM_TABLE].data_size = tables_disk.offset;
3563
streams[WINMD_STREAM_TABLE].data = tables_disk.ptr;
3564
3565
len = (strings.offset + 3) & ~3;
3566
add_bytes( &strings, pad, len - strings.offset );
3567
3568
streams[WINMD_STREAM_STRING].data_size = strings.offset;
3569
streams[WINMD_STREAM_STRING].data = strings.ptr;
3570
3571
len = (userstrings.offset + 3) & ~3;
3572
add_bytes( &userstrings, pad, len - userstrings.offset );
3573
3574
streams[WINMD_STREAM_USERSTRING].data_size = userstrings.offset;
3575
streams[WINMD_STREAM_USERSTRING].data = userstrings.ptr;
3576
3577
len = (blobs.offset + 3) & ~3;
3578
add_bytes( &blobs, pad, len - blobs.offset );
3579
3580
streams[WINMD_STREAM_BLOB].data_size = blobs.offset;
3581
streams[WINMD_STREAM_BLOB].data = blobs.ptr;
3582
3583
streams[WINMD_STREAM_GUID].data_size = guids.offset;
3584
streams[WINMD_STREAM_GUID].data = guids.ptr;
3585
3586
for (i = 0; i < WINMD_STREAM_MAX; i++)
3587
{
3588
if (!streams[i].data_size) continue;
3589
offset += streams[i].header_size;
3590
}
3591
for (i = 0; i < WINMD_STREAM_MAX; i++)
3592
{
3593
if (!streams[i].data_size) continue;
3594
streams[i].data_offset = offset;
3595
offset += streams[i].data_size;
3596
}
3597
}
3598
3599
static void write_streams( void )
3600
{
3601
UINT i;
3602
for (i = 0; i < WINMD_STREAM_MAX; i++)
3603
{
3604
if (!streams[i].data_size) continue;
3605
put_data( streams[i].data, streams[i].data_size );
3606
}
3607
}
3608
3609
void write_metadata( const statement_list_t *stmts )
3610
{
3611
static const BYTE pad[FILE_ALIGNMENT];
3612
UINT image_size, file_size, i;
3613
3614
if (!do_metadata || !winrt_mode) return;
3615
3616
build_streams( stmts );
3617
3618
image_size = FILE_ALIGNMENT + sizeof(cor_header) + 8 + sizeof(metadata_header);
3619
for (i = 0; i < WINMD_STREAM_MAX; i++) image_size += streams[i].header_size + streams[i].data_size;
3620
3621
init_output_buffer();
3622
3623
write_headers( image_size );
3624
write_streams( );
3625
3626
file_size = (image_size + FILE_ALIGNMENT - 1) & ~(FILE_ALIGNMENT - 1);
3627
put_data( pad, file_size - image_size );
3628
3629
flush_output_buffer( metadata_name );
3630
}
3631
3632