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