1 /* 2 * Typelib (SLTG) generation 3 * 4 * Copyright 2015,2016 Dmitry Timoshkov 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "config.h" 22 #include "wine/port.h" 23 24 #include <stdlib.h> 25 #include <string.h> 26 #include <stdarg.h> 27 #include <stdio.h> 28 #include <ctype.h> 29 #include <time.h> 30 31 #define NONAMELESSUNION 32 33 #include <typedefs.h> 34 #include <nls.h> 35 36 #include "widl.h" 37 #include "typelib.h" 38 #include "typelib_struct.h" 39 #include "utils.h" 40 #include "header.h" 41 #include "typetree.h" 42 43 static const GUID sltg_library_guid = { 0x204ff,0,0,{ 0xc0,0,0,0,0,0,0,0x46 } }; 44 45 struct sltg_data 46 { 47 int size, allocated; 48 char *data; 49 }; 50 51 struct sltg_library 52 { 53 short name; 54 char *helpstring; 55 char *helpfile; 56 int helpcontext; 57 int syskind; 58 LCID lcid; 59 int libflags; 60 int version; 61 GUID uuid; 62 }; 63 64 struct sltg_block 65 { 66 int length; 67 int index_string; 68 void *data; 69 struct sltg_block *next; 70 }; 71 72 struct sltg_typelib 73 { 74 typelib_t *typelib; 75 struct sltg_data index; 76 struct sltg_data name_table; 77 struct sltg_library library; 78 struct sltg_block *blocks; 79 int n_file_blocks; 80 int first_block; 81 int typeinfo_count; 82 int typeinfo_size; 83 struct sltg_block *typeinfo; 84 }; 85 86 struct sltg_hrefmap 87 { 88 int href_count; 89 int *href; 90 }; 91 92 #include "pshpack1.h" 93 struct sltg_typeinfo_header 94 { 95 short magic; 96 int href_offset; 97 int res06; 98 int member_offset; 99 int res0e; 100 int version; 101 int res16; 102 struct 103 { 104 unsigned unknown1 : 3; 105 unsigned flags : 13; 106 unsigned unknown2 : 8; 107 unsigned typekind : 8; 108 } misc; 109 int res1e; 110 }; 111 112 struct sltg_member_header 113 { 114 short res00; 115 short res02; 116 char res04; 117 int extra; 118 }; 119 120 struct sltg_variable 121 { 122 char magic; /* 0x0a */ 123 char flags; 124 short next; 125 short name; 126 short byte_offs; /* pos in struct, or offset to const type or const data (if flags & 0x08) */ 127 short type; /* if flags & 0x02 this is the type, else offset to type */ 128 int memid; 129 short helpcontext; 130 short helpstring; 131 short varflags; /* only present if magic & 0x02 */ 132 }; 133 134 struct sltg_tail 135 { 136 short cFuncs; 137 short cVars; 138 short cImplTypes; 139 short res06; /* always 0000 */ 140 short funcs_off; /* offset to functions (starting from the member header) */ 141 short vars_off; /* offset to vars (starting from the member header) */ 142 short impls_off; /* offset to implemented types (starting from the member header) */ 143 short funcs_bytes; /* bytes used by function data */ 144 short vars_bytes; /* bytes used by var data */ 145 short impls_bytes; /* bytes used by implemented type data */ 146 short tdescalias_vt; /* for TKIND_ALIAS */ 147 short res16; /* always ffff */ 148 short res18; /* always 0000 */ 149 short res1a; /* always 0000 */ 150 short simple_alias; /* tdescalias_vt is a vt rather than an offset? */ 151 short res1e; /* always 0000 */ 152 short cbSizeInstance; 153 short cbAlignment; 154 short res24; 155 short res26; 156 short cbSizeVft; 157 short res2a; /* always ffff */ 158 short res2c; /* always ffff */ 159 short res2e; /* always ffff */ 160 short res30; /* always ffff */ 161 short res32; /* unknown */ 162 short type_bytes; /* bytes used by type descriptions */ 163 }; 164 165 struct sltg_hrefinfo 166 { 167 char magic; /* 0xdf */ 168 char res01; /* 0x00 */ 169 int res02; /* 0xffffffff */ 170 int res06; /* 0xffffffff */ 171 int res0a; /* 0xffffffff */ 172 int res0e; /* 0xffffffff */ 173 int res12; /* 0xffffffff */ 174 int res16; /* 0xffffffff */ 175 int res1a; /* 0xffffffff */ 176 int res1e; /* 0xffffffff */ 177 int res22; /* 0xffffffff */ 178 int res26; /* 0xffffffff */ 179 int res2a; /* 0xffffffff */ 180 int res2e; /* 0xffffffff */ 181 int res32; /* 0xffffffff */ 182 int res36; /* 0xffffffff */ 183 int res3a; /* 0xffffffff */ 184 int res3e; /* 0xffffffff */ 185 short res42;/* 0xffff */ 186 int number; /* this is 8 times the number of refs */ 187 /* Now we have number bytes (8 for each ref) of SLTG_UnknownRefInfo */ 188 189 short res50;/* 0xffff */ 190 char res52; /* 0x01 */ 191 int res53; /* 0x00000000 */ 192 /* Now we have number/8 SLTG_Names (first WORD is no of bytes in the ascii 193 * string). Strings look like "*\Rxxxx*#n". If xxxx == ffff then the 194 * ref refers to the nth type listed in this library (0 based). Else 195 * the xxxx (which maybe fewer than 4 digits) is the offset into the name 196 * table to a string "*\G{<guid>}#1.0#0#C:\WINNT\System32\stdole32.tlb#" 197 * The guid is the typelib guid; the ref again refers to the nth type of 198 * the imported typelib. 199 */ 200 201 char resxx; /* 0xdf */ 202 }; 203 204 struct sltg_function 205 { 206 char magic; /* 0x4c, 0xcb or 0x8b with optional SLTG_FUNCTION_FLAGS_PRESENT flag */ 207 char flags; /* high nibble is INVOKE_KIND, low nibble = 2 */ 208 short next; /* byte offset from beginning of group to next fn */ 209 short name; /* Offset within name table to name */ 210 int dispid; /* dispid */ 211 short helpcontext; /* helpcontext (again 1 is special) */ 212 short helpstring; /* helpstring offset to offset */ 213 short arg_off; /* offset to args from start of block */ 214 char nacc; /* lowest 3bits are CALLCONV, rest are no of args */ 215 char retnextopt; /* if 0x80 bit set ret type follows else next WORD 216 is offset to ret type. No of optional args is 217 middle 6 bits */ 218 short rettype; /* return type VT_?? or offset to ret type */ 219 short vtblpos; /* position in vtbl? */ 220 short funcflags; /* present if magic & 0x20 */ 221 /* Param list starts, repeat next two as required */ 222 #if 0 223 WORD name; /* offset to 2nd letter of name */ 224 WORD+ type; /* VT_ of param */ 225 #endif 226 }; 227 228 struct sltg_impl_info 229 { 230 short res00; 231 short next; 232 short res04; 233 char impltypeflags; 234 char res07; 235 short res08; 236 short ref; 237 short res0c; 238 short res0e; 239 short res10; 240 short res12; 241 short pos; 242 }; 243 244 #include "poppack.h" 245 246 static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type); 247 static void add_interface_typeinfo(struct sltg_typelib *typelib, type_t *type); 248 static void add_enum_typeinfo(struct sltg_typelib *typelib, type_t *type); 249 static void add_union_typeinfo(struct sltg_typelib *typelib, type_t *type); 250 static void add_coclass_typeinfo(struct sltg_typelib *typelib, type_t *type); 251 252 static void init_sltg_data(struct sltg_data *data) 253 { 254 data->size = 0; 255 data->allocated = 0x10; 256 data->data = xmalloc(0x10); 257 } 258 259 static int add_index(struct sltg_data *index, const char *name) 260 { 261 int name_offset = index->size; 262 int new_size = index->size + strlen(name) + 1; 263 264 chat("add_index: name_offset %d, \"%s\"\n", name_offset, name); 265 266 if (new_size > index->allocated) 267 { 268 index->allocated = max(index->allocated * 2, new_size); 269 index->data = xrealloc(index->data, index->allocated); 270 } 271 272 strcpy(index->data + index->size, name); 273 index->size = new_size; 274 275 return name_offset; 276 } 277 278 static void init_index(struct sltg_data *index) 279 { 280 static const char compobj[] = { 1,'C','o','m','p','O','b','j',0 }; 281 282 init_sltg_data(index); 283 284 add_index(index, compobj); 285 } 286 287 static int add_name(struct sltg_typelib *sltg, const char *name) 288 { 289 int name_offset = sltg->name_table.size; 290 int new_size = sltg->name_table.size + strlen(name) + 1 + 8; 291 int aligned_size; 292 293 chat("add_name: %s\n", name); 294 295 aligned_size = (new_size + 0x1f) & ~0x1f; 296 if (aligned_size - new_size < 4) 297 new_size = aligned_size; 298 else 299 new_size = (new_size + 1) & ~1; 300 301 if (new_size > sltg->name_table.allocated) 302 { 303 sltg->name_table.allocated = max(sltg->name_table.allocated * 2, new_size); 304 sltg->name_table.data = xrealloc(sltg->name_table.data, sltg->name_table.allocated); 305 } 306 307 memset(sltg->name_table.data + sltg->name_table.size, 0xff, 8); 308 strcpy(sltg->name_table.data + sltg->name_table.size + 8, name); 309 sltg->name_table.size = new_size; 310 sltg->name_table.data[sltg->name_table.size - 1] = 0; /* clear alignment */ 311 312 return name_offset; 313 } 314 315 static void init_name_table(struct sltg_typelib *sltg) 316 { 317 init_sltg_data(&sltg->name_table); 318 } 319 320 static void init_library(struct sltg_typelib *sltg) 321 { 322 const attr_t *attr; 323 324 sltg->library.name = add_name(sltg, sltg->typelib->name); 325 sltg->library.helpstring = NULL; 326 sltg->library.helpcontext = 0; 327 sltg->library.syskind = typelib_kind; 328 sltg->library.lcid = 0x0409; 329 sltg->library.libflags = 0; 330 sltg->library.version = 0; 331 sltg->library.helpfile = NULL; 332 memset(&sltg->library.uuid, 0, sizeof(sltg->library.uuid)); 333 334 if (!sltg->typelib->attrs) return; 335 336 LIST_FOR_EACH_ENTRY(attr, sltg->typelib->attrs, const attr_t, entry) 337 { 338 const expr_t *expr; 339 340 switch (attr->type) 341 { 342 case ATTR_VERSION: 343 sltg->library.version = attr->u.ival; 344 break; 345 case ATTR_HELPSTRING: 346 sltg->library.helpstring = attr->u.pval; 347 break; 348 case ATTR_HELPFILE: 349 sltg->library.helpfile = attr->u.pval; 350 break; 351 case ATTR_UUID: 352 sltg->library.uuid = *(GUID *)attr->u.pval; 353 break; 354 case ATTR_HELPCONTEXT: 355 expr = attr->u.pval; 356 sltg->library.helpcontext = expr->cval; 357 break; 358 case ATTR_LIBLCID: 359 expr = attr->u.pval; 360 sltg->library.lcid = expr->cval; 361 break; 362 case ATTR_CONTROL: 363 sltg->library.libflags |= 0x02; /* LIBFLAG_FCONTROL */ 364 break; 365 case ATTR_HIDDEN: 366 sltg->library.libflags |= 0x04; /* LIBFLAG_FHIDDEN */ 367 break; 368 case ATTR_RESTRICTED: 369 sltg->library.libflags |= 0x01; /* LIBFLAG_FRESTRICTED */ 370 break; 371 default: 372 break; 373 } 374 } 375 } 376 377 static void add_block_index(struct sltg_typelib *sltg, void *data, int size, int index) 378 { 379 struct sltg_block *block = xmalloc(sizeof(*block)); 380 381 block->length = size; 382 block->data = data; 383 block->index_string = index; 384 block->next = NULL; 385 386 if (sltg->blocks) 387 { 388 struct sltg_block *blocks = sltg->blocks; 389 390 while (blocks->next) 391 blocks = blocks->next; 392 393 blocks->next = block; 394 } 395 else 396 sltg->blocks = block; 397 398 sltg->n_file_blocks++; 399 } 400 401 static void add_block(struct sltg_typelib *sltg, void *data, int size, const char *name) 402 { 403 struct sltg_block *block = xmalloc(sizeof(*block)); 404 int index; 405 406 chat("add_block: %p,%d,\"%s\"\n", data, size, name); 407 408 index = add_index(&sltg->index, name); 409 410 add_block_index(sltg, data, size, index); 411 } 412 413 static void *create_library_block(struct sltg_typelib *typelib, int *size, int *index) 414 { 415 void *block; 416 short *p; 417 418 *size = sizeof(short) * 9 + sizeof(int) * 3 + sizeof(GUID); 419 if (typelib->library.helpstring) *size += strlen(typelib->library.helpstring); 420 if (typelib->library.helpfile) *size += strlen(typelib->library.helpfile); 421 422 block = xmalloc(*size); 423 p = block; 424 *p++ = 0x51cc; /* magic */ 425 *p++ = 3; /* res02 */ 426 *p++ = typelib->library.name; 427 *p++ = 0xffff; /* res06 */ 428 if (typelib->library.helpstring) 429 { 430 *p++ = strlen(typelib->library.helpstring); 431 strcpy((char *)p, typelib->library.helpstring); 432 p = (short *)((char *)p + strlen(typelib->library.helpstring)); 433 } 434 else 435 *p++ = 0xffff; 436 if (typelib->library.helpfile) 437 { 438 *p++ = strlen(typelib->library.helpfile); 439 strcpy((char *)p, typelib->library.helpfile); 440 p = (short *)((char *)p + strlen(typelib->library.helpfile)); 441 } 442 else 443 *p++ = 0xffff; 444 *(int *)p = typelib->library.helpcontext; 445 p += 2; 446 *p++ = typelib->library.syskind; 447 *p++ = typelib->library.lcid; 448 *(int *)p = 0; /* res12 */ 449 p += 2; 450 *p++ = typelib->library.libflags; 451 *(int *)p = typelib->library.version; 452 p += 2; 453 *(GUID *)p = typelib->library.uuid; 454 455 *index = add_index(&typelib->index, "dir"); 456 457 return block; 458 } 459 460 static const char *new_index_name(void) 461 { 462 static char name[11] = "0000000000"; 463 static int pos = 0; 464 char *new_name; 465 466 if (name[pos] == 'Z') 467 { 468 pos++; 469 if (pos > 9) 470 error("too many index names\n"); 471 } 472 473 name[pos]++; 474 475 new_name = xmalloc(sizeof(name)); 476 strcpy(new_name, name); 477 return new_name; 478 } 479 480 static void sltg_add_typeinfo(struct sltg_typelib *sltg, void *data, int size, const char *name) 481 { 482 struct sltg_block *block = xmalloc(sizeof(*block)); 483 484 chat("sltg_add_typeinfo: %p,%d,%s\n", data, size, name); 485 486 block->length = size; 487 block->data = data; 488 block->index_string = 0; 489 block->next = NULL; 490 491 if (sltg->typeinfo) 492 { 493 struct sltg_block *typeinfo = sltg->typeinfo; 494 495 while (typeinfo->next) 496 typeinfo = typeinfo->next; 497 498 typeinfo->next = block; 499 } 500 else 501 sltg->typeinfo = block; 502 503 sltg->typeinfo_count++; 504 sltg->typeinfo_size += size; 505 } 506 507 static void append_data(struct sltg_data *block, const void *data, int size) 508 { 509 int new_size = block->size + size; 510 511 if (new_size > block->allocated) 512 { 513 block->allocated = max(block->allocated * 2, new_size); 514 block->data = xrealloc(block->data, block->allocated); 515 } 516 517 memcpy(block->data + block->size, data, size); 518 block->size = new_size; 519 } 520 521 static void add_module_typeinfo(struct sltg_typelib *typelib, type_t *type) 522 { 523 error("add_module_typeinfo: %s not implemented\n", type->name); 524 } 525 526 static const char *add_typeinfo_block(struct sltg_typelib *typelib, const type_t *type, int kind) 527 { 528 const char *index_name, *other_name; 529 void *block; 530 short *p; 531 int size, helpcontext = 0; 532 GUID guid = { 0 }; 533 const expr_t *expr; 534 535 index_name = new_index_name(); 536 other_name = new_index_name(); 537 538 expr = get_attrp(type->attrs, ATTR_HELPCONTEXT); 539 if (expr) helpcontext = expr->cval; 540 541 p = get_attrp(type->attrs, ATTR_UUID); 542 if (p) guid = *(GUID *)p; 543 544 size = sizeof(short) * 8 + 10 /* index_name */ * 2 + sizeof(int) + sizeof(GUID); 545 546 block = xmalloc(size); 547 p = block; 548 *p++ = strlen(index_name); 549 strcpy((char *)p, index_name); 550 p = (short *)((char *)p + strlen(index_name)); 551 *p++ = strlen(other_name); 552 strcpy((char *)p, other_name); 553 p = (short *)((char *)p + strlen(other_name)); 554 *p++ = -1; /* res1a */ 555 *p++ = add_name(typelib, type->name); /* name offset */ 556 *p++ = 0; /* FIXME: helpstring */ 557 *p++ = -1; /* res20 */ 558 *(int *)p = helpcontext; 559 p += 2; 560 *p++ = -1; /* res26 */ 561 *(GUID *)p = guid; 562 p += sizeof(GUID)/2; 563 *p = kind; 564 565 sltg_add_typeinfo(typelib, block, size, index_name); 566 567 return index_name; 568 } 569 570 static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, int kind, 571 const struct sltg_hrefmap *hrefmap) 572 { 573 ti->magic = 0x0501; 574 ti->href_offset = -1; 575 ti->res06 = -1; 576 ti->res0e = -1; 577 ti->version = get_attrv(type->attrs, ATTR_VERSION); 578 ti->res16 = 0xfffe0000; 579 ti->misc.unknown1 = 0x02; 580 ti->misc.flags = 0; /* FIXME */ 581 ti->misc.unknown2 = 0x02; 582 ti->misc.typekind = kind; 583 ti->res1e = 0; 584 585 ti->member_offset = sizeof(*ti); 586 587 if (hrefmap->href_count) 588 { 589 char name[64]; 590 int i, hrefinfo_size; 591 592 hrefinfo_size = sizeof(struct sltg_hrefinfo); 593 594 for (i = 0; i < hrefmap->href_count; i++) 595 { 596 sprintf(name, "*\\Rffff*#%x", hrefmap->href[i]); 597 hrefinfo_size += 8 + 2 + strlen(name); 598 } 599 600 ti->href_offset = ti->member_offset; 601 ti->member_offset += hrefinfo_size; 602 } 603 } 604 605 static void init_sltg_tail(struct sltg_tail *tail) 606 { 607 tail->cFuncs = 0; 608 tail->cVars = 0; 609 tail->cImplTypes = 0; 610 tail->res06 = 0; 611 tail->funcs_off = -1; 612 tail->vars_off = -1; 613 tail->impls_off = -1; 614 tail->funcs_bytes = -1; 615 tail->vars_bytes = -1; 616 tail->impls_bytes = -1; 617 tail->tdescalias_vt = -1; 618 tail->res16 = -1; 619 tail->res18 = 0; 620 tail->res1a = 0; 621 tail->simple_alias = 0; 622 tail->res1e = 0; 623 tail->cbSizeInstance = 0; 624 tail->cbAlignment = 4; 625 tail->res24 = -1; 626 tail->res26 = -1; 627 tail->cbSizeVft = 0; 628 tail->res2a = -1; 629 tail->res2c = -1; 630 tail->res2e = -1; 631 tail->res30 = -1; 632 tail->res32 = 0; 633 tail->type_bytes = 0; 634 } 635 636 static void write_hrefmap(struct sltg_data *data, const struct sltg_hrefmap *hrefmap) 637 { 638 struct sltg_hrefinfo hrefinfo; 639 char name[64]; 640 int i; 641 642 if (!hrefmap->href_count) return; 643 644 hrefinfo.magic = 0xdf; 645 hrefinfo.res01 = 0; 646 hrefinfo.res02 = -1; 647 hrefinfo.res06 = -1; 648 hrefinfo.res0a = -1; 649 hrefinfo.res0e = -1; 650 hrefinfo.res12 = -1; 651 hrefinfo.res16 = -1; 652 hrefinfo.res1a = -1; 653 hrefinfo.res1e = -1; 654 hrefinfo.res22 = -1; 655 hrefinfo.res26 = -1; 656 hrefinfo.res2a = -1; 657 hrefinfo.res2e = -1; 658 hrefinfo.res32 = -1; 659 hrefinfo.res36 = -1; 660 hrefinfo.res3a = -1; 661 hrefinfo.res3e = -1; 662 hrefinfo.res42 = -1; 663 hrefinfo.number = hrefmap->href_count * 8; 664 hrefinfo.res50 = -1; 665 hrefinfo.res52 = 1; 666 hrefinfo.res53 = 0; 667 hrefinfo.resxx = 0xdf; 668 669 append_data(data, &hrefinfo, offsetof(struct sltg_hrefinfo, res50)); 670 671 for (i = 0; i < hrefmap->href_count; i++) 672 append_data(data, "\xff\xff\xff\xff\xff\xff\xff\xff", 8); 673 674 append_data(data, &hrefinfo.res50, 7); 675 676 for (i = 0; i < hrefmap->href_count; i++) 677 { 678 short len; 679 680 sprintf(name, "*\\Rffff*#%x", hrefmap->href[i]); 681 len = strlen(name); 682 683 append_data(data, &len, sizeof(len)); 684 append_data(data, name, len); 685 } 686 687 append_data(data, &hrefinfo.resxx, sizeof(hrefinfo.resxx)); 688 } 689 690 static void dump_var_desc(const char *data, int size) 691 { 692 const unsigned char *p = (const unsigned char *)data; 693 int i; 694 695 if (!(debuglevel & (DEBUGLEVEL_TRACE | DEBUGLEVEL_CHAT))) return; 696 697 chat("dump_var_desc: size %d bytes\n", size); 698 699 for (i = 0; i < size; i++) 700 fprintf(stderr, " %02x", *p++); 701 702 fprintf(stderr, "\n"); 703 } 704 705 static int get_element_size(type_t *type) 706 { 707 int vt = get_type_vt(type); 708 709 switch (vt) 710 { 711 case VT_I1: 712 case VT_UI1: 713 return 1; 714 715 case VT_INT: 716 case VT_UINT: 717 return typelib_kind == SYS_WIN16 ? 2 : 4; 718 719 case VT_UI2: 720 case VT_I2: 721 case VT_BOOL: 722 return 2; 723 724 case VT_I4: 725 case VT_UI4: 726 case VT_R4: 727 case VT_ERROR: 728 case VT_HRESULT: 729 return 4; 730 731 case VT_R8: 732 case VT_I8: 733 case VT_UI8: 734 case VT_CY: 735 case VT_DATE: 736 return 8; 737 738 case VT_DECIMAL: 739 return 16; 740 741 case VT_PTR: 742 case VT_UNKNOWN: 743 case VT_DISPATCH: 744 case VT_BSTR: 745 case VT_LPSTR: 746 case VT_LPWSTR: 747 return pointer_size; 748 749 case VT_VOID: 750 return 0; 751 752 case VT_VARIANT: 753 return pointer_size == 8 ? 24 : 16; 754 755 case VT_USERDEFINED: 756 return 0; 757 758 default: 759 error("get_element_size: unrecognized vt %d\n", vt); 760 break; 761 } 762 763 return 0; 764 } 765 766 static int local_href(struct sltg_hrefmap *hrefmap, int typelib_href) 767 { 768 int i, href = -1; 769 770 for (i = 0; i < hrefmap->href_count; i++) 771 { 772 if (hrefmap->href[i] == typelib_href) 773 { 774 href = i; 775 break; 776 } 777 } 778 779 if (href == -1) 780 { 781 href = hrefmap->href_count; 782 783 if (hrefmap->href) 784 hrefmap->href = xrealloc(hrefmap->href, sizeof(*hrefmap->href) * (hrefmap->href_count + 1)); 785 else 786 hrefmap->href = xmalloc(sizeof(*hrefmap->href)); 787 788 hrefmap->href[hrefmap->href_count] = typelib_href; 789 hrefmap->href_count++; 790 } 791 792 chat("typelib href %d mapped to local href %d\n", typelib_href, href); 793 794 return href << 2; 795 } 796 797 static short write_var_desc(struct sltg_typelib *typelib, struct sltg_data *data, type_t *type, short param_flags, 798 short flags, short base_offset, int *size_instance, struct sltg_hrefmap *hrefmap) 799 { 800 short vt, vt_flags, desc_offset; 801 802 chat("write_var_desc: type %p, type->name %s\n", 803 type, type->name ? type->name : "NULL"); 804 805 if (is_array(type) && !type_array_is_decl_as_ptr(type)) 806 { 807 int num_dims, elements, array_start, size, array_size; 808 type_t *atype; 809 struct 810 { 811 short cDims; 812 short fFeatures; 813 int cbElements; 814 int cLocks; 815 void *pvData; 816 int bound[2]; 817 } *array; 818 int *bound; 819 short vt_off[2]; 820 821 elements = 1; 822 num_dims = 0; 823 824 atype = type; 825 826 while (is_array(atype) && !type_array_is_decl_as_ptr(atype)) 827 { 828 num_dims++; 829 elements *= type_array_get_dim(atype); 830 831 atype = type_array_get_element(atype); 832 } 833 834 chat("write_var_desc: VT_CARRAY: %d dimensions, %d elements\n", num_dims, elements); 835 836 array_start = data->size; 837 838 size = sizeof(*array) + (num_dims - 1) * 8 /* sizeof(SAFEARRAYBOUND) */; 839 array = xmalloc(size); 840 841 array->cDims = num_dims; 842 array->fFeatures = 0x0004; /* FADF_EMBEDDED */ 843 array->cbElements = get_element_size(atype); 844 array->cLocks = 0; 845 array->pvData = NULL; 846 847 bound = array->bound; 848 849 array_size = array->cbElements; 850 atype = type; 851 852 while (is_array(atype) && !type_array_is_decl_as_ptr(atype)) 853 { 854 bound[0] = type_array_get_dim(atype); 855 array_size *= bound[0]; 856 bound[1] = 0; 857 bound += 2; 858 859 atype = type_array_get_element(atype); 860 } 861 862 if (size_instance) 863 { 864 *size_instance += array_size; 865 size_instance = NULL; /* don't account for element size */ 866 } 867 868 append_data(data, array, size); 869 870 desc_offset = data->size; 871 872 vt_off[0] = VT_CARRAY; 873 vt_off[1] = array_start + base_offset; 874 append_data(data, vt_off, sizeof(vt_off)); 875 876 /* fall through to write array element description */ 877 type = atype; 878 } 879 else 880 desc_offset = data->size; 881 882 vt = get_type_vt(type); 883 884 if (vt == VT_PTR) 885 { 886 type_t *ref = is_ptr(type) ? type_pointer_get_ref(type) : type_array_get_element(type); 887 888 if (is_ptr(ref)) 889 { 890 chat("write_var_desc: vt VT_PTR | 0x0400 | %04x\n", param_flags); 891 vt = VT_PTR | 0x0400 | param_flags; 892 append_data(data, &vt, sizeof(vt)); 893 write_var_desc(typelib, data, ref, 0, 0, base_offset, size_instance, hrefmap); 894 } 895 else 896 write_var_desc(typelib, data, ref, param_flags, 0x0e00, base_offset, size_instance, hrefmap); 897 return desc_offset; 898 } 899 900 chat("write_var_desc: vt %d, flags %04x\n", vt, flags); 901 902 vt_flags = vt | flags | param_flags; 903 append_data(data, &vt_flags, sizeof(vt_flags)); 904 905 if (vt == VT_USERDEFINED) 906 { 907 short href; 908 909 while (type->typelib_idx < 0 && type_is_alias(type)) 910 type = type_alias_get_aliasee(type); 911 912 chat("write_var_desc: VT_USERDEFINED, type %p, name %s, real type %d, href %d\n", 913 type, type->name, type_get_type(type), type->typelib_idx); 914 915 if (type->typelib_idx == -1) 916 { 917 chat("write_var_desc: trying to ref not added type\n"); 918 919 switch (type_get_type(type)) 920 { 921 case TYPE_STRUCT: 922 add_structure_typeinfo(typelib, type); 923 break; 924 case TYPE_INTERFACE: 925 add_interface_typeinfo(typelib, type); 926 break; 927 case TYPE_ENUM: 928 add_enum_typeinfo(typelib, type); 929 break; 930 case TYPE_UNION: 931 add_union_typeinfo(typelib, type); 932 break; 933 case TYPE_COCLASS: 934 add_coclass_typeinfo(typelib, type); 935 break; 936 default: 937 error("write_var_desc: VT_USERDEFINED - unhandled type %d\n", 938 type_get_type(type)); 939 } 940 } 941 942 if (type->typelib_idx == -1) 943 error("write_var_desc: trying to ref not added type\n"); 944 945 href = local_href(hrefmap, type->typelib_idx); 946 chat("write_var_desc: VT_USERDEFINED, local href %d\n", href); 947 948 append_data(data, &href, sizeof(href)); 949 } 950 951 if (size_instance) 952 *size_instance += get_element_size(type); 953 954 return desc_offset; 955 } 956 957 static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type) 958 { 959 struct sltg_data data, *var_data = NULL; 960 struct sltg_hrefmap hrefmap; 961 const char *index_name; 962 struct sltg_typeinfo_header ti; 963 struct sltg_member_header member; 964 struct sltg_tail tail; 965 int member_offset, var_count = 0, var_data_size = 0, size_instance = 0; 966 short *type_desc_offset = NULL; 967 968 if (type->typelib_idx != -1) return; 969 970 chat("add_structure_typeinfo: type %p, type->name %s\n", type, type->name); 971 972 type->typelib_idx = typelib->n_file_blocks; 973 974 hrefmap.href_count = 0; 975 hrefmap.href = NULL; 976 977 if (type_struct_get_fields(type)) 978 { 979 int i = 0; 980 var_t *var; 981 982 var_count = list_count(type_struct_get_fields(type)); 983 984 var_data = xmalloc(var_count * sizeof(*var_data)); 985 type_desc_offset = xmalloc(var_count * sizeof(*type_desc_offset)); 986 987 LIST_FOR_EACH_ENTRY(var, type_struct_get_fields(type), var_t, entry) 988 { 989 short base_offset; 990 991 chat("add_structure_typeinfo: var %p (%s), type %p (%s)\n", 992 var, var->name, var->type, var->type->name); 993 994 init_sltg_data(&var_data[i]); 995 996 base_offset = var_data_size + (i + 1) * sizeof(struct sltg_variable); 997 type_desc_offset[i] = write_var_desc(typelib, &var_data[i], var->type, 0, 0, 998 base_offset, &size_instance, &hrefmap); 999 dump_var_desc(var_data[i].data, var_data[i].size); 1000 1001 if (var_data[i].size > sizeof(short)) 1002 var_data_size += var_data[i].size; 1003 i++; 1004 } 1005 } 1006 1007 init_sltg_data(&data); 1008 1009 index_name = add_typeinfo_block(typelib, type, TKIND_RECORD); 1010 1011 init_typeinfo(&ti, type, TKIND_RECORD, &hrefmap); 1012 append_data(&data, &ti, sizeof(ti)); 1013 1014 write_hrefmap(&data, &hrefmap); 1015 1016 member_offset = data.size; 1017 1018 member.res00 = 0x0001; 1019 member.res02 = 0xffff; 1020 member.res04 = 0x01; 1021 member.extra = var_data_size + var_count * sizeof(struct sltg_variable); 1022 append_data(&data, &member, sizeof(member)); 1023 1024 var_data_size = 0; 1025 1026 if (type_struct_get_fields(type)) 1027 { 1028 int i = 0; 1029 short next = member_offset; 1030 var_t *var; 1031 1032 LIST_FOR_EACH_ENTRY(var, type_struct_get_fields(type), var_t, entry) 1033 { 1034 struct sltg_variable variable; 1035 1036 next += sizeof(variable); 1037 1038 variable.magic = 0x2a; /* always write flags to simplify calculations */ 1039 variable.name = add_name(typelib, var->name); 1040 variable.byte_offs = 0; 1041 if (var_data[i].size > sizeof(short)) 1042 { 1043 variable.flags = 0; 1044 var_data_size = next - member_offset + type_desc_offset[i]; 1045 variable.type = var_data_size; 1046 next += var_data[i].size; 1047 } 1048 else 1049 { 1050 variable.flags = 0x02; 1051 variable.type = *(short *)var_data[i].data; 1052 } 1053 variable.next = i < var_count - 1 ? next - member_offset : -1; 1054 variable.memid = 0x40000000 + i; 1055 variable.helpcontext = -2; /* 0xfffe */ 1056 variable.helpstring = -1; 1057 variable.varflags = 0; 1058 1059 append_data(&data, &variable, sizeof(variable)); 1060 if (var_data[i].size > sizeof(short)) 1061 append_data(&data, var_data[i].data, var_data[i].size); 1062 1063 i++; 1064 } 1065 } 1066 1067 init_sltg_tail(&tail); 1068 1069 tail.cVars = var_count; 1070 tail.vars_off = 0; 1071 tail.vars_bytes = var_data_size; 1072 tail.cbSizeInstance = size_instance; 1073 tail.type_bytes = data.size - member_offset - sizeof(member); 1074 append_data(&data, &tail, sizeof(tail)); 1075 1076 add_block(typelib, data.data, data.size, index_name); 1077 } 1078 1079 static importinfo_t *find_importinfo(typelib_t *typelib, const char *name) 1080 { 1081 importlib_t *importlib; 1082 1083 LIST_FOR_EACH_ENTRY(importlib, &typelib->importlibs, importlib_t, entry) 1084 { 1085 int i; 1086 1087 for (i = 0; i < importlib->ntypeinfos; i++) 1088 { 1089 if (!strcmp(name, importlib->importinfos[i].name)) 1090 { 1091 chat("Found %s in importlib list\n", name); 1092 return &importlib->importinfos[i]; 1093 } 1094 } 1095 } 1096 1097 return NULL; 1098 } 1099 1100 static int get_func_flags(const var_t *func, int *dispid, int *invokekind, int *helpcontext, const char **helpstring) 1101 { 1102 const attr_t *attr; 1103 int flags; 1104 1105 *invokekind = 1 /* INVOKE_FUNC */; 1106 *helpcontext = -2; 1107 *helpstring = NULL; 1108 1109 if (!func->attrs) return 0; 1110 1111 flags = 0; 1112 1113 LIST_FOR_EACH_ENTRY(attr, func->attrs, const attr_t, entry) 1114 { 1115 expr_t *expr = attr->u.pval; 1116 switch(attr->type) 1117 { 1118 case ATTR_BINDABLE: 1119 flags |= 0x4; /* FUNCFLAG_FBINDABLE */ 1120 break; 1121 case ATTR_DEFAULTBIND: 1122 flags |= 0x20; /* FUNCFLAG_FDEFAULTBIND */ 1123 break; 1124 case ATTR_DEFAULTCOLLELEM: 1125 flags |= 0x100; /* FUNCFLAG_FDEFAULTCOLLELEM */ 1126 break; 1127 case ATTR_DISPLAYBIND: 1128 flags |= 0x10; /* FUNCFLAG_FDISPLAYBIND */ 1129 break; 1130 case ATTR_HELPCONTEXT: 1131 *helpcontext = expr->u.lval; 1132 break; 1133 case ATTR_HELPSTRING: 1134 *helpstring = attr->u.pval; 1135 break; 1136 case ATTR_HIDDEN: 1137 flags |= 0x40; /* FUNCFLAG_FHIDDEN */ 1138 break; 1139 case ATTR_ID: 1140 *dispid = expr->cval; 1141 break; 1142 case ATTR_IMMEDIATEBIND: 1143 flags |= 0x1000; /* FUNCFLAG_FIMMEDIATEBIND */ 1144 break; 1145 case ATTR_NONBROWSABLE: 1146 flags |= 0x400; /* FUNCFLAG_FNONBROWSABLE */ 1147 break; 1148 case ATTR_PROPGET: 1149 *invokekind = 0x2; /* INVOKE_PROPERTYGET */ 1150 break; 1151 case ATTR_PROPPUT: 1152 *invokekind = 0x4; /* INVOKE_PROPERTYPUT */ 1153 break; 1154 case ATTR_PROPPUTREF: 1155 *invokekind = 0x8; /* INVOKE_PROPERTYPUTREF */ 1156 break; 1157 /* FIXME: FUNCFLAG_FREPLACEABLE */ 1158 case ATTR_REQUESTEDIT: 1159 flags |= 0x8; /* FUNCFLAG_FREQUESTEDIT */ 1160 break; 1161 case ATTR_RESTRICTED: 1162 flags |= 0x1; /* FUNCFLAG_FRESTRICTED */ 1163 break; 1164 case ATTR_SOURCE: 1165 flags |= 0x2; /* FUNCFLAG_FSOURCE */ 1166 break; 1167 case ATTR_UIDEFAULT: 1168 flags |= 0x200; /* FUNCFLAG_FUIDEFAULT */ 1169 break; 1170 case ATTR_USESGETLASTERROR: 1171 flags |= 0x80; /* FUNCFLAG_FUSESGETLASTERROR */ 1172 break; 1173 default: 1174 break; 1175 } 1176 } 1177 1178 return flags; 1179 } 1180 1181 static int get_param_flags(const var_t *param) 1182 { 1183 const attr_t *attr; 1184 int flags, in, out; 1185 1186 if (!param->attrs) return 0; 1187 1188 flags = 0; 1189 in = out = 0; 1190 1191 LIST_FOR_EACH_ENTRY(attr, param->attrs, const attr_t, entry) 1192 { 1193 switch(attr->type) 1194 { 1195 case ATTR_IN: 1196 in++; 1197 break; 1198 case ATTR_OUT: 1199 out++; 1200 break; 1201 case ATTR_PARAMLCID: 1202 flags |= 0x2000; 1203 break; 1204 case ATTR_RETVAL: 1205 flags |= 0x80; 1206 break; 1207 default: 1208 chat("unhandled param attr %d\n", attr->type); 1209 break; 1210 } 1211 } 1212 1213 if (out) 1214 { 1215 if (in) 1216 flags |= 0x8000; 1217 else 1218 flags |= 0x4000; 1219 } 1220 else if (!in) 1221 flags |= 0xc000; 1222 1223 return flags; 1224 } 1225 1226 1227 static int add_func_desc(struct sltg_typelib *typelib, struct sltg_data *data, var_t *func, 1228 int idx, int dispid, short base_offset, struct sltg_hrefmap *hrefmap) 1229 { 1230 struct sltg_data ret_data, *arg_data; 1231 int arg_count = 0, arg_data_size, optional = 0, defaults = 0, old_size; 1232 int funcflags = 0, invokekind = 1 /* INVOKE_FUNC */, helpcontext; 1233 const char *helpstring; 1234 const var_t *arg; 1235 short ret_desc_offset, *arg_desc_offset, arg_offset; 1236 struct sltg_function func_desc; 1237 1238 chat("add_func_desc: %s, idx %#x, dispid %#x\n", func->name, idx, dispid); 1239 1240 old_size = data->size; 1241 1242 init_sltg_data(&ret_data); 1243 ret_desc_offset = write_var_desc(typelib, &ret_data, type_function_get_rettype(func->type), 1244 0, 0, base_offset, NULL, hrefmap); 1245 dump_var_desc(ret_data.data, ret_data.size); 1246 1247 arg_data_size = 0; 1248 arg_offset = base_offset + sizeof(struct sltg_function); 1249 1250 if (ret_data.size > sizeof(short)) 1251 { 1252 arg_data_size += ret_data.size; 1253 arg_offset += ret_data.size; 1254 } 1255 1256 if (type_get_function_args(func->type)) 1257 { 1258 int i = 0; 1259 1260 arg_count = list_count(type_get_function_args(func->type)); 1261 1262 arg_data = xmalloc(arg_count * sizeof(*arg_data)); 1263 arg_desc_offset = xmalloc(arg_count * sizeof(*arg_desc_offset)); 1264 1265 arg_offset += arg_count * 2 * sizeof(short); 1266 1267 LIST_FOR_EACH_ENTRY(arg, type_get_function_args(func->type), const var_t, entry) 1268 { 1269 const attr_t *attr; 1270 short param_flags = get_param_flags(arg); 1271 1272 chat("add_func_desc: arg[%d] %p (%s), type %p (%s)\n", 1273 i, arg, arg->name, arg->type, arg->type->name); 1274 1275 init_sltg_data(&arg_data[i]); 1276 1277 arg_desc_offset[i] = write_var_desc(typelib, &arg_data[i], arg->type, param_flags, 0, 1278 arg_offset, NULL, hrefmap); 1279 dump_var_desc(arg_data[i].data, arg_data[i].size); 1280 1281 if (arg_data[i].size > sizeof(short)) 1282 { 1283 arg_data_size += arg_data[i].size; 1284 arg_offset += arg_data[i].size;; 1285 } 1286 1287 i++; 1288 1289 if (!arg->attrs) continue; 1290 1291 LIST_FOR_EACH_ENTRY(attr, arg->attrs, const attr_t, entry) 1292 { 1293 if (attr->type == ATTR_DEFAULTVALUE) 1294 defaults++; 1295 else if(attr->type == ATTR_OPTIONAL) 1296 optional++; 1297 } 1298 } 1299 } 1300 1301 funcflags = get_func_flags(func, &dispid, &invokekind, &helpcontext, &helpstring); 1302 1303 if (base_offset != -1) 1304 chat("add_func_desc: flags %#x, dispid %#x, invokekind %d, helpcontext %#x, helpstring %s\n", 1305 funcflags, dispid, invokekind, helpcontext, helpstring); 1306 1307 func_desc.magic = 0x6c; /* always write flags to simplify calculations */ 1308 func_desc.flags = (invokekind << 4) | 0x02; 1309 if (idx & 0x80000000) 1310 { 1311 func_desc.next = -1; 1312 idx &= ~0x80000000; 1313 } 1314 else 1315 func_desc.next = base_offset + sizeof(func_desc) + arg_data_size + arg_count * 2 * sizeof(short); 1316 func_desc.name = base_offset != -1 ? add_name(typelib, func->name) : -1; 1317 func_desc.dispid = dispid; 1318 func_desc.helpcontext = helpcontext; 1319 func_desc.helpstring = (helpstring && base_offset != -1) ? add_name(typelib, helpstring) : -1; 1320 func_desc.arg_off = arg_count ? base_offset + sizeof(func_desc) : -1; 1321 func_desc.nacc = (arg_count << 3) | 4 /* CC_STDCALL */; 1322 func_desc.retnextopt = (optional << 1); 1323 if (ret_data.size > sizeof(short)) 1324 { 1325 func_desc.rettype = base_offset + sizeof(func_desc) + ret_desc_offset; 1326 if (arg_count) 1327 func_desc.arg_off += ret_data.size; 1328 } 1329 else 1330 { 1331 func_desc.retnextopt |= 0x80; 1332 func_desc.rettype = *(short *)ret_data.data; 1333 } 1334 func_desc.vtblpos = idx * pointer_size; 1335 func_desc.funcflags = funcflags; 1336 1337 append_data(data, &func_desc, sizeof(func_desc)); 1338 1339 arg_offset = base_offset + sizeof(struct sltg_function); 1340 1341 if (ret_data.size > sizeof(short)) 1342 { 1343 append_data(data, ret_data.data, ret_data.size); 1344 func_desc.arg_off += ret_data.size; 1345 arg_offset += ret_data.size; 1346 } 1347 1348 if (arg_count) 1349 { 1350 int i = 0; 1351 1352 arg_offset += arg_count * 2 * sizeof(short); 1353 1354 LIST_FOR_EACH_ENTRY(arg, type_get_function_args(func->type), const var_t, entry) 1355 { 1356 short name, type_offset; 1357 1358 name = base_offset != -1 ? add_name(typelib, arg->name) : -1; 1359 1360 if (arg_data[i].size > sizeof(short)) 1361 { 1362 type_offset = (arg_offset + arg_desc_offset[i]); 1363 arg_offset += arg_data[i].size; 1364 } 1365 else 1366 { 1367 name |= 1; 1368 type_offset = *(short *)arg_data[i].data; 1369 } 1370 1371 append_data(data, &name, sizeof(name)); 1372 append_data(data, &type_offset, sizeof(type_offset)); 1373 1374 if (base_offset != -1) 1375 chat("add_func_desc: arg[%d] - name %s (%#x), type_offset %#x\n", 1376 i, arg->name, name, type_offset); 1377 1378 i++; 1379 } 1380 1381 for (i = 0; i < arg_count; i++) 1382 { 1383 if (arg_data[i].size > sizeof(short)) 1384 append_data(data, arg_data[i].data, arg_data[i].size); 1385 } 1386 } 1387 1388 return data->size - old_size; 1389 } 1390 1391 static void write_impl_href(struct sltg_data *data, short href) 1392 { 1393 struct sltg_impl_info impl_info; 1394 1395 impl_info.res00 = 0x004a; 1396 impl_info.next = -1; 1397 impl_info.res04 = -1; 1398 impl_info.impltypeflags = 0; 1399 impl_info.res07 = 0x80; 1400 impl_info.res08 = 0x0012; 1401 impl_info.ref = href; 1402 impl_info.res0c = 0x4001; 1403 impl_info.res0e = -2; /* 0xfffe */ 1404 impl_info.res10 = -1; 1405 impl_info.res12 = 0x001d; 1406 impl_info.pos = 0; 1407 1408 append_data(data, &impl_info, sizeof(impl_info)); 1409 } 1410 1411 static void add_interface_typeinfo(struct sltg_typelib *typelib, type_t *iface) 1412 { 1413 const statement_t *stmt_func; 1414 importinfo_t *ref_importinfo = NULL; 1415 short inherit_href = -1; 1416 struct sltg_data data; 1417 struct sltg_hrefmap hrefmap; 1418 const char *index_name; 1419 struct sltg_typeinfo_header ti; 1420 struct sltg_member_header member; 1421 struct sltg_tail tail; 1422 int member_offset, base_offset, func_data_size, i; 1423 int func_count, inherited_func_count = 0; 1424 int dispid, inherit_level = 0; 1425 1426 if (iface->typelib_idx != -1) return; 1427 1428 chat("add_interface_typeinfo: type %p, type->name %s\n", iface, iface->name); 1429 1430 if (!iface->details.iface) 1431 { 1432 error("interface %s is referenced but not defined\n", iface->name); 1433 return; 1434 } 1435 1436 if (is_attr(iface->attrs, ATTR_DISPINTERFACE)) 1437 { 1438 error("support for dispinterface %s is not implemented\n", iface->name); 1439 return; 1440 } 1441 1442 hrefmap.href_count = 0; 1443 hrefmap.href = NULL; 1444 1445 if (type_iface_get_inherit(iface)) 1446 { 1447 type_t *inherit; 1448 1449 inherit = type_iface_get_inherit(iface); 1450 1451 chat("add_interface_typeinfo: inheriting from base interface %s\n", inherit->name); 1452 1453 ref_importinfo = find_importinfo(typelib->typelib, inherit->name); 1454 1455 if (!ref_importinfo && type_iface_get_inherit(inherit)) 1456 add_interface_typeinfo(typelib, inherit); 1457 1458 if (ref_importinfo) 1459 error("support for imported interfaces is not implemented\n"); 1460 1461 inherit_href = local_href(&hrefmap, inherit->typelib_idx); 1462 1463 while (inherit) 1464 { 1465 inherit_level++; 1466 inherited_func_count += list_count(type_iface_get_stmts(inherit)); 1467 inherit = type_iface_get_inherit(inherit); 1468 } 1469 } 1470 1471 /* check typelib_idx again, it could have been added while resolving the parent interface */ 1472 if (iface->typelib_idx != -1) return; 1473 1474 iface->typelib_idx = typelib->n_file_blocks; 1475 1476 /* pass 1: calculate function descriptions data size */ 1477 init_sltg_data(&data); 1478 1479 STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(iface)) 1480 { 1481 add_func_desc(typelib, &data, stmt_func->u.var, -1, -1, -1, &hrefmap); 1482 } 1483 1484 func_data_size = data.size; 1485 1486 /* pass 2: write function descriptions */ 1487 init_sltg_data(&data); 1488 1489 func_count = list_count(type_iface_get_stmts(iface)); 1490 1491 index_name = add_typeinfo_block(typelib, iface, TKIND_INTERFACE); 1492 1493 init_typeinfo(&ti, iface, TKIND_INTERFACE, &hrefmap); 1494 append_data(&data, &ti, sizeof(ti)); 1495 1496 write_hrefmap(&data, &hrefmap); 1497 1498 member_offset = data.size; 1499 base_offset = 0; 1500 1501 member.res00 = 0x0001; 1502 member.res02 = 0xffff; 1503 member.res04 = 0x01; 1504 member.extra = func_data_size; 1505 if (inherit_href != -1) 1506 { 1507 member.extra += sizeof(struct sltg_impl_info); 1508 base_offset += sizeof(struct sltg_impl_info); 1509 } 1510 append_data(&data, &member, sizeof(member)); 1511 1512 if (inherit_href != -1) 1513 write_impl_href(&data, inherit_href); 1514 1515 i = 0; 1516 dispid = 0x60000000 | (inherit_level << 16); 1517 1518 STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(iface)) 1519 { 1520 int idx = inherited_func_count + i; 1521 1522 if (i == func_count - 1) idx |= 0x80000000; 1523 1524 base_offset += add_func_desc(typelib, &data, stmt_func->u.var, 1525 idx, dispid + i, base_offset, &hrefmap); 1526 i++; 1527 } 1528 1529 init_sltg_tail(&tail); 1530 1531 tail.cFuncs = func_count; 1532 tail.funcs_off = 0; 1533 tail.funcs_bytes = func_data_size; 1534 tail.cbSizeInstance = pointer_size; 1535 tail.cbAlignment = pointer_size; 1536 tail.cbSizeVft = (inherited_func_count + func_count) * pointer_size; 1537 tail.type_bytes = data.size - member_offset - sizeof(member); 1538 tail.res24 = 0; 1539 tail.res26 = 0; 1540 if (inherit_href != -1) 1541 { 1542 tail.cImplTypes++; 1543 tail.impls_off = 0; 1544 tail.impls_bytes = 0; 1545 1546 tail.funcs_off += sizeof(struct sltg_impl_info); 1547 } 1548 append_data(&data, &tail, sizeof(tail)); 1549 1550 add_block(typelib, data.data, data.size, index_name); 1551 } 1552 1553 static void add_enum_typeinfo(struct sltg_typelib *typelib, type_t *type) 1554 { 1555 error("add_enum_typeinfo: %s not implemented\n", type->name); 1556 } 1557 1558 static void add_union_typeinfo(struct sltg_typelib *typelib, type_t *type) 1559 { 1560 error("add_union_typeinfo: %s not implemented\n", type->name); 1561 } 1562 1563 static void add_coclass_typeinfo(struct sltg_typelib *typelib, type_t *type) 1564 { 1565 error("add_coclass_typeinfo: %s not implemented\n", type->name); 1566 } 1567 1568 static void add_type_typeinfo(struct sltg_typelib *typelib, type_t *type) 1569 { 1570 chat("add_type_typeinfo: adding %s, type %d\n", type->name, type_get_type(type)); 1571 1572 switch (type_get_type(type)) 1573 { 1574 case TYPE_INTERFACE: 1575 add_interface_typeinfo(typelib, type); 1576 break; 1577 case TYPE_STRUCT: 1578 add_structure_typeinfo(typelib, type); 1579 break; 1580 case TYPE_ENUM: 1581 add_enum_typeinfo(typelib, type); 1582 break; 1583 case TYPE_UNION: 1584 add_union_typeinfo(typelib, type); 1585 break; 1586 case TYPE_COCLASS: 1587 add_coclass_typeinfo(typelib, type); 1588 break; 1589 case TYPE_BASIC: 1590 case TYPE_POINTER: 1591 break; 1592 default: 1593 error("add_type_typeinfo: unhandled type %d for %s\n", type_get_type(type), type->name); 1594 break; 1595 } 1596 } 1597 1598 static void add_statement(struct sltg_typelib *typelib, const statement_t *stmt) 1599 { 1600 switch(stmt->type) 1601 { 1602 case STMT_LIBRARY: 1603 case STMT_IMPORT: 1604 case STMT_PRAGMA: 1605 case STMT_CPPQUOTE: 1606 case STMT_DECLARATION: 1607 /* not included in typelib */ 1608 break; 1609 case STMT_IMPORTLIB: 1610 /* not processed here */ 1611 break; 1612 1613 case STMT_TYPEDEF: 1614 { 1615 const type_list_t *type_entry = stmt->u.type_list; 1616 for (; type_entry; type_entry = type_entry->next) 1617 { 1618 /* in old style typelibs all types are public */ 1619 add_type_typeinfo(typelib, type_entry->type); 1620 } 1621 break; 1622 } 1623 1624 case STMT_MODULE: 1625 add_module_typeinfo(typelib, stmt->u.type); 1626 break; 1627 1628 case STMT_TYPE: 1629 case STMT_TYPEREF: 1630 { 1631 type_t *type = stmt->u.type; 1632 add_type_typeinfo(typelib, type); 1633 break; 1634 } 1635 1636 default: 1637 error("add_statement: unhandled statement type %d\n", stmt->type); 1638 break; 1639 } 1640 } 1641 1642 static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_start) 1643 { 1644 char pad[0x40]; 1645 struct sltg_header 1646 { 1647 int magic; 1648 short n_file_blocks; 1649 short res06; 1650 short size_of_index; 1651 short first_blk; 1652 GUID uuid; 1653 int res1c; 1654 int res20; 1655 } header; 1656 struct sltg_block_entry 1657 { 1658 int length; 1659 short index_string; 1660 short next; 1661 } entry; 1662 struct sltg_block *block; 1663 int i; 1664 1665 header.magic = 0x47544c53; 1666 header.n_file_blocks = sltg->n_file_blocks + 1; 1667 header.res06 = 9; 1668 header.size_of_index = sltg->index.size; 1669 header.first_blk = 1; 1670 header.uuid = sltg_library_guid; 1671 header.res1c = 0x00000044; 1672 header.res20 = 0xffff0000; 1673 1674 put_data(&header, sizeof(header)); 1675 1676 block = sltg->blocks; 1677 for (i = 0; i < sltg->n_file_blocks - 1; i++) 1678 { 1679 assert(block->next != NULL); 1680 1681 entry.length = block->length; 1682 entry.index_string = block->index_string; 1683 entry.next = header.first_blk + i + 1; 1684 chat("sltg_write_header: writing block entry %d: length %#x, index_string %#x, next %#x\n", 1685 i, entry.length, entry.index_string, entry.next); 1686 put_data(&entry, sizeof(entry)); 1687 1688 block = block->next; 1689 } 1690 1691 assert(block->next == NULL); 1692 1693 /* library block length includes helpstrings and name table */ 1694 entry.length = block->length + 0x40 + 2 + sltg->typeinfo_size + 4 + 6 + 12 + 0x200 + sltg->name_table.size + 12; 1695 entry.index_string = block->index_string; 1696 entry.next = 0; 1697 chat("sltg_write_header: writing library block entry %d: length %#x, index_string %#x, next %#x\n", 1698 i, entry.length, entry.index_string, entry.next); 1699 put_data(&entry, sizeof(entry)); 1700 1701 chat("sltg_write_header: writing index: %d bytes\n", sltg->index.size); 1702 put_data(sltg->index.data, sltg->index.size); 1703 memset(pad, 0, 9); 1704 put_data(pad, 9); 1705 1706 block = sltg->blocks; 1707 for (i = 0; i < sltg->n_file_blocks - 1; i++) 1708 { 1709 chat("sltg_write_header: writing block %d: %d bytes\n", i, block->length); 1710 1711 put_data(block->data, block->length); 1712 block = block->next; 1713 } 1714 1715 assert(block->next == NULL); 1716 1717 /* library block */ 1718 chat("library_block_start = %#lx\n", (SIZE_T)output_buffer_pos); 1719 *library_block_start = output_buffer_pos; 1720 chat("sltg_write_header: writing library block %d: %d bytes\n", i, block->length); 1721 put_data(block->data, block->length); 1722 1723 chat("sltg_write_header: writing pad 0x40 bytes\n"); 1724 memset(pad, 0xff, 0x40); 1725 put_data(pad, 0x40); 1726 } 1727 1728 static void sltg_write_typeinfo(struct sltg_typelib *typelib) 1729 { 1730 int i; 1731 struct sltg_block *block; 1732 short count = typelib->typeinfo_count; 1733 1734 put_data(&count, sizeof(count)); 1735 1736 block = typelib->typeinfo; 1737 for (i = 0; i < typelib->typeinfo_count; i++) 1738 { 1739 chat("sltg_write_typeinfo: writing block %d: %d bytes\n", i, block->length); 1740 1741 put_data(block->data, block->length); 1742 block = block->next; 1743 } 1744 assert(block == NULL); 1745 } 1746 1747 static void sltg_write_helpstrings(struct sltg_typelib *typelib) 1748 { 1749 static const char dummy[6]; 1750 1751 chat("sltg_write_helpstrings: writing dummy 6 bytes\n"); 1752 1753 put_data(dummy, sizeof(dummy)); 1754 } 1755 1756 static void sltg_write_nametable(struct sltg_typelib *typelib) 1757 { 1758 static const short dummy[6] = { 0xffff,1,2,0xff00,0xffff,0xffff }; 1759 char pad[0x200]; 1760 1761 chat("sltg_write_nametable: writing 12+0x200+%d bytes\n", typelib->name_table.size); 1762 1763 put_data(dummy, sizeof(dummy)); 1764 memset(pad, 0xff, 0x200); 1765 put_data(pad, 0x200); 1766 put_data(&typelib->name_table.size, sizeof(typelib->name_table.size)); 1767 put_data(typelib->name_table.data, typelib->name_table.size); 1768 } 1769 1770 static void sltg_write_remainder(void) 1771 { 1772 static const short dummy1[] = { 1,0xfffe,0x0a03,0,0xffff,0xffff }; 1773 static const short dummy2[] = { 0xffff,0xffff,0x0200,0,0,0 }; 1774 static const char dummy3[] = { 0xf4,0x39,0xb2,0x71,0,0,0,0,0,0,0,0,0,0,0,0 }; 1775 static const char TYPELIB[] = { 8,0,0,0,'T','Y','P','E','L','I','B',0 }; 1776 int pad; 1777 1778 pad = 0x01ffff01; 1779 put_data(&pad, sizeof(pad)); 1780 pad = 0; 1781 put_data(&pad, sizeof(pad)); 1782 1783 put_data(dummy1, sizeof(dummy1)); 1784 1785 put_data(&sltg_library_guid, sizeof(sltg_library_guid)); 1786 1787 put_data(TYPELIB, sizeof(TYPELIB)); 1788 1789 put_data(dummy2, sizeof(dummy2)); 1790 put_data(dummy3, sizeof(dummy3)); 1791 } 1792 1793 static void save_all_changes(struct sltg_typelib *typelib) 1794 { 1795 int library_block_start; 1796 int *name_table_offset; 1797 1798 sltg_write_header(typelib, &library_block_start); 1799 sltg_write_typeinfo(typelib); 1800 1801 name_table_offset = (int *)(output_buffer + output_buffer_pos); 1802 chat("name_table_offset = %#lx\n", (SIZE_T)output_buffer_pos); 1803 put_data(&library_block_start, sizeof(library_block_start)); 1804 1805 sltg_write_helpstrings(typelib); 1806 1807 *name_table_offset = output_buffer_pos - library_block_start; 1808 chat("*name_table_offset = %#x\n", *name_table_offset); 1809 1810 sltg_write_nametable(typelib); 1811 sltg_write_remainder(); 1812 1813 if (strendswith(typelib_name, ".res")) /* create a binary resource file */ 1814 { 1815 char typelib_id[13] = "#1"; 1816 1817 expr_t *expr = get_attrp(typelib->typelib->attrs, ATTR_ID); 1818 if (expr) 1819 sprintf(typelib_id, "#%d", expr->cval); 1820 add_output_to_resources("TYPELIB", typelib_id); 1821 output_typelib_regscript(typelib->typelib); 1822 flush_output_resources(typelib_name); 1823 } 1824 else flush_output_buffer(typelib_name); 1825 } 1826 1827 int create_sltg_typelib(typelib_t *typelib) 1828 { 1829 struct sltg_typelib sltg; 1830 const statement_t *stmt; 1831 void *library_block; 1832 int library_block_size, library_block_index; 1833 1834 pointer_size = (typelib_kind == SYS_WIN64) ? 8 : 4; 1835 1836 sltg.typelib = typelib; 1837 sltg.typeinfo_count = 0; 1838 sltg.typeinfo_size = 0; 1839 sltg.typeinfo = NULL; 1840 sltg.blocks = NULL; 1841 sltg.n_file_blocks = 0; 1842 sltg.first_block = 1; 1843 1844 init_index(&sltg.index); 1845 init_name_table(&sltg); 1846 init_library(&sltg); 1847 1848 library_block = create_library_block(&sltg, &library_block_size, &library_block_index); 1849 1850 if (typelib->stmts) 1851 LIST_FOR_EACH_ENTRY(stmt, typelib->stmts, const statement_t, entry) 1852 add_statement(&sltg, stmt); 1853 1854 add_block_index(&sltg, library_block, library_block_size, library_block_index); 1855 1856 save_all_changes(&sltg); 1857 1858 return 1; 1859 } 1860