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