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