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 "winerror.h"
44 #include "windef.h"
45 #include "winbase.h"
46 #include "winnls.h"
47
48 #include "widltypes.h"
49 #include "typelib.h"
50 #include "typelib_struct.h"
51 #include "utils.h"
52 #include "header.h"
53 #include "hash.h"
54
55 enum MSFT_segment_index {
56 MSFT_SEG_TYPEINFO = 0, /* type information */
57 MSFT_SEG_IMPORTINFO, /* import information */
58 MSFT_SEG_IMPORTFILES, /* import filenames */
59 MSFT_SEG_REFERENCES, /* references (?) */
60 MSFT_SEG_GUIDHASH, /* hash table for guids? */
61 MSFT_SEG_GUID, /* guid storage */
62 MSFT_SEG_NAMEHASH, /* hash table for names */
63 MSFT_SEG_NAME, /* name storage */
64 MSFT_SEG_STRING, /* string storage */
65 MSFT_SEG_TYPEDESC, /* type descriptions */
66 MSFT_SEG_ARRAYDESC, /* array descriptions */
67 MSFT_SEG_CUSTDATA, /* custom data */
68 MSFT_SEG_CUSTDATAGUID, /* custom data guids */
69 MSFT_SEG_UNKNOWN, /* ??? */
70 MSFT_SEG_UNKNOWN2, /* ??? */
71 MSFT_SEG_MAX /* total number of segments */
72 };
73
74 typedef struct tagMSFT_ImpFile {
75 int guid;
76 LCID lcid;
77 int version;
78 char filename[0]; /* preceded by two bytes of encoded (length << 2) + flags in the low two bits. */
79 } MSFT_ImpFile;
80
81 typedef struct _msft_typelib_t
82 {
83 typelib_t *typelib;
84 MSFT_Header typelib_header;
85 MSFT_pSeg typelib_segdir[MSFT_SEG_MAX];
86 char *typelib_segment_data[MSFT_SEG_MAX];
87 int typelib_segment_block_length[MSFT_SEG_MAX];
88
89 INT typelib_typeinfo_offsets[0x200]; /* Hope that's enough. */
90
91 INT *typelib_namehash_segment;
92 INT *typelib_guidhash_segment;
93
94 INT help_string_dll_offset;
95
96 struct _msft_typeinfo_t *typeinfos;
97 struct _msft_typeinfo_t *last_typeinfo;
98 } msft_typelib_t;
99
100 typedef struct _msft_typeinfo_t
101 {
102 msft_typelib_t *typelib;
103 MSFT_TypeInfoBase *typeinfo;
104
105 int typekind;
106
107 unsigned int var_data_allocated;
108 int *var_data;
109
110 unsigned int func_data_allocated;
111 int *func_data;
112
113 int vars_allocated;
114 int *var_indices;
115 int *var_names;
116 int *var_offsets;
117
118 int funcs_allocated;
119 int *func_indices;
120 int *func_names;
121 int *func_offsets;
122
123 int datawidth;
124
125 struct _msft_typeinfo_t *next_typeinfo;
126 } msft_typeinfo_t;
127
128
129
130 /*================== Internal functions ===================================*/
131
132 /****************************************************************************
133 * ctl2_init_header
134 *
135 * Initializes the type library header of a new typelib.
136 */
137 static void ctl2_init_header(
138 msft_typelib_t *typelib) /* [I] The typelib to initialize. */
139 {
140 typelib->typelib_header.magic1 = 0x5446534d;
141 typelib->typelib_header.magic2 = 0x00010002;
142 typelib->typelib_header.posguid = -1;
143 typelib->typelib_header.lcid = 0x0409; /* or do we use the current one? */
144 typelib->typelib_header.lcid2 = 0x0;
145 typelib->typelib_header.varflags = 0x40;
146 typelib->typelib_header.version = 0;
147 typelib->typelib_header.flags = 0;
148 typelib->typelib_header.nrtypeinfos = 0;
149 typelib->typelib_header.helpstring = -1;
150 typelib->typelib_header.helpstringcontext = 0;
151 typelib->typelib_header.helpcontext = 0;
152 typelib->typelib_header.nametablecount = 0;
153 typelib->typelib_header.nametablechars = 0;
154 typelib->typelib_header.NameOffset = -1;
155 typelib->typelib_header.helpfile = -1;
156 typelib->typelib_header.CustomDataOffset = -1;
157 typelib->typelib_header.res44 = 0x20;
158 typelib->typelib_header.res48 = 0x80;
159 typelib->typelib_header.dispatchpos = -1;
160 typelib->typelib_header.nimpinfos = 0;
161 }
162
163 /****************************************************************************
164 * ctl2_init_segdir
165 *
166 * Initializes the segment directory of a new typelib.
167 */
168 static void ctl2_init_segdir(
169 msft_typelib_t *typelib) /* [I] The typelib to initialize. */
170 {
171 int i;
172 MSFT_pSeg *segdir;
173
174 segdir = &typelib->typelib_segdir[MSFT_SEG_TYPEINFO];
175
176 for (i = 0; i < 15; i++) {
177 segdir[i].offset = -1;
178 segdir[i].length = 0;
179 segdir[i].res08 = -1;
180 segdir[i].res0c = 0x0f;
181 }
182 }
183
184 /****************************************************************************
185 * ctl2_hash_guid
186 *
187 * Generates a hash key from a GUID.
188 *
189 * RETURNS
190 *
191 * The hash key for the GUID.
192 */
193 static int ctl2_hash_guid(
194 REFGUID guid) /* [I] The guid to hash. */
195 {
196 int hash;
197 int i;
198
199 hash = 0;
200 for (i = 0; i < 8; i ++) {
201 hash ^= ((const short *)guid)[i];
202 }
203
204 return hash & 0x1f;
205 }
206
207 /****************************************************************************
208 * ctl2_find_guid
209 *
210 * Locates a guid in a type library.
211 *
212 * RETURNS
213 *
214 * The offset into the GUID segment of the guid, or -1 if not found.
215 */
216 static int ctl2_find_guid(
217 msft_typelib_t *typelib, /* [I] The typelib to operate against. */
218 int hash_key, /* [I] The hash key for the guid. */
219 REFGUID guid) /* [I] The guid to find. */
220 {
221 int offset;
222 MSFT_GuidEntry *guidentry;
223
224 offset = typelib->typelib_guidhash_segment[hash_key];
225 while (offset != -1) {
226 guidentry = (MSFT_GuidEntry *)&typelib->typelib_segment_data[MSFT_SEG_GUID][offset];
227
228 if (!memcmp(guidentry, guid, sizeof(GUID))) return offset;
229
230 offset = guidentry->next_hash;
231 }
232
233 return offset;
234 }
235
236 /****************************************************************************
237 * ctl2_find_name
238 *
239 * Locates a name in a type library.
240 *
241 * RETURNS
242 *
243 * The offset into the NAME segment of the name, or -1 if not found.
244 *
245 * NOTES
246 *
247 * The name must be encoded as with ctl2_encode_name().
248 */
249 static int ctl2_find_name(
250 msft_typelib_t *typelib, /* [I] The typelib to operate against. */
251 char *name) /* [I] The encoded name to find. */
252 {
253 int offset;
254 int *namestruct;
255
256 offset = typelib->typelib_namehash_segment[name[2] & 0x7f];
257 while (offset != -1) {
258 namestruct = (int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][offset];
259
260 if (!((namestruct[2] ^ *((int *)name)) & 0xffff00ff)) {
261 /* hash codes and lengths match, final test */
262 if (!strncasecmp(name+4, (void *)(namestruct+3), name[0])) break;
263 }
264
265 /* move to next item in hash bucket */
266 offset = namestruct[1];
267 }
268
269 return offset;
270 }
271
272 /****************************************************************************
273 * ctl2_encode_name
274 *
275 * Encodes a name string to a form suitable for storing into a type library
276 * or comparing to a name stored in a type library.
277 *
278 * RETURNS
279 *
280 * The length of the encoded name, including padding and length+hash fields.
281 *
282 * NOTES
283 *
284 * Will throw an exception if name or result are NULL. Is not multithread
285 * safe in the slightest.
286 */
287 static int ctl2_encode_name(
288 msft_typelib_t *typelib, /* [I] The typelib to operate against (used for LCID only). */
289 const char *name, /* [I] The name string to encode. */
290 char **result) /* [O] A pointer to a pointer to receive the encoded name. */
291 {
292 int length;
293 static char converted_name[0x104];
294 int offset;
295 int value;
296
297 length = strlen(name);
298 memcpy(converted_name + 4, name, length);
299
300 converted_name[length + 4] = 0;
301
302
303 value = lhash_val_of_name_sys(typelib->typelib_header.varflags & 0x0f, typelib->typelib_header.lcid, converted_name + 4);
304
305 #ifdef WORDS_BIGENDIAN
306 converted_name[3] = length & 0xff;
307 converted_name[2] = 0x00;
308 converted_name[1] = value;
309 converted_name[0] = value >> 8;
310 #else
311 converted_name[0] = length & 0xff;
312 converted_name[1] = 0x00;
313 converted_name[2] = value;
314 converted_name[3] = value >> 8;
315 #endif
316
317 for (offset = (4 - length) & 3; offset; offset--) converted_name[length + offset + 3] = 0x57;
318
319 *result = converted_name;
320
321 return (length + 7) & ~3;
322 }
323
324 /****************************************************************************
325 * ctl2_encode_string
326 *
327 * Encodes a string to a form suitable for storing into a type library or
328 * comparing to a string stored in a type library.
329 *
330 * RETURNS
331 *
332 * The length of the encoded string, including padding and length fields.
333 *
334 * NOTES
335 *
336 * Will throw an exception if string or result are NULL. Is not multithread
337 * safe in the slightest.
338 */
339 static int ctl2_encode_string(
340 const char *string, /* [I] The string to encode. */
341 char **result) /* [O] A pointer to a pointer to receive the encoded string. */
342 {
343 int length;
344 static char converted_string[0x104];
345 int offset;
346
347 length = strlen(string);
348 memcpy(converted_string + 2, string, length);
349
350 #ifdef WORDS_BIGENDIAN
351 converted_string[1] = length & 0xff;
352 converted_string[0] = (length >> 8) & 0xff;
353 #else
354 converted_string[0] = length & 0xff;
355 converted_string[1] = (length >> 8) & 0xff;
356 #endif
357
358 if(length < 3) { /* strings of this length are padded with up to 8 bytes incl the 2 byte length */
359 for(offset = 0; offset < 4; offset++)
360 converted_string[length + offset + 2] = 0x57;
361 length += 4;
362 }
363 for (offset = (4 - (length + 2)) & 3; offset; offset--) converted_string[length + offset + 1] = 0x57;
364
365 *result = converted_string;
366
367 return (length + 5) & ~3;
368 }
369
370 /****************************************************************************
371 * ctl2_alloc_segment
372 *
373 * Allocates memory from a segment in a type library.
374 *
375 * RETURNS
376 *
377 * Success: The offset within the segment of the new data area.
378 *
379 * BUGS
380 *
381 * Does not (yet) handle the case where the allocated segment memory needs to grow.
382 */
383 static int ctl2_alloc_segment(
384 msft_typelib_t *typelib, /* [I] The type library in which to allocate. */
385 enum MSFT_segment_index segment, /* [I] The segment in which to allocate. */
386 int size, /* [I] The amount to allocate. */
387 int block_size) /* [I] Initial allocation block size, or 0 for default. */
388 {
389 int offset;
390
391 if(!typelib->typelib_segment_data[segment]) {
392 if (!block_size) block_size = 0x2000;
393
394 typelib->typelib_segment_block_length[segment] = block_size;
395 typelib->typelib_segment_data[segment] = xmalloc(block_size);
396 if (!typelib->typelib_segment_data[segment]) return -1;
397 memset(typelib->typelib_segment_data[segment], 0x57, block_size);
398 }
399
400 while ((typelib->typelib_segdir[segment].length + size) > typelib->typelib_segment_block_length[segment]) {
401 char *block;
402
403 block_size = typelib->typelib_segment_block_length[segment];
404 block = xrealloc(typelib->typelib_segment_data[segment], block_size << 1);
405
406 if (segment == MSFT_SEG_TYPEINFO) {
407 /* TypeInfos have a direct pointer to their memory space, so we have to fix them up. */
408 msft_typeinfo_t *typeinfo;
409
410 for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
411 typeinfo->typeinfo = (void *)&block[((char *)typeinfo->typeinfo) - typelib->typelib_segment_data[segment]];
412 }
413 }
414
415 memset(block + block_size, 0x57, block_size);
416 typelib->typelib_segment_block_length[segment] = block_size << 1;
417 typelib->typelib_segment_data[segment] = block;
418 }
419
420 offset = typelib->typelib_segdir[segment].length;
421 typelib->typelib_segdir[segment].length += size;
422
423 return offset;
424 }
425
426 /****************************************************************************
427 * ctl2_alloc_typeinfo
428 *
429 * Allocates and initializes a typeinfo structure in a type library.
430 *
431 * RETURNS
432 *
433 * Success: The offset of the new typeinfo.
434 * Failure: -1 (this is invariably an out of memory condition).
435 */
436 static int ctl2_alloc_typeinfo(
437 msft_typelib_t *typelib, /* [I] The type library to allocate in. */
438 int nameoffset) /* [I] The offset of the name for this typeinfo. */
439 {
440 int offset;
441 MSFT_TypeInfoBase *typeinfo;
442
443 offset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEINFO, sizeof(MSFT_TypeInfoBase), 0);
444
445 typelib->typelib_typeinfo_offsets[typelib->typelib_header.nrtypeinfos++] = offset;
446
447 typeinfo = (void *)(typelib->typelib_segment_data[MSFT_SEG_TYPEINFO] + offset);
448
449 typeinfo->typekind = (typelib->typelib_header.nrtypeinfos - 1) << 16;
450 typeinfo->memoffset = -1; /* should be EOF if no elements */
451 typeinfo->res2 = 0;
452 typeinfo->res3 = -1;
453 typeinfo->res4 = 3;
454 typeinfo->res5 = 0;
455 typeinfo->cElement = 0;
456 typeinfo->res7 = 0;
457 typeinfo->res8 = 0;
458 typeinfo->res9 = 0;
459 typeinfo->resA = 0;
460 typeinfo->posguid = -1;
461 typeinfo->flags = 0;
462 typeinfo->NameOffset = nameoffset;
463 typeinfo->version = 0;
464 typeinfo->docstringoffs = -1;
465 typeinfo->helpstringcontext = 0;
466 typeinfo->helpcontext = 0;
467 typeinfo->oCustData = -1;
468 typeinfo->cbSizeVft = 0;
469 typeinfo->cImplTypes = 0;
470 typeinfo->size = 0;
471 typeinfo->datatype1 = -1;
472 typeinfo->datatype2 = 0;
473 typeinfo->res18 = 0;
474 typeinfo->res19 = -1;
475
476 return offset;
477 }
478
479 /****************************************************************************
480 * ctl2_alloc_guid
481 *
482 * Allocates and initializes a GUID structure in a type library. Also updates
483 * the GUID hash table as needed.
484 *
485 * RETURNS
486 *
487 * Success: The offset of the new GUID.
488 */
489 static int ctl2_alloc_guid(
490 msft_typelib_t *typelib, /* [I] The type library to allocate in. */
491 MSFT_GuidEntry *guid) /* [I] The GUID to store. */
492 {
493 int offset;
494 MSFT_GuidEntry *guid_space;
495 int hash_key;
496
497 hash_key = ctl2_hash_guid(&guid->guid);
498
499 offset = ctl2_find_guid(typelib, hash_key, &guid->guid);
500 if (offset != -1) return offset;
501
502 offset = ctl2_alloc_segment(typelib, MSFT_SEG_GUID, sizeof(MSFT_GuidEntry), 0);
503
504 guid_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_GUID] + offset);
505 *guid_space = *guid;
506
507 guid_space->next_hash = typelib->typelib_guidhash_segment[hash_key];
508 typelib->typelib_guidhash_segment[hash_key] = offset;
509
510 return offset;
511 }
512
513 /****************************************************************************
514 * ctl2_alloc_name
515 *
516 * Allocates and initializes a name within a type library. Also updates the
517 * name hash table as needed.
518 *
519 * RETURNS
520 *
521 * Success: The offset within the segment of the new name.
522 * Failure: -1 (this is invariably an out of memory condition).
523 */
524 static int ctl2_alloc_name(
525 msft_typelib_t *typelib, /* [I] The type library to allocate in. */
526 const char *name) /* [I] The name to store. */
527 {
528 int length;
529 int offset;
530 MSFT_NameIntro *name_space;
531 char *encoded_name;
532
533 length = ctl2_encode_name(typelib, name, &encoded_name);
534
535 offset = ctl2_find_name(typelib, encoded_name);
536 if (offset != -1) return offset;
537
538 offset = ctl2_alloc_segment(typelib, MSFT_SEG_NAME, length + 8, 0);
539
540 name_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_NAME] + offset);
541 name_space->hreftype = -1;
542 name_space->next_hash = -1;
543 memcpy(&name_space->namelen, encoded_name, length);
544
545 if (typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] != -1)
546 name_space->next_hash = typelib->typelib_namehash_segment[encoded_name[2] & 0x7f];
547
548 typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] = offset;
549
550 typelib->typelib_header.nametablecount += 1;
551 typelib->typelib_header.nametablechars += *encoded_name;
552
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 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) & 0xff)
579 | (typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 0] & 0xff)) + 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
588 return offset;
589 }
590
591 /****************************************************************************
592 * alloc_msft_importinfo
593 *
594 * Allocates and initializes an import information structure in a type library.
595 *
596 * RETURNS
597 *
598 * Success: The offset of the new importinfo.
599 * Failure: -1 (this is invariably an out of memory condition).
600 */
601 static int alloc_msft_importinfo(
602 msft_typelib_t *typelib, /* [I] The type library to allocate in. */
603 MSFT_ImpInfo *impinfo) /* [I] The import information to store. */
604 {
605 int offset;
606 MSFT_ImpInfo *impinfo_space;
607
608 for (offset = 0;
609 offset < typelib->typelib_segdir[MSFT_SEG_IMPORTINFO].length;
610 offset += sizeof(MSFT_ImpInfo)) {
611 if (!memcmp(&(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO][offset]),
612 impinfo, sizeof(MSFT_ImpInfo))) {
613 return offset;
614 }
615 }
616
617 impinfo->flags |= typelib->typelib_header.nimpinfos++;
618
619 offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTINFO, sizeof(MSFT_ImpInfo), 0);
620
621 impinfo_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO] + offset);
622 *impinfo_space = *impinfo;
623
624 return offset;
625 }
626
627 /****************************************************************************
628 * alloc_importfile
629 *
630 * Allocates and initializes an import file definition in a type library.
631 *
632 * RETURNS
633 *
634 * Success: The offset of the new importinfo.
635 * Failure: -1 (this is invariably an out of memory condition).
636 */
637 static int alloc_importfile(
638 msft_typelib_t *typelib, /* [I] The type library to allocate in. */
639 int guidoffset, /* [I] The offset to the GUID for the imported library. */
640 int major_version, /* [I] The major version number of the imported library. */
641 int minor_version, /* [I] The minor version number of the imported library. */
642 const char *filename) /* [I] The filename of the imported library. */
643 {
644 int length;
645 int offset;
646 MSFT_ImpFile *importfile;
647 char *encoded_string;
648
649 length = ctl2_encode_string(filename, &encoded_string);
650
651 encoded_string[0] <<= 2;
652 encoded_string[0] |= 1;
653
654 for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_IMPORTFILES].length;
655 offset += ((((typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xd] << 8) & 0xff)
656 | (typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xc] & 0xff)) >> 2) + 0xc) {
657 if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES] + offset + 0xc, length)) return offset;
658 }
659
660 offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTFILES, length + 0xc, 0);
661
662 importfile = (MSFT_ImpFile *)&typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset];
663 importfile->guid = guidoffset;
664 importfile->lcid = typelib->typelib_header.lcid2;
665 importfile->version = major_version | (minor_version << 16);
666 memcpy(&importfile->filename, encoded_string, length);
667
668 return offset;
669 }
670
671 static void alloc_importinfo(msft_typelib_t *typelib, importinfo_t *importinfo)
672 {
673 importlib_t *importlib = importinfo->importlib;
674
675 chat("alloc_importinfo: %s\n", importinfo->name);
676
677 if(!importlib->allocated) {
678 MSFT_GuidEntry guid;
679 int guid_idx;
680
681 chat("allocating importlib %s\n", importlib->name);
682
683 importlib->allocated = -1;
684
685 memcpy(&guid.guid, &importlib->guid, sizeof(GUID));
686 guid.hreftype = 2;
687
688 guid_idx = ctl2_alloc_guid(typelib, &guid);
689
690 alloc_importfile(typelib, guid_idx, importlib->version&0xffff,
691 importlib->version>>16, importlib->name);
692 }
693
694 if(importinfo->offset == -1 || !(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID)) {
695 MSFT_ImpInfo impinfo;
696
697 impinfo.flags = importinfo->flags;
698 impinfo.oImpFile = 0;
699
700 if(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
701 MSFT_GuidEntry guid;
702
703 guid.hreftype = 0;
704 memcpy(&guid.guid, &importinfo->guid, sizeof(GUID));
705
706 impinfo.oGuid = ctl2_alloc_guid(typelib, &guid);
707
708 importinfo->offset = alloc_msft_importinfo(typelib, &impinfo);
709
710 typelib->typelib_segment_data[MSFT_SEG_GUID][impinfo.oGuid+sizeof(GUID)]
711 = importinfo->offset+1;
712
713 if(!strcmp(importinfo->name, "IDispatch"))
714 typelib->typelib_header.dispatchpos = importinfo->offset+1;
715 }else {
716 impinfo.oGuid = importinfo->id;
717 importinfo->offset = alloc_msft_importinfo(typelib, &impinfo);
718 }
719 }
720 }
721
722 static importinfo_t *find_importinfo(msft_typelib_t *typelib, const char *name)
723 {
724 importlib_t *importlib;
725 int i;
726
727 chat("search importlib %s\n", name);
728
729 if(!name)
730 return NULL;
731
732 LIST_FOR_EACH_ENTRY( importlib, &typelib->typelib->importlibs, importlib_t, entry )
733 {
734 for(i=0; i < importlib->ntypeinfos; i++) {
735 if(!strcmp(name, importlib->importinfos[i].name)) {
736 chat("Found %s in importlib.\n", name);
737 return importlib->importinfos+i;
738 }
739 }
740 }
741
742 return NULL;
743 }
744
745 static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure);
746 static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface);
747 static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration);
748 static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls);
749 static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface);
750
751
752 /****************************************************************************
753 * encode_type
754 *
755 * Encodes a type, storing information in the TYPEDESC and ARRAYDESC
756 * segments as needed.
757 *
758 * RETURNS
759 *
760 * Success: 0.
761 * Failure: -1.
762 */
763 static int encode_type(
764 msft_typelib_t *typelib, /* [I] The type library in which to encode the TYPEDESC. */
765 int vt, /* [I] vt to encode */
766 type_t *type, /* [I] type */
767 int *encoded_type, /* [O] The encoded type description. */
768 int *width, /* [O] The width of the type, or NULL. */
769 int *alignment, /* [O] The alignment of the type, or NULL. */
770 int *decoded_size) /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */
771 {
772 int default_type;
773 int scratch;
774 int typeoffset;
775 int *typedata;
776 int target_type;
777 int child_size = 0;
778
779 chat("encode_type vt %d type %p\n", vt, type);
780
781 default_type = 0x80000000 | (vt << 16) | vt;
782 if (!width) width = &scratch;
783 if (!alignment) alignment = &scratch;
784 if (!decoded_size) decoded_size = &scratch;
785
786
787 switch (vt) {
788 case VT_I1:
789 case VT_UI1:
790 *encoded_type = default_type;
791 *width = 1;
792 *alignment = 1;
793 break;
794
795 case VT_INT:
796 *encoded_type = 0x80000000 | (VT_I4 << 16) | VT_INT;
797 if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) {
798 *width = 2;
799 *alignment = 2;
800 } else {
801 *width = 4;
802 *alignment = 4;
803 }
804 break;
805
806 case VT_UINT:
807 *encoded_type = 0x80000000 | (VT_UI4 << 16) | VT_UINT;
808 if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) {
809 *width = 2;
810 *alignment = 2;
811 } else {
812 *width = 4;
813 *alignment = 4;
814 }
815 break;
816
817 case VT_UI2:
818 case VT_I2:
819 case VT_BOOL:
820 *encoded_type = default_type;
821 *width = 2;
822 *alignment = 2;
823 break;
824
825 case VT_I4:
826 case VT_UI4:
827 case VT_R4:
828 case VT_ERROR:
829 case VT_BSTR:
830 case VT_HRESULT:
831 *encoded_type = default_type;
832 *width = 4;
833 *alignment = 4;
834 break;
835
836 case VT_R8:
837 case VT_I8:
838 case VT_UI8:
839 *encoded_type = default_type;
840 *width = 8;
841 *alignment = 8;
842 break;
843
844 case VT_CY:
845 case VT_DATE:
846 *encoded_type = default_type;
847 *width = 8;
848 *alignment = 8;
849 break;
850
851 case VT_VOID:
852 *encoded_type = 0x80000000 | (VT_EMPTY << 16) | vt;
853 *width = 0;
854 *alignment = 1;
855 break;
856
857 case VT_UNKNOWN:
858 case VT_DISPATCH:
859 *encoded_type = default_type;
860 *width = 4;
861 *alignment = 4;
862 break;
863
864 case VT_VARIANT:
865 *encoded_type = default_type;
866 break;
867
868 case VT_LPSTR:
869 case VT_LPWSTR:
870 *encoded_type = 0xfffe0000 | vt;
871 *width = 4;
872 *alignment = 4;
873 break;
874
875 case VT_PTR:
876 {
877 int next_vt;
878 for(next_vt = 0; type->ref; type = type->ref) {
879 next_vt = get_type_vt(type->ref);
880 if (next_vt != 0)
881 break;
882 }
883 /* if no type found then it must be void */
884 if (next_vt == 0)
885 next_vt = VT_VOID;
886
887 encode_type(typelib, next_vt, type->ref, &target_type, NULL, NULL, &child_size);
888 if(type->ref && (type->ref->type == RPC_FC_IP)) {
889 chat("encode_type: skipping ptr\n");
890 *encoded_type = target_type;
891 *width = 4;
892 *alignment = 4;
893 *decoded_size = child_size;
894 break;
895 }
896
897 for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
898 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
899 if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
900 }
901
902 if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
903 int mix_field;
904
905 if (target_type & 0x80000000) {
906 mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
907 } else {
908 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
909 mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
910 }
911
912 typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
913 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
914
915 typedata[0] = (mix_field << 16) | VT_PTR;
916 typedata[1] = target_type;
917 }
918
919 *encoded_type = typeoffset;
920
921 *width = 4;
922 *alignment = 4;
923 *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
924 break;
925 }
926
927
928 case VT_SAFEARRAY:
929 {
930 int next_vt;
931
932 /* skip over SAFEARRAY type straight to element type */
933 type = type->ref;
934
935 for(next_vt = 0; type->ref; type = type->ref) {
936 next_vt = get_type_vt(type->ref);
937 if (next_vt != 0)
938 break;
939 }
940
941 encode_type(typelib, next_vt, type->ref, &target_type, NULL, NULL, &child_size);
942
943 for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
944 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
945 if (((typedata[0] & 0xffff) == VT_SAFEARRAY) && (typedata[1] == target_type)) break;
946 }
947
948 if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
949 int mix_field;
950
951 if (target_type & 0x80000000) {
952 mix_field = ((target_type >> 16) & VT_TYPEMASK) | VT_ARRAY;
953 } else {
954 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
955 mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
956 }
957
958 typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
959 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
960
961 typedata[0] = (mix_field << 16) | VT_SAFEARRAY;
962 typedata[1] = target_type;
963 }
964
965 *encoded_type = typeoffset;
966
967 *width = 4;
968 *alignment = 4;
969 *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
970 break;
971 }
972
973
974 case VT_USERDEFINED:
975 {
976 int typeinfo_offset;
977
978 /* typedef'd types without public attribute aren't included in the typelib */
979 while (type->typelib_idx < 0 && type->kind == TKIND_ALIAS && !is_attr(type->attrs, ATTR_PUBLIC))
980 type = type->orig;
981
982 chat("encode_type: VT_USERDEFINED - type %p name = %s type->type %d idx %d\n", type,
983 type->name, type->type, type->typelib_idx);
984
985 if(type->typelib_idx == -1) {