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