Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/tools/widl/write_msft.c
4389 views
1
/*
2
* Typelib v2 (MSFT) generation
3
*
4
* Copyright 2004 Alastair Bridgewater
5
* 2004, 2005 Huw Davies
6
*
7
* This library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* This library is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this library; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20
*
21
* --------------------------------------------------------------------------------------
22
* Known problems:
23
*
24
* Badly incomplete.
25
*
26
* Only works on little-endian systems.
27
*
28
*/
29
30
#include "config.h"
31
32
#include <stdlib.h>
33
#include <string.h>
34
#include <stdarg.h>
35
#include <stdio.h>
36
#include <ctype.h>
37
#include <time.h>
38
39
#include "widl.h"
40
#include "typelib.h"
41
#include "typelib_struct.h"
42
#include "utils.h"
43
#include "header.h"
44
#include "hash.h"
45
#include "typetree.h"
46
#include "parser.h"
47
#include "typegen.h"
48
49
enum MSFT_segment_index {
50
MSFT_SEG_TYPEINFO = 0, /* type information */
51
MSFT_SEG_IMPORTINFO, /* import information */
52
MSFT_SEG_IMPORTFILES, /* import filenames */
53
MSFT_SEG_REFERENCES, /* references (?) */
54
MSFT_SEG_GUIDHASH, /* hash table for guids? */
55
MSFT_SEG_GUID, /* guid storage */
56
MSFT_SEG_NAMEHASH, /* hash table for names */
57
MSFT_SEG_NAME, /* name storage */
58
MSFT_SEG_STRING, /* string storage */
59
MSFT_SEG_TYPEDESC, /* type descriptions */
60
MSFT_SEG_ARRAYDESC, /* array descriptions */
61
MSFT_SEG_CUSTDATA, /* custom data */
62
MSFT_SEG_CUSTDATAGUID, /* custom data guids */
63
MSFT_SEG_UNKNOWN, /* ??? */
64
MSFT_SEG_UNKNOWN2, /* ??? */
65
MSFT_SEG_MAX /* total number of segments */
66
};
67
68
typedef struct tagMSFT_ImpFile {
69
int guid;
70
int lcid;
71
int version;
72
char filename[0]; /* preceded by two bytes of encoded (length << 2) + flags in the low two bits. */
73
} MSFT_ImpFile;
74
75
typedef struct _msft_typelib_t
76
{
77
typelib_t *typelib;
78
MSFT_Header typelib_header;
79
MSFT_pSeg typelib_segdir[MSFT_SEG_MAX];
80
unsigned char *typelib_segment_data[MSFT_SEG_MAX];
81
int typelib_segment_block_length[MSFT_SEG_MAX];
82
83
int typelib_typeinfo_offsets[0x200]; /* Hope that's enough. */
84
85
int *typelib_namehash_segment;
86
int *typelib_guidhash_segment;
87
88
int help_string_dll_offset;
89
90
struct _msft_typeinfo_t *typeinfos;
91
struct _msft_typeinfo_t *last_typeinfo;
92
} msft_typelib_t;
93
94
typedef struct _msft_typeinfo_t
95
{
96
msft_typelib_t *typelib;
97
MSFT_TypeInfoBase *typeinfo;
98
99
int typekind;
100
101
unsigned int var_data_allocated;
102
int *var_data;
103
104
unsigned int func_data_allocated;
105
int *func_data;
106
107
int vars_allocated;
108
int *var_indices;
109
int *var_names;
110
int *var_offsets;
111
112
int funcs_allocated;
113
int *func_indices;
114
int *func_names;
115
int *func_offsets;
116
117
int datawidth;
118
119
struct _msft_typeinfo_t *next_typeinfo;
120
} msft_typeinfo_t;
121
122
123
124
/*================== Internal functions ===================================*/
125
126
/****************************************************************************
127
* ctl2_init_header
128
*
129
* Initializes the type library header of a new typelib.
130
*/
131
static void ctl2_init_header(
132
msft_typelib_t *typelib) /* [I] The typelib to initialize. */
133
{
134
typelib->typelib_header.magic1 = 0x5446534d;
135
typelib->typelib_header.magic2 = 0x00010002;
136
typelib->typelib_header.posguid = -1;
137
typelib->typelib_header.lcid = 0x0409;
138
typelib->typelib_header.lcid2 = 0x0;
139
typelib->typelib_header.varflags = 0x40;
140
typelib->typelib_header.version = 0;
141
typelib->typelib_header.flags = 0;
142
typelib->typelib_header.nrtypeinfos = 0;
143
typelib->typelib_header.helpstring = -1;
144
typelib->typelib_header.helpstringcontext = 0;
145
typelib->typelib_header.helpcontext = 0;
146
typelib->typelib_header.nametablecount = 0;
147
typelib->typelib_header.nametablechars = 0;
148
typelib->typelib_header.NameOffset = -1;
149
typelib->typelib_header.helpfile = -1;
150
typelib->typelib_header.CustomDataOffset = -1;
151
typelib->typelib_header.res44 = 0x20;
152
typelib->typelib_header.res48 = 0x80;
153
typelib->typelib_header.dispatchpos = -1;
154
typelib->typelib_header.nimpinfos = 0;
155
}
156
157
/****************************************************************************
158
* ctl2_init_segdir
159
*
160
* Initializes the segment directory of a new typelib.
161
*/
162
static void ctl2_init_segdir(
163
msft_typelib_t *typelib) /* [I] The typelib to initialize. */
164
{
165
int i;
166
MSFT_pSeg *segdir;
167
168
segdir = &typelib->typelib_segdir[MSFT_SEG_TYPEINFO];
169
170
for (i = 0; i < MSFT_SEG_MAX; i++) {
171
segdir[i].offset = -1;
172
segdir[i].length = 0;
173
segdir[i].res08 = -1;
174
segdir[i].res0c = 0x0f;
175
}
176
}
177
178
/****************************************************************************
179
* ctl2_hash_guid
180
*
181
* Generates a hash key from a GUID.
182
*
183
* RETURNS
184
*
185
* The hash key for the GUID.
186
*/
187
static int ctl2_hash_guid(const struct uuid *guid)
188
{
189
int hash;
190
int i;
191
192
hash = 0;
193
for (i = 0; i < 8; i ++) {
194
hash ^= ((const short *)guid)[i];
195
}
196
197
return hash & 0x1f;
198
}
199
200
/****************************************************************************
201
* ctl2_find_guid
202
*
203
* Locates a guid in a type library.
204
*
205
* RETURNS
206
*
207
* The offset into the GUID segment of the guid, or -1 if not found.
208
*/
209
static int ctl2_find_guid(
210
msft_typelib_t *typelib, /* [I] The typelib to operate against. */
211
int hash_key, /* [I] The hash key for the guid. */
212
const struct uuid *guid) /* [I] The guid to find. */
213
{
214
int offset;
215
MSFT_GuidEntry *guidentry;
216
217
offset = typelib->typelib_guidhash_segment[hash_key];
218
while (offset != -1) {
219
guidentry = (MSFT_GuidEntry *)&typelib->typelib_segment_data[MSFT_SEG_GUID][offset];
220
221
if (!memcmp(guidentry, guid, sizeof(*guid))) return offset;
222
223
offset = guidentry->next_hash;
224
}
225
226
return offset;
227
}
228
229
/****************************************************************************
230
* ctl2_find_name
231
*
232
* Locates a name in a type library.
233
*
234
* RETURNS
235
*
236
* The offset into the NAME segment of the name, or -1 if not found.
237
*
238
* NOTES
239
*
240
* The name must be encoded as with ctl2_encode_name().
241
*/
242
static int ctl2_find_name(
243
msft_typelib_t *typelib, /* [I] The typelib to operate against. */
244
char *name) /* [I] The encoded name to find. */
245
{
246
int offset;
247
int *namestruct;
248
249
offset = typelib->typelib_namehash_segment[name[2] & 0x7f];
250
while (offset != -1) {
251
namestruct = (int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][offset];
252
253
if (!((namestruct[2] ^ *((int *)name)) & 0xffff00ff)) {
254
/* hash codes and lengths match, final test */
255
if (!strncasecmp(name+4, (void *)(namestruct+3), name[0])) break;
256
}
257
258
/* move to next item in hash bucket */
259
offset = namestruct[1];
260
}
261
262
return offset;
263
}
264
265
/****************************************************************************
266
* ctl2_encode_name
267
*
268
* Encodes a name string to a form suitable for storing into a type library
269
* or comparing to a name stored in a type library.
270
*
271
* RETURNS
272
*
273
* The length of the encoded name, including padding and length+hash fields.
274
*
275
* NOTES
276
*
277
* Will throw an exception if name or result are NULL. Is not multithread
278
* safe in the slightest.
279
*/
280
static int ctl2_encode_name(
281
msft_typelib_t *typelib, /* [I] The typelib to operate against (used for LCID only). */
282
const char *name, /* [I] The name string to encode. */
283
char **result) /* [O] A pointer to a pointer to receive the encoded name. */
284
{
285
char *converted_name;
286
size_t length, size;
287
int offset;
288
int value;
289
290
length = strlen(name);
291
size = (length + 7) & ~3;
292
converted_name = xmalloc(size + 1);
293
memcpy(converted_name + 4, name, length);
294
converted_name[length + 4] = 0;
295
296
value = lhash_val_of_name_sys(typelib->typelib_header.varflags & 0x0f, typelib->typelib_header.lcid, converted_name + 4);
297
298
converted_name[0] = length & 0xff;
299
converted_name[1] = length >> 8;
300
converted_name[2] = value;
301
converted_name[3] = value >> 8;
302
303
for (offset = (4 - length) & 3; offset; offset--) converted_name[length + offset + 3] = 0x57;
304
305
*result = converted_name;
306
307
return size;
308
}
309
310
/****************************************************************************
311
* ctl2_encode_string
312
*
313
* Encodes a string to a form suitable for storing into a type library or
314
* comparing to a string stored in a type library.
315
*
316
* RETURNS
317
*
318
* The length of the encoded string, including padding and length fields.
319
*
320
* NOTES
321
*
322
* Will throw an exception if string or result are NULL. Is not multithread
323
* safe in the slightest.
324
*/
325
static int ctl2_encode_string(
326
const char *string, /* [I] The string to encode. */
327
char **result) /* [O] A pointer to a pointer to receive the encoded string. */
328
{
329
char *converted_string;
330
size_t length, size;
331
int offset;
332
333
length = strlen(string);
334
size = (length + 5) & ~3;
335
if (length < 3) size += 4;
336
converted_string = xmalloc(size);
337
memcpy(converted_string + 2, string, length);
338
converted_string[0] = length & 0xff;
339
converted_string[1] = (length >> 8) & 0xff;
340
341
if(length < 3) { /* strings of this length are padded with up to 8 bytes incl the 2 byte length */
342
for(offset = 0; offset < 4; offset++)
343
converted_string[length + offset + 2] = 0x57;
344
length += 4;
345
}
346
for (offset = (4 - (length + 2)) & 3; offset; offset--) converted_string[length + offset + 1] = 0x57;
347
348
*result = converted_string;
349
return size;
350
}
351
352
/****************************************************************************
353
* ctl2_alloc_segment
354
*
355
* Allocates memory from a segment in a type library.
356
*
357
* RETURNS
358
*
359
* Success: The offset within the segment of the new data area.
360
*
361
* BUGS
362
*
363
* Does not (yet) handle the case where the allocated segment memory needs to grow.
364
*/
365
static int ctl2_alloc_segment(
366
msft_typelib_t *typelib, /* [I] The type library in which to allocate. */
367
enum MSFT_segment_index segment, /* [I] The segment in which to allocate. */
368
int size, /* [I] The amount to allocate. */
369
int block_size) /* [I] Initial allocation block size, or 0 for default. */
370
{
371
int offset;
372
373
if(!typelib->typelib_segment_data[segment]) {
374
if (!block_size) block_size = 0x2000;
375
376
typelib->typelib_segment_block_length[segment] = block_size;
377
typelib->typelib_segment_data[segment] = xmalloc(block_size);
378
if (!typelib->typelib_segment_data[segment]) return -1;
379
memset(typelib->typelib_segment_data[segment], 0x57, block_size);
380
}
381
382
while ((typelib->typelib_segdir[segment].length + size) > typelib->typelib_segment_block_length[segment]) {
383
unsigned char *block;
384
385
block_size = typelib->typelib_segment_block_length[segment];
386
block = xrealloc(typelib->typelib_segment_data[segment], block_size << 1);
387
388
if (segment == MSFT_SEG_TYPEINFO) {
389
/* TypeInfos have a direct pointer to their memory space, so we have to fix them up. */
390
msft_typeinfo_t *typeinfo;
391
392
for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
393
typeinfo->typeinfo = (void *)&block[((unsigned char *)typeinfo->typeinfo) - typelib->typelib_segment_data[segment]];
394
}
395
}
396
397
memset(block + block_size, 0x57, block_size);
398
typelib->typelib_segment_block_length[segment] = block_size << 1;
399
typelib->typelib_segment_data[segment] = block;
400
}
401
402
offset = typelib->typelib_segdir[segment].length;
403
typelib->typelib_segdir[segment].length += size;
404
405
return offset;
406
}
407
408
/****************************************************************************
409
* ctl2_alloc_typeinfo
410
*
411
* Allocates and initializes a typeinfo structure in a type library.
412
*
413
* RETURNS
414
*
415
* Success: The offset of the new typeinfo.
416
* Failure: -1 (this is invariably an out of memory condition).
417
*/
418
static int ctl2_alloc_typeinfo(
419
msft_typelib_t *typelib, /* [I] The type library to allocate in. */
420
int nameoffset) /* [I] The offset of the name for this typeinfo. */
421
{
422
int offset;
423
MSFT_TypeInfoBase *typeinfo;
424
425
offset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEINFO, sizeof(MSFT_TypeInfoBase), 0);
426
427
typelib->typelib_typeinfo_offsets[typelib->typelib_header.nrtypeinfos++] = offset;
428
429
typeinfo = (void *)(typelib->typelib_segment_data[MSFT_SEG_TYPEINFO] + offset);
430
431
typeinfo->typekind = (typelib->typelib_header.nrtypeinfos - 1) << 16;
432
typeinfo->memoffset = -1; /* should be EOF if no elements */
433
typeinfo->res2 = 0;
434
typeinfo->res3 = -1;
435
typeinfo->res4 = 3;
436
typeinfo->res5 = 0;
437
typeinfo->cElement = 0;
438
typeinfo->res7 = 0;
439
typeinfo->res8 = 0;
440
typeinfo->res9 = 0;
441
typeinfo->resA = 0;
442
typeinfo->posguid = -1;
443
typeinfo->flags = 0;
444
typeinfo->NameOffset = nameoffset;
445
typeinfo->version = 0;
446
typeinfo->docstringoffs = -1;
447
typeinfo->helpstringcontext = 0;
448
typeinfo->helpcontext = 0;
449
typeinfo->oCustData = -1;
450
typeinfo->cbSizeVft = 0;
451
typeinfo->cImplTypes = 0;
452
typeinfo->size = 0;
453
typeinfo->datatype1 = -1;
454
typeinfo->datatype2 = 0;
455
typeinfo->res18 = 0;
456
typeinfo->res19 = -1;
457
458
return offset;
459
}
460
461
/****************************************************************************
462
* ctl2_alloc_guid
463
*
464
* Allocates and initializes a GUID structure in a type library. Also updates
465
* the GUID hash table as needed.
466
*
467
* RETURNS
468
*
469
* Success: The offset of the new GUID.
470
*/
471
static int ctl2_alloc_guid(
472
msft_typelib_t *typelib, /* [I] The type library to allocate in. */
473
MSFT_GuidEntry *guid) /* [I] The GUID to store. */
474
{
475
int offset;
476
MSFT_GuidEntry *guid_space;
477
int hash_key;
478
479
chat("adding uuid {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
480
guid->guid.Data1, guid->guid.Data2, guid->guid.Data3,
481
guid->guid.Data4[0], guid->guid.Data4[1], guid->guid.Data4[2], guid->guid.Data4[3],
482
guid->guid.Data4[4], guid->guid.Data4[5], guid->guid.Data4[6], guid->guid.Data4[7]);
483
484
hash_key = ctl2_hash_guid(&guid->guid);
485
486
offset = ctl2_find_guid(typelib, hash_key, &guid->guid);
487
if (offset != -1)
488
{
489
if (is_warning_enabled(2368))
490
warning("duplicate uuid {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
491
guid->guid.Data1, guid->guid.Data2, guid->guid.Data3,
492
guid->guid.Data4[0], guid->guid.Data4[1], guid->guid.Data4[2], guid->guid.Data4[3],
493
guid->guid.Data4[4], guid->guid.Data4[5], guid->guid.Data4[6], guid->guid.Data4[7]);
494
return -1;
495
}
496
497
offset = ctl2_alloc_segment(typelib, MSFT_SEG_GUID, sizeof(MSFT_GuidEntry), 0);
498
499
guid_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_GUID] + offset);
500
*guid_space = *guid;
501
502
guid_space->next_hash = typelib->typelib_guidhash_segment[hash_key];
503
typelib->typelib_guidhash_segment[hash_key] = offset;
504
505
return offset;
506
}
507
508
/****************************************************************************
509
* ctl2_alloc_name
510
*
511
* Allocates and initializes a name within a type library. Also updates the
512
* name hash table as needed.
513
*
514
* RETURNS
515
*
516
* Success: The offset within the segment of the new name.
517
* Failure: -1 (this is invariably an out of memory condition).
518
*/
519
static int ctl2_alloc_name(
520
msft_typelib_t *typelib, /* [I] The type library to allocate in. */
521
const char *name) /* [I] The name to store. */
522
{
523
int length;
524
int offset;
525
MSFT_NameIntro *name_space;
526
char *encoded_name;
527
528
length = ctl2_encode_name(typelib, name, &encoded_name);
529
530
offset = ctl2_find_name(typelib, encoded_name);
531
if (offset != -1)
532
{
533
free(encoded_name);
534
return offset;
535
}
536
537
offset = ctl2_alloc_segment(typelib, MSFT_SEG_NAME, length + 8, 0);
538
539
name_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_NAME] + offset);
540
name_space->hreftype = -1;
541
name_space->next_hash = -1;
542
memcpy(&name_space->namelen, encoded_name, length);
543
544
if (typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] != -1)
545
name_space->next_hash = typelib->typelib_namehash_segment[encoded_name[2] & 0x7f];
546
547
typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] = offset;
548
549
typelib->typelib_header.nametablecount += 1;
550
typelib->typelib_header.nametablechars += *encoded_name;
551
552
free(encoded_name);
553
return offset;
554
}
555
556
/****************************************************************************
557
* ctl2_alloc_string
558
*
559
* Allocates and initializes a string in a type library.
560
*
561
* RETURNS
562
*
563
* Success: The offset within the segment of the new string.
564
* Failure: -1 (this is invariably an out of memory condition).
565
*/
566
static int ctl2_alloc_string(
567
msft_typelib_t *typelib, /* [I] The type library to allocate in. */
568
const char *string) /* [I] The string to store. */
569
{
570
int length;
571
int offset;
572
unsigned char *string_space;
573
char *encoded_string;
574
575
length = ctl2_encode_string(string, &encoded_string);
576
577
for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_STRING].length;
578
offset += (((typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 1] << 8) |
579
typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 0]) + 5) & ~3) {
580
if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_STRING] + offset, length)) return offset;
581
}
582
583
offset = ctl2_alloc_segment(typelib, MSFT_SEG_STRING, length, 0);
584
585
string_space = typelib->typelib_segment_data[MSFT_SEG_STRING] + offset;
586
memcpy(string_space, encoded_string, length);
587
free(encoded_string);
588
589
return offset;
590
}
591
592
/****************************************************************************
593
* alloc_msft_importinfo
594
*
595
* Allocates and initializes an import information structure in a type library.
596
*
597
* RETURNS
598
*
599
* Success: The offset of the new importinfo.
600
* Failure: -1 (this is invariably an out of memory condition).
601
*/
602
static int alloc_msft_importinfo(
603
msft_typelib_t *typelib, /* [I] The type library to allocate in. */
604
MSFT_ImpInfo *impinfo) /* [I] The import information to store. */
605
{
606
int offset;
607
MSFT_ImpInfo *impinfo_space;
608
609
for (offset = 0;
610
offset < typelib->typelib_segdir[MSFT_SEG_IMPORTINFO].length;
611
offset += sizeof(MSFT_ImpInfo)) {
612
if (!memcmp(&(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO][offset]),
613
impinfo, sizeof(MSFT_ImpInfo))) {
614
return offset;
615
}
616
}
617
618
impinfo->flags |= typelib->typelib_header.nimpinfos++;
619
620
offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTINFO, sizeof(MSFT_ImpInfo), 0);
621
622
impinfo_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO] + offset);
623
*impinfo_space = *impinfo;
624
625
return offset;
626
}
627
628
/****************************************************************************
629
* alloc_importfile
630
*
631
* Allocates and initializes an import file definition in a type library.
632
*
633
* RETURNS
634
*
635
* Success: The offset of the new importinfo.
636
* Failure: -1 (this is invariably an out of memory condition).
637
*/
638
static int alloc_importfile(
639
msft_typelib_t *typelib, /* [I] The type library to allocate in. */
640
int guidoffset, /* [I] The offset to the GUID for the imported library. */
641
int major_version, /* [I] The major version number of the imported library. */
642
int minor_version, /* [I] The minor version number of the imported library. */
643
const char *filename) /* [I] The filename of the imported library. */
644
{
645
int length;
646
int offset;
647
MSFT_ImpFile *importfile;
648
char *encoded_string;
649
650
length = ctl2_encode_string(filename, &encoded_string);
651
652
encoded_string[0] <<= 2;
653
encoded_string[0] |= 1;
654
655
for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_IMPORTFILES].length;
656
offset += (((typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xd] << 8) |
657
typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xc]) >> 2) + 0xc) {
658
if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES] + offset + 0xc, length)) return offset;
659
}
660
661
offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTFILES, length + 0xc, 0);
662
663
importfile = (MSFT_ImpFile *)&typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset];
664
importfile->guid = guidoffset;
665
importfile->lcid = typelib->typelib_header.lcid2;
666
importfile->version = major_version | (minor_version << 16);
667
memcpy(&importfile->filename, encoded_string, length);
668
free(encoded_string);
669
670
return offset;
671
}
672
673
static void alloc_importinfo(msft_typelib_t *typelib, importinfo_t *importinfo)
674
{
675
importlib_t *importlib = importinfo->importlib;
676
677
chat("alloc_importinfo: %s\n", importinfo->name);
678
679
if(!importlib->allocated) {
680
MSFT_GuidEntry guid;
681
int guid_idx;
682
683
chat("allocating importlib %s\n", importlib->name);
684
685
importlib->allocated = -1;
686
687
memcpy(&guid.guid, &importlib->guid, sizeof(guid.guid));
688
guid.hreftype = 2;
689
690
guid_idx = ctl2_alloc_guid(typelib, &guid);
691
692
importlib->offset = alloc_importfile(typelib, guid_idx, importlib->version & 0xffff,
693
importlib->version >> 16, importlib->name);
694
}
695
696
if(importinfo->offset == -1 || !(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID)) {
697
MSFT_ImpInfo impinfo;
698
699
impinfo.flags = importinfo->flags;
700
impinfo.oImpFile = importlib->offset;
701
702
if(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
703
MSFT_GuidEntry guid;
704
705
guid.hreftype = 0;
706
memcpy(&guid.guid, &importinfo->guid, sizeof(guid.guid));
707
708
impinfo.oGuid = ctl2_alloc_guid(typelib, &guid);
709
710
importinfo->offset = alloc_msft_importinfo(typelib, &impinfo);
711
712
typelib->typelib_segment_data[MSFT_SEG_GUID][impinfo.oGuid+sizeof(guid.guid)]
713
= importinfo->offset+1;
714
715
if(!strcmp(importinfo->name, "IDispatch"))
716
typelib->typelib_header.dispatchpos = importinfo->offset+1;
717
}else {
718
impinfo.oGuid = importinfo->id;
719
importinfo->offset = alloc_msft_importinfo(typelib, &impinfo);
720
}
721
}
722
}
723
724
static importinfo_t *find_importinfo(msft_typelib_t *typelib, const char *name)
725
{
726
importlib_t *importlib;
727
int i;
728
729
chat("search importlib %s\n", name);
730
731
if(!name)
732
return NULL;
733
734
LIST_FOR_EACH_ENTRY( importlib, &typelib->typelib->importlibs, importlib_t, entry )
735
{
736
for(i=0; i < importlib->ntypeinfos; i++) {
737
if(!strcmp(name, importlib->importinfos[i].name)) {
738
chat("Found %s in importlib.\n", name);
739
return importlib->importinfos+i;
740
}
741
}
742
}
743
744
return NULL;
745
}
746
747
static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure);
748
static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface);
749
static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration);
750
static void add_union_typeinfo(msft_typelib_t *typelib, type_t *tunion);
751
static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls);
752
static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface);
753
static void add_typedef_typeinfo(msft_typelib_t *typelib, type_t *dispinterface);
754
755
756
/****************************************************************************
757
* encode_type
758
*
759
* Encodes a type, storing information in the TYPEDESC and ARRAYDESC
760
* segments as needed.
761
*
762
* RETURNS
763
*
764
* Success: 0.
765
* Failure: -1.
766
*/
767
static int encode_type(
768
msft_typelib_t *typelib, /* [I] The type library in which to encode the TYPEDESC. */
769
int vt, /* [I] vt to encode */
770
type_t *type, /* [I] type */
771
int *encoded_type, /* [O] The encoded type description. */
772
int *decoded_size) /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */
773
{
774
int default_type;
775
int scratch;
776
int typeoffset;
777
int *typedata;
778
int target_type;
779
int child_size = 0;
780
781
chat("encode_type vt %d type %p\n", vt, type);
782
783
default_type = 0x80000000 | (vt << 16) | vt;
784
if (!decoded_size) decoded_size = &scratch;
785
786
*decoded_size = 0;
787
788
switch (vt) {
789
case VT_I1:
790
case VT_UI1:
791
*encoded_type = default_type;
792
break;
793
794
case VT_INT:
795
*encoded_type = 0x80000000 | (VT_I4 << 16) | VT_INT;
796
break;
797
798
case VT_UINT:
799
*encoded_type = 0x80000000 | (VT_UI4 << 16) | VT_UINT;
800
break;
801
802
case VT_UI2:
803
case VT_I2:
804
case VT_BOOL:
805
*encoded_type = default_type;
806
break;
807
808
case VT_I4:
809
case VT_UI4:
810
case VT_R4:
811
case VT_ERROR:
812
case VT_HRESULT:
813
*encoded_type = default_type;
814
break;
815
816
case VT_R8:
817
case VT_I8:
818
case VT_UI8:
819
*encoded_type = default_type;
820
break;
821
822
case VT_CY:
823
case VT_DATE:
824
*encoded_type = default_type;
825
break;
826
827
case VT_DECIMAL:
828
*encoded_type = default_type;
829
break;
830
831
case VT_VOID:
832
*encoded_type = 0x80000000 | (VT_EMPTY << 16) | vt;
833
break;
834
835
case VT_UNKNOWN:
836
case VT_DISPATCH:
837
case VT_BSTR:
838
*encoded_type = default_type;
839
break;
840
841
case VT_VARIANT:
842
*encoded_type = default_type;
843
break;
844
845
case VT_LPSTR:
846
case VT_LPWSTR:
847
*encoded_type = 0xfffe0000 | vt;
848
break;
849
850
case VT_PTR:
851
{
852
int next_vt;
853
for(next_vt = 0; is_ptr(type); type = type_pointer_get_ref_type(type)) {
854
next_vt = get_type_vt(type_pointer_get_ref_type(type));
855
if (next_vt != 0)
856
break;
857
}
858
/* if no type found then it must be void */
859
if (next_vt == 0)
860
next_vt = VT_VOID;
861
862
encode_type(typelib, next_vt, type_pointer_get_ref_type(type),
863
&target_type, &child_size);
864
/* these types already have an implicit pointer, so we don't need to
865
* add another */
866
if(next_vt == VT_DISPATCH || next_vt == VT_UNKNOWN) {
867
chat("encode_type: skipping ptr\n");
868
*encoded_type = target_type;
869
*decoded_size = child_size;
870
break;
871
}
872
873
for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
874
typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
875
if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
876
}
877
878
if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
879
int mix_field;
880
881
if (target_type & 0x80000000) {
882
mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
883
} else {
884
typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
885
mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
886
}
887
888
typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
889
typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
890
891
typedata[0] = (mix_field << 16) | VT_PTR;
892
typedata[1] = target_type;
893
}
894
895
*encoded_type = typeoffset;
896
897
*decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
898
break;
899
}
900
901
case VT_SAFEARRAY:
902
{
903
type_t *element_type = type_alias_get_aliasee_type(type_array_get_element_type(type));
904
int next_vt = get_type_vt(element_type);
905
906
encode_type(typelib, next_vt, type_alias_get_aliasee_type(type_array_get_element_type(type)),
907
&target_type, &child_size);
908
909
for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
910
typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
911
if (((typedata[0] & 0xffff) == VT_SAFEARRAY) && (typedata[1] == target_type)) break;
912
}
913
914
if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
915
int mix_field;
916
917
if (target_type & 0x80000000) {
918
mix_field = ((target_type >> 16) & VT_TYPEMASK) | VT_ARRAY;
919
} else {
920
typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
921
mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
922
}
923
924
typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
925
typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
926
927
typedata[0] = (mix_field << 16) | VT_SAFEARRAY;
928
typedata[1] = target_type;
929
}
930
931
*encoded_type = typeoffset;
932
933
*decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
934
break;
935
}
936
937
case VT_USERDEFINED:
938
{
939
importinfo_t *importinfo;
940
int typeinfo_offset;
941
942
if (type->typelib_idx > -1)
943
{
944
chat("encode_type: VT_USERDEFINED - found already defined type %s at %d\n",
945
type->name, type->typelib_idx);
946
typeinfo_offset = typelib->typelib_typeinfo_offsets[type->typelib_idx];
947
}
948
else if ((importinfo = find_importinfo(typelib, type->name)))
949
{
950
chat("encode_type: VT_USERDEFINED - found imported type %s in %s\n",
951
type->name, importinfo->importlib->name);
952
alloc_importinfo(typelib, importinfo);
953
typeinfo_offset = importinfo->offset | 0x1;
954
}
955
else
956
{
957
/* Typedefs without the [public] attribute aren't included in the
958
* typelib, unless the aliasee is an anonymous UDT or the typedef
959
* is wire-marshalled. In the latter case the wire-marshal type,
960
* which may be a non-public alias, is used instead. */
961
while (type_is_alias(type))
962
{
963
if (is_attr(type->attrs, ATTR_WIREMARSHAL))
964
{
965
type = get_attrp(type->attrs, ATTR_WIREMARSHAL);
966
break;
967
}
968
else if (!is_attr(type->attrs, ATTR_PUBLIC))
969
type = type_alias_get_aliasee_type(type);
970
else
971
break;
972
}
973
974
chat("encode_type: VT_USERDEFINED - adding new type %s, real type %d\n",
975
type->name, type_get_type(type));
976
977
switch (type_get_type_detect_alias(type))
978
{
979
case TYPE_STRUCT:
980
case TYPE_ENCAPSULATED_UNION:
981
add_structure_typeinfo(typelib, type);
982
break;
983
case TYPE_INTERFACE:
984
add_interface_typeinfo(typelib, type);
985
break;
986
case TYPE_ENUM:
987
add_enum_typeinfo(typelib, type);
988
break;
989
case TYPE_UNION:
990
add_union_typeinfo(typelib, type);
991
break;
992
case TYPE_COCLASS:
993
add_coclass_typeinfo(typelib, type);
994
break;
995
case TYPE_ALIAS:
996
add_typedef_typeinfo(typelib, type);
997
break;
998
default:
999
error("encode_type: VT_USERDEFINED - unhandled type %d\n",
1000
type_get_type(type));
1001
}
1002
1003
typeinfo_offset = typelib->typelib_typeinfo_offsets[type->typelib_idx];
1004
}
1005
for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
1006
typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1007
if ((typedata[0] == ((0x7fff << 16) | VT_USERDEFINED)) && (typedata[1] == typeinfo_offset)) break;
1008
}
1009
1010
if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
1011
typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
1012
typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1013
1014
typedata[0] = (0x7fff << 16) | VT_USERDEFINED;
1015
typedata[1] = typeinfo_offset;
1016
}
1017
1018
*encoded_type = typeoffset;
1019
break;
1020
}
1021
1022
default:
1023
error("encode_type: unrecognized type %d.\n", vt);
1024
*encoded_type = default_type;
1025
break;
1026
}
1027
1028
return 0;
1029
}
1030
1031
static void dump_type(type_t *t)
1032
{
1033
chat("dump_type: %p name %s type %d attrs %p\n", t, t->name, type_get_type(t), t->attrs);
1034
}
1035
1036
static int encode_var(
1037
msft_typelib_t *typelib, /* [I] The type library in which to encode the TYPEDESC. */
1038
type_t *type, /* [I] The type description to encode. */
1039
var_t *var, /* [I] The var to encode. */
1040
int *encoded_type, /* [O] The encoded type description. */
1041
int *decoded_size) /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */
1042
{
1043
int typeoffset;
1044
int *typedata;
1045
int target_type;
1046
int child_size;
1047
int vt;
1048
int scratch;
1049
1050
if (!decoded_size) decoded_size = &scratch;
1051
*decoded_size = 0;
1052
1053
chat("encode_var: var %p type %p type->name %s\n",
1054
var, type, type->name ? type->name : "NULL");
1055
1056
if (is_array(type) && !type_array_is_decl_as_ptr(type)) {
1057
int num_dims, arrayoffset;
1058
type_t *atype;
1059
int *arraydata;
1060
1061
num_dims = 0;
1062
for (atype = type;
1063
is_array(atype) && !type_array_is_decl_as_ptr(atype);
1064
atype = type_array_get_element_type(atype))
1065
++num_dims;
1066
1067
chat("array with %d dimensions\n", num_dims);
1068
encode_var(typelib, atype, var, &target_type, NULL);
1069
arrayoffset = ctl2_alloc_segment(typelib, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(int), 0);
1070
arraydata = (void *)&typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
1071
1072
arraydata[0] = target_type;
1073
arraydata[1] = num_dims;
1074
arraydata[1] |= ((num_dims * 2 * sizeof(int)) << 16);
1075
1076
arraydata += 2;
1077
for (atype = type;
1078
is_array(atype) && !type_array_is_decl_as_ptr(atype);
1079
atype = type_array_get_element_type(atype))
1080
{
1081
arraydata[0] = type_array_get_dim(atype);
1082
arraydata[1] = 0;
1083
arraydata += 2;
1084
}
1085
1086
typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
1087
typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1088
1089
typedata[0] = (0x7ffe << 16) | VT_CARRAY;
1090
typedata[1] = arrayoffset;
1091
1092
*encoded_type = typeoffset;
1093
*decoded_size = 20 /*sizeof(ARRAYDESC)*/ + (num_dims - 1) * 8 /*sizeof(SAFEARRAYBOUND)*/;
1094
return 0;
1095
}
1096
1097
vt = get_type_vt(type);
1098
if (vt == VT_PTR) {
1099
type_t *ref = is_ptr(type) ?
1100
type_pointer_get_ref_type(type) : type_array_get_element_type(type);
1101
int skip_ptr = encode_var(typelib, ref, var, &target_type, &child_size);
1102
1103
if(skip_ptr == 2) {
1104
chat("encode_var: skipping ptr\n");
1105
*encoded_type = target_type;
1106
*decoded_size = child_size;
1107
return 0;
1108
}
1109
1110
for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
1111
typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1112
if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
1113
}
1114
1115
if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
1116
int mix_field;
1117
1118
if (target_type & 0x80000000) {
1119
mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
1120
} else if (get_type_vt(ref) == VT_SAFEARRAY) {
1121
type_t *element_type = type_alias_get_aliasee_type(type_array_get_element_type(ref));
1122
mix_field = get_type_vt(element_type) | VT_ARRAY | VT_BYREF;
1123
} else {
1124
typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
1125
mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
1126
}
1127
1128
typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
1129
typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1130
1131
typedata[0] = (mix_field << 16) | VT_PTR;
1132
typedata[1] = target_type;
1133
}
1134
1135
*encoded_type = typeoffset;
1136
1137
*decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
1138
return 0;
1139
}
1140
1141
dump_type(type);
1142
1143
encode_type(typelib, vt, type, encoded_type, decoded_size);
1144
/* these types already have an implicit pointer, so we don't need to
1145
* add another */
1146
if(vt == VT_DISPATCH || vt == VT_UNKNOWN) return 2;
1147
return 0;
1148
}
1149
1150
static unsigned int get_ulong_val(unsigned int val, int vt)
1151
{
1152
switch(vt) {
1153
case VT_I2:
1154
case VT_BOOL:
1155
case VT_UI2:
1156
return val & 0xffff;
1157
case VT_I1:
1158
case VT_UI1:
1159
return val & 0xff;
1160
}
1161
1162
return val;
1163
}
1164
1165
static void write_int_value(msft_typelib_t *typelib, int *out, int vt, int value)
1166
{
1167
const unsigned int lv = get_ulong_val(value, vt);
1168
if ((lv & 0x3ffffff) == lv) {
1169
*out = 0x80000000;
1170
*out |= vt << 26;
1171
*out |= lv;
1172
} else {
1173
int offset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATA, 8, 0);
1174
*((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = vt;
1175
memcpy(&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2], &value, 4);
1176
*((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+6]) = 0x5757;
1177
*out = offset;
1178
}
1179
}
1180
1181
static void write_string_value(msft_typelib_t *typelib, int *out, const char *value)
1182
{
1183
int len = strlen(value), seg_len = (len + 6 + 3) & ~0x3;
1184
int offset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATA, seg_len, 0);
1185
*((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = VT_BSTR;
1186
memcpy(&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2], &len, sizeof(len));
1187
memcpy(&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+6], value, len);
1188
len += 6;
1189
while(len < seg_len) {
1190
*((char *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+len]) = 0x57;
1191
len++;
1192
}
1193
*out = offset;
1194
}
1195
1196
static void write_default_value(msft_typelib_t *typelib, type_t *type, expr_t *expr, int *out)
1197
{
1198
int vt;
1199
1200
if (expr->type == EXPR_STRLIT || expr->type == EXPR_WSTRLIT) {
1201
vt = get_type_vt(type);
1202
if (vt != VT_BSTR && vt != VT_VARIANT)
1203
error("string default value applied to non-string type\n");
1204
chat("default value '%s'\n", expr->u.sval);
1205
write_string_value(typelib, out, expr->u.sval);
1206
return;
1207
}
1208
1209
if (type_get_type(type) == TYPE_ENUM) {
1210
vt = VT_I4;
1211
} else if (is_ptr(type)) {
1212
vt = get_type_vt(type_pointer_get_ref_type(type));
1213
if (vt == VT_USERDEFINED)
1214
vt = VT_I4;
1215
if (expr->cval)
1216
warning("non-null pointer default value\n");
1217
} else {
1218
vt = get_type_vt(type);
1219
switch(vt) {
1220
case VT_I2:
1221
case VT_I4:
1222
case VT_R4:
1223
case VT_BOOL:
1224
case VT_I1:
1225
case VT_UI1:
1226
case VT_UI2:
1227
case VT_UI4:
1228
case VT_INT:
1229
case VT_UINT:
1230
case VT_HRESULT:
1231
break;
1232
case VT_USERDEFINED:
1233
vt = VT_I4;
1234
break;
1235
case VT_VARIANT: {
1236
switch (expr->type) {
1237
case EXPR_DOUBLE:
1238
vt = VT_R4;
1239
break;
1240
case EXPR_NUM:
1241
vt = VT_I4;
1242
break;
1243
default:
1244
warning("can't write default VT_VARIANT value for expression type %d.\n", expr->type);
1245
return;
1246
}
1247
break;
1248
}
1249
default:
1250
warning("can't write value of type %d yet\n", vt);
1251
return;
1252
}
1253
}
1254
1255
write_int_value(typelib, out, vt, expr->cval);
1256
}
1257
1258
static void set_custdata(msft_typelib_t *typelib, const struct uuid *guid,
1259
int vt, const void *value, int *offset)
1260
{
1261
int guidoffset;
1262
int custoffset;
1263
int *custdata;
1264
int data_out;
1265
int hash_key;
1266
1267
hash_key = ctl2_hash_guid(guid);
1268
guidoffset = ctl2_find_guid(typelib, hash_key, guid);
1269
if(guidoffset == -1) {
1270
/* add GUID that was not already present */
1271
MSFT_GuidEntry guidentry;
1272
guidentry.guid = *guid;
1273
1274
guidentry.hreftype = -1;
1275
guidentry.next_hash = -1;
1276
1277
guidoffset = ctl2_alloc_guid(typelib, &guidentry);
1278
}
1279
1280
if(vt == VT_BSTR)
1281
/* TODO midl appears to share a single reference if the same string is used as custdata in multiple places */
1282
write_string_value(typelib, &data_out, value);
1283
else
1284
write_int_value(typelib, &data_out, vt, *(int*)value);
1285
1286
custoffset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATAGUID, 12, 0);
1287
1288
custdata = (int *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATAGUID][custoffset];
1289
custdata[0] = guidoffset;
1290
custdata[1] = data_out;
1291
custdata[2] = *offset;
1292
*offset = custoffset;
1293
}
1294
1295
static void set_custdata_attr(msft_typelib_t *typelib, attr_custdata_t *custdata, int *offset)
1296
{
1297
switch(custdata->pval->type) {
1298
case EXPR_STRLIT:
1299
case EXPR_WSTRLIT:
1300
set_custdata(typelib, &custdata->id, VT_BSTR, custdata->pval->u.sval, offset);
1301
break;
1302
case EXPR_NUM:
1303
set_custdata(typelib, &custdata->id, VT_I4, &custdata->pval->u.integer.value, offset);
1304
break;
1305
default:
1306
error("custom() attribute with unknown type\n");
1307
break;
1308
}
1309
}
1310
1311
static int add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index)
1312
{
1313
int offset, name_offset;
1314
int *typedata, typedata_size;
1315
int i, id, next_idx;
1316
int decoded_size, extra_attr = 0;
1317
int num_params = 0, num_optional = 0, num_defaults = 0;
1318
int has_arg_custdata = 0;
1319
var_t *arg;
1320
unsigned char *namedata;
1321
const attr_t *attr;
1322
unsigned int funcflags = 0, callconv = 4 /* CC_STDCALL */;
1323
unsigned int funckind, invokekind = 1 /* INVOKE_FUNC */;
1324
int help_context = 0, help_string_context = 0, help_string_offset = -1;
1325
int func_custdata_offset = -1;
1326
int entry = -1, entry_is_ord = 0;
1327
int lcid_retval_count = 0;
1328
1329
chat("add_func_desc(%p,%d)\n", typeinfo, index);
1330
1331
id = ((0x6000 | (typeinfo->typeinfo->datatype2 & 0xffff)) << 16) | index;
1332
1333
switch(typeinfo->typekind) {
1334
case TKIND_DISPATCH:
1335
funckind = 0x4; /* FUNC_DISPATCH */
1336
break;
1337
case TKIND_MODULE:
1338
funckind = 0x3; /* FUNC_STATIC */
1339
break;
1340
default:
1341
funckind = 0x1; /* FUNC_PUREVIRTUAL */
1342
break;
1343
}
1344
1345
if (is_local( func->attrs )) {
1346
chat("add_func_desc: skipping local function\n");
1347
return FALSE;
1348
}
1349
1350
if (type_function_get_args(func->declspec.type))
1351
LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), var_t, entry )
1352
{
1353
num_params++;
1354
if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) {
1355
if(attr->type == ATTR_DEFAULTVALUE)
1356
num_defaults++;
1357
else if(attr->type == ATTR_OPTIONAL)
1358
num_optional++;
1359
else if(attr->type == ATTR_CUSTOM)
1360
has_arg_custdata = 1;
1361
}
1362
}
1363
1364
chat("add_func_desc: num of params %d\n", num_params);
1365
1366
name_offset = ctl2_alloc_name(typeinfo->typelib, func->name);
1367
1368
if (func->attrs) LIST_FOR_EACH_ENTRY( attr, func->attrs, const attr_t, entry ) {
1369
expr_t *expr = attr->u.pval;
1370
switch(attr->type) {
1371
case ATTR_BINDABLE:
1372
funcflags |= 0x4; /* FUNCFLAG_FBINDABLE */
1373
break;
1374
case ATTR_CUSTOM:
1375
set_custdata_attr(typeinfo->typelib, attr->u.pval, &func_custdata_offset);
1376
break;
1377
case ATTR_DEFAULTBIND:
1378
funcflags |= 0x20; /* FUNCFLAG_FDEFAULTBIND */
1379
break;
1380
case ATTR_DEFAULTCOLLELEM:
1381
funcflags |= 0x100; /* FUNCFLAG_FDEFAULTCOLLELEM */
1382
break;
1383
case ATTR_DISPLAYBIND:
1384
funcflags |= 0x10; /* FUNCFLAG_FDISPLAYBIND */
1385
break;
1386
case ATTR_ENTRY:
1387
extra_attr = max(extra_attr, 3);
1388
if (expr->type == EXPR_STRLIT || expr->type == EXPR_WSTRLIT)
1389
entry = ctl2_alloc_string(typeinfo->typelib, attr->u.pval);
1390
else {
1391
entry = expr->cval;
1392
entry_is_ord = 1;
1393
}
1394
break;
1395
case ATTR_HELPCONTEXT:
1396
extra_attr = max(extra_attr, 1);
1397
help_context = expr->u.integer.value;
1398
break;
1399
case ATTR_HELPSTRING:
1400
extra_attr = max(extra_attr, 2);
1401
help_string_offset = ctl2_alloc_string(typeinfo->typelib, attr->u.pval);
1402
break;
1403
case ATTR_HELPSTRINGCONTEXT:
1404
extra_attr = max(extra_attr, 6);
1405
help_string_context = expr->u.integer.value;
1406
break;
1407
case ATTR_HIDDEN:
1408
funcflags |= 0x40; /* FUNCFLAG_FHIDDEN */
1409
break;
1410
case ATTR_ID:
1411
id = expr->cval;
1412
break;
1413
case ATTR_IMMEDIATEBIND:
1414
funcflags |= 0x1000; /* FUNCFLAG_FIMMEDIATEBIND */
1415
break;
1416
case ATTR_NONBROWSABLE:
1417
funcflags |= 0x400; /* FUNCFLAG_FNONBROWSABLE */
1418
break;
1419
case ATTR_OUT:
1420
break;
1421
case ATTR_DEFAULT_OVERLOAD:
1422
case ATTR_OVERLOAD:
1423
break;
1424
case ATTR_PROPGET:
1425
invokekind = 0x2; /* INVOKE_PROPERTYGET */
1426
break;
1427
case ATTR_PROPPUT:
1428
invokekind = 0x4; /* INVOKE_PROPERTYPUT */
1429
break;
1430
case ATTR_PROPPUTREF:
1431
invokekind = 0x8; /* INVOKE_PROPERTYPUTREF */
1432
break;
1433
/* FIXME: FUNCFLAG_FREPLACEABLE */
1434
case ATTR_REQUESTEDIT:
1435
funcflags |= 0x8; /* FUNCFLAG_FREQUESTEDIT */
1436
break;
1437
case ATTR_RESTRICTED:
1438
funcflags |= 0x1; /* FUNCFLAG_FRESTRICTED */
1439
break;
1440
case ATTR_SOURCE:
1441
funcflags |= 0x2; /* FUNCFLAG_FSOURCE */
1442
break;
1443
case ATTR_UIDEFAULT:
1444
funcflags |= 0x200; /* FUNCFLAG_FUIDEFAULT */
1445
break;
1446
case ATTR_USESGETLASTERROR:
1447
funcflags |= 0x80; /* FUNCFLAG_FUSESGETLASTERROR */
1448
break;
1449
case ATTR_VARARG:
1450
if (num_optional || num_defaults)
1451
warning("add_func_desc: ignoring vararg in function with optional or defaultvalue params\n");
1452
else
1453
num_optional = -1;
1454
break;
1455
default:
1456
break;
1457
}
1458
}
1459
1460
if(has_arg_custdata || func_custdata_offset != -1) {
1461
extra_attr = max(extra_attr, 7 + num_params);
1462
}
1463
1464
/* allocate type data space for us */
1465
typedata_size = 0x18 + extra_attr * sizeof(int) + (num_params * (num_defaults ? 16 : 12));
1466
1467
if (!typeinfo->func_data) {
1468
typeinfo->func_data = xmalloc(0x100);
1469
typeinfo->func_data_allocated = 0x100;
1470
typeinfo->func_data[0] = 0;
1471
}
1472
1473
if(typeinfo->func_data[0] + typedata_size + sizeof(int) > typeinfo->func_data_allocated) {
1474
typeinfo->func_data_allocated = max(typeinfo->func_data_allocated * 2,
1475
typeinfo->func_data[0] + typedata_size + sizeof(int));
1476
typeinfo->func_data = xrealloc(typeinfo->func_data, typeinfo->func_data_allocated);
1477
}
1478
1479
offset = typeinfo->func_data[0];
1480
typeinfo->func_data[0] += typedata_size;
1481
typedata = typeinfo->func_data + (offset >> 2) + 1;
1482
1483
1484
/* find func with the same name - if it exists use its id */
1485
for(i = 0; i < (typeinfo->typeinfo->cElement & 0xffff); i++) {
1486
if(name_offset == typeinfo->func_names[i]) {
1487
id = typeinfo->func_indices[i];
1488
break;
1489
}
1490
}
1491
1492
/* find the first func with the same id and link via the hiword of typedata[4] */
1493
next_idx = index;
1494
for(i = 0; i < (typeinfo->typeinfo->cElement & 0xffff); i++) {
1495
if(id == typeinfo->func_indices[i]) {
1496
next_idx = typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] >> 16;
1497
typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] &= 0xffff;
1498
typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] |= (index << 16);
1499
break;
1500
}
1501
}
1502
1503
/* fill out the basic type information */
1504
typedata[0] = typedata_size | (index << 16);
1505
encode_var(typeinfo->typelib, type_function_get_rettype(func->declspec.type), func,
1506
&typedata[1], &decoded_size);
1507
typedata[2] = funcflags;
1508
typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft;
1509
typedata[4] = (next_idx << 16) | (callconv << 8) | (invokekind << 3) | funckind;
1510
if(has_arg_custdata || func_custdata_offset != -1) typedata[4] |= 0x0080;
1511
if(num_defaults) typedata[4] |= 0x1000;
1512
if(entry_is_ord) typedata[4] |= 0x2000;
1513
typedata[5] = (num_optional << 16) | num_params;
1514
1515
/* NOTE: High word of typedata[3] is total size of FUNCDESC + size of all ELEMDESCs for params + TYPEDESCs for pointer params and return types. */
1516
/* That is, total memory allocation required to reconstitute the FUNCDESC in its entirety. */
1517
typedata[3] += (16 /*sizeof(ELEMDESC)*/ * num_params) << 16;
1518
typedata[3] += (24 /*sizeof(PARAMDESCEX)*/ * num_defaults) << 16;
1519
1520
switch(extra_attr) {
1521
default:
1522
if(extra_attr > 7 + num_params) warning("unknown number of optional attrs\n");
1523
/* typedata[13..+num_params] = arg_custdata_offset handled in below loop */
1524
case 7: typedata[12] = func_custdata_offset;
1525
case 6: typedata[11] = help_string_context;
1526
case 5: typedata[10] = -1;
1527
case 4: typedata[9] = -1;
1528
case 3: typedata[8] = entry;
1529
case 2: typedata[7] = help_string_offset;
1530
case 1: typedata[6] = help_context;
1531
case 0:
1532
break;
1533
}
1534
1535
if (type_function_get_args(func->declspec.type))
1536
{
1537
i = 0;
1538
LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), var_t, entry )
1539
{
1540
int paramflags = 0;
1541
int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3;
1542
int *defaultdata = num_defaults ? typedata + 6 + extra_attr + i : NULL;
1543
int arg_custdata_offset = -1;
1544
1545
if(defaultdata) *defaultdata = -1;
1546
1547
encode_var(typeinfo->typelib, arg->declspec.type, arg, paramdata, &decoded_size);
1548
if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) {
1549
switch(attr->type) {
1550
case ATTR_CUSTOM:
1551
set_custdata_attr(typeinfo->typelib, attr->u.pval, &arg_custdata_offset);
1552
break;
1553
case ATTR_DEFAULTVALUE:
1554
{
1555
paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */
1556
write_default_value(typeinfo->typelib, arg->declspec.type, (expr_t *)attr->u.pval, defaultdata);
1557
break;
1558
}
1559
case ATTR_IN:
1560
paramflags |= 0x01; /* PARAMFLAG_FIN */
1561
break;
1562
case ATTR_OPTIONAL:
1563
paramflags |= 0x10; /* PARAMFLAG_FOPT */
1564
break;
1565
case ATTR_OUT:
1566
paramflags |= 0x02; /* PARAMFLAG_FOUT */
1567
break;
1568
case ATTR_PARAMLCID:
1569
paramflags |= 0x04; /* PARAMFLAG_LCID */
1570
lcid_retval_count++;
1571
break;
1572
case ATTR_RETVAL:
1573
paramflags |= 0x08; /* PARAMFLAG_FRETVAL */
1574
lcid_retval_count++;
1575
break;
1576
default:
1577
chat("unhandled param attr %d\n", attr->type);
1578
break;
1579
}
1580
if(extra_attr > 7 + i) {
1581
typedata[13+i] = arg_custdata_offset;
1582
}
1583
}
1584
paramdata[1] = -1;
1585
paramdata[2] = paramflags;
1586
typedata[3] += decoded_size << 16;
1587
1588
i++;
1589
}
1590
}
1591
1592
if(lcid_retval_count == 1)
1593
typedata[4] |= 0x4000;
1594
else if(lcid_retval_count == 2)
1595
typedata[4] |= 0x8000;
1596
1597
if(typeinfo->funcs_allocated == 0) {
1598
typeinfo->funcs_allocated = 10;
1599
typeinfo->func_indices = xmalloc(typeinfo->funcs_allocated * sizeof(int));
1600
typeinfo->func_names = xmalloc(typeinfo->funcs_allocated * sizeof(int));
1601
typeinfo->func_offsets = xmalloc(typeinfo->funcs_allocated * sizeof(int));
1602
}
1603
if(typeinfo->funcs_allocated == (typeinfo->typeinfo->cElement & 0xffff)) {
1604
typeinfo->funcs_allocated *= 2;
1605
typeinfo->func_indices = xrealloc(typeinfo->func_indices, typeinfo->funcs_allocated * sizeof(int));
1606
typeinfo->func_names = xrealloc(typeinfo->func_names, typeinfo->funcs_allocated * sizeof(int));
1607
typeinfo->func_offsets = xrealloc(typeinfo->func_offsets, typeinfo->funcs_allocated * sizeof(int));
1608
}
1609
1610
/* update the index data */
1611
typeinfo->func_indices[typeinfo->typeinfo->cElement & 0xffff] = id;
1612
typeinfo->func_offsets[typeinfo->typeinfo->cElement & 0xffff] = offset;
1613
typeinfo->func_names[typeinfo->typeinfo->cElement & 0xffff] = name_offset;
1614
1615
/* ??? */
1616
if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x20;
1617
typeinfo->typeinfo->res2 <<= 1;
1618
/* ??? */
1619
if (index < 2) typeinfo->typeinfo->res2 += num_params << 4;
1620
1621
if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0;
1622
typeinfo->typeinfo->res3 += 0x38 + num_params * 0x10;
1623
if(num_defaults) typeinfo->typeinfo->res3 += num_params * 0x4;
1624
1625
/* adjust size of VTBL */
1626
if(funckind != 0x3 /* FUNC_STATIC */)
1627
typeinfo->typeinfo->cbSizeVft += pointer_size;
1628
1629
/* Increment the number of function elements */
1630
typeinfo->typeinfo->cElement += 1;
1631
1632
namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + name_offset;
1633
if (*((int *)namedata) == -1) {
1634
*((int *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16];
1635
if(typeinfo->typekind == TKIND_MODULE)
1636
namedata[9] |= 0x10;
1637
} else
1638
namedata[9] &= ~0x10;
1639
1640
if(typeinfo->typekind == TKIND_MODULE)
1641
namedata[9] |= 0x20;
1642
1643
if (type_function_get_args(func->declspec.type))
1644
{
1645
i = 0;
1646
LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), var_t, entry )
1647
{
1648
/* don't give the last arg of a [propput*] func a name */
1649
if(i != num_params - 1 || (invokekind != 0x4 /* INVOKE_PROPERTYPUT */ && invokekind != 0x8 /* INVOKE_PROPERTYPUTREF */))
1650
{
1651
int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3;
1652
offset = ctl2_alloc_name(typeinfo->typelib, arg->name);
1653
paramdata[1] = offset;
1654
}
1655
i++;
1656
}
1657
}
1658
return TRUE;
1659
}
1660
1661
static void add_var_desc(msft_typeinfo_t *typeinfo, unsigned int index, var_t* var)
1662
{
1663
int offset, id;
1664
unsigned int typedata_size;
1665
int extra_attr = 0;
1666
int *typedata;
1667
unsigned int var_datawidth, var_alignment = 0;
1668
int var_type_size, var_kind = 0 /* VAR_PERINSTANCE */;
1669
int alignment;
1670
int varflags = 0;
1671
const attr_t *attr;
1672
unsigned char *namedata;
1673
int var_num = (typeinfo->typeinfo->cElement >> 16) & 0xffff;
1674
int var_custdata_offset = -1;
1675
1676
if (!var->name)
1677
var->name = gen_name();
1678
1679
chat("add_var_desc(%d, %s)\n", index, var->name);
1680
1681
id = 0x40000000 + index;
1682
1683
if (var->attrs) LIST_FOR_EACH_ENTRY( attr, var->attrs, const attr_t, entry ) {
1684
expr_t *expr = attr->u.pval;
1685
switch(attr->type) {
1686
case ATTR_BINDABLE:
1687
varflags |= 0x04; /* VARFLAG_FBINDABLE */
1688
break;
1689
case ATTR_CUSTOM:
1690
extra_attr = max(extra_attr,4);
1691
set_custdata_attr(typeinfo->typelib, attr->u.pval, &var_custdata_offset);
1692
break;
1693
case ATTR_DEFAULTBIND:
1694
varflags |= 0x20; /* VARFLAG_FDEFAULTBIND */
1695
break;
1696
case ATTR_DEFAULTCOLLELEM:
1697
varflags |= 0x100; /* VARFLAG_FDEFAULTCOLLELEM */
1698
break;
1699
case ATTR_DISPLAYBIND:
1700
varflags |= 0x10; /* VARFLAG_FDISPLAYBIND */
1701
break;
1702
case ATTR_HIDDEN:
1703
varflags |= 0x40; /* VARFLAG_FHIDDEN */
1704
break;
1705
case ATTR_ID:
1706
id = expr->cval;
1707
break;
1708
case ATTR_IMMEDIATEBIND:
1709
varflags |= 0x1000; /* VARFLAG_FIMMEDIATEBIND */
1710
break;
1711
case ATTR_NONBROWSABLE:
1712
varflags |= 0x400; /* VARFLAG_FNONBROWSABLE */
1713
break;
1714
case ATTR_READONLY:
1715
varflags |= 0x01; /* VARFLAG_FREADONLY */
1716
break;
1717
/* FIXME: VARFLAG_FREPLACEABLE */
1718
case ATTR_REQUESTEDIT:
1719
varflags |= 0x08; /* VARFLAG_FREQUESTEDIT */
1720
break;
1721
case ATTR_RESTRICTED:
1722
varflags |= 0x80; /* VARFLAG_FRESTRICTED */
1723
break;
1724
case ATTR_SOURCE:
1725
varflags |= 0x02; /* VARFLAG_FSOURCE */
1726
break;
1727
case ATTR_UIDEFAULT:
1728
varflags |= 0x0200; /* VARFLAG_FUIDEFAULT */
1729
break;
1730
default:
1731
break;
1732
}
1733
}
1734
1735
/* allocate type data space for us */
1736
typedata_size = 0x14 + extra_attr * sizeof(int);
1737
1738
if (!typeinfo->var_data) {
1739
typeinfo->var_data = xmalloc(0x100);
1740
typeinfo->var_data_allocated = 0x100;
1741
typeinfo->var_data[0] = 0;
1742
}
1743
1744
if(typeinfo->var_data[0] + typedata_size + sizeof(int) > typeinfo->var_data_allocated) {
1745
typeinfo->var_data_allocated = max(typeinfo->var_data_allocated * 2,
1746
typeinfo->var_data[0] + typedata_size + sizeof(int));
1747
typeinfo->var_data = xrealloc(typeinfo->var_data, typeinfo->var_data_allocated);
1748
}
1749
1750
offset = typeinfo->var_data[0];
1751
typeinfo->var_data[0] += typedata_size;
1752
typedata = typeinfo->var_data + (offset >> 2) + 1;
1753
1754
/* fill out the basic type information */
1755
typedata[0] = typedata_size | (index << 16);
1756
typedata[2] = varflags;
1757
typedata[3] = (36 /*sizeof(VARDESC)*/ << 16) | 0;
1758
1759
if(typeinfo->vars_allocated == 0) {
1760
typeinfo->vars_allocated = 10;
1761
typeinfo->var_indices = xmalloc(typeinfo->vars_allocated * sizeof(int));
1762
typeinfo->var_names = xmalloc(typeinfo->vars_allocated * sizeof(int));
1763
typeinfo->var_offsets = xmalloc(typeinfo->vars_allocated * sizeof(int));
1764
}
1765
if(typeinfo->vars_allocated == var_num) {
1766
typeinfo->vars_allocated *= 2;
1767
typeinfo->var_indices = xrealloc(typeinfo->var_indices, typeinfo->vars_allocated * sizeof(int));
1768
typeinfo->var_names = xrealloc(typeinfo->var_names, typeinfo->vars_allocated * sizeof(int));
1769
typeinfo->var_offsets = xrealloc(typeinfo->var_offsets, typeinfo->vars_allocated * sizeof(int));
1770
}
1771
/* update the index data */
1772
typeinfo->var_indices[var_num] = id;
1773
typeinfo->var_names[var_num] = -1;
1774
typeinfo->var_offsets[var_num] = offset;
1775
1776
/* figure out type widths and whatnot */
1777
var_datawidth = type_memsize_and_alignment(var->declspec.type, &var_alignment);
1778
encode_var(typeinfo->typelib, var->declspec.type, var, &typedata[1], &var_type_size);
1779
1780
/* pad out starting position to data width */
1781
typeinfo->datawidth += var_alignment - 1;
1782
typeinfo->datawidth &= ~(var_alignment - 1);
1783
1784
switch(typeinfo->typekind) {
1785
case TKIND_ENUM:
1786
write_int_value(typeinfo->typelib, &typedata[4], VT_I4, var->eval->cval);
1787
var_kind = 2; /* VAR_CONST */
1788
var_type_size += 16; /* sizeof(VARIANT) */
1789
typeinfo->datawidth = var_datawidth;
1790
break;
1791
case TKIND_RECORD:
1792
typedata[4] = typeinfo->datawidth;
1793
typeinfo->datawidth += var_datawidth;
1794
break;
1795
case TKIND_UNION:
1796
typedata[4] = 0;
1797
typeinfo->datawidth = max(typeinfo->datawidth, var_datawidth);
1798
break;
1799
case TKIND_DISPATCH:
1800
var_kind = 3; /* VAR_DISPATCH */
1801
typedata[4] = 0;
1802
typeinfo->datawidth = pointer_size;
1803
break;
1804
default:
1805
error("add_var_desc: unhandled type kind %d\n", typeinfo->typekind);
1806
break;
1807
}
1808
1809
/* add type description size to total required allocation */
1810
typedata[3] += var_type_size << 16 | var_kind;
1811
1812
switch(extra_attr) {
1813
case 5: typedata[9] = -1 /*help_string_context*/;
1814
case 4: typedata[8] = var_custdata_offset;
1815
case 3: typedata[7] = -1;
1816
case 2: typedata[6] = -1 /*help_string_offset*/;
1817
case 1: typedata[5] = -1 /*help_context*/;
1818
case 0:
1819
break;
1820
default:
1821
warning("unknown number of optional attrs\n");
1822
}
1823
1824
/* fix type alignment */
1825
alignment = (typeinfo->typeinfo->typekind >> 11) & 0x1f;
1826
if (alignment < var_alignment) {
1827
alignment = var_alignment;
1828
typeinfo->typeinfo->typekind &= ~0xffc0;
1829
typeinfo->typeinfo->typekind |= alignment << 11 | alignment << 6;
1830
}
1831
1832
/* ??? */
1833
if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x1a;
1834
if ((index == 0) || (index == 1) || (index == 2) || (index == 4) || (index == 9)) {
1835
typeinfo->typeinfo->res2 <<= 1;
1836
}
1837
1838
/* ??? */
1839
if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0;
1840
typeinfo->typeinfo->res3 += 0x2c;
1841
1842
/* increment the number of variable elements */
1843
typeinfo->typeinfo->cElement += 0x10000;
1844
1845
/* pad data width to alignment */
1846
typeinfo->typeinfo->size = (typeinfo->datawidth + (alignment - 1)) & ~(alignment - 1);
1847
1848
offset = ctl2_alloc_name(typeinfo->typelib, var->name);
1849
1850
namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset;
1851
if (*((int *)namedata) == -1) {
1852
*((int *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16];
1853
if(typeinfo->typekind != TKIND_DISPATCH)
1854
namedata[9] |= 0x10;
1855
} else
1856
namedata[9] &= ~0x10;
1857
1858
if (typeinfo->typekind == TKIND_ENUM) {
1859
namedata[9] |= 0x20;
1860
}
1861
typeinfo->var_names[var_num] = offset;
1862
}
1863
1864
static void add_impl_type(msft_typeinfo_t *typeinfo, type_t *ref, importinfo_t *importinfo)
1865
{
1866
if(importinfo) {
1867
alloc_importinfo(typeinfo->typelib, importinfo);
1868
typeinfo->typeinfo->datatype1 = importinfo->offset+1;
1869
}else {
1870
if(ref->typelib_idx == -1)
1871
add_interface_typeinfo(typeinfo->typelib, ref);
1872
if(ref->typelib_idx == -1)
1873
error("add_impl_type: unable to add inherited interface\n");
1874
1875
typeinfo->typeinfo->datatype1 = typeinfo->typelib->typelib_typeinfo_offsets[ref->typelib_idx];
1876
}
1877
1878
typeinfo->typeinfo->cImplTypes++;
1879
}
1880
1881
static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_kind kind,
1882
const char *name, const attr_list_t *attrs)
1883
{
1884
const attr_t *attr;
1885
msft_typeinfo_t *msft_typeinfo;
1886
int nameoffset;
1887
int typeinfo_offset;
1888
MSFT_TypeInfoBase *typeinfo;
1889
MSFT_GuidEntry guidentry;
1890
1891
chat("create_msft_typeinfo: name %s kind %d index %d\n", name, kind, typelib->typelib_header.nrtypeinfos);
1892
1893
msft_typeinfo = xmalloc(sizeof(*msft_typeinfo));
1894
memset( msft_typeinfo, 0, sizeof(*msft_typeinfo) );
1895
1896
msft_typeinfo->typelib = typelib;
1897
1898
nameoffset = ctl2_alloc_name(typelib, name);
1899
typeinfo_offset = ctl2_alloc_typeinfo(typelib, nameoffset);
1900
typeinfo = (MSFT_TypeInfoBase *)&typelib->typelib_segment_data[MSFT_SEG_TYPEINFO][typeinfo_offset];
1901
1902
typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset + 9] = 0x38;
1903
*((int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset]) = typeinfo_offset;
1904
1905
msft_typeinfo->typekind = kind;
1906
msft_typeinfo->typeinfo = typeinfo;
1907
1908
typeinfo->typekind |= kind | 0x20;
1909
1910
if(kind == TKIND_COCLASS)
1911
typeinfo->flags |= 0x2; /* TYPEFLAG_FCANCREATE */
1912
1913
if (attrs) LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) {
1914
switch(attr->type) {
1915
case ATTR_AGGREGATABLE:
1916
if (kind == TKIND_COCLASS)
1917
typeinfo->flags |= 0x400; /* TYPEFLAG_FAGGREGATABLE */
1918
break;
1919
1920
case ATTR_APPOBJECT:
1921
if (kind == TKIND_COCLASS)
1922
typeinfo->flags |= 0x1; /* TYPEFLAG_FAPPOBJECT */
1923
break;
1924
1925
case ATTR_CONTROL:
1926
if (kind == TKIND_COCLASS)
1927
typeinfo->flags |= 0x20; /* TYPEFLAG_FCONTROL */
1928
break;
1929
case ATTR_CUSTOM:
1930
set_custdata_attr(typelib, attr->u.pval, &typeinfo->oCustData);
1931
break;
1932
case ATTR_DLLNAME:
1933
{
1934
int offset = ctl2_alloc_string(typelib, attr->u.pval);
1935
typeinfo->datatype1 = offset;
1936
break;
1937
}
1938
1939
case ATTR_DUAL:
1940
/* FIXME: check interface is compatible */
1941
typeinfo->typekind = (typeinfo->typekind & ~0xff) | 0x34;
1942
typeinfo->flags |= 0x140; /* TYPEFLAG_FDUAL | TYPEFLAG_FOLEAUTOMATION */
1943
break;
1944
1945
case ATTR_HELPCONTEXT:
1946
{
1947
expr_t *expr = (expr_t*)attr->u.pval;
1948
typeinfo->helpcontext = expr->cval;
1949
break;
1950
}
1951
case ATTR_HELPSTRING:
1952
{
1953
int offset = ctl2_alloc_string(typelib, attr->u.pval);
1954
if (offset == -1) break;
1955
typeinfo->docstringoffs = offset;
1956
break;
1957
}
1958
case ATTR_HELPSTRINGCONTEXT:
1959
{
1960
expr_t *expr = (expr_t*)attr->u.pval;
1961
typeinfo->helpstringcontext = expr->cval;
1962
break;
1963
}
1964
case ATTR_HIDDEN:
1965
typeinfo->flags |= 0x10; /* TYPEFLAG_FHIDDEN */
1966
break;
1967
1968
case ATTR_LICENSED:
1969
typeinfo->flags |= 0x04; /* TYPEFLAG_FLICENSED */
1970
break;
1971
1972
case ATTR_NONCREATABLE:
1973
typeinfo->flags &= ~0x2; /* TYPEFLAG_FCANCREATE */
1974
break;
1975
1976
case ATTR_NONEXTENSIBLE:
1977
typeinfo->flags |= 0x80; /* TYPEFLAG_FNONEXTENSIBLE */
1978
break;
1979
1980
case ATTR_OLEAUTOMATION:
1981
typeinfo->flags |= 0x100; /* TYPEFLAG_FOLEAUTOMATION */
1982
break;
1983
1984
/* FIXME: TYPEFLAG_FPREDCLID */
1985
1986
case ATTR_PROXY:
1987
typeinfo->flags |= 0x4000; /* TYPEFLAG_FPROXY */
1988
break;
1989
1990
/* FIXME: TYPEFLAG_FREPLACEABLE */
1991
1992
case ATTR_RESTRICTED:
1993
typeinfo->flags |= 0x200; /* TYPEFLAG_FRESTRICTED */
1994
break;
1995
1996
case ATTR_UUID:
1997
guidentry.guid = *(struct uuid *)attr->u.pval;
1998
guidentry.hreftype = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16];
1999
guidentry.next_hash = -1;
2000
typeinfo->posguid = ctl2_alloc_guid(typelib, &guidentry);
2001
#if 0
2002
if (IsEqualIID(guid, &IID_IDispatch)) {
2003
typelib->typelib_header.dispatchpos = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16];
2004
}
2005
#endif
2006
break;
2007
2008
case ATTR_VERSION:
2009
{
2010
const version_t *version = attr->u.pval;
2011
unsigned short major = version ? version->major : 0, minor = version ? version->minor : 0;
2012
2013
typeinfo->version = (minor << 16) | major;
2014
break;
2015
}
2016
default:
2017
break;
2018
}
2019
}
2020
2021
if (typelib->last_typeinfo) typelib->last_typeinfo->next_typeinfo = msft_typeinfo;
2022
typelib->last_typeinfo = msft_typeinfo;
2023
if (!typelib->typeinfos) typelib->typeinfos = msft_typeinfo;
2024
2025
2026
return msft_typeinfo;
2027
}
2028
2029
static void add_dispatch(msft_typelib_t *typelib)
2030
{
2031
int guid_offset, impfile_offset, hash_key;
2032
MSFT_GuidEntry guidentry;
2033
MSFT_ImpInfo impinfo;
2034
static const struct uuid stdole = {0x00020430,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
2035
static const struct uuid iid_idispatch = {0x00020400,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
2036
2037
if(typelib->typelib_header.dispatchpos != -1) return;
2038
2039
guidentry.guid = stdole;
2040
guidentry.hreftype = 2;
2041
guidentry.next_hash = -1;
2042
hash_key = ctl2_hash_guid(&guidentry.guid);
2043
guid_offset = ctl2_find_guid(typelib, hash_key, &guidentry.guid);
2044
if (guid_offset == -1)
2045
guid_offset = ctl2_alloc_guid(typelib, &guidentry);
2046
impfile_offset = alloc_importfile(typelib, guid_offset, 2, 0, "stdole2.tlb");
2047
2048
guidentry.guid = iid_idispatch;
2049
guidentry.hreftype = 1;
2050
guidentry.next_hash = -1;
2051
impinfo.flags = TKIND_INTERFACE << 24 | MSFT_IMPINFO_OFFSET_IS_GUID;
2052
impinfo.oImpFile = impfile_offset;
2053
hash_key = ctl2_hash_guid(&guidentry.guid);
2054
guid_offset = ctl2_find_guid(typelib, hash_key, &guidentry.guid);
2055
if (guid_offset == -1)
2056
guid_offset = ctl2_alloc_guid(typelib, &guidentry);
2057
impinfo.oGuid = guid_offset;
2058
typelib->typelib_header.dispatchpos = alloc_msft_importinfo(typelib, &impinfo) | 0x01;
2059
}
2060
2061
static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface)
2062
{
2063
int num_parents = 0, num_funcs = 0;
2064
importinfo_t *importinfo = NULL;
2065
const statement_t *stmt_func;
2066
type_t *inherit, *ref;
2067
int idx = 0;
2068
var_t *func;
2069
var_t *var;
2070
msft_typeinfo_t *msft_typeinfo;
2071
2072
if (-1 < dispinterface->typelib_idx)
2073
return;
2074
2075
inherit = type_dispiface_get_inherit(dispinterface);
2076
2077
if (inherit)
2078
{
2079
importinfo = find_importinfo(typelib, inherit->name);
2080
2081
if (!importinfo && type_iface_get_inherit(inherit) && inherit->typelib_idx == -1)
2082
add_interface_typeinfo(typelib, inherit);
2083
}
2084
2085
/* check typelib_idx again, it could have been added while resolving the parent interface */
2086
if (-1 < dispinterface->typelib_idx)
2087
return;
2088
2089
dispinterface->typelib_idx = typelib->typelib_header.nrtypeinfos;
2090
msft_typeinfo = create_msft_typeinfo(typelib, TKIND_DISPATCH, dispinterface->name,
2091
dispinterface->attrs);
2092
2093
msft_typeinfo->typeinfo->size = pointer_size;
2094
msft_typeinfo->typeinfo->typekind |= pointer_size << 11 | pointer_size << 6;
2095
2096
msft_typeinfo->typeinfo->flags |= 0x1000; /* TYPEFLAG_FDISPATCHABLE */
2097
add_dispatch(typelib);
2098
2099
if (inherit)
2100
{
2101
add_impl_type(msft_typeinfo, inherit, importinfo);
2102
msft_typeinfo->typeinfo->typekind |= 0x10;
2103
}
2104
2105
/* count the number of inherited interfaces and non-local functions */
2106
for (ref = inherit; ref; ref = type_iface_get_inherit(ref))
2107
{
2108
num_parents++;
2109
STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(ref) )
2110
{
2111
var_t *func = stmt_func->u.var;
2112
if (!is_local(func->attrs)) num_funcs++;
2113
}
2114
}
2115
msft_typeinfo->typeinfo->datatype2 = num_funcs << 16 | num_parents;
2116
msft_typeinfo->typeinfo->cbSizeVft = num_funcs * pointer_size;
2117
2118
msft_typeinfo->typeinfo->cImplTypes = 1; /* IDispatch */
2119
2120
/* count the no of methods, as the variable indices come after the funcs */
2121
if (dispinterface->details.iface->disp_methods)
2122
LIST_FOR_EACH_ENTRY( func, dispinterface->details.iface->disp_methods, var_t, entry )
2123
idx++;
2124
2125
if (type_dispiface_get_props(dispinterface))
2126
LIST_FOR_EACH_ENTRY( var, type_dispiface_get_props(dispinterface), var_t, entry )
2127
add_var_desc(msft_typeinfo, idx++, var);
2128
2129
if (type_dispiface_get_methods(dispinterface))
2130
{
2131
idx = 0;
2132
LIST_FOR_EACH_ENTRY( func, type_dispiface_get_methods(dispinterface), var_t, entry )
2133
if(add_func_desc(msft_typeinfo, func, idx))
2134
idx++;
2135
}
2136
2137
typelib->typelib->reg_ifaces = xrealloc(typelib->typelib->reg_ifaces,
2138
(typelib->typelib->reg_iface_count + 1) * sizeof(dispinterface));
2139
typelib->typelib->reg_ifaces[typelib->typelib->reg_iface_count++] = dispinterface;
2140
}
2141
2142
static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface)
2143
{
2144
int idx = 0;
2145
const statement_t *stmt_func;
2146
type_t *ref;
2147
msft_typeinfo_t *msft_typeinfo;
2148
importinfo_t *ref_importinfo = NULL;
2149
int num_parents = 0, num_funcs = 0;
2150
type_t *inherit;
2151
const type_t *derived;
2152
2153
if (-1 < interface->typelib_idx)
2154
return;
2155
2156
if (!interface->details.iface)
2157
{
2158
error( "interface %s is referenced but not defined\n", interface->name );
2159
return;
2160
}
2161
2162
if (is_attr(interface->attrs, ATTR_DISPINTERFACE)) {
2163
add_dispinterface_typeinfo(typelib, interface);
2164
return;
2165
}
2166
2167
/* midl adds the parent interface first, unless the parent itself
2168
has no parent (i.e. it stops before IUnknown). */
2169
2170
inherit = type_iface_get_inherit(interface);
2171
2172
if(inherit) {
2173
ref_importinfo = find_importinfo(typelib, inherit->name);
2174
2175
if(!ref_importinfo && type_iface_get_inherit(inherit) &&
2176
inherit->typelib_idx == -1)
2177
add_interface_typeinfo(typelib, inherit);
2178
}
2179
2180
/* check typelib_idx again, it could have been added while resolving the parent interface */
2181
if (-1 < interface->typelib_idx)
2182
return;
2183
2184
interface->typelib_idx = typelib->typelib_header.nrtypeinfos;
2185
msft_typeinfo = create_msft_typeinfo(typelib, TKIND_INTERFACE, interface->name, interface->attrs);
2186
msft_typeinfo->typeinfo->size = pointer_size;
2187
msft_typeinfo->typeinfo->typekind |= 0x0200;
2188
msft_typeinfo->typeinfo->typekind |= pointer_size << 11;
2189
2190
for (derived = inherit; derived; derived = type_iface_get_inherit(derived))
2191
if (derived->name && !strcmp(derived->name, "IDispatch"))
2192
msft_typeinfo->typeinfo->flags |= 0x1000; /* TYPEFLAG_FDISPATCHABLE */
2193
2194
if(type_iface_get_inherit(interface))
2195
add_impl_type(msft_typeinfo, type_iface_get_inherit(interface),
2196
ref_importinfo);
2197
2198
/* count the number of inherited interfaces and non-local functions */
2199
for(ref = inherit; ref; ref = type_iface_get_inherit(ref)) {
2200
num_parents++;
2201
STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(ref) ) {
2202
var_t *func = stmt_func->u.var;
2203
if (!is_local(func->attrs)) num_funcs++;
2204
}
2205
}
2206
msft_typeinfo->typeinfo->datatype2 = num_funcs << 16 | num_parents;
2207
msft_typeinfo->typeinfo->cbSizeVft = num_funcs * pointer_size;
2208
2209
STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(interface) ) {
2210
var_t *func = stmt_func->u.var;
2211
if(add_func_desc(msft_typeinfo, func, idx))
2212
idx++;
2213
}
2214
2215
if (is_attr(interface->attrs, ATTR_OLEAUTOMATION) || is_attr(interface->attrs, ATTR_DUAL))
2216
{
2217
typelib->typelib->reg_ifaces = xrealloc(typelib->typelib->reg_ifaces,
2218
(typelib->typelib->reg_iface_count + 1) * sizeof(interface));
2219
typelib->typelib->reg_ifaces[typelib->typelib->reg_iface_count++] = interface;
2220
}
2221
}
2222
2223
static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure)
2224
{
2225
var_list_t *fields;
2226
int idx = 0;
2227
var_t *cur;
2228
msft_typeinfo_t *msft_typeinfo;
2229
2230
if (-1 < structure->typelib_idx)
2231
return;
2232
2233
if (!structure->name)
2234
structure->name = gen_name();
2235
2236
structure->typelib_idx = typelib->typelib_header.nrtypeinfos;
2237
msft_typeinfo = create_msft_typeinfo(typelib, TKIND_RECORD, structure->name, structure->attrs);
2238
msft_typeinfo->typeinfo->size = 0;
2239
2240
if (type_get_type(structure) == TYPE_STRUCT)
2241
fields = type_struct_get_fields(structure);
2242
else
2243
fields = type_encapsulated_union_get_fields(structure);
2244
2245
if (fields)
2246
{
2247
LIST_FOR_EACH_ENTRY( cur, fields, var_t, entry )
2248
add_var_desc(msft_typeinfo, idx++, cur);
2249
}
2250
}
2251
2252
static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration)
2253
{
2254
int idx = 0;
2255
var_t *cur;
2256
msft_typeinfo_t *msft_typeinfo;
2257
2258
if (-1 < enumeration->typelib_idx)
2259
return;
2260
2261
enumeration->typelib_idx = typelib->typelib_header.nrtypeinfos;
2262
msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ENUM, enumeration->name, enumeration->attrs);
2263
msft_typeinfo->typeinfo->size = 0;
2264
2265
if (type_enum_get_values(enumeration))
2266
LIST_FOR_EACH_ENTRY( cur, type_enum_get_values(enumeration), var_t, entry )
2267
add_var_desc(msft_typeinfo, idx++, cur);
2268
}
2269
2270
static void add_union_typeinfo(msft_typelib_t *typelib, type_t *tunion)
2271
{
2272
int idx = 0;
2273
var_t *cur;
2274
msft_typeinfo_t *msft_typeinfo;
2275
2276
if (-1 < tunion->typelib_idx)
2277
return;
2278
2279
if (!tunion->name)
2280
tunion->name = gen_name();
2281
2282
tunion->typelib_idx = typelib->typelib_header.nrtypeinfos;
2283
msft_typeinfo = create_msft_typeinfo(typelib, TKIND_UNION, tunion->name, tunion->attrs);
2284
msft_typeinfo->typeinfo->size = 0;
2285
2286
if (type_union_get_cases(tunion))
2287
LIST_FOR_EACH_ENTRY(cur, type_union_get_cases(tunion), var_t, entry)
2288
add_var_desc(msft_typeinfo, idx++, cur);
2289
}
2290
2291
static void add_typedef_typeinfo(msft_typelib_t *typelib, type_t *tdef)
2292
{
2293
msft_typeinfo_t *msft_typeinfo = NULL;
2294
int datatype1, datatype2, duplicate = 0;
2295
unsigned int size, alignment = 0;
2296
type_t *type;
2297
2298
if (-1 < tdef->typelib_idx)
2299
return;
2300
2301
type = type_alias_get_aliasee_type(tdef);
2302
2303
if (!type->name || strcmp(tdef->name, type->name) != 0)
2304
{
2305
tdef->typelib_idx = typelib->typelib_header.nrtypeinfos;
2306
msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ALIAS, tdef->name, tdef->attrs);
2307
}
2308
else
2309
duplicate = 1;
2310
2311
encode_type(typelib, get_type_vt(type), type, &datatype1, &datatype2);
2312
size = type_memsize_and_alignment(type, &alignment);
2313
2314
if (msft_typeinfo)
2315
{
2316
msft_typeinfo->typeinfo->datatype1 = datatype1;
2317
msft_typeinfo->typeinfo->size = size;
2318
msft_typeinfo->typeinfo->datatype2 = datatype2;
2319
msft_typeinfo->typeinfo->typekind |= (alignment << 11 | alignment << 6);
2320
}
2321
2322
/* avoid adding duplicate type definitions */
2323
if (duplicate)
2324
tdef->typelib_idx = type->typelib_idx;
2325
}
2326
2327
static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls)
2328
{
2329
msft_typeinfo_t *msft_typeinfo;
2330
typeref_t *iref;
2331
int num_ifaces = 0, offset, i;
2332
MSFT_RefRecord *ref, *first = NULL, *first_source = NULL;
2333
int have_default = 0, have_default_source = 0;
2334
const attr_t *attr;
2335
typeref_list_t *ifaces;
2336
2337
if (-1 < cls->typelib_idx)
2338
return;
2339
2340
cls->typelib_idx = typelib->typelib_header.nrtypeinfos;
2341
msft_typeinfo = create_msft_typeinfo(typelib, TKIND_COCLASS, cls->name, cls->attrs);
2342
2343
ifaces = type_coclass_get_ifaces(cls);
2344
if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, typeref_t, entry ) num_ifaces++;
2345
2346
offset = msft_typeinfo->typeinfo->datatype1 = ctl2_alloc_segment(typelib, MSFT_SEG_REFERENCES,
2347
num_ifaces * sizeof(*ref), 0);
2348
2349
i = 0;
2350
if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, typeref_t, entry ) {
2351
if(iref->type->typelib_idx == -1)
2352
add_interface_typeinfo(typelib, iref->type);
2353
ref = (MSFT_RefRecord*) (typelib->typelib_segment_data[MSFT_SEG_REFERENCES] + offset + i * sizeof(*ref));
2354
ref->reftype = typelib->typelib_typeinfo_offsets[iref->type->typelib_idx];
2355
ref->flags = 0;
2356
ref->oCustData = -1;
2357
ref->onext = -1;
2358
if(i < num_ifaces - 1)
2359
ref->onext = offset + (i + 1) * sizeof(*ref);
2360
2361
if (iref->attrs) LIST_FOR_EACH_ENTRY( attr, iref->attrs, const attr_t, entry ) {
2362
switch(attr->type) {
2363
case ATTR_DEFAULT:
2364
ref->flags |= 0x1; /* IMPLTYPEFLAG_FDEFAULT */
2365
break;
2366
case ATTR_DEFAULTVTABLE:
2367
ref->flags |= 0x8; /* IMPLTYPEFLAG_FDEFAULTVTABLE */
2368
break;
2369
case ATTR_RESTRICTED:
2370
ref->flags |= 0x4; /* IMPLTYPEFLAG_FRESTRICTED */
2371
break;
2372
case ATTR_SOURCE:
2373
ref->flags |= 0x2; /* IMPLTYPEFLAG_FSOURCE */
2374
break;
2375
default:
2376
warning("add_coclass_typeinfo: unhandled attr %d\n", attr->type);
2377
}
2378
}
2379
if(ref->flags & 0x1) { /* IMPLTYPEFLAG_FDEFAULT */
2380
if(ref->flags & 0x2) /* IMPLTYPEFLAG_SOURCE */
2381
have_default_source = 1;
2382
else
2383
have_default = 1;
2384
}
2385
2386
/* If the interface is non-restricted and we haven't already had one then
2387
remember it so that we can use it as a default later */
2388
if((ref->flags & 0x4) == 0) { /* IMPLTYPEFLAG_FRESTRICTED */
2389
if(ref->flags & 0x2) { /* IMPLTYPEFLAG_FSOURCE */
2390
if(!first_source)
2391
first_source = ref;
2392
}
2393
else if(!first)
2394
first = ref;
2395
}
2396
i++;
2397
}
2398
2399
/* If we haven't had a default interface, then set the default flags on the
2400
first ones */
2401
if(!have_default && first)
2402
first->flags |= 0x1;
2403
if(!have_default_source && first_source)
2404
first_source->flags |= 0x1;
2405
2406
msft_typeinfo->typeinfo->cImplTypes = num_ifaces;
2407
msft_typeinfo->typeinfo->size = pointer_size;
2408
msft_typeinfo->typeinfo->typekind |= 0x2200;
2409
}
2410
2411
static void add_module_typeinfo(msft_typelib_t *typelib, type_t *module)
2412
{
2413
int idx = 0;
2414
const statement_t *stmt;
2415
msft_typeinfo_t *msft_typeinfo;
2416
2417
if (-1 < module->typelib_idx)
2418
return;
2419
2420
module->typelib_idx = typelib->typelib_header.nrtypeinfos;
2421
msft_typeinfo = create_msft_typeinfo(typelib, TKIND_MODULE, module->name, module->attrs);
2422
msft_typeinfo->typeinfo->typekind |= 0x0a00;
2423
2424
STATEMENTS_FOR_EACH_FUNC( stmt, module->details.module->stmts ) {
2425
var_t *func = stmt->u.var;
2426
if(add_func_desc(msft_typeinfo, func, idx))
2427
idx++;
2428
}
2429
2430
msft_typeinfo->typeinfo->size = idx;
2431
}
2432
2433
static void add_type_typeinfo(msft_typelib_t *typelib, type_t *type)
2434
{
2435
switch (type_get_type(type)) {
2436
case TYPE_INTERFACE:
2437
add_interface_typeinfo(typelib, type);
2438
break;
2439
case TYPE_STRUCT:
2440
case TYPE_ENCAPSULATED_UNION:
2441
add_structure_typeinfo(typelib, type);
2442
break;
2443
case TYPE_ENUM:
2444
add_enum_typeinfo(typelib, type);
2445
break;
2446
case TYPE_UNION:
2447
add_union_typeinfo(typelib, type);
2448
break;
2449
case TYPE_COCLASS:
2450
add_coclass_typeinfo(typelib, type);
2451
break;
2452
case TYPE_BASIC:
2453
case TYPE_POINTER:
2454
case TYPE_ARRAY:
2455
break;
2456
default:
2457
error("add_entry: unhandled type 0x%x for %s\n",
2458
type_get_type(type), type->name);
2459
break;
2460
}
2461
}
2462
2463
static void add_entry(msft_typelib_t *typelib, const statement_t *stmt)
2464
{
2465
switch(stmt->type) {
2466
case STMT_LIBRARY:
2467
case STMT_IMPORT:
2468
case STMT_PRAGMA:
2469
case STMT_CPPQUOTE:
2470
case STMT_DECLARATION:
2471
/* not included in typelib */
2472
break;
2473
case STMT_IMPORTLIB:
2474
/* not processed here */
2475
break;
2476
case STMT_TYPEDEF:
2477
{
2478
typeref_t *ref;
2479
if (stmt->u.type_list) LIST_FOR_EACH_ENTRY(ref, stmt->u.type_list, typeref_t, entry) {
2480
/* if the type is public then add the typedef, otherwise attempt
2481
* to add the aliased type */
2482
if (is_attr(ref->type->attrs, ATTR_PUBLIC))
2483
add_typedef_typeinfo(typelib, ref->type);
2484
else
2485
add_type_typeinfo(typelib, type_alias_get_aliasee_type(ref->type));
2486
}
2487
break;
2488
}
2489
case STMT_MODULE:
2490
add_module_typeinfo(typelib, stmt->u.type);
2491
break;
2492
case STMT_TYPE:
2493
case STMT_TYPEREF:
2494
{
2495
type_t *type = stmt->u.type;
2496
add_type_typeinfo(typelib, type);
2497
break;
2498
}
2499
}
2500
}
2501
2502
static void set_name(msft_typelib_t *typelib)
2503
{
2504
int offset;
2505
2506
offset = ctl2_alloc_name(typelib, typelib->typelib->name);
2507
if (offset == -1) return;
2508
typelib->typelib_header.NameOffset = offset;
2509
return;
2510
}
2511
2512
static void set_version(msft_typelib_t *typelib)
2513
{
2514
unsigned short major, minor;
2515
2516
get_version( typelib->typelib->attrs, &major, &minor );
2517
typelib->typelib_header.version = (minor << 16) | major;
2518
}
2519
2520
static void set_guid(msft_typelib_t *typelib)
2521
{
2522
MSFT_GuidEntry guidentry = { {0}, -2, -1 };
2523
int offset;
2524
struct uuid *ptr = get_attrp( typelib->typelib->attrs, ATTR_UUID );
2525
2526
if (ptr) guidentry.guid = *ptr;
2527
2528
offset = ctl2_alloc_guid(typelib, &guidentry);
2529
typelib->typelib_header.posguid = offset;
2530
2531
return;
2532
}
2533
2534
static void set_doc_string(msft_typelib_t *typelib)
2535
{
2536
char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRING );
2537
2538
if (str)
2539
{
2540
int offset = ctl2_alloc_string(typelib, str);
2541
if (offset != -1) typelib->typelib_header.helpstring = offset;
2542
}
2543
}
2544
2545
static void set_help_file_name(msft_typelib_t *typelib)
2546
{
2547
char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPFILE );
2548
2549
if (str)
2550
{
2551
int offset = ctl2_alloc_string(typelib, str);
2552
if (offset != -1)
2553
{
2554
typelib->typelib_header.helpfile = offset;
2555
typelib->typelib_header.varflags |= 0x10;
2556
}
2557
}
2558
}
2559
2560
static void set_help_context(msft_typelib_t *typelib)
2561
{
2562
const expr_t *expr = get_attrp( typelib->typelib->attrs, ATTR_HELPCONTEXT );
2563
if (expr) typelib->typelib_header.helpcontext = expr->cval;
2564
}
2565
2566
static void set_help_string_dll(msft_typelib_t *typelib)
2567
{
2568
char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRINGDLL );
2569
2570
if (str)
2571
{
2572
int offset = ctl2_alloc_string(typelib, str);
2573
if (offset != -1)
2574
{
2575
typelib->help_string_dll_offset = offset;
2576
typelib->typelib_header.varflags |= 0x100;
2577
}
2578
}
2579
}
2580
2581
static void set_help_string_context(msft_typelib_t *typelib)
2582
{
2583
const expr_t *expr = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRINGCONTEXT );
2584
if (expr) typelib->typelib_header.helpstringcontext = expr->cval;
2585
}
2586
2587
static void set_lcid(msft_typelib_t *typelib)
2588
{
2589
const expr_t *lcid_expr = get_attrp( typelib->typelib->attrs, ATTR_LIBLCID );
2590
if(lcid_expr)
2591
{
2592
typelib->typelib_header.lcid = lcid_expr->cval;
2593
typelib->typelib_header.lcid2 = lcid_expr->cval;
2594
}
2595
}
2596
2597
static void set_lib_flags(msft_typelib_t *typelib)
2598
{
2599
const attr_t *attr;
2600
2601
typelib->typelib_header.flags = 0;
2602
if (!typelib->typelib->attrs) return;
2603
LIST_FOR_EACH_ENTRY( attr, typelib->typelib->attrs, const attr_t, entry )
2604
{
2605
switch(attr->type) {
2606
case ATTR_CONTROL:
2607
typelib->typelib_header.flags |= 0x02; /* LIBFLAG_FCONTROL */
2608
break;
2609
case ATTR_HIDDEN:
2610
typelib->typelib_header.flags |= 0x04; /* LIBFLAG_FHIDDEN */
2611
break;
2612
case ATTR_RESTRICTED:
2613
typelib->typelib_header.flags |= 0x01; /* LIBFLAG_FRESTRICTED */
2614
break;
2615
default:
2616
break;
2617
}
2618
}
2619
return;
2620
}
2621
2622
static void ctl2_write_segment(msft_typelib_t *typelib, int segment)
2623
{
2624
if (typelib->typelib_segment_data[segment])
2625
put_data(typelib->typelib_segment_data[segment], typelib->typelib_segdir[segment].length);
2626
}
2627
2628
static void ctl2_finalize_typeinfos(msft_typelib_t *typelib, int filesize)
2629
{
2630
msft_typeinfo_t *typeinfo;
2631
2632
for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
2633
typeinfo->typeinfo->memoffset = filesize;
2634
if (typeinfo->func_data)
2635
filesize += typeinfo->func_data[0] + ((typeinfo->typeinfo->cElement & 0xffff) * 12);
2636
if (typeinfo->var_data)
2637
filesize += typeinfo->var_data[0] + (((typeinfo->typeinfo->cElement >> 16) & 0xffff) * 12);
2638
if (typeinfo->func_data || typeinfo->var_data)
2639
filesize += 4;
2640
}
2641
}
2642
2643
static int ctl2_finalize_segment(msft_typelib_t *typelib, int filepos, int segment)
2644
{
2645
if (typelib->typelib_segdir[segment].length) {
2646
typelib->typelib_segdir[segment].offset = filepos;
2647
} else {
2648
typelib->typelib_segdir[segment].offset = -1;
2649
}
2650
2651
return typelib->typelib_segdir[segment].length;
2652
}
2653
2654
2655
static void ctl2_write_typeinfos(msft_typelib_t *typelib)
2656
{
2657
msft_typeinfo_t *typeinfo;
2658
int typedata_size;
2659
2660
for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
2661
if (!typeinfo->func_data && !typeinfo->var_data) continue;
2662
typedata_size = 0;
2663
if (typeinfo->func_data)
2664
typedata_size = typeinfo->func_data[0];
2665
if (typeinfo->var_data)
2666
typedata_size += typeinfo->var_data[0];
2667
put_data(&typedata_size, sizeof(int));
2668
if (typeinfo->func_data)
2669
put_data(typeinfo->func_data + 1, typeinfo->func_data[0]);
2670
if (typeinfo->var_data)
2671
put_data(typeinfo->var_data + 1, typeinfo->var_data[0]);
2672
if (typeinfo->func_indices)
2673
put_data(typeinfo->func_indices, (typeinfo->typeinfo->cElement & 0xffff) * 4);
2674
if (typeinfo->var_indices)
2675
put_data(typeinfo->var_indices, (typeinfo->typeinfo->cElement >> 16) * 4);
2676
if (typeinfo->func_names)
2677
put_data(typeinfo->func_names, (typeinfo->typeinfo->cElement & 0xffff) * 4);
2678
if (typeinfo->var_names)
2679
put_data(typeinfo->var_names, (typeinfo->typeinfo->cElement >> 16) * 4);
2680
if (typeinfo->func_offsets)
2681
put_data(typeinfo->func_offsets, (typeinfo->typeinfo->cElement & 0xffff) * 4);
2682
if (typeinfo->var_offsets) {
2683
int add = 0, i, offset;
2684
if(typeinfo->func_data)
2685
add = typeinfo->func_data[0];
2686
for(i = 0; i < (typeinfo->typeinfo->cElement >> 16); i++) {
2687
offset = typeinfo->var_offsets[i];
2688
offset += add;
2689
put_data(&offset, 4);
2690
}
2691
}
2692
}
2693
}
2694
2695
static void save_all_changes(msft_typelib_t *typelib)
2696
{
2697
int filepos;
2698
2699
chat("save_all_changes(%p)\n", typelib);
2700
2701
filepos = sizeof(MSFT_Header) + sizeof(MSFT_SegDir);
2702
if(typelib->typelib_header.varflags & 0x100) filepos += 4; /* helpstringdll */
2703
filepos += typelib->typelib_header.nrtypeinfos * 4;
2704
2705
filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_TYPEINFO);
2706
filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_GUIDHASH);
2707
filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_GUID);
2708
filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_REFERENCES);
2709
filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_IMPORTINFO);
2710
filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_IMPORTFILES);
2711
filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_NAMEHASH);
2712
filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_NAME);
2713
filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_STRING);
2714
filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_TYPEDESC);
2715
filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_ARRAYDESC);
2716
filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_CUSTDATA);
2717
filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_CUSTDATAGUID);
2718
2719
ctl2_finalize_typeinfos(typelib, filepos);
2720
2721
init_output_buffer();
2722
2723
put_data(&typelib->typelib_header, sizeof(typelib->typelib_header));
2724
if(typelib->typelib_header.varflags & 0x100)
2725
put_data(&typelib->help_string_dll_offset, sizeof(typelib->help_string_dll_offset));
2726
2727
put_data(typelib->typelib_typeinfo_offsets, typelib->typelib_header.nrtypeinfos * 4);
2728
put_data(&typelib->typelib_segdir, sizeof(typelib->typelib_segdir));
2729
ctl2_write_segment( typelib, MSFT_SEG_TYPEINFO );
2730
ctl2_write_segment( typelib, MSFT_SEG_GUIDHASH );
2731
ctl2_write_segment( typelib, MSFT_SEG_GUID );
2732
ctl2_write_segment( typelib, MSFT_SEG_REFERENCES );
2733
ctl2_write_segment( typelib, MSFT_SEG_IMPORTINFO );
2734
ctl2_write_segment( typelib, MSFT_SEG_IMPORTFILES );
2735
ctl2_write_segment( typelib, MSFT_SEG_NAMEHASH );
2736
ctl2_write_segment( typelib, MSFT_SEG_NAME );
2737
ctl2_write_segment( typelib, MSFT_SEG_STRING );
2738
ctl2_write_segment( typelib, MSFT_SEG_TYPEDESC );
2739
ctl2_write_segment( typelib, MSFT_SEG_ARRAYDESC );
2740
ctl2_write_segment( typelib, MSFT_SEG_CUSTDATA );
2741
ctl2_write_segment( typelib, MSFT_SEG_CUSTDATAGUID );
2742
2743
ctl2_write_typeinfos(typelib);
2744
2745
if (strendswith( typelib_name, ".res" )) /* create a binary resource file */
2746
{
2747
char typelib_id[13] = "#1";
2748
2749
expr_t *expr = get_attrp( typelib->typelib->attrs, ATTR_ID );
2750
if (expr)
2751
snprintf( typelib_id, sizeof(typelib_id), "#%d", expr->cval );
2752
add_output_to_resources( "TYPELIB", typelib_id );
2753
if (strendswith( typelib_name, "_t.res" )) /* add typelib registration */
2754
output_typelib_regscript( typelib->typelib );
2755
}
2756
else flush_output_buffer( typelib_name );
2757
}
2758
2759
int create_msft_typelib(typelib_t *typelib)
2760
{
2761
msft_typelib_t *msft;
2762
int failed = 0;
2763
const statement_t *stmt;
2764
const attr_t *attr;
2765
time_t cur_time;
2766
unsigned int version = 7 << 24 | 555; /* 7.00.0555 */
2767
static const struct uuid midl_time_guid = {0xde77ba63,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}};
2768
static const struct uuid midl_version_guid = {0xde77ba64,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}};
2769
static const struct uuid midl_info_guid = {0xde77ba65,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}};
2770
char info_string[128];
2771
2772
msft = xmalloc(sizeof(*msft));
2773
memset(msft, 0, sizeof(*msft));
2774
msft->typelib = typelib;
2775
2776
ctl2_init_header(msft);
2777
ctl2_init_segdir(msft);
2778
2779
msft->typelib_header.varflags |= (pointer_size == 8) ? SYS_WIN64 : SYS_WIN32;
2780
2781
/*
2782
* The following two calls return an offset or -1 if out of memory. We
2783
* specifically need an offset of 0, however, so...
2784
*/
2785
if (ctl2_alloc_segment(msft, MSFT_SEG_GUIDHASH, 0x80, 0x80)) { failed = 1; }
2786
if (ctl2_alloc_segment(msft, MSFT_SEG_NAMEHASH, 0x200, 0x200)) { failed = 1; }
2787
2788
if(failed)
2789
{
2790
free(msft);
2791
return 0;
2792
}
2793
2794
msft->typelib_guidhash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_GUIDHASH];
2795
msft->typelib_namehash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_NAMEHASH];
2796
2797
memset(msft->typelib_guidhash_segment, 0xff, 0x80);
2798
memset(msft->typelib_namehash_segment, 0xff, 0x200);
2799
2800
set_lib_flags(msft);
2801
set_lcid(msft);
2802
set_help_file_name(msft);
2803
set_doc_string(msft);
2804
set_guid(msft);
2805
set_version(msft);
2806
set_name(msft);
2807
set_help_context(msft);
2808
set_help_string_dll(msft);
2809
set_help_string_context(msft);
2810
2811
if (typelib->attrs) LIST_FOR_EACH_ENTRY( attr, typelib->attrs, const attr_t, entry ) {
2812
switch(attr->type) {
2813
case ATTR_CUSTOM:
2814
set_custdata_attr(msft, attr->u.pval, &msft->typelib_header.CustomDataOffset);
2815
break;
2816
default:
2817
break;
2818
}
2819
}
2820
2821
/* midl adds three sets of custom data to the library:
2822
* - 2147483647 (INT_MAX, previously the current Unix time)
2823
* - midl's version number
2824
* - a string representation of those
2825
*/
2826
cur_time = 2147483647;
2827
snprintf(info_string, sizeof(info_string), "Created by WIDL version %s at %s", PACKAGE_VERSION, asctime(gmtime(&cur_time)));
2828
set_custdata(msft, &midl_info_guid, VT_BSTR, info_string, &msft->typelib_header.CustomDataOffset);
2829
set_custdata(msft, &midl_time_guid, VT_UI4, &cur_time, &msft->typelib_header.CustomDataOffset);
2830
set_custdata(msft, &midl_version_guid, VT_UI4, &version, &msft->typelib_header.CustomDataOffset);
2831
2832
if (typelib->stmts)
2833
LIST_FOR_EACH_ENTRY( stmt, typelib->stmts, const statement_t, entry )
2834
add_entry(msft, stmt);
2835
2836
save_all_changes(msft);
2837
free(msft);
2838
return 1;
2839
}
2840
2841