1 /* 2 * IDL Compiler 3 * 4 * Copyright 2004 Ove Kaaven 5 * Copyright 2006 Jacek Caban for CodeWeavers 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include "config.h" 23 #include "wine/port.h" 24 #include "wine/wpp.h" 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <stdarg.h> 29 #ifdef HAVE_UNISTD_H 30 # include <unistd.h> 31 #endif 32 #include <string.h> 33 #include <ctype.h> 34 35 #include <typedefs.h> 36 #include "widl.h" 37 #include "utils.h" 38 #include "parser.h" 39 #include "header.h" 40 #include "typelib.h" 41 #include "widltypes.h" 42 #include "typelib_struct.h" 43 #include "typetree.h" 44 45 static typelib_t *typelib; 46 47 /* List of oleauto types that should be recognized by name. 48 * (most of) these seem to be intrinsic types in mktyplib. 49 * This table MUST be alphabetically sorted on the kw field. 50 */ 51 static const struct oatype { 52 const char *kw; 53 unsigned short vt; 54 } oatypes[] = { 55 {"BSTR", VT_BSTR}, 56 {"CURRENCY", VT_CY}, 57 {"DATE", VT_DATE}, 58 {"DECIMAL", VT_DECIMAL}, 59 {"HRESULT", VT_HRESULT}, 60 {"LPSTR", VT_LPSTR}, 61 {"LPWSTR", VT_LPWSTR}, 62 {"SCODE", VT_ERROR}, 63 {"VARIANT", VT_VARIANT}, 64 {"VARIANT_BOOL", VT_BOOL} 65 }; 66 #define NTYPES (sizeof(oatypes)/sizeof(oatypes[0])) 67 #define KWP(p) ((const struct oatype *)(p)) 68 69 static int kw_cmp_func(const void *s1, const void *s2) 70 { 71 return strcmp(KWP(s1)->kw, KWP(s2)->kw); 72 } 73 74 static unsigned short builtin_vt(const type_t *t) 75 { 76 const char *kw = t->name; 77 struct oatype key; 78 const struct oatype *kwp; 79 key.kw = kw; 80 #ifdef KW_BSEARCH 81 kwp = bsearch(&key, oatypes, NTYPES, sizeof(oatypes[0]), kw_cmp_func); 82 #else 83 { 84 unsigned int i; 85 for (kwp=NULL, i=0; i < NTYPES; i++) 86 if (!kw_cmp_func(&key, &oatypes[i])) { 87 kwp = &oatypes[i]; 88 break; 89 } 90 } 91 #endif 92 if (kwp) { 93 return kwp->vt; 94 } 95 if (is_string_type (t->attrs, t)) 96 { 97 const type_t *elem_type; 98 if (is_array(t)) 99 elem_type = type_array_get_element(t); 100 else 101 elem_type = type_pointer_get_ref(t); 102 if (type_get_type(elem_type) == TYPE_BASIC) 103 { 104 switch (type_basic_get_type(elem_type)) 105 { 106 case TYPE_BASIC_CHAR: return VT_LPSTR; 107 case TYPE_BASIC_WCHAR: return VT_LPWSTR; 108 default: break; 109 } 110 } 111 } 112 return 0; 113 } 114 115 static int match(const char*n, const char*m) 116 { 117 if (!n) return 0; 118 return !strcmp(n, m); 119 } 120 121 unsigned short get_type_vt(type_t *t) 122 { 123 unsigned short vt; 124 125 chat("get_type_vt: %p type->name %s\n", t, t->name); 126 if (t->name) { 127 vt = builtin_vt(t); 128 if (vt) return vt; 129 } 130 131 if (type_is_alias(t) && is_attr(t->attrs, ATTR_PUBLIC)) 132 return VT_USERDEFINED; 133 134 switch (type_get_type(t)) { 135 case TYPE_BASIC: 136 switch (type_basic_get_type(t)) { 137 case TYPE_BASIC_BYTE: 138 return VT_UI1; 139 case TYPE_BASIC_CHAR: 140 case TYPE_BASIC_INT8: 141 if (type_basic_get_sign(t) > 0) 142 return VT_UI1; 143 else 144 return VT_I1; 145 case TYPE_BASIC_WCHAR: 146 return VT_I2; /* mktyplib seems to parse wchar_t as short */ 147 case TYPE_BASIC_INT16: 148 if (type_basic_get_sign(t) > 0) 149 return VT_UI2; 150 else 151 return VT_I2; 152 case TYPE_BASIC_INT: 153 if (type_basic_get_sign(t) > 0) 154 return VT_UINT; 155 else 156 return VT_INT; 157 case TYPE_BASIC_INT32: 158 case TYPE_BASIC_ERROR_STATUS_T: 159 if (type_basic_get_sign(t) > 0) 160 return VT_UI4; 161 else 162 return VT_I4; 163 case TYPE_BASIC_INT64: 164 case TYPE_BASIC_HYPER: 165 if (type_basic_get_sign(t) > 0) 166 return VT_UI8; 167 else 168 return VT_I8; 169 case TYPE_BASIC_INT3264: 170 if (typelib_kind == SYS_WIN64) 171 { 172 if (type_basic_get_sign(t) > 0) 173 return VT_UI8; 174 else 175 return VT_I8; 176 } 177 else 178 { 179 if (type_basic_get_sign(t) > 0) 180 return VT_UI4; 181 else 182 return VT_I4; 183 } 184 case TYPE_BASIC_FLOAT: 185 return VT_R4; 186 case TYPE_BASIC_DOUBLE: 187 return VT_R8; 188 case TYPE_BASIC_HANDLE: 189 error("handles can't be used in typelibs\n"); 190 } 191 break; 192 193 case TYPE_POINTER: 194 return VT_PTR; 195 196 case TYPE_ARRAY: 197 if (type_array_is_decl_as_ptr(t)) 198 { 199 if (match(type_array_get_element(t)->name, "SAFEARRAY")) 200 return VT_SAFEARRAY; 201 } 202 else 203 error("get_type_vt: array types not supported\n"); 204 return VT_PTR; 205 206 case TYPE_INTERFACE: 207 if(match(t->name, "IUnknown")) 208 return VT_UNKNOWN; 209 if(match(t->name, "IDispatch")) 210 return VT_DISPATCH; 211 return VT_USERDEFINED; 212 213 case TYPE_ENUM: 214 case TYPE_STRUCT: 215 case TYPE_COCLASS: 216 case TYPE_MODULE: 217 case TYPE_UNION: 218 case TYPE_ENCAPSULATED_UNION: 219 return VT_USERDEFINED; 220 221 case TYPE_VOID: 222 return VT_VOID; 223 224 case TYPE_ALIAS: 225 /* aliases should be filtered out by the type_get_type call above */ 226 assert(0); 227 break; 228 229 case TYPE_FUNCTION: 230 error("get_type_vt: functions not supported\n"); 231 break; 232 233 case TYPE_BITFIELD: 234 error("get_type_vt: bitfields not supported\n"); 235 break; 236 } 237 return 0; 238 } 239 240 void start_typelib(typelib_t *typelib_type) 241 { 242 if (!do_typelib) return; 243 typelib = typelib_type; 244 } 245 246 void end_typelib(void) 247 { 248 if (!typelib) return; 249 250 if (do_old_typelib) 251 create_sltg_typelib(typelib); 252 else 253 create_msft_typelib(typelib); 254 } 255 256 static void tlb_read(int fd, void *buf, int count) 257 { 258 if(read(fd, buf, count) < count) 259 error("error while reading importlib.\n"); 260 } 261 262 static void tlb_lseek(int fd, off_t offset) 263 { 264 if(lseek(fd, offset, SEEK_SET) == -1) 265 error("lseek failed\n"); 266 } 267 268 static void msft_read_guid(int fd, MSFT_SegDir *segdir, int offset, GUID *guid) 269 { 270 tlb_lseek(fd, segdir->pGuidTab.offset+offset); 271 tlb_read(fd, guid, sizeof(GUID)); 272 } 273 274 static void read_msft_importlib(importlib_t *importlib, int fd) 275 { 276 MSFT_Header header; 277 MSFT_SegDir segdir; 278 int *typeinfo_offs; 279 int i; 280 281 importlib->allocated = 0; 282 283 tlb_lseek(fd, 0); 284 tlb_read(fd, &header, sizeof(header)); 285 286 importlib->version = header.version; 287 288 typeinfo_offs = xmalloc(header.nrtypeinfos*sizeof(INT)); 289 tlb_read(fd, typeinfo_offs, header.nrtypeinfos*sizeof(INT)); 290 tlb_read(fd, &segdir, sizeof(segdir)); 291 292 msft_read_guid(fd, &segdir, header.posguid, &importlib->guid); 293 294 importlib->ntypeinfos = header.nrtypeinfos; 295 importlib->importinfos = xmalloc(importlib->ntypeinfos*sizeof(importinfo_t)); 296 297 for(i=0; i < importlib->ntypeinfos; i++) { 298 MSFT_TypeInfoBase base; 299 MSFT_NameIntro nameintro; 300 int len; 301 302 tlb_lseek(fd, sizeof(MSFT_Header) + header.nrtypeinfos*sizeof(INT) + sizeof(MSFT_SegDir) 303 + typeinfo_offs[i]); 304 tlb_read(fd, &base, sizeof(base)); 305 306 importlib->importinfos[i].importlib = importlib; 307 importlib->importinfos[i].flags = (base.typekind&0xf)<<24; 308 importlib->importinfos[i].offset = -1; 309 importlib->importinfos[i].id = i; 310 311 if(base.posguid != -1) { 312 importlib->importinfos[i].flags |= MSFT_IMPINFO_OFFSET_IS_GUID; 313 msft_read_guid(fd, &segdir, base.posguid, &importlib->importinfos[i].guid); 314 } 315 else memset( &importlib->importinfos[i].guid, 0, sizeof(importlib->importinfos[i].guid)); 316 317 tlb_lseek(fd, segdir.pNametab.offset + base.NameOffset); 318 tlb_read(fd, &nameintro, sizeof(nameintro)); 319 320 len = nameintro.namelen & 0xff; 321 322 importlib->importinfos[i].name = xmalloc(len+1); 323 tlb_read(fd, importlib->importinfos[i].name, len); 324 importlib->importinfos[i].name[len] = 0; 325 } 326 327 free(typeinfo_offs); 328 } 329 330 static void read_importlib(importlib_t *importlib) 331 { 332 int fd; 333 INT magic; 334 char *file_name; 335 336 file_name = wpp_find_include(importlib->name, NULL); 337 if(file_name) { 338 fd = open(file_name, O_RDONLY | O_BINARY ); 339 free(file_name); 340 }else { 341 fd = open(importlib->name, O_RDONLY | O_BINARY ); 342 } 343 344 if(fd < 0) 345 error("Could not open importlib %s.\n", importlib->name); 346 347 tlb_read(fd, &magic, sizeof(magic)); 348 349 switch(magic) { 350 case MSFT_MAGIC: 351 read_msft_importlib(importlib, fd); 352 break; 353 default: 354 error("Wrong or unsupported typelib magic %x\n", magic); 355 }; 356 357 close(fd); 358 } 359 360 void add_importlib(const char *name) 361 { 362 importlib_t *importlib; 363 364 if(!typelib) return; 365 366 LIST_FOR_EACH_ENTRY( importlib, &typelib->importlibs, importlib_t, entry ) 367 if(!strcmp(name, importlib->name)) 368 return; 369 370 chat("add_importlib: %s\n", name); 371 372 importlib = xmalloc(sizeof(*importlib)); 373 memset( importlib, 0, sizeof(*importlib) ); 374 importlib->name = xstrdup(name); 375 376 read_importlib(importlib); 377 list_add_head( &typelib->importlibs, &importlib->entry ); 378 } 379