Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenwrite_msft.c
Go to the documentation of this file.
00001 /* 00002 * Typelib v2 (MSFT) generation 00003 * 00004 * Copyright 2004 Alastair Bridgewater 00005 * 2004, 2005 Huw Davies 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 * 00021 * -------------------------------------------------------------------------------------- 00022 * Known problems: 00023 * 00024 * Badly incomplete. 00025 * 00026 * Only works on little-endian systems. 00027 * 00028 */ 00029 00030 #include "config.h" 00031 #include "wine/port.h" 00032 00033 #include <stdlib.h> 00034 #include <string.h> 00035 #include <stdarg.h> 00036 #include <stdio.h> 00037 #include <ctype.h> 00038 #include <time.h> 00039 00040 #define NONAMELESSUNION 00041 #define NONAMELESSSTRUCT 00042 00043 #include <typedefs.h> 00044 #include <nls.h> 00045 00046 #include "widl.h" 00047 #include "typelib.h" 00048 #include "typelib_struct.h" 00049 #include "utils.h" 00050 #include "header.h" 00051 #include "hash.h" 00052 #include "typetree.h" 00053 00054 enum MSFT_segment_index { 00055 MSFT_SEG_TYPEINFO = 0, /* type information */ 00056 MSFT_SEG_IMPORTINFO, /* import information */ 00057 MSFT_SEG_IMPORTFILES, /* import filenames */ 00058 MSFT_SEG_REFERENCES, /* references (?) */ 00059 MSFT_SEG_GUIDHASH, /* hash table for guids? */ 00060 MSFT_SEG_GUID, /* guid storage */ 00061 MSFT_SEG_NAMEHASH, /* hash table for names */ 00062 MSFT_SEG_NAME, /* name storage */ 00063 MSFT_SEG_STRING, /* string storage */ 00064 MSFT_SEG_TYPEDESC, /* type descriptions */ 00065 MSFT_SEG_ARRAYDESC, /* array descriptions */ 00066 MSFT_SEG_CUSTDATA, /* custom data */ 00067 MSFT_SEG_CUSTDATAGUID, /* custom data guids */ 00068 MSFT_SEG_UNKNOWN, /* ??? */ 00069 MSFT_SEG_UNKNOWN2, /* ??? */ 00070 MSFT_SEG_MAX /* total number of segments */ 00071 }; 00072 00073 typedef struct tagMSFT_ImpFile { 00074 int guid; 00075 LCID lcid; 00076 int version; 00077 char filename[0]; /* preceded by two bytes of encoded (length << 2) + flags in the low two bits. */ 00078 } MSFT_ImpFile; 00079 00080 typedef struct _msft_typelib_t 00081 { 00082 typelib_t *typelib; 00083 MSFT_Header typelib_header; 00084 MSFT_pSeg typelib_segdir[MSFT_SEG_MAX]; 00085 unsigned char *typelib_segment_data[MSFT_SEG_MAX]; 00086 int typelib_segment_block_length[MSFT_SEG_MAX]; 00087 00088 INT typelib_typeinfo_offsets[0x200]; /* Hope that's enough. */ 00089 00090 INT *typelib_namehash_segment; 00091 INT *typelib_guidhash_segment; 00092 00093 INT help_string_dll_offset; 00094 00095 struct _msft_typeinfo_t *typeinfos; 00096 struct _msft_typeinfo_t *last_typeinfo; 00097 } msft_typelib_t; 00098 00099 typedef struct _msft_typeinfo_t 00100 { 00101 msft_typelib_t *typelib; 00102 MSFT_TypeInfoBase *typeinfo; 00103 00104 int typekind; 00105 00106 unsigned int var_data_allocated; 00107 int *var_data; 00108 00109 unsigned int func_data_allocated; 00110 int *func_data; 00111 00112 int vars_allocated; 00113 int *var_indices; 00114 int *var_names; 00115 int *var_offsets; 00116 00117 int funcs_allocated; 00118 int *func_indices; 00119 int *func_names; 00120 int *func_offsets; 00121 00122 int datawidth; 00123 00124 struct _msft_typeinfo_t *next_typeinfo; 00125 } msft_typeinfo_t; 00126 00127 00128 00129 /*================== Internal functions ===================================*/ 00130 00131 /**************************************************************************** 00132 * ctl2_init_header 00133 * 00134 * Initializes the type library header of a new typelib. 00135 */ 00136 static void ctl2_init_header( 00137 msft_typelib_t *typelib) /* [I] The typelib to initialize. */ 00138 { 00139 typelib->typelib_header.magic1 = 0x5446534d; 00140 typelib->typelib_header.magic2 = 0x00010002; 00141 typelib->typelib_header.posguid = -1; 00142 typelib->typelib_header.lcid = 0x0409; 00143 typelib->typelib_header.lcid2 = 0x0; 00144 typelib->typelib_header.varflags = 0x40; 00145 typelib->typelib_header.version = 0; 00146 typelib->typelib_header.flags = 0; 00147 typelib->typelib_header.nrtypeinfos = 0; 00148 typelib->typelib_header.helpstring = -1; 00149 typelib->typelib_header.helpstringcontext = 0; 00150 typelib->typelib_header.helpcontext = 0; 00151 typelib->typelib_header.nametablecount = 0; 00152 typelib->typelib_header.nametablechars = 0; 00153 typelib->typelib_header.NameOffset = -1; 00154 typelib->typelib_header.helpfile = -1; 00155 typelib->typelib_header.CustomDataOffset = -1; 00156 typelib->typelib_header.res44 = 0x20; 00157 typelib->typelib_header.res48 = 0x80; 00158 typelib->typelib_header.dispatchpos = -1; 00159 typelib->typelib_header.nimpinfos = 0; 00160 } 00161 00162 /**************************************************************************** 00163 * ctl2_init_segdir 00164 * 00165 * Initializes the segment directory of a new typelib. 00166 */ 00167 static void ctl2_init_segdir( 00168 msft_typelib_t *typelib) /* [I] The typelib to initialize. */ 00169 { 00170 int i; 00171 MSFT_pSeg *segdir; 00172 00173 segdir = &typelib->typelib_segdir[MSFT_SEG_TYPEINFO]; 00174 00175 for (i = 0; i < 15; i++) { 00176 segdir[i].offset = -1; 00177 segdir[i].length = 0; 00178 segdir[i].res08 = -1; 00179 segdir[i].res0c = 0x0f; 00180 } 00181 } 00182 00183 /**************************************************************************** 00184 * ctl2_hash_guid 00185 * 00186 * Generates a hash key from a GUID. 00187 * 00188 * RETURNS 00189 * 00190 * The hash key for the GUID. 00191 */ 00192 static int ctl2_hash_guid( 00193 REFGUID guid) /* [I] The guid to hash. */ 00194 { 00195 int hash; 00196 int i; 00197 00198 hash = 0; 00199 for (i = 0; i < 8; i ++) { 00200 hash ^= ((const short *)guid)[i]; 00201 } 00202 00203 return hash & 0x1f; 00204 } 00205 00206 /**************************************************************************** 00207 * ctl2_find_guid 00208 * 00209 * Locates a guid in a type library. 00210 * 00211 * RETURNS 00212 * 00213 * The offset into the GUID segment of the guid, or -1 if not found. 00214 */ 00215 static int ctl2_find_guid( 00216 msft_typelib_t *typelib, /* [I] The typelib to operate against. */ 00217 int hash_key, /* [I] The hash key for the guid. */ 00218 REFGUID guid) /* [I] The guid to find. */ 00219 { 00220 int offset; 00221 MSFT_GuidEntry *guidentry; 00222 00223 offset = typelib->typelib_guidhash_segment[hash_key]; 00224 while (offset != -1) { 00225 guidentry = (MSFT_GuidEntry *)&typelib->typelib_segment_data[MSFT_SEG_GUID][offset]; 00226 00227 if (!memcmp(guidentry, guid, sizeof(GUID))) return offset; 00228 00229 offset = guidentry->next_hash; 00230 } 00231 00232 return offset; 00233 } 00234 00235 /**************************************************************************** 00236 * ctl2_find_name 00237 * 00238 * Locates a name in a type library. 00239 * 00240 * RETURNS 00241 * 00242 * The offset into the NAME segment of the name, or -1 if not found. 00243 * 00244 * NOTES 00245 * 00246 * The name must be encoded as with ctl2_encode_name(). 00247 */ 00248 static int ctl2_find_name( 00249 msft_typelib_t *typelib, /* [I] The typelib to operate against. */ 00250 char *name) /* [I] The encoded name to find. */ 00251 { 00252 int offset; 00253 int *namestruct; 00254 00255 offset = typelib->typelib_namehash_segment[name[2] & 0x7f]; 00256 while (offset != -1) { 00257 namestruct = (int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][offset]; 00258 00259 if (!((namestruct[2] ^ *((int *)name)) & 0xffff00ff)) { 00260 /* hash codes and lengths match, final test */ 00261 if (!strncasecmp(name+4, (void *)(namestruct+3), name[0])) break; 00262 } 00263 00264 /* move to next item in hash bucket */ 00265 offset = namestruct[1]; 00266 } 00267 00268 return offset; 00269 } 00270 00271 /**************************************************************************** 00272 * ctl2_encode_name 00273 * 00274 * Encodes a name string to a form suitable for storing into a type library 00275 * or comparing to a name stored in a type library. 00276 * 00277 * RETURNS 00278 * 00279 * The length of the encoded name, including padding and length+hash fields. 00280 * 00281 * NOTES 00282 * 00283 * Will throw an exception if name or result are NULL. Is not multithread 00284 * safe in the slightest. 00285 */ 00286 static int ctl2_encode_name( 00287 msft_typelib_t *typelib, /* [I] The typelib to operate against (used for LCID only). */ 00288 const char *name, /* [I] The name string to encode. */ 00289 char **result) /* [O] A pointer to a pointer to receive the encoded name. */ 00290 { 00291 int length; 00292 static char converted_name[0x104]; 00293 int offset; 00294 int value; 00295 00296 length = strlen(name); 00297 memcpy(converted_name + 4, name, length); 00298 00299 converted_name[length + 4] = 0; 00300 00301 00302 value = lhash_val_of_name_sys(typelib->typelib_header.varflags & 0x0f, typelib->typelib_header.lcid, converted_name + 4); 00303 00304 #ifdef WORDS_BIGENDIAN 00305 converted_name[3] = length & 0xff; 00306 converted_name[2] = 0x00; 00307 converted_name[1] = value; 00308 converted_name[0] = value >> 8; 00309 #else 00310 converted_name[0] = length & 0xff; 00311 converted_name[1] = 0x00; 00312 converted_name[2] = value; 00313 converted_name[3] = value >> 8; 00314 #endif 00315 00316 for (offset = (4 - length) & 3; offset; offset--) converted_name[length + offset + 3] = 0x57; 00317 00318 *result = converted_name; 00319 00320 return (length + 7) & ~3; 00321 } 00322 00323 /**************************************************************************** 00324 * ctl2_encode_string 00325 * 00326 * Encodes a string to a form suitable for storing into a type library or 00327 * comparing to a string stored in a type library. 00328 * 00329 * RETURNS 00330 * 00331 * The length of the encoded string, including padding and length fields. 00332 * 00333 * NOTES 00334 * 00335 * Will throw an exception if string or result are NULL. Is not multithread 00336 * safe in the slightest. 00337 */ 00338 static int ctl2_encode_string( 00339 const char *string, /* [I] The string to encode. */ 00340 char **result) /* [O] A pointer to a pointer to receive the encoded string. */ 00341 { 00342 int length; 00343 static char converted_string[0x104]; 00344 int offset; 00345 00346 length = strlen(string); 00347 memcpy(converted_string + 2, string, length); 00348 00349 #ifdef WORDS_BIGENDIAN 00350 converted_string[1] = length & 0xff; 00351 converted_string[0] = (length >> 8) & 0xff; 00352 #else 00353 converted_string[0] = length & 0xff; 00354 converted_string[1] = (length >> 8) & 0xff; 00355 #endif 00356 00357 if(length < 3) { /* strings of this length are padded with up to 8 bytes incl the 2 byte length */ 00358 for(offset = 0; offset < 4; offset++) 00359 converted_string[length + offset + 2] = 0x57; 00360 length += 4; 00361 } 00362 for (offset = (4 - (length + 2)) & 3; offset; offset--) converted_string[length + offset + 1] = 0x57; 00363 00364 *result = converted_string; 00365 00366 return (length + 5) & ~3; 00367 } 00368 00369 /**************************************************************************** 00370 * ctl2_alloc_segment 00371 * 00372 * Allocates memory from a segment in a type library. 00373 * 00374 * RETURNS 00375 * 00376 * Success: The offset within the segment of the new data area. 00377 * 00378 * BUGS 00379 * 00380 * Does not (yet) handle the case where the allocated segment memory needs to grow. 00381 */ 00382 static int ctl2_alloc_segment( 00383 msft_typelib_t *typelib, /* [I] The type library in which to allocate. */ 00384 enum MSFT_segment_index segment, /* [I] The segment in which to allocate. */ 00385 int size, /* [I] The amount to allocate. */ 00386 int block_size) /* [I] Initial allocation block size, or 0 for default. */ 00387 { 00388 int offset; 00389 00390 if(!typelib->typelib_segment_data[segment]) { 00391 if (!block_size) block_size = 0x2000; 00392 00393 typelib->typelib_segment_block_length[segment] = block_size; 00394 typelib->typelib_segment_data[segment] = xmalloc(block_size); 00395 if (!typelib->typelib_segment_data[segment]) return -1; 00396 memset(typelib->typelib_segment_data[segment], 0x57, block_size); 00397 } 00398 00399 while ((typelib->typelib_segdir[segment].length + size) > typelib->typelib_segment_block_length[segment]) { 00400 unsigned char *block; 00401 00402 block_size = typelib->typelib_segment_block_length[segment]; 00403 block = xrealloc(typelib->typelib_segment_data[segment], block_size << 1); 00404 00405 if (segment == MSFT_SEG_TYPEINFO) { 00406 /* TypeInfos have a direct pointer to their memory space, so we have to fix them up. */ 00407 msft_typeinfo_t *typeinfo; 00408 00409 for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) { 00410 typeinfo->typeinfo = (void *)&block[((unsigned char *)typeinfo->typeinfo) - typelib->typelib_segment_data[segment]]; 00411 } 00412 } 00413 00414 memset(block + block_size, 0x57, block_size); 00415 typelib->typelib_segment_block_length[segment] = block_size << 1; 00416 typelib->typelib_segment_data[segment] = block; 00417 } 00418 00419 offset = typelib->typelib_segdir[segment].length; 00420 typelib->typelib_segdir[segment].length += size; 00421 00422 return offset; 00423 } 00424 00425 /**************************************************************************** 00426 * ctl2_alloc_typeinfo 00427 * 00428 * Allocates and initializes a typeinfo structure in a type library. 00429 * 00430 * RETURNS 00431 * 00432 * Success: The offset of the new typeinfo. 00433 * Failure: -1 (this is invariably an out of memory condition). 00434 */ 00435 static int ctl2_alloc_typeinfo( 00436 msft_typelib_t *typelib, /* [I] The type library to allocate in. */ 00437 int nameoffset) /* [I] The offset of the name for this typeinfo. */ 00438 { 00439 int offset; 00440 MSFT_TypeInfoBase *typeinfo; 00441 00442 offset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEINFO, sizeof(MSFT_TypeInfoBase), 0); 00443 00444 typelib->typelib_typeinfo_offsets[typelib->typelib_header.nrtypeinfos++] = offset; 00445 00446 typeinfo = (void *)(typelib->typelib_segment_data[MSFT_SEG_TYPEINFO] + offset); 00447 00448 typeinfo->typekind = (typelib->typelib_header.nrtypeinfos - 1) << 16; 00449 typeinfo->memoffset = -1; /* should be EOF if no elements */ 00450 typeinfo->res2 = 0; 00451 typeinfo->res3 = -1; 00452 typeinfo->res4 = 3; 00453 typeinfo->res5 = 0; 00454 typeinfo->cElement = 0; 00455 typeinfo->res7 = 0; 00456 typeinfo->res8 = 0; 00457 typeinfo->res9 = 0; 00458 typeinfo->resA = 0; 00459 typeinfo->posguid = -1; 00460 typeinfo->flags = 0; 00461 typeinfo->NameOffset = nameoffset; 00462 typeinfo->version = 0; 00463 typeinfo->docstringoffs = -1; 00464 typeinfo->helpstringcontext = 0; 00465 typeinfo->helpcontext = 0; 00466 typeinfo->oCustData = -1; 00467 typeinfo->cbSizeVft = 0; 00468 typeinfo->cImplTypes = 0; 00469 typeinfo->size = 0; 00470 typeinfo->datatype1 = -1; 00471 typeinfo->datatype2 = 0; 00472 typeinfo->res18 = 0; 00473 typeinfo->res19 = -1; 00474 00475 return offset; 00476 } 00477 00478 /**************************************************************************** 00479 * ctl2_alloc_guid 00480 * 00481 * Allocates and initializes a GUID structure in a type library. Also updates 00482 * the GUID hash table as needed. 00483 * 00484 * RETURNS 00485 * 00486 * Success: The offset of the new GUID. 00487 */ 00488 static int ctl2_alloc_guid( 00489 msft_typelib_t *typelib, /* [I] The type library to allocate in. */ 00490 MSFT_GuidEntry *guid) /* [I] The GUID to store. */ 00491 { 00492 int offset; 00493 MSFT_GuidEntry *guid_space; 00494 int hash_key; 00495 00496 hash_key = ctl2_hash_guid(&guid->guid); 00497 00498 offset = ctl2_find_guid(typelib, hash_key, &guid->guid); 00499 if (offset != -1) return offset; 00500 00501 offset = ctl2_alloc_segment(typelib, MSFT_SEG_GUID, sizeof(MSFT_GuidEntry), 0); 00502 00503 guid_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_GUID] + offset); 00504 *guid_space = *guid; 00505 00506 guid_space->next_hash = typelib->typelib_guidhash_segment[hash_key]; 00507 typelib->typelib_guidhash_segment[hash_key] = offset; 00508 00509 return offset; 00510 } 00511 00512 /**************************************************************************** 00513 * ctl2_alloc_name 00514 * 00515 * Allocates and initializes a name within a type library. Also updates the 00516 * name hash table as needed. 00517 * 00518 * RETURNS 00519 * 00520 * Success: The offset within the segment of the new name. 00521 * Failure: -1 (this is invariably an out of memory condition). 00522 */ 00523 static int ctl2_alloc_name( 00524 msft_typelib_t *typelib, /* [I] The type library to allocate in. */ 00525 const char *name) /* [I] The name to store. */ 00526 { 00527 int length; 00528 int offset; 00529 MSFT_NameIntro *name_space; 00530 char *encoded_name; 00531 00532 length = ctl2_encode_name(typelib, name, &encoded_name); 00533 00534 offset = ctl2_find_name(typelib, encoded_name); 00535 if (offset != -1) return offset; 00536 00537 offset = ctl2_alloc_segment(typelib, MSFT_SEG_NAME, length + 8, 0); 00538 00539 name_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_NAME] + offset); 00540 name_space->hreftype = -1; 00541 name_space->next_hash = -1; 00542 memcpy(&name_space->namelen, encoded_name, length); 00543 00544 if (typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] != -1) 00545 name_space->next_hash = typelib->typelib_namehash_segment[encoded_name[2] & 0x7f]; 00546 00547 typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] = offset; 00548 00549 typelib->typelib_header.nametablecount += 1; 00550 typelib->typelib_header.nametablechars += *encoded_name; 00551 00552 return offset; 00553 } 00554 00555 /**************************************************************************** 00556 * ctl2_alloc_string 00557 * 00558 * Allocates and initializes a string in a type library. 00559 * 00560 * RETURNS 00561 * 00562 * Success: The offset within the segment of the new string. 00563 * Failure: -1 (this is invariably an out of memory condition). 00564 */ 00565 static int ctl2_alloc_string( 00566 msft_typelib_t *typelib, /* [I] The type library to allocate in. */ 00567 const char *string) /* [I] The string to store. */ 00568 { 00569 int length; 00570 int offset; 00571 unsigned char *string_space; 00572 char *encoded_string; 00573 00574 length = ctl2_encode_string(string, &encoded_string); 00575 00576 for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_STRING].length; 00577 offset += (((typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 1] << 8) | 00578 typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 0]) + 5) & ~3) { 00579 if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_STRING] + offset, length)) return offset; 00580 } 00581 00582 offset = ctl2_alloc_segment(typelib, MSFT_SEG_STRING, length, 0); 00583 00584 string_space = typelib->typelib_segment_data[MSFT_SEG_STRING] + offset; 00585 memcpy(string_space, encoded_string, length); 00586 00587 return offset; 00588 } 00589 00590 /**************************************************************************** 00591 * alloc_msft_importinfo 00592 * 00593 * Allocates and initializes an import information structure in a type library. 00594 * 00595 * RETURNS 00596 * 00597 * Success: The offset of the new importinfo. 00598 * Failure: -1 (this is invariably an out of memory condition). 00599 */ 00600 static int alloc_msft_importinfo( 00601 msft_typelib_t *typelib, /* [I] The type library to allocate in. */ 00602 MSFT_ImpInfo *impinfo) /* [I] The import information to store. */ 00603 { 00604 int offset; 00605 MSFT_ImpInfo *impinfo_space; 00606 00607 for (offset = 0; 00608 offset < typelib->typelib_segdir[MSFT_SEG_IMPORTINFO].length; 00609 offset += sizeof(MSFT_ImpInfo)) { 00610 if (!memcmp(&(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO][offset]), 00611 impinfo, sizeof(MSFT_ImpInfo))) { 00612 return offset; 00613 } 00614 } 00615 00616 impinfo->flags |= typelib->typelib_header.nimpinfos++; 00617 00618 offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTINFO, sizeof(MSFT_ImpInfo), 0); 00619 00620 impinfo_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO] + offset); 00621 *impinfo_space = *impinfo; 00622 00623 return offset; 00624 } 00625 00626 /**************************************************************************** 00627 * alloc_importfile 00628 * 00629 * Allocates and initializes an import file definition in a type library. 00630 * 00631 * RETURNS 00632 * 00633 * Success: The offset of the new importinfo. 00634 * Failure: -1 (this is invariably an out of memory condition). 00635 */ 00636 static int alloc_importfile( 00637 msft_typelib_t *typelib, /* [I] The type library to allocate in. */ 00638 int guidoffset, /* [I] The offset to the GUID for the imported library. */ 00639 int major_version, /* [I] The major version number of the imported library. */ 00640 int minor_version, /* [I] The minor version number of the imported library. */ 00641 const char *filename) /* [I] The filename of the imported library. */ 00642 { 00643 int length; 00644 int offset; 00645 MSFT_ImpFile *importfile; 00646 char *encoded_string; 00647 00648 length = ctl2_encode_string(filename, &encoded_string); 00649 00650 encoded_string[0] <<= 2; 00651 encoded_string[0] |= 1; 00652 00653 for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_IMPORTFILES].length; 00654 offset += (((typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xd] << 8) | 00655 typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xc]) >> 2) + 0xc) { 00656 if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES] + offset + 0xc, length)) return offset; 00657 } 00658 00659 offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTFILES, length + 0xc, 0); 00660 00661 importfile = (MSFT_ImpFile *)&typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset]; 00662 importfile->guid = guidoffset; 00663 importfile->lcid = typelib->typelib_header.lcid2; 00664 importfile->version = major_version | (minor_version << 16); 00665 memcpy(&importfile->filename, encoded_string, length); 00666 00667 return offset; 00668 } 00669 00670 static void alloc_importinfo(msft_typelib_t *typelib, importinfo_t *importinfo) 00671 { 00672 importlib_t *importlib = importinfo->importlib; 00673 00674 chat("alloc_importinfo: %s\n", importinfo->name); 00675 00676 if(!importlib->allocated) { 00677 MSFT_GuidEntry guid; 00678 int guid_idx; 00679 00680 chat("allocating importlib %s\n", importlib->name); 00681 00682 importlib->allocated = -1; 00683 00684 memcpy(&guid.guid, &importlib->guid, sizeof(GUID)); 00685 guid.hreftype = 2; 00686 00687 guid_idx = ctl2_alloc_guid(typelib, &guid); 00688 00689 alloc_importfile(typelib, guid_idx, importlib->version&0xffff, 00690 importlib->version>>16, importlib->name); 00691 } 00692 00693 if(importinfo->offset == -1 || !(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID)) { 00694 MSFT_ImpInfo impinfo; 00695 00696 impinfo.flags = importinfo->flags; 00697 impinfo.oImpFile = 0; 00698 00699 if(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID) { 00700 MSFT_GuidEntry guid; 00701 00702 guid.hreftype = 0; 00703 memcpy(&guid.guid, &importinfo->guid, sizeof(GUID)); 00704 00705 impinfo.oGuid = ctl2_alloc_guid(typelib, &guid); 00706 00707 importinfo->offset = alloc_msft_importinfo(typelib, &impinfo); 00708 00709 typelib->typelib_segment_data[MSFT_SEG_GUID][impinfo.oGuid+sizeof(GUID)] 00710 = importinfo->offset+1; 00711 00712 if(!strcmp(importinfo->name, "IDispatch")) 00713 typelib->typelib_header.dispatchpos = importinfo->offset+1; 00714 }else { 00715 impinfo.oGuid = importinfo->id; 00716 importinfo->offset = alloc_msft_importinfo(typelib, &impinfo); 00717 } 00718 } 00719 } 00720 00721 static importinfo_t *find_importinfo(msft_typelib_t *typelib, const char *name) 00722 { 00723 importlib_t *importlib; 00724 int i; 00725 00726 chat("search importlib %s\n", name); 00727 00728 if(!name) 00729 return NULL; 00730 00731 LIST_FOR_EACH_ENTRY( importlib, &typelib->typelib->importlibs, importlib_t, entry ) 00732 { 00733 for(i=0; i < importlib->ntypeinfos; i++) { 00734 if(!strcmp(name, importlib->importinfos[i].name)) { 00735 chat("Found %s in importlib.\n", name); 00736 return importlib->importinfos+i; 00737 } 00738 } 00739 } 00740 00741 return NULL; 00742 } 00743 00744 static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure); 00745 static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface); 00746 static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration); 00747 static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls); 00748 static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface); 00749 00750 00751 /**************************************************************************** 00752 * encode_type 00753 * 00754 * Encodes a type, storing information in the TYPEDESC and ARRAYDESC 00755 * segments as needed. 00756 * 00757 * RETURNS 00758 * 00759 * Success: 0. 00760 * Failure: -1. 00761 */ 00762 static int encode_type( 00763 msft_typelib_t *typelib, /* [I] The type library in which to encode the TYPEDESC. */ 00764 int vt, /* [I] vt to encode */ 00765 type_t *type, /* [I] type */ 00766 int *encoded_type, /* [O] The encoded type description. */ 00767 int *width, /* [O] The width of the type, or NULL. */ 00768 int *alignment, /* [O] The alignment of the type, or NULL. */ 00769 int *decoded_size) /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */ 00770 { 00771 int default_type; 00772 int scratch; 00773 int typeoffset; 00774 int *typedata; 00775 int target_type; 00776 int child_size = 0; 00777 00778 chat("encode_type vt %d type %p\n", vt, type); 00779 00780 default_type = 0x80000000 | (vt << 16) | vt; 00781 if (!width) width = &scratch; 00782 if (!alignment) alignment = &scratch; 00783 if (!decoded_size) decoded_size = &scratch; 00784 00785 00786 switch (vt) { 00787 case VT_I1: 00788 case VT_UI1: 00789 *encoded_type = default_type; 00790 *width = 1; 00791 *alignment = 1; 00792 break; 00793 00794 case VT_INT: 00795 *encoded_type = 0x80000000 | (VT_I4 << 16) | VT_INT; 00796 if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) { 00797 *width = 2; 00798 *alignment = 2; 00799 } else { 00800 *width = 4; 00801 *alignment = 4; 00802 } 00803 break; 00804 00805 case VT_UINT: 00806 *encoded_type = 0x80000000 | (VT_UI4 << 16) | VT_UINT; 00807 if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) { 00808 *width = 2; 00809 *alignment = 2; 00810 } else { 00811 *width = 4; 00812 *alignment = 4; 00813 } 00814 break; 00815 00816 case VT_UI2: 00817 case VT_I2: 00818 case VT_BOOL: 00819 *encoded_type = default_type; 00820 *width = 2; 00821 *alignment = 2; 00822 break; 00823 00824 case VT_I4: 00825 case VT_UI4: 00826 case VT_R4: 00827 case VT_ERROR: 00828 case VT_BSTR: 00829 case VT_HRESULT: 00830 *encoded_type = default_type; 00831 *width = 4; 00832 *alignment = 4; 00833 break; 00834 00835 case VT_R8: 00836 case VT_I8: 00837 case VT_UI8: 00838 *encoded_type = default_type; 00839 *width = 8; 00840 *alignment = 8; 00841 break; 00842 00843 case VT_CY: 00844 case VT_DATE: 00845 *encoded_type = default_type; 00846 *width = 8; 00847 *alignment = 8; 00848 break; 00849 00850 case VT_DECIMAL: 00851 *encoded_type = default_type; 00852 *width = 16; 00853 *alignment = 8; 00854 break; 00855 00856 case VT_VOID: 00857 *encoded_type = 0x80000000 | (VT_EMPTY << 16) | vt; 00858 *width = 0; 00859 *alignment = 1; 00860 break; 00861 00862 case VT_UNKNOWN: 00863 case VT_DISPATCH: 00864 *encoded_type = default_type; 00865 *width = 4; 00866 *alignment = 4; 00867 break; 00868 00869 case VT_VARIANT: 00870 *encoded_type = default_type; 00871 break; 00872 00873 case VT_LPSTR: 00874 case VT_LPWSTR: 00875 *encoded_type = 0xfffe0000 | vt; 00876 *width = 4; 00877 *alignment = 4; 00878 break; 00879 00880 case VT_PTR: 00881 { 00882 int next_vt; 00883 for(next_vt = 0; is_ptr(type); type = type_pointer_get_ref(type)) { 00884 next_vt = get_type_vt(type_pointer_get_ref(type)); 00885 if (next_vt != 0) 00886 break; 00887 } 00888 /* if no type found then it must be void */ 00889 if (next_vt == 0) 00890 next_vt = VT_VOID; 00891 00892 encode_type(typelib, next_vt, type_pointer_get_ref(type), 00893 &target_type, NULL, NULL, &child_size); 00894 /* these types already have an implicit pointer, so we don't need to 00895 * add another */ 00896 if(next_vt == VT_DISPATCH || next_vt == VT_UNKNOWN) { 00897 chat("encode_type: skipping ptr\n"); 00898 *encoded_type = target_type; 00899 *width = 4; 00900 *alignment = 4; 00901 *decoded_size = child_size; 00902 break; 00903 } 00904 00905 for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) { 00906 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; 00907 if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break; 00908 } 00909 00910 if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) { 00911 int mix_field; 00912 00913 if (target_type & 0x80000000) { 00914 mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF; 00915 } else { 00916 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type]; 00917 mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe; 00918 } 00919 00920 typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0); 00921 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; 00922 00923 typedata[0] = (mix_field << 16) | VT_PTR; 00924 typedata[1] = target_type; 00925 } 00926 00927 *encoded_type = typeoffset; 00928 00929 *width = 4; 00930 *alignment = 4; 00931 *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size; 00932 break; 00933 } 00934 00935 00936 case VT_SAFEARRAY: 00937 { 00938 type_t *element_type = type_alias_get_aliasee(type_array_get_element(type)); 00939 int next_vt = get_type_vt(element_type); 00940 00941 encode_type(typelib, next_vt, type_alias_get_aliasee(type_array_get_element(type)), &target_type, NULL, NULL, &child_size); 00942 00943 for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) { 00944 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; 00945 if (((typedata[0] & 0xffff) == VT_SAFEARRAY) && (typedata[1] == target_type)) break; 00946 } 00947 00948 if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) { 00949 int mix_field; 00950 00951 if (target_type & 0x80000000) { 00952 mix_field = ((target_type >> 16) & VT_TYPEMASK) | VT_ARRAY; 00953 } else { 00954 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type]; 00955 mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe; 00956 } 00957 00958 typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0); 00959 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; 00960 00961 typedata[0] = (mix_field << 16) | VT_SAFEARRAY; 00962 typedata[1] = target_type; 00963 } 00964 00965 *encoded_type = typeoffset; 00966 00967 *width = 4; 00968 *alignment = 4; 00969 *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size; 00970 break; 00971 } 00972 00973 00974 case VT_USERDEFINED: 00975 { 00976 int typeinfo_offset; 00977 00978 /* typedef'd types without public attribute aren't included in the typelib */ 00979 while (type->typelib_idx < 0 && type_is_alias(type) && !is_attr(type->attrs, ATTR_PUBLIC)) 00980 type = type_alias_get_aliasee(type); 00981 00982 chat("encode_type: VT_USERDEFINED - type %p name = %s real type %d idx %d\n", type, 00983 type->name, type_get_type(type), type->typelib_idx); 00984 00985 if(type->typelib_idx == -1) { 00986 chat("encode_type: trying to ref not added type\n"); 00987 switch (type_get_type(type)) { 00988 case TYPE_STRUCT: 00989 add_structure_typeinfo(typelib, type); 00990 break; 00991 case TYPE_INTERFACE: 00992 add_interface_typeinfo(typelib, type); 00993 break; 00994 case TYPE_ENUM: 00995 add_enum_typeinfo(typelib, type); 00996 break; 00997 case TYPE_COCLASS: 00998 add_coclass_typeinfo(typelib, type); 00999 break; 01000 default: 01001 error("encode_type: VT_USERDEFINED - unhandled type %d\n", 01002 type_get_type(type)); 01003 } 01004 } 01005 01006 typeinfo_offset = typelib->typelib_typeinfo_offsets[type->typelib_idx]; 01007 for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) { 01008 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; 01009 if ((typedata[0] == ((0x7fff << 16) | VT_USERDEFINED)) && (typedata[1] == typeinfo_offset)) break; 01010 } 01011 01012 if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) { 01013 typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0); 01014 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; 01015 01016 typedata[0] = (0x7fff << 16) | VT_USERDEFINED; 01017 typedata[1] = typeinfo_offset; 01018 } 01019 01020 *encoded_type = typeoffset; 01021 *width = 0; 01022 *alignment = 1; 01023 break; 01024 } 01025 01026 default: 01027 error("encode_type: unrecognized type %d.\n", vt); 01028 *encoded_type = default_type; 01029 *width = 0; 01030 *alignment = 1; 01031 break; 01032 } 01033 01034 return 0; 01035 } 01036 01037 static void dump_type(type_t *t) 01038 { 01039 chat("dump_type: %p name %s type %d attrs %p\n", t, t->name, type_get_type(t), t->attrs); 01040 } 01041 01042 static int encode_var( 01043 msft_typelib_t *typelib, /* [I] The type library in which to encode the TYPEDESC. */ 01044 type_t *type, /* [I] The type description to encode. */ 01045 var_t *var, /* [I] The var to encode. */ 01046 int *encoded_type, /* [O] The encoded type description. */ 01047 int *width, /* [O] The width of the type, or NULL. */ 01048 int *alignment, /* [O] The alignment of the type, or NULL. */ 01049 int *decoded_size) /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */ 01050 { 01051 int typeoffset; 01052 int *typedata; 01053 int target_type; 01054 int child_size; 01055 int vt; 01056 int scratch; 01057 01058 if (!width) width = &scratch; 01059 if (!alignment) alignment = &scratch; 01060 if (!decoded_size) decoded_size = &scratch; 01061 *decoded_size = 0; 01062 01063 chat("encode_var: var %p type %p type->name %s\n", 01064 var, type, type->name ? type->name : "NULL"); 01065 01066 if (is_array(type) && !type_array_is_decl_as_ptr(type)) { 01067 int num_dims, elements = 1, arrayoffset; 01068 type_t *atype; 01069 int *arraydata; 01070 01071 num_dims = 0; 01072 for (atype = type; 01073 is_array(atype) && !type_array_is_decl_as_ptr(atype); 01074 atype = type_array_get_element(atype)) 01075 ++num_dims; 01076 01077 chat("array with %d dimensions\n", num_dims); 01078 encode_var(typelib, atype, var, &target_type, width, alignment, NULL); 01079 arrayoffset = ctl2_alloc_segment(typelib, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(int), 0); 01080 arraydata = (void *)&typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset]; 01081 01082 arraydata[0] = target_type; 01083 arraydata[1] = num_dims; 01084 arraydata[1] |= ((num_dims * 2 * sizeof(int)) << 16); 01085 01086 arraydata += 2; 01087 for (atype = type; 01088 is_array(atype) && !type_array_is_decl_as_ptr(atype); 01089 atype = type_array_get_element(atype)) 01090 { 01091 arraydata[0] = type_array_get_dim(atype); 01092 arraydata[1] = 0; 01093 arraydata += 2; 01094 elements *= type_array_get_dim(atype); 01095 } 01096 01097 typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0); 01098 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; 01099 01100 typedata[0] = (0x7ffe << 16) | VT_CARRAY; 01101 typedata[1] = arrayoffset; 01102 01103 *encoded_type = typeoffset; 01104 *width = *width * elements; 01105 *decoded_size = 20 /*sizeof(ARRAYDESC)*/ + (num_dims - 1) * 8 /*sizeof(SAFEARRAYBOUND)*/; 01106 return 0; 01107 } 01108 01109 vt = get_type_vt(type); 01110 if (vt == VT_PTR) { 01111 type_t *ref = is_ptr(type) ? 01112 type_pointer_get_ref(type) : type_array_get_element(type); 01113 int skip_ptr = encode_var(typelib, ref, var, 01114 &target_type, NULL, NULL, &child_size); 01115 01116 if(skip_ptr == 2) { 01117 chat("encode_var: skipping ptr\n"); 01118 *encoded_type = target_type; 01119 *decoded_size = child_size; 01120 *width = 4; 01121 *alignment = 4; 01122 return 0; 01123 } 01124 01125 for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) { 01126 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; 01127 if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break; 01128 } 01129 01130 if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) { 01131 int mix_field; 01132 01133 if (target_type & 0x80000000) { 01134 mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF; 01135 } else { 01136 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type]; 01137 mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe; 01138 } 01139 01140 typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0); 01141 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; 01142 01143 typedata[0] = (mix_field << 16) | VT_PTR; 01144 typedata[1] = target_type; 01145 } 01146 01147 *encoded_type = typeoffset; 01148 01149 *width = 4; 01150 *alignment = 4; 01151 *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size; 01152 return 0; 01153 } 01154 01155 dump_type(type); 01156 01157 encode_type(typelib, vt, type, encoded_type, width, alignment, decoded_size); 01158 /* these types already have an implicit pointer, so we don't need to 01159 * add another */ 01160 if(vt == VT_DISPATCH || vt == VT_UNKNOWN) return 2; 01161 return 0; 01162 } 01163 01164 static unsigned int get_ulong_val(unsigned int val, int vt) 01165 { 01166 switch(vt) { 01167 case VT_I2: 01168 case VT_BOOL: 01169 case VT_UI2: 01170 return val & 0xffff; 01171 case VT_I1: 01172 case VT_UI1: 01173 return val & 0xff; 01174 } 01175 01176 return val; 01177 } 01178 01179 static void write_value(msft_typelib_t* typelib, int *out, int vt, const void *value) 01180 { 01181 switch(vt) { 01182 case VT_I2: 01183 case VT_I4: 01184 case VT_R4: 01185 case VT_BOOL: 01186 case VT_I1: 01187 case VT_UI1: 01188 case VT_UI2: 01189 case VT_UI4: 01190 case VT_INT: 01191 case VT_UINT: 01192 case VT_HRESULT: 01193 case VT_PTR: 01194 { 01195 const unsigned int lv = get_ulong_val(*(const unsigned int *)value, vt); 01196 if((lv & 0x3ffffff) == lv) { 01197 *out = 0x80000000; 01198 *out |= vt << 26; 01199 *out |= lv; 01200 } else { 01201 int offset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATA, 8, 0); 01202 *((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = vt; 01203 memcpy(&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2], value, 4); 01204 *((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+6]) = 0x5757; 01205 *out = offset; 01206 } 01207 return; 01208 } 01209 case VT_BSTR: 01210 { 01211 const char *s = (const char *) value; 01212 int len = strlen(s), seg_len = (len + 6 + 3) & ~0x3; 01213 int offset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATA, seg_len, 0); 01214 *((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = vt; 01215 memcpy(&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2], &len, sizeof(len)); 01216 memcpy(&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+6], value, len); 01217 len += 6; 01218 while(len < seg_len) { 01219 *((char *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+len]) = 0x57; 01220 len++; 01221 } 01222 *out = offset; 01223 return; 01224 } 01225 01226 default: 01227 warning("can't write value of type %d yet\n", vt); 01228 } 01229 return; 01230 } 01231 01232 static HRESULT set_custdata(msft_typelib_t *typelib, REFGUID guid, 01233 int vt, int value, int *offset) 01234 { 01235 MSFT_GuidEntry guidentry; 01236 int guidoffset; 01237 int custoffset; 01238 int *custdata; 01239 int data_out; 01240 01241 guidentry.guid = *guid; 01242 01243 guidentry.hreftype = -1; 01244 guidentry.next_hash = -1; 01245 01246 guidoffset = ctl2_alloc_guid(typelib, &guidentry); 01247 write_value(typelib, &data_out, vt, &value); 01248 01249 custoffset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATAGUID, 12, 0); 01250 01251 custdata = (int *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATAGUID][custoffset]; 01252 custdata[0] = guidoffset; 01253 custdata[1] = data_out; 01254 custdata[2] = *offset; 01255 *offset = custoffset; 01256 01257 return S_OK; 01258 } 01259 01260 static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) 01261 { 01262 int offset, name_offset; 01263 int *typedata, typedata_size; 01264 int i, id, next_idx; 01265 int decoded_size, extra_attr = 0; 01266 int num_params = 0, num_optional = 0, num_defaults = 0; 01267 var_t *arg; 01268 unsigned char *namedata; 01269 const attr_t *attr; 01270 unsigned int funcflags = 0, callconv = 4 /* CC_STDCALL */; 01271 unsigned int funckind, invokekind = 1 /* INVOKE_FUNC */; 01272 int help_context = 0, help_string_context = 0, help_string_offset = -1; 01273 int entry = -1, entry_is_ord = 0; 01274 int lcid_retval_count = 0; 01275 01276 chat("add_func_desc(%p,%d)\n", typeinfo, index); 01277 01278 id = ((0x6000 | (typeinfo->typeinfo->datatype2 & 0xffff)) << 16) | index; 01279 01280 switch(typeinfo->typekind) { 01281 case TKIND_DISPATCH: 01282 funckind = 0x4; /* FUNC_DISPATCH */ 01283 break; 01284 case TKIND_MODULE: 01285 funckind = 0x3; /* FUNC_STATIC */ 01286 break; 01287 default: 01288 funckind = 0x1; /* FUNC_PUREVIRTUAL */ 01289 break; 01290 } 01291 01292 if (is_local( func->attrs )) { 01293 chat("add_func_desc: skipping local function\n"); 01294 return S_FALSE; 01295 } 01296 01297 if (type_get_function_args(func->type)) 01298 LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry ) 01299 { 01300 num_params++; 01301 if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) { 01302 if(attr->type == ATTR_DEFAULTVALUE) 01303 num_defaults++; 01304 else if(attr->type == ATTR_OPTIONAL) 01305 num_optional++; 01306 } 01307 } 01308 01309 chat("add_func_desc: num of params %d\n", num_params); 01310 01311 name_offset = ctl2_alloc_name(typeinfo->typelib, func->name); 01312 01313 if (func->attrs) LIST_FOR_EACH_ENTRY( attr, func->attrs, const attr_t, entry ) { 01314 expr_t *expr = attr->u.pval; 01315 switch(attr->type) { 01316 case ATTR_BINDABLE: 01317 funcflags |= 0x4; /* FUNCFLAG_FBINDABLE */ 01318 break; 01319 case ATTR_DEFAULTBIND: 01320 funcflags |= 0x20; /* FUNCFLAG_FDEFAULTBIND */ 01321 break; 01322 case ATTR_DEFAULTCOLLELEM: 01323 funcflags |= 0x100; /* FUNCFLAG_FDEFAULTCOLLELEM */ 01324 break; 01325 case ATTR_DISPLAYBIND: 01326 funcflags |= 0x10; /* FUNCFLAG_FDISPLAYBIND */ 01327 break; 01328 case ATTR_ENTRY: 01329 extra_attr = max(extra_attr, 3); 01330 if (expr->type == EXPR_STRLIT || expr->type == EXPR_WSTRLIT) 01331 entry = ctl2_alloc_string(typeinfo->typelib, attr->u.pval); 01332 else { 01333 entry = expr->cval; 01334 entry_is_ord = 1; 01335 } 01336 break; 01337 case ATTR_HELPCONTEXT: 01338 extra_attr = max(extra_attr, 1); 01339 help_context = expr->u.lval; 01340 break; 01341 case ATTR_HELPSTRING: 01342 extra_attr = max(extra_attr, 2); 01343 help_string_offset = ctl2_alloc_string(typeinfo->typelib, attr->u.pval); 01344 break; 01345 case ATTR_HELPSTRINGCONTEXT: 01346 extra_attr = max(extra_attr, 6); 01347 help_string_context = expr->u.lval; 01348 break; 01349 case ATTR_HIDDEN: 01350 funcflags |= 0x40; /* FUNCFLAG_FHIDDEN */ 01351 break; 01352 case ATTR_ID: 01353 id = expr->cval; 01354 break; 01355 case ATTR_IMMEDIATEBIND: 01356 funcflags |= 0x1000; /* FUNCFLAG_FIMMEDIATEBIND */ 01357 break; 01358 case ATTR_NONBROWSABLE: 01359 funcflags |= 0x400; /* FUNCFLAG_FNONBROWSABLE */ 01360 break; 01361 case ATTR_OUT: 01362 break; 01363 case ATTR_PROPGET: 01364 invokekind = 0x2; /* INVOKE_PROPERTYGET */ 01365 break; 01366 case ATTR_PROPPUT: 01367 invokekind = 0x4; /* INVOKE_PROPERTYPUT */ 01368 break; 01369 case ATTR_PROPPUTREF: 01370 invokekind = 0x8; /* INVOKE_PROPERTYPUTREF */ 01371 break; 01372 /* FIXME: FUNCFLAG_FREPLACEABLE */ 01373 case ATTR_REQUESTEDIT: 01374 funcflags |= 0x8; /* FUNCFLAG_FREQUESTEDIT */ 01375 break; 01376 case ATTR_RESTRICTED: 01377 funcflags |= 0x1; /* FUNCFLAG_FRESTRICTED */ 01378 break; 01379 case ATTR_SOURCE: 01380 funcflags |= 0x2; /* FUNCFLAG_FSOURCE */ 01381 break; 01382 case ATTR_UIDEFAULT: 01383 funcflags |= 0x200; /* FUNCFLAG_FUIDEFAULT */ 01384 break; 01385 case ATTR_USESGETLASTERROR: 01386 funcflags |= 0x80; /* FUNCFLAG_FUSESGETLASTERROR */ 01387 break; 01388 case ATTR_VARARG: 01389 if (num_optional || num_defaults) 01390 warning("add_func_desc: ignoring vararg in function with optional or defaultvalue params\n"); 01391 else 01392 num_optional = -1; 01393 break; 01394 default: 01395 break; 01396 } 01397 } 01398 01399 /* allocate type data space for us */ 01400 typedata_size = 0x18 + extra_attr * sizeof(int) + (num_params * (num_defaults ? 16 : 12)); 01401 01402 if (!typeinfo->func_data) { 01403 typeinfo->func_data = xmalloc(0x100); 01404 typeinfo->func_data_allocated = 0x100; 01405 typeinfo->func_data[0] = 0; 01406 } 01407 01408 if(typeinfo->func_data[0] + typedata_size + sizeof(int) > typeinfo->func_data_allocated) { 01409 typeinfo->func_data_allocated = max(typeinfo->func_data_allocated * 2, 01410 typeinfo->func_data[0] + typedata_size + sizeof(int)); 01411 typeinfo->func_data = xrealloc(typeinfo->func_data, typeinfo->func_data_allocated); 01412 } 01413 01414 offset = typeinfo->func_data[0]; 01415 typeinfo->func_data[0] += typedata_size; 01416 typedata = typeinfo->func_data + (offset >> 2) + 1; 01417 01418 01419 /* find func with the same name - if it exists use its id */ 01420 for(i = 0; i < (typeinfo->typeinfo->cElement & 0xffff); i++) { 01421 if(name_offset == typeinfo->func_names[i]) { 01422 id = typeinfo->func_indices[i]; 01423 break; 01424 } 01425 } 01426 01427 /* find the first func with the same id and link via the hiword of typedata[4] */ 01428 next_idx = index; 01429 for(i = 0; i < (typeinfo->typeinfo->cElement & 0xffff); i++) { 01430 if(id == typeinfo->func_indices[i]) { 01431 next_idx = typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] >> 16; 01432 typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] &= 0xffff; 01433 typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] |= (index << 16); 01434 break; 01435 } 01436 } 01437 01438 /* fill out the basic type information */ 01439 typedata[0] = typedata_size | (index << 16); 01440 encode_var(typeinfo->typelib, type_function_get_rettype(func->type), func, &typedata[1], NULL, NULL, &decoded_size); 01441 typedata[2] = funcflags; 01442 typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft; 01443 typedata[4] = (next_idx << 16) | (callconv << 8) | (invokekind << 3) | funckind; 01444 if(num_defaults) typedata[4] |= 0x1000; 01445 if(entry_is_ord) typedata[4] |= 0x2000; 01446 typedata[5] = (num_optional << 16) | num_params; 01447 01448 /* NOTE: High word of typedata[3] is total size of FUNCDESC + size of all ELEMDESCs for params + TYPEDESCs for pointer params and return types. */ 01449 /* That is, total memory allocation required to reconstitute the FUNCDESC in its entirety. */ 01450 typedata[3] += (16 /*sizeof(ELEMDESC)*/ * num_params) << 16; 01451 typedata[3] += (24 /*sizeof(PARAMDESCEX)*/ * num_defaults) << 16; 01452 01453 switch(extra_attr) { 01454 case 6: typedata[11] = help_string_context; 01455 case 5: typedata[10] = -1; 01456 case 4: typedata[9] = -1; 01457 case 3: typedata[8] = entry; 01458 case 2: typedata[7] = help_string_offset; 01459 case 1: typedata[6] = help_context; 01460 case 0: 01461 break; 01462 default: 01463 warning("unknown number of optional attrs\n"); 01464 } 01465 01466 if (type_get_function_args(func->type)) 01467 { 01468 i = 0; 01469 LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry ) 01470 { 01471 int paramflags = 0; 01472 int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3; 01473 int *defaultdata = num_defaults ? typedata + 6 + extra_attr + i : NULL; 01474 01475 if(defaultdata) *defaultdata = -1; 01476 01477 encode_var(typeinfo->typelib, arg->type, arg, paramdata, NULL, NULL, &decoded_size); 01478 if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) { 01479 switch(attr->type) { 01480 case ATTR_DEFAULTVALUE: 01481 { 01482 int vt; 01483 expr_t *expr = (expr_t *)attr->u.pval; 01484 if (type_get_type(arg->type) == TYPE_ENUM) 01485 vt = VT_INT; 01486 else 01487 vt = get_type_vt(arg->type); 01488 paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */ 01489 if (expr->type == EXPR_STRLIT || expr->type == EXPR_WSTRLIT) 01490 { 01491 if (vt != VT_BSTR) error("string default value applied to non-string type\n"); 01492 chat("default value '%s'\n", expr->u.sval); 01493 write_value(typeinfo->typelib, defaultdata, vt, expr->u.sval); 01494 } 01495 else 01496 { 01497 chat("default value %d\n", expr->cval); 01498 write_value(typeinfo->typelib, defaultdata, vt, &expr->cval); 01499 } 01500 break; 01501 } 01502 case ATTR_IN: 01503 paramflags |= 0x01; /* PARAMFLAG_FIN */ 01504 break; 01505 case ATTR_OPTIONAL: 01506 paramflags |= 0x10; /* PARAMFLAG_FOPT */ 01507 break; 01508 case ATTR_OUT: 01509 paramflags |= 0x02; /* PARAMFLAG_FOUT */ 01510 break; 01511 case ATTR_PARAMLCID: 01512 paramflags |= 0x04; /* PARAMFLAG_LCID */ 01513 lcid_retval_count++; 01514 break; 01515 case ATTR_RETVAL: 01516 paramflags |= 0x08; /* PARAMFLAG_FRETVAL */ 01517 lcid_retval_count++; 01518 break; 01519 default: 01520 chat("unhandled param attr %d\n", attr->type); 01521 break; 01522 } 01523 } 01524 paramdata[1] = -1; 01525 paramdata[2] = paramflags; 01526 typedata[3] += decoded_size << 16; 01527 01528 i++; 01529 } 01530 } 01531 01532 if(lcid_retval_count == 1) 01533 typedata[4] |= 0x4000; 01534 else if(lcid_retval_count == 2) 01535 typedata[4] |= 0x8000; 01536 01537 if(typeinfo->funcs_allocated == 0) { 01538 typeinfo->funcs_allocated = 10; 01539 typeinfo->func_indices = xmalloc(typeinfo->funcs_allocated * sizeof(int)); 01540 typeinfo->func_names = xmalloc(typeinfo->funcs_allocated * sizeof(int)); 01541 typeinfo->func_offsets = xmalloc(typeinfo->funcs_allocated * sizeof(int)); 01542 } 01543 if(typeinfo->funcs_allocated == (typeinfo->typeinfo->cElement & 0xffff)) { 01544 typeinfo->funcs_allocated *= 2; 01545 typeinfo->func_indices = xrealloc(typeinfo->func_indices, typeinfo->funcs_allocated * sizeof(int)); 01546 typeinfo->func_names = xrealloc(typeinfo->func_names, typeinfo->funcs_allocated * sizeof(int)); 01547 typeinfo->func_offsets = xrealloc(typeinfo->func_offsets, typeinfo->funcs_allocated * sizeof(int)); 01548 } 01549 01550 /* update the index data */ 01551 typeinfo->func_indices[typeinfo->typeinfo->cElement & 0xffff] = id; 01552 typeinfo->func_offsets[typeinfo->typeinfo->cElement & 0xffff] = offset; 01553 typeinfo->func_names[typeinfo->typeinfo->cElement & 0xffff] = name_offset; 01554 01555 /* ??? */ 01556 if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x20; 01557 typeinfo->typeinfo->res2 <<= 1; 01558 /* ??? */ 01559 if (index < 2) typeinfo->typeinfo->res2 += num_params << 4; 01560 01561 if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0; 01562 typeinfo->typeinfo->res3 += 0x38 + num_params * 0x10; 01563 if(num_defaults) typeinfo->typeinfo->res3 += num_params * 0x4; 01564 01565 /* adjust size of VTBL */ 01566 if(funckind != 0x3 /* FUNC_STATIC */) 01567 typeinfo->typeinfo->cbSizeVft += pointer_size; 01568 01569 /* Increment the number of function elements */ 01570 typeinfo->typeinfo->cElement += 1; 01571 01572 namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + name_offset; 01573 if (*((INT *)namedata) == -1) { 01574 *((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16]; 01575 if(typeinfo->typekind == TKIND_MODULE) 01576 namedata[9] |= 0x10; 01577 } else 01578 namedata[9] &= ~0x10; 01579 01580 if(typeinfo->typekind == TKIND_MODULE) 01581 namedata[9] |= 0x20; 01582 01583 if (type_get_function_args(func->type)) 01584 { 01585 i = 0; 01586 LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry ) 01587 { 01588 /* don't give the last arg of a [propput*] func a name */ 01589 if(i != num_params - 1 || (invokekind != 0x4 /* INVOKE_PROPERTYPUT */ && invokekind != 0x8 /* INVOKE_PROPERTYPUTREF */)) 01590 { 01591 int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3; 01592 offset = ctl2_alloc_name(typeinfo->typelib, arg->name); 01593 paramdata[1] = offset; 01594 } 01595 i++; 01596 } 01597 } 01598 return S_OK; 01599 } 01600 01601 static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) 01602 { 01603 int offset, id; 01604 unsigned int typedata_size; 01605 INT *typedata; 01606 int var_datawidth; 01607 int var_alignment; 01608 int var_type_size, var_kind = 0 /* VAR_PERINSTANCE */; 01609 int alignment; 01610 int varflags = 0; 01611 const attr_t *attr; 01612 unsigned char *namedata; 01613 int var_num = (typeinfo->typeinfo->cElement >> 16) & 0xffff; 01614 01615 chat("add_var_desc(%d, %s)\n", index, var->name); 01616 01617 id = 0x40000000 + index; 01618 01619 if (var->attrs) LIST_FOR_EACH_ENTRY( attr, var->attrs, const attr_t, entry ) { 01620 expr_t *expr = attr->u.pval; 01621 switch(attr->type) { 01622 case ATTR_BINDABLE: 01623 varflags |= 0x04; /* VARFLAG_FBINDABLE */ 01624 break; 01625 case ATTR_DEFAULTBIND: 01626 varflags |= 0x20; /* VARFLAG_FDEFAULTBIND */ 01627 break; 01628 case ATTR_DEFAULTCOLLELEM: 01629 varflags |= 0x100; /* VARFLAG_FDEFAULTCOLLELEM */ 01630 break; 01631 case ATTR_DISPLAYBIND: 01632 varflags |= 0x10; /* VARFLAG_FDISPLAYBIND */ 01633 break; 01634 case ATTR_HIDDEN: 01635 varflags |= 0x40; /* VARFLAG_FHIDDEN */ 01636 break; 01637 case ATTR_ID: 01638 id = expr->cval; 01639 break; 01640 case ATTR_IMMEDIATEBIND: 01641 varflags |= 0x1000; /* VARFLAG_FIMMEDIATEBIND */ 01642 break; 01643 case ATTR_NONBROWSABLE: 01644 varflags |= 0x400; /* VARFLAG_FNONBROWSABLE */ 01645 break; 01646 case ATTR_READONLY: 01647 varflags |= 0x01; /* VARFLAG_FREADONLY */ 01648 break; 01649 /* FIXME: VARFLAG_FREPLACEABLE */ 01650 case ATTR_REQUESTEDIT: 01651 varflags |= 0x08; /* VARFLAG_FREQUESTEDIT */ 01652 break; 01653 case ATTR_RESTRICTED: 01654 varflags |= 0x80; /* VARFLAG_FRESTRICTED */ 01655 break; 01656 case ATTR_SOURCE: 01657 varflags |= 0x02; /* VARFLAG_FSOURCE */ 01658 break; 01659 case ATTR_UIDEFAULT: 01660 varflags |= 0x0200; /* VARFLAG_FUIDEFAULT */ 01661 break; 01662 default: 01663 break; 01664 } 01665 } 01666 01667 /* allocate type data space for us */ 01668 typedata_size = 0x14; 01669 01670 if (!typeinfo->var_data) { 01671 typeinfo->var_data = xmalloc(0x100); 01672 typeinfo->var_data_allocated = 0x100; 01673 typeinfo->var_data[0] = 0; 01674 } 01675 01676 if(typeinfo->var_data[0] + typedata_size + sizeof(int) > typeinfo->var_data_allocated) { 01677 typeinfo->var_data_allocated = max(typeinfo->var_data_allocated * 2, 01678 typeinfo->var_data[0] + typedata_size + sizeof(int)); 01679 typeinfo->var_data = xrealloc(typeinfo->var_data, typeinfo->var_data_allocated); 01680 } 01681 01682 offset = typeinfo->var_data[0]; 01683 typeinfo->var_data[0] += typedata_size; 01684 typedata = typeinfo->var_data + (offset >> 2) + 1; 01685 01686 /* fill out the basic type information */ 01687 typedata[0] = typedata_size | (index << 16); 01688 typedata[2] = varflags; 01689 typedata[3] = (36 /*sizeof(VARDESC)*/ << 16) | 0; 01690 01691 if(typeinfo->vars_allocated == 0) { 01692 typeinfo->vars_allocated = 10; 01693 typeinfo->var_indices = xmalloc(typeinfo->vars_allocated * sizeof(int)); 01694 typeinfo->var_names = xmalloc(typeinfo->vars_allocated * sizeof(int)); 01695 typeinfo->var_offsets = xmalloc(typeinfo->vars_allocated * sizeof(int)); 01696 } 01697 if(typeinfo->vars_allocated == var_num) { 01698 typeinfo->vars_allocated *= 2; 01699 typeinfo->var_indices = xrealloc(typeinfo->var_indices, typeinfo->vars_allocated * sizeof(int)); 01700 typeinfo->var_names = xrealloc(typeinfo->var_names, typeinfo->vars_allocated * sizeof(int)); 01701 typeinfo->var_offsets = xrealloc(typeinfo->var_offsets, typeinfo->vars_allocated * sizeof(int)); 01702 } 01703 /* update the index data */ 01704 typeinfo->var_indices[var_num] = id; 01705 typeinfo->var_names[var_num] = -1; 01706 typeinfo->var_offsets[var_num] = offset; 01707 01708 /* figure out type widths and whatnot */ 01709 encode_var(typeinfo->typelib, var->type, var, &typedata[1], &var_datawidth, 01710 &var_alignment, &var_type_size); 01711 01712 /* pad out starting position to data width */ 01713 typeinfo->datawidth += var_alignment - 1; 01714 typeinfo->datawidth &= ~(var_alignment - 1); 01715 01716 switch(typeinfo->typekind) { 01717 case TKIND_ENUM: 01718 write_value(typeinfo->typelib, &typedata[4], VT_I4, &var->eval->cval); 01719 var_kind = 2; /* VAR_CONST */ 01720 var_type_size += 16; /* sizeof(VARIANT) */ 01721 typeinfo->datawidth = var_datawidth; 01722 break; 01723 case TKIND_RECORD: 01724 typedata[4] = typeinfo->datawidth; 01725 typeinfo->datawidth += var_datawidth; 01726 break; 01727 case TKIND_DISPATCH: 01728 var_kind = 3; /* VAR_DISPATCH */ 01729 typeinfo->datawidth = 4; 01730 var_alignment = 4; 01731 break; 01732 default: 01733 error("add_var_desc: unhandled type kind %d\n", typeinfo->typekind); 01734 break; 01735 } 01736 01737 /* add type description size to total required allocation */ 01738 typedata[3] += var_type_size << 16 | var_kind; 01739 01740 /* fix type alignment */ 01741 alignment = (typeinfo->typeinfo->typekind >> 11) & 0x1f; 01742 if (alignment < var_alignment) { 01743 alignment = var_alignment; 01744 typeinfo->typeinfo->typekind &= ~0xffc0; 01745 typeinfo->typeinfo->typekind |= alignment << 11 | alignment << 6; 01746 } 01747 01748 /* ??? */ 01749 if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x1a; 01750 if ((index == 0) || (index == 1) || (index == 2) || (index == 4) || (index == 9)) { 01751 typeinfo->typeinfo->res2 <<= 1; 01752 } 01753 01754 /* ??? */ 01755 if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0; 01756 typeinfo->typeinfo->res3 += 0x2c; 01757 01758 /* increment the number of variable elements */ 01759 typeinfo->typeinfo->cElement += 0x10000; 01760 01761 /* pad data width to alignment */ 01762 typeinfo->typeinfo->size = (typeinfo->datawidth + (alignment - 1)) & ~(alignment - 1); 01763 01764 offset = ctl2_alloc_name(typeinfo->typelib, var->name); 01765 if (offset == -1) return E_OUTOFMEMORY; 01766 01767 namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset; 01768 if (*((INT *)namedata) == -1) { 01769 *((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16]; 01770 if(typeinfo->typekind != TKIND_DISPATCH) 01771 namedata[9] |= 0x10; 01772 } else 01773 namedata[9] &= ~0x10; 01774 01775 if (typeinfo->typekind == TKIND_ENUM) { 01776 namedata[9] |= 0x20; 01777 } 01778 typeinfo->var_names[var_num] = offset; 01779 01780 return S_OK; 01781 } 01782 01783 static HRESULT add_impl_type(msft_typeinfo_t *typeinfo, type_t *ref, importinfo_t *importinfo) 01784 { 01785 if(importinfo) { 01786 alloc_importinfo(typeinfo->typelib, importinfo); 01787 typeinfo->typeinfo->datatype1 = importinfo->offset+1; 01788 }else { 01789 if(ref->typelib_idx == -1) 01790 add_interface_typeinfo(typeinfo->typelib, ref); 01791 if(ref->typelib_idx == -1) 01792 error("add_impl_type: unable to add inherited interface\n"); 01793 01794 typeinfo->typeinfo->datatype1 = typeinfo->typelib->typelib_typeinfo_offsets[ref->typelib_idx]; 01795 } 01796 01797 typeinfo->typeinfo->cImplTypes++; 01798 return S_OK; 01799 } 01800 01801 static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_kind kind, 01802 const char *name, const attr_list_t *attrs) 01803 { 01804 const attr_t *attr; 01805 msft_typeinfo_t *msft_typeinfo; 01806 int nameoffset; 01807 int typeinfo_offset; 01808 MSFT_TypeInfoBase *typeinfo; 01809 MSFT_GuidEntry guidentry; 01810 01811 chat("create_msft_typeinfo: name %s kind %d\n", name, kind); 01812 01813 msft_typeinfo = xmalloc(sizeof(*msft_typeinfo)); 01814 memset( msft_typeinfo, 0, sizeof(*msft_typeinfo) ); 01815 01816 msft_typeinfo->typelib = typelib; 01817 01818 nameoffset = ctl2_alloc_name(typelib, name); 01819 typeinfo_offset = ctl2_alloc_typeinfo(typelib, nameoffset); 01820 typeinfo = (MSFT_TypeInfoBase *)&typelib->typelib_segment_data[MSFT_SEG_TYPEINFO][typeinfo_offset]; 01821 01822 typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset + 9] = 0x38; 01823 *((int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset]) = typeinfo_offset; 01824 01825 msft_typeinfo->typekind = kind; 01826 msft_typeinfo->typeinfo = typeinfo; 01827 01828 typeinfo->typekind |= kind | 0x20; 01829 01830 if(kind == TKIND_COCLASS) 01831 typeinfo->flags |= 0x2; /* TYPEFLAG_FCANCREATE */ 01832 01833 if (attrs) LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) { 01834 switch(attr->type) { 01835 case ATTR_AGGREGATABLE: 01836 if (kind == TKIND_COCLASS) 01837 typeinfo->flags |= 0x400; /* TYPEFLAG_FAGGREGATABLE */ 01838 break; 01839 01840 case ATTR_APPOBJECT: 01841 if (kind == TKIND_COCLASS) 01842 typeinfo->flags |= 0x1; /* TYPEFLAG_FAPPOBJECT */ 01843 break; 01844 01845 case ATTR_CONTROL: 01846 if (kind == TKIND_COCLASS) 01847 typeinfo->flags |= 0x20; /* TYPEFLAG_FCONTROL */ 01848 break; 01849 01850 case ATTR_DLLNAME: 01851 { 01852 int offset = ctl2_alloc_string(typelib, attr->u.pval); 01853 typeinfo->datatype1 = offset; 01854 break; 01855 } 01856 01857 case ATTR_DUAL: 01858 /* FIXME: check interface is compatible */ 01859 typeinfo->typekind = (typeinfo->typekind & ~0xff) | 0x34; 01860 typeinfo->flags |= 0x140; /* TYPEFLAG_FDUAL | TYPEFLAG_FOLEAUTOMATION */ 01861 break; 01862 01863 case ATTR_HELPCONTEXT: 01864 { 01865 expr_t *expr = (expr_t*)attr->u.pval; 01866 typeinfo->helpcontext = expr->cval; 01867 break; 01868 } 01869 case ATTR_HELPSTRING: 01870 { 01871 int offset = ctl2_alloc_string(typelib, attr->u.pval); 01872 if (offset == -1) break; 01873 typeinfo->docstringoffs = offset; 01874 break; 01875 } 01876 case ATTR_HELPSTRINGCONTEXT: 01877 { 01878 expr_t *expr = (expr_t*)attr->u.pval; 01879 typeinfo->helpstringcontext = expr->cval; 01880 break; 01881 } 01882 case ATTR_HIDDEN: 01883 typeinfo->flags |= 0x10; /* TYPEFLAG_FHIDDEN */ 01884 break; 01885 01886 case ATTR_LICENSED: 01887 typeinfo->flags |= 0x04; /* TYPEFLAG_FLICENSED */ 01888 break; 01889 01890 case ATTR_NONCREATABLE: 01891 typeinfo->flags &= ~0x2; /* TYPEFLAG_FCANCREATE */ 01892 break; 01893 01894 case ATTR_NONEXTENSIBLE: 01895 typeinfo->flags |= 0x80; /* TYPEFLAG_FNONEXTENSIBLE */ 01896 break; 01897 01898 case ATTR_OLEAUTOMATION: 01899 typeinfo->flags |= 0x100; /* TYPEFLAG_FOLEAUTOMATION */ 01900 break; 01901 01902 /* FIXME: TYPEFLAG_FPREDCLID */ 01903 01904 case ATTR_PROXY: 01905 typeinfo->flags |= 0x4000; /* TYPEFLAG_FPROXY */ 01906 break; 01907 01908 /* FIXME: TYPEFLAG_FREPLACEABLE */ 01909 01910 case ATTR_RESTRICTED: 01911 typeinfo->flags |= 0x200; /* TYPEFLAG_FRESTRICTED */ 01912 break; 01913 01914 case ATTR_UUID: 01915 guidentry.guid = *(GUID*)attr->u.pval; 01916 guidentry.hreftype = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16]; 01917 guidentry.next_hash = -1; 01918 typeinfo->posguid = ctl2_alloc_guid(typelib, &guidentry); 01919 #if 0 01920 if (IsEqualIID(guid, &IID_IDispatch)) { 01921 typelib->typelib_header.dispatchpos = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16]; 01922 } 01923 #endif 01924 break; 01925 01926 case ATTR_VERSION: 01927 typeinfo->version = attr->u.ival; 01928 break; 01929 01930 default: 01931 break; 01932 } 01933 } 01934 01935 if (typelib->last_typeinfo) typelib->last_typeinfo->next_typeinfo = msft_typeinfo; 01936 typelib->last_typeinfo = msft_typeinfo; 01937 if (!typelib->typeinfos) typelib->typeinfos = msft_typeinfo; 01938 01939 01940 return msft_typeinfo; 01941 } 01942 01943 static void add_dispatch(msft_typelib_t *typelib) 01944 { 01945 int guid_offset, impfile_offset; 01946 MSFT_GuidEntry guidentry; 01947 MSFT_ImpInfo impinfo; 01948 GUID stdole = {0x00020430,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; 01949 GUID iid_idispatch = {0x00020400,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; 01950 01951 if(typelib->typelib_header.dispatchpos != -1) return; 01952 01953 guidentry.guid = stdole; 01954 guidentry.hreftype = 2; 01955 guidentry.next_hash = -1; 01956 guid_offset = ctl2_alloc_guid(typelib, &guidentry); 01957 impfile_offset = alloc_importfile(typelib, guid_offset, 2, 0, "stdole2.tlb"); 01958 01959 guidentry.guid = iid_idispatch; 01960 guidentry.hreftype = 1; 01961 guidentry.next_hash = -1; 01962 impinfo.flags = TKIND_INTERFACE << 24 | MSFT_IMPINFO_OFFSET_IS_GUID; 01963 impinfo.oImpFile = impfile_offset; 01964 impinfo.oGuid = ctl2_alloc_guid(typelib, &guidentry); 01965 typelib->typelib_header.dispatchpos = alloc_msft_importinfo(typelib, &impinfo) | 0x01; 01966 } 01967 01968 static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface) 01969 { 01970 int idx = 0; 01971 var_t *func; 01972 var_t *var; 01973 msft_typeinfo_t *msft_typeinfo; 01974 01975 if (-1 < dispinterface->typelib_idx) 01976 return; 01977 01978 dispinterface->typelib_idx = typelib->typelib_header.nrtypeinfos; 01979 msft_typeinfo = create_msft_typeinfo(typelib, TKIND_DISPATCH, dispinterface->name, 01980 dispinterface->attrs); 01981 01982 msft_typeinfo->typeinfo->size = 4; 01983 msft_typeinfo->typeinfo->typekind |= 0x2100; 01984 01985 msft_typeinfo->typeinfo->flags |= 0x1000; /* TYPEFLAG_FDISPATCHABLE */ 01986 add_dispatch(typelib); 01987 msft_typeinfo->typeinfo->cImplTypes = 1; 01988 01989 /* count the no of methods, as the variable indices come after the funcs */ 01990 if (dispinterface->details.iface->disp_methods) 01991 LIST_FOR_EACH_ENTRY( func, dispinterface->details.iface->disp_methods, var_t, entry ) 01992 idx++; 01993 01994 if (type_dispiface_get_props(dispinterface)) 01995 LIST_FOR_EACH_ENTRY( var, type_dispiface_get_props(dispinterface), var_t, entry ) 01996 add_var_desc(msft_typeinfo, idx++, var); 01997 01998 if (type_dispiface_get_methods(dispinterface)) 01999 { 02000 idx = 0; 02001 LIST_FOR_EACH_ENTRY( func, type_dispiface_get_methods(dispinterface), var_t, entry ) 02002 if(add_func_desc(msft_typeinfo, func, idx) == S_OK) 02003 idx++; 02004 } 02005 } 02006 02007 static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface) 02008 { 02009 int idx = 0; 02010 const statement_t *stmt_func; 02011 type_t *ref; 02012 msft_typeinfo_t *msft_typeinfo; 02013 importinfo_t *ref_importinfo = NULL; 02014 int num_parents = 0, num_funcs = 0; 02015 type_t *inherit; 02016 const type_t *derived; 02017 02018 if (-1 < interface->typelib_idx) 02019 return; 02020 02021 if (!interface->details.iface) 02022 { 02023 error( "interface %s is referenced but not defined\n", interface->name ); 02024 return; 02025 } 02026 02027 if (is_attr(interface->attrs, ATTR_DISPINTERFACE)) 02028 return add_dispinterface_typeinfo(typelib, interface); 02029 02030 /* midl adds the parent interface first, unless the parent itself 02031 has no parent (i.e. it stops before IUnknown). */ 02032 02033 inherit = type_iface_get_inherit(interface); 02034 02035 if(inherit) { 02036 ref_importinfo = find_importinfo(typelib, inherit->name); 02037 02038 if(!ref_importinfo && type_iface_get_inherit(inherit) && 02039 inherit->typelib_idx == -1) 02040 add_interface_typeinfo(typelib, inherit); 02041 } 02042 02043 interface->typelib_idx = typelib->typelib_header.nrtypeinfos; 02044 msft_typeinfo = create_msft_typeinfo(typelib, TKIND_INTERFACE, interface->name, interface->attrs); 02045 msft_typeinfo->typeinfo->size = 4; 02046 msft_typeinfo->typeinfo->typekind |= 0x2200; 02047 02048 for (derived = inherit; derived; derived = type_iface_get_inherit(derived)) 02049 if (derived->name && !strcmp(derived->name, "IDispatch")) 02050 msft_typeinfo->typeinfo->flags |= 0x1000; /* TYPEFLAG_FDISPATCHABLE */ 02051 02052 /* can't be dual if it doesn't derive from IDispatch */ 02053 if (!(msft_typeinfo->typeinfo->flags & 0x1000)) /* TYPEFLAG_FDISPATCHABLE */ 02054 msft_typeinfo->typeinfo->flags &= ~0x40; /* TYPEFLAG_FDUAL */ 02055 02056 if(type_iface_get_inherit(interface)) 02057 add_impl_type(msft_typeinfo, type_iface_get_inherit(interface), 02058 ref_importinfo); 02059 02060 /* count the number of inherited interfaces and non-local functions */ 02061 for(ref = inherit; ref; ref = type_iface_get_inherit(ref)) { 02062 num_parents++; 02063 STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(ref) ) { 02064 var_t *func = stmt_func->u.var; 02065 if (!is_local(func->attrs)) num_funcs++; 02066 } 02067 } 02068 msft_typeinfo->typeinfo->datatype2 = num_funcs << 16 | num_parents; 02069 msft_typeinfo->typeinfo->cbSizeVft = num_funcs * pointer_size; 02070 02071 STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(interface) ) { 02072 var_t *func = stmt_func->u.var; 02073 if(add_func_desc(msft_typeinfo, func, idx) == S_OK) 02074 idx++; 02075 } 02076 } 02077 02078 static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure) 02079 { 02080 int idx = 0; 02081 var_t *cur; 02082 msft_typeinfo_t *msft_typeinfo; 02083 02084 if (-1 < structure->typelib_idx) 02085 return; 02086 02087 structure->typelib_idx = typelib->typelib_header.nrtypeinfos; 02088 msft_typeinfo = create_msft_typeinfo(typelib, TKIND_RECORD, structure->name, structure->attrs); 02089 msft_typeinfo->typeinfo->size = 0; 02090 02091 if (type_struct_get_fields(structure)) 02092 LIST_FOR_EACH_ENTRY( cur, type_struct_get_fields(structure), var_t, entry ) 02093 add_var_desc(msft_typeinfo, idx++, cur); 02094 } 02095 02096 static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration) 02097 { 02098 int idx = 0; 02099 var_t *cur; 02100 msft_typeinfo_t *msft_typeinfo; 02101 02102 enumeration->typelib_idx = typelib->typelib_header.nrtypeinfos; 02103 msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ENUM, enumeration->name, enumeration->attrs); 02104 msft_typeinfo->typeinfo->size = 0; 02105 02106 if (type_enum_get_values(enumeration)) 02107 LIST_FOR_EACH_ENTRY( cur, type_enum_get_values(enumeration), var_t, entry ) 02108 add_var_desc(msft_typeinfo, idx++, cur); 02109 } 02110 02111 static void add_typedef_typeinfo(msft_typelib_t *typelib, type_t *tdef) 02112 { 02113 msft_typeinfo_t *msft_typeinfo; 02114 int alignment; 02115 02116 if (-1 < tdef->typelib_idx) 02117 return; 02118 02119 tdef->typelib_idx = typelib->typelib_header.nrtypeinfos; 02120 msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ALIAS, tdef->name, tdef->attrs); 02121 encode_type(typelib, get_type_vt(type_alias_get_aliasee(tdef)), 02122 type_alias_get_aliasee(tdef), 02123 &msft_typeinfo->typeinfo->datatype1, 02124 &msft_typeinfo->typeinfo->size, 02125 &alignment, &msft_typeinfo->typeinfo->datatype2); 02126 msft_typeinfo->typeinfo->typekind |= (alignment << 11 | alignment << 6); 02127 } 02128 02129 static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls) 02130 { 02131 msft_typeinfo_t *msft_typeinfo; 02132 ifref_t *iref; 02133 int num_ifaces = 0, offset, i; 02134 MSFT_RefRecord *ref, *first = NULL, *first_source = NULL; 02135 int have_default = 0, have_default_source = 0; 02136 const attr_t *attr; 02137 ifref_list_t *ifaces; 02138 02139 if (-1 < cls->typelib_idx) 02140 return; 02141 02142 cls->typelib_idx = typelib->typelib_header.nrtypeinfos; 02143 msft_typeinfo = create_msft_typeinfo(typelib, TKIND_COCLASS, cls->name, cls->attrs); 02144 02145 ifaces = type_coclass_get_ifaces(cls); 02146 if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, ifref_t, entry ) num_ifaces++; 02147 02148 offset = msft_typeinfo->typeinfo->datatype1 = ctl2_alloc_segment(typelib, MSFT_SEG_REFERENCES, 02149 num_ifaces * sizeof(*ref), 0); 02150 02151 i = 0; 02152 if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, ifref_t, entry ) { 02153 if(iref->iface->typelib_idx == -1) 02154 add_interface_typeinfo(typelib, iref->iface); 02155 ref = (MSFT_RefRecord*) (typelib->typelib_segment_data[MSFT_SEG_REFERENCES] + offset + i * sizeof(*ref)); 02156 ref->reftype = typelib->typelib_typeinfo_offsets[iref->iface->typelib_idx]; 02157 ref->flags = 0; 02158 ref->oCustData = -1; 02159 ref->onext = -1; 02160 if(i < num_ifaces - 1) 02161 ref->onext = offset + (i + 1) * sizeof(*ref); 02162 02163 if (iref->attrs) LIST_FOR_EACH_ENTRY( attr, iref->attrs, const attr_t, entry ) { 02164 switch(attr->type) { 02165 case ATTR_DEFAULT: 02166 ref->flags |= 0x1; /* IMPLTYPEFLAG_FDEFAULT */ 02167 break; 02168 case ATTR_DEFAULTVTABLE: 02169 ref->flags |= 0x8; /* IMPLTYPEFLAG_FDEFAULTVTABLE */ 02170 break; 02171 case ATTR_RESTRICTED: 02172 ref->flags |= 0x4; /* IMPLTYPEFLAG_FRESTRICTED */ 02173 break; 02174 case ATTR_SOURCE: 02175 ref->flags |= 0x2; /* IMPLTYPEFLAG_FSOURCE */ 02176 break; 02177 default: 02178 warning("add_coclass_typeinfo: unhandled attr %d\n", attr->type); 02179 } 02180 } 02181 if(ref->flags & 0x1) { /* IMPLTYPEFLAG_FDEFAULT */ 02182 if(ref->flags & 0x2) /* IMPLTYPEFLAG_SOURCE */ 02183 have_default_source = 1; 02184 else 02185 have_default = 1; 02186 } 02187 02188 /* If the interface is non-restricted and we haven't already had one then 02189 remember it so that we can use it as a default later */ 02190 if((ref->flags & 0x4) == 0) { /* IMPLTYPEFLAG_FRESTRICTED */ 02191 if(ref->flags & 0x2) { /* IMPLTYPEFLAG_FSOURCE */ 02192 if(!first_source) 02193 first_source = ref; 02194 } 02195 else if(!first) 02196 first = ref; 02197 } 02198 i++; 02199 } 02200 02201 /* If we haven't had a default interface, then set the default flags on the 02202 first ones */ 02203 if(!have_default && first) 02204 first->flags |= 0x1; 02205 if(!have_default_source && first_source) 02206 first_source->flags |= 0x1; 02207 02208 msft_typeinfo->typeinfo->cImplTypes = num_ifaces; 02209 msft_typeinfo->typeinfo->size = 4; 02210 msft_typeinfo->typeinfo->typekind |= 0x2200; 02211 } 02212 02213 static void add_module_typeinfo(msft_typelib_t *typelib, type_t *module) 02214 { 02215 int idx = 0; 02216 const statement_t *stmt; 02217 msft_typeinfo_t *msft_typeinfo; 02218 02219 if (-1 < module->typelib_idx) 02220 return; 02221 02222 module->typelib_idx = typelib->typelib_header.nrtypeinfos; 02223 msft_typeinfo = create_msft_typeinfo(typelib, TKIND_MODULE, module->name, module->attrs); 02224 msft_typeinfo->typeinfo->typekind |= 0x0a00; 02225 02226 STATEMENTS_FOR_EACH_FUNC( stmt, module->details.module->stmts ) { 02227 var_t *func = stmt->u.var; 02228 if(add_func_desc(msft_typeinfo, func, idx) == S_OK) 02229 idx++; 02230 } 02231 02232 msft_typeinfo->typeinfo->size = idx; 02233 } 02234 02235 static void add_type_typeinfo(msft_typelib_t *typelib, type_t *type) 02236 { 02237 switch (type_get_type(type)) { 02238 case TYPE_INTERFACE: 02239 add_interface_typeinfo(typelib, type); 02240 break; 02241 case TYPE_STRUCT: 02242 add_structure_typeinfo(typelib, type); 02243 break; 02244 case TYPE_ENUM: 02245 add_enum_typeinfo(typelib, type); 02246 break; 02247 case TYPE_COCLASS: 02248 add_coclass_typeinfo(typelib, type); 02249 break; 02250 case TYPE_BASIC: 02251 case TYPE_POINTER: 02252 break; 02253 default: 02254 error("add_entry: unhandled type 0x%x for %s\n", 02255 type_get_type(type), type->name); 02256 break; 02257 } 02258 } 02259 02260 static void add_entry(msft_typelib_t *typelib, const statement_t *stmt) 02261 { 02262 switch(stmt->type) { 02263 case STMT_LIBRARY: 02264 case STMT_IMPORT: 02265 case STMT_CPPQUOTE: 02266 case STMT_DECLARATION: 02267 /* not included in typelib */ 02268 break; 02269 case STMT_IMPORTLIB: 02270 /* not processed here */ 02271 break; 02272 case STMT_TYPEDEF: 02273 { 02274 const type_list_t *type_entry = stmt->u.type_list; 02275 for (; type_entry; type_entry = type_entry->next) { 02276 /* if the type is public then add the typedef, otherwise attempt 02277 * to add the aliased type */ 02278 if (is_attr(type_entry->type->attrs, ATTR_PUBLIC)) 02279 add_typedef_typeinfo(typelib, type_entry->type); 02280 else 02281 add_type_typeinfo(typelib, type_alias_get_aliasee(type_entry->type)); 02282 } 02283 break; 02284 } 02285 case STMT_MODULE: 02286 add_module_typeinfo(typelib, stmt->u.type); 02287 break; 02288 case STMT_TYPE: 02289 case STMT_TYPEREF: 02290 { 02291 type_t *type = stmt->u.type; 02292 add_type_typeinfo(typelib, type); 02293 break; 02294 } 02295 } 02296 } 02297 02298 static void set_name(msft_typelib_t *typelib) 02299 { 02300 int offset; 02301 02302 offset = ctl2_alloc_name(typelib, typelib->typelib->name); 02303 if (offset == -1) return; 02304 typelib->typelib_header.NameOffset = offset; 02305 return; 02306 } 02307 02308 static void set_version(msft_typelib_t *typelib) 02309 { 02310 typelib->typelib_header.version = get_attrv( typelib->typelib->attrs, ATTR_VERSION ); 02311 } 02312 02313 static void set_guid(msft_typelib_t *typelib) 02314 { 02315 MSFT_GuidEntry guidentry; 02316 int offset; 02317 void *ptr; 02318 GUID guid = {0,0,0,{0,0,0,0,0,0}}; 02319 02320 guidentry.guid = guid; 02321 guidentry.hreftype = -2; 02322 guidentry.next_hash = -1; 02323 02324 ptr = get_attrp( typelib->typelib->attrs, ATTR_UUID ); 02325 if (ptr) guidentry.guid = *(GUID *)ptr; 02326 02327 offset = ctl2_alloc_guid(typelib, &guidentry); 02328 typelib->typelib_header.posguid = offset; 02329 02330 return; 02331 } 02332 02333 static void set_doc_string(msft_typelib_t *typelib) 02334 { 02335 char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRING ); 02336 02337 if (str) 02338 { 02339 int offset = ctl2_alloc_string(typelib, str); 02340 if (offset != -1) typelib->typelib_header.helpstring = offset; 02341 } 02342 } 02343 02344 static void set_help_file_name(msft_typelib_t *typelib) 02345 { 02346 char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPFILE ); 02347 02348 if (str) 02349 { 02350 int offset = ctl2_alloc_string(typelib, str); 02351 if (offset != -1) 02352 { 02353 typelib->typelib_header.helpfile = offset; 02354 typelib->typelib_header.varflags |= 0x10; 02355 } 02356 } 02357 } 02358 02359 static void set_help_context(msft_typelib_t *typelib) 02360 { 02361 const expr_t *expr = get_attrp( typelib->typelib->attrs, ATTR_HELPCONTEXT ); 02362 if (expr) typelib->typelib_header.helpcontext = expr->cval; 02363 } 02364 02365 static void set_help_string_dll(msft_typelib_t *typelib) 02366 { 02367 char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRINGDLL ); 02368 02369 if (str) 02370 { 02371 int offset = ctl2_alloc_string(typelib, str); 02372 if (offset != -1) 02373 { 02374 typelib->help_string_dll_offset = offset; 02375 typelib->typelib_header.varflags |= 0x100; 02376 } 02377 } 02378 } 02379 02380 static void set_help_string_context(msft_typelib_t *typelib) 02381 { 02382 const expr_t *expr = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRINGCONTEXT ); 02383 if (expr) typelib->typelib_header.helpstringcontext = expr->cval; 02384 } 02385 02386 static void set_lcid(msft_typelib_t *typelib) 02387 { 02388 const expr_t *lcid_expr = get_attrp( typelib->typelib->attrs, ATTR_LIBLCID ); 02389 if(lcid_expr) 02390 { 02391 typelib->typelib_header.lcid = lcid_expr->cval; 02392 typelib->typelib_header.lcid2 = lcid_expr->cval; 02393 } 02394 } 02395 02396 static void set_lib_flags(msft_typelib_t *typelib) 02397 { 02398 const attr_t *attr; 02399 02400 typelib->typelib_header.flags = 0; 02401 if (!typelib->typelib->attrs) return; 02402 LIST_FOR_EACH_ENTRY( attr, typelib->typelib->attrs, const attr_t, entry ) 02403 { 02404 switch(attr->type) { 02405 case ATTR_CONTROL: 02406 typelib->typelib_header.flags |= 0x02; /* LIBFLAG_FCONTROL */ 02407 break; 02408 case ATTR_HIDDEN: 02409 typelib->typelib_header.flags |= 0x04; /* LIBFLAG_FHIDDEN */ 02410 break; 02411 case ATTR_RESTRICTED: 02412 typelib->typelib_header.flags |= 0x01; /* LIBFLAG_FRESTRICTED */ 02413 break; 02414 default: 02415 break; 02416 } 02417 } 02418 return; 02419 } 02420 02421 static void ctl2_write_segment(msft_typelib_t *typelib, int segment) 02422 { 02423 put_data(typelib->typelib_segment_data[segment], typelib->typelib_segdir[segment].length); 02424 } 02425 02426 static void ctl2_finalize_typeinfos(msft_typelib_t *typelib, int filesize) 02427 { 02428 msft_typeinfo_t *typeinfo; 02429 02430 for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) { 02431 typeinfo->typeinfo->memoffset = filesize; 02432 if (typeinfo->func_data) 02433 filesize += typeinfo->func_data[0] + ((typeinfo->typeinfo->cElement & 0xffff) * 12); 02434 if (typeinfo->var_data) 02435 filesize += typeinfo->var_data[0] + (((typeinfo->typeinfo->cElement >> 16) & 0xffff) * 12); 02436 if (typeinfo->func_data || typeinfo->var_data) 02437 filesize += 4; 02438 } 02439 } 02440 02441 static int ctl2_finalize_segment(msft_typelib_t *typelib, int filepos, int segment) 02442 { 02443 if (typelib->typelib_segdir[segment].length) { 02444 typelib->typelib_segdir[segment].offset = filepos; 02445 } else { 02446 typelib->typelib_segdir[segment].offset = -1; 02447 } 02448 02449 return typelib->typelib_segdir[segment].length; 02450 } 02451 02452 02453 static void ctl2_write_typeinfos(msft_typelib_t *typelib) 02454 { 02455 msft_typeinfo_t *typeinfo; 02456 int typedata_size; 02457 02458 for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) { 02459 if (!typeinfo->func_data && !typeinfo->var_data) continue; 02460 typedata_size = 0; 02461 if (typeinfo->func_data) 02462 typedata_size = typeinfo->func_data[0]; 02463 if (typeinfo->var_data) 02464 typedata_size += typeinfo->var_data[0]; 02465 put_data(&typedata_size, sizeof(int)); 02466 if (typeinfo->func_data) 02467 put_data(typeinfo->func_data + 1, typeinfo->func_data[0]); 02468 if (typeinfo->var_data) 02469 put_data(typeinfo->var_data + 1, typeinfo->var_data[0]); 02470 if (typeinfo->func_indices) 02471 put_data(typeinfo->func_indices, (typeinfo->typeinfo->cElement & 0xffff) * 4); 02472 if (typeinfo->var_indices) 02473 put_data(typeinfo->var_indices, (typeinfo->typeinfo->cElement >> 16) * 4); 02474 if (typeinfo->func_names) 02475 put_data(typeinfo->func_names, (typeinfo->typeinfo->cElement & 0xffff) * 4); 02476 if (typeinfo->var_names) 02477 put_data(typeinfo->var_names, (typeinfo->typeinfo->cElement >> 16) * 4); 02478 if (typeinfo->func_offsets) 02479 put_data(typeinfo->func_offsets, (typeinfo->typeinfo->cElement & 0xffff) * 4); 02480 if (typeinfo->var_offsets) { 02481 int add = 0, i, offset; 02482 if(typeinfo->func_data) 02483 add = typeinfo->func_data[0]; 02484 for(i = 0; i < (typeinfo->typeinfo->cElement >> 16); i++) { 02485 offset = typeinfo->var_offsets[i]; 02486 offset += add; 02487 put_data(&offset, 4); 02488 } 02489 } 02490 } 02491 } 02492 02493 static void save_all_changes(msft_typelib_t *typelib) 02494 { 02495 int filepos; 02496 02497 chat("save_all_changes(%p)\n", typelib); 02498 02499 filepos = sizeof(MSFT_Header) + sizeof(MSFT_SegDir); 02500 if(typelib->typelib_header.varflags & 0x100) filepos += 4; /* helpstringdll */ 02501 filepos += typelib->typelib_header.nrtypeinfos * 4; 02502 02503 filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_TYPEINFO); 02504 filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_GUIDHASH); 02505 filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_GUID); 02506 filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_REFERENCES); 02507 filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_IMPORTINFO); 02508 filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_IMPORTFILES); 02509 filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_NAMEHASH); 02510 filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_NAME); 02511 filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_STRING); 02512 filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_TYPEDESC); 02513 filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_ARRAYDESC); 02514 filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_CUSTDATA); 02515 filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_CUSTDATAGUID); 02516 02517 ctl2_finalize_typeinfos(typelib, filepos); 02518 02519 byte_swapped = 0; 02520 init_output_buffer(); 02521 02522 put_data(&typelib->typelib_header, sizeof(typelib->typelib_header)); 02523 if(typelib->typelib_header.varflags & 0x100) 02524 put_data(&typelib->help_string_dll_offset, sizeof(typelib->help_string_dll_offset)); 02525 02526 put_data(typelib->typelib_typeinfo_offsets, typelib->typelib_header.nrtypeinfos * 4); 02527 put_data(&typelib->typelib_segdir, sizeof(typelib->typelib_segdir)); 02528 ctl2_write_segment( typelib, MSFT_SEG_TYPEINFO ); 02529 ctl2_write_segment( typelib, MSFT_SEG_GUIDHASH ); 02530 ctl2_write_segment( typelib, MSFT_SEG_GUID ); 02531 ctl2_write_segment( typelib, MSFT_SEG_REFERENCES ); 02532 ctl2_write_segment( typelib, MSFT_SEG_IMPORTINFO ); 02533 ctl2_write_segment( typelib, MSFT_SEG_IMPORTFILES ); 02534 ctl2_write_segment( typelib, MSFT_SEG_NAMEHASH ); 02535 ctl2_write_segment( typelib, MSFT_SEG_NAME ); 02536 ctl2_write_segment( typelib, MSFT_SEG_STRING ); 02537 ctl2_write_segment( typelib, MSFT_SEG_TYPEDESC ); 02538 ctl2_write_segment( typelib, MSFT_SEG_ARRAYDESC ); 02539 ctl2_write_segment( typelib, MSFT_SEG_CUSTDATA ); 02540 ctl2_write_segment( typelib, MSFT_SEG_CUSTDATAGUID ); 02541 02542 ctl2_write_typeinfos(typelib); 02543 02544 if (strendswith( typelib_name, ".res" )) /* create a binary resource file */ 02545 { 02546 add_output_to_resources( "TYPELIB", "#1" ); 02547 output_typelib_regscript( typelib->typelib ); 02548 flush_output_resources( typelib_name ); 02549 } 02550 else flush_output_buffer( typelib_name ); 02551 } 02552 02553 int create_msft_typelib(typelib_t *typelib) 02554 { 02555 msft_typelib_t *msft; 02556 int failed = 0; 02557 const statement_t *stmt; 02558 time_t cur_time; 02559 char *time_override; 02560 unsigned int version = 5 << 24 | 1 << 16 | 164; /* 5.01.0164 */ 02561 GUID midl_time_guid = {0xde77ba63,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; 02562 GUID midl_version_guid = {0xde77ba64,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; 02563 02564 pointer_size = (typelib_kind == SYS_WIN64) ? 8 : 4; 02565 02566 msft = xmalloc(sizeof(*msft)); 02567 memset(msft, 0, sizeof(*msft)); 02568 msft->typelib = typelib; 02569 02570 ctl2_init_header(msft); 02571 ctl2_init_segdir(msft); 02572 02573 msft->typelib_header.varflags |= typelib_kind; 02574 02575 /* 02576 * The following two calls return an offset or -1 if out of memory. We 02577 * specifically need an offset of 0, however, so... 02578 */ 02579 if (ctl2_alloc_segment(msft, MSFT_SEG_GUIDHASH, 0x80, 0x80)) { failed = 1; } 02580 if (ctl2_alloc_segment(msft, MSFT_SEG_NAMEHASH, 0x200, 0x200)) { failed = 1; } 02581 02582 if(failed) 02583 { 02584 free(msft); 02585 return 0; 02586 } 02587 02588 msft->typelib_guidhash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_GUIDHASH]; 02589 msft->typelib_namehash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_NAMEHASH]; 02590 02591 memset(msft->typelib_guidhash_segment, 0xff, 0x80); 02592 memset(msft->typelib_namehash_segment, 0xff, 0x200); 02593 02594 set_lib_flags(msft); 02595 set_lcid(msft); 02596 set_help_file_name(msft); 02597 set_doc_string(msft); 02598 set_guid(msft); 02599 set_version(msft); 02600 set_name(msft); 02601 set_help_context(msft); 02602 set_help_string_dll(msft); 02603 set_help_string_context(msft); 02604 02605 /* midl adds two sets of custom data to the library: the current unix time 02606 and midl's version number */ 02607 time_override = getenv( "WIDL_TIME_OVERRIDE"); 02608 cur_time = time_override ? atol( time_override) : time(NULL); 02609 set_custdata(msft, &midl_time_guid, VT_UI4, cur_time, &msft->typelib_header.CustomDataOffset); 02610 set_custdata(msft, &midl_version_guid, VT_UI4, version, &msft->typelib_header.CustomDataOffset); 02611 02612 if (typelib->stmts) 02613 LIST_FOR_EACH_ENTRY( stmt, typelib->stmts, const statement_t, entry ) 02614 add_entry(msft, stmt); 02615 02616 save_all_changes(msft); 02617 free(msft); 02618 return 1; 02619 } Generated on Sat May 26 2012 04:36:55 for ReactOS by
1.7.6.1
|