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 #ifdef __REACTOS__ 36 #include <typedefs.h> 37 #else 38 #include "windef.h" 39 #include "winbase.h" 40 #endif 41 42 #include "widl.h" 43 #include "utils.h" 44 #include "parser.h" 45 #include "header.h" 46 #include "typelib.h" 47 #include "widltypes.h" 48 #include "typelib_struct.h" 49 #include "typetree.h" 50 51 #ifdef __REACTOS__ 52 static typelib_t *typelib; 53 #endif 54 55 /* List of oleauto types that should be recognized by name. 56 * (most of) these seem to be intrinsic types in mktyplib. 57 * This table MUST be alphabetically sorted on the kw field. 58 */ 59 static const struct oatype { 60 const char *kw; 61 unsigned short vt; 62 } oatypes[] = { 63 {"BSTR", VT_BSTR}, 64 {"CURRENCY", VT_CY}, 65 {"DATE", VT_DATE}, 66 {"DECIMAL", VT_DECIMAL}, 67 {"HRESULT", VT_HRESULT}, 68 {"LPSTR", VT_LPSTR}, 69 {"LPWSTR", VT_LPWSTR}, 70 {"SCODE", VT_ERROR}, 71 {"VARIANT", VT_VARIANT}, 72 {"VARIANT_BOOL", VT_BOOL} 73 }; 74 #define NTYPES (sizeof(oatypes)/sizeof(oatypes[0])) 75 #define KWP(p) ((const struct oatype *)(p)) 76 77 static int kw_cmp_func(const void *s1, const void *s2) 78 { 79 return strcmp(KWP(s1)->kw, KWP(s2)->kw); 80 } 81 82 static unsigned short builtin_vt(const type_t *t) 83 { 84 const char *kw = t->name; 85 struct oatype key; 86 const struct oatype *kwp; 87 key.kw = kw; 88 #ifdef KW_BSEARCH 89 kwp = bsearch(&key, oatypes, NTYPES, sizeof(oatypes[0]), kw_cmp_func); 90 #else 91 { 92 unsigned int i; 93 for (kwp=NULL, i=0; i < NTYPES; i++) 94 if (!kw_cmp_func(&key, &oatypes[i])) { 95 kwp = &oatypes[i]; 96 break; 97 } 98 } 99 #endif 100 if (kwp) { 101 return kwp->vt; 102 } 103 if (is_string_type (t->attrs, t)) 104 { 105 const type_t *elem_type; 106 if (is_array(t)) 107 elem_type = type_array_get_element(t); 108 else 109 elem_type = type_pointer_get_ref(t); 110 if (type_get_type(elem_type) == TYPE_BASIC) 111 { 112 switch (type_basic_get_type(elem_type)) 113 { 114 case TYPE_BASIC_CHAR: return VT_LPSTR; 115 case TYPE_BASIC_WCHAR: return VT_LPWSTR; 116 default: break; 117 } 118 } 119 } 120 return 0; 121 } 122 123 static int match(const char*n, const char*m) 124 { 125 if (!n) return 0; 126 return !strcmp(n, m); 127 } 128 129 unsigned short get_type_vt(type_t *t) 130 { 131 unsigned short vt; 132 133 chat("get_type_vt: %p type->name %s\n", t, t->name); 134 if (t->name) { 135 vt = builtin_vt(t); 136 if (vt) return vt; 137 } 138 139 if (type_is_alias(t) && is_attr(t->attrs, ATTR_PUBLIC)) 140 return VT_USERDEFINED; 141 142 switch (type_get_type(t)) { 143 case TYPE_BASIC: 144 switch (type_basic_get_type(t)) { 145 case TYPE_BASIC_BYTE: 146 return VT_UI1; 147 case TYPE_BASIC_CHAR: 148 case TYPE_BASIC_INT8: 149 if (type_basic_get_sign(t) > 0) 150 return VT_UI1; 151 else 152 return VT_I1; 153 case TYPE_BASIC_WCHAR: 154 return VT_I2; /* mktyplib seems to parse wchar_t as short */ 155 case TYPE_BASIC_INT16: 156 if (type_basic_get_sign(t) > 0) 157 return VT_UI2; 158 else 159 return VT_I2; 160 case TYPE_BASIC_INT: 161 if (type_basic_get_sign(t) > 0) 162 return VT_UINT; 163 else 164 return VT_INT; 165 case TYPE_BASIC_INT32: 166 case TYPE_BASIC_LONG: 167 case TYPE_BASIC_ERROR_STATUS_T: 168 if (type_basic_get_sign(t) > 0) 169 return VT_UI4; 170 else 171 return VT_I4; 172 case TYPE_BASIC_INT64: 173 case TYPE_BASIC_HYPER: 174 if (type_basic_get_sign(t) > 0) 175 return VT_UI8; 176 else 177 return VT_I8; 178 case TYPE_BASIC_INT3264: 179 if (pointer_size == 8) 180 { 181 if (type_basic_get_sign(t) > 0) 182 return VT_UI8; 183 else 184 return VT_I8; 185 } 186 else 187 { 188 if (type_basic_get_sign(t) > 0) 189 return VT_UI4; 190 else 191 return VT_I4; 192 } 193 case TYPE_BASIC_FLOAT: 194 return VT_R4; 195 case TYPE_BASIC_DOUBLE: 196 return VT_R8; 197 case TYPE_BASIC_HANDLE: 198 error("handles can't be used in typelibs\n"); 199 } 200 break; 201 202 case TYPE_POINTER: 203 return VT_PTR; 204 205 case TYPE_ARRAY: 206 if (type_array_is_decl_as_ptr(t)) 207 { 208 if (match(type_array_get_element(t)->name, "SAFEARRAY")) 209 return VT_SAFEARRAY; 210 return VT_PTR; 211 } 212 else 213 return VT_CARRAY; 214 215 case TYPE_INTERFACE: 216 if(match(t->name, "IUnknown")) 217 return VT_UNKNOWN; 218 if(match(t->name, "IDispatch")) 219 return VT_DISPATCH; 220 return VT_USERDEFINED; 221 222 case TYPE_ENUM: 223 case TYPE_STRUCT: 224 case TYPE_COCLASS: 225 case TYPE_MODULE: 226 case TYPE_UNION: 227 case TYPE_ENCAPSULATED_UNION: 228 return VT_USERDEFINED; 229 230 case TYPE_VOID: 231 return VT_VOID; 232 233 case TYPE_ALIAS: 234 /* aliases should be filtered out by the type_get_type call above */ 235 assert(0); 236 break; 237 238 case TYPE_FUNCTION: 239 error("get_type_vt: functions not supported\n"); 240 break; 241 242 case TYPE_BITFIELD: 243 error("get_type_vt: bitfields not supported\n"); 244 break; 245 } 246 return 0; 247 } 248 249 #ifdef __REACTOS__ 250 void start_typelib(typelib_t *typelib_type) 251 { 252 if (!do_typelib) return; 253 typelib = typelib_type; 254 } 255 256 void end_typelib(void) 257 { 258 if (!typelib) return; 259 260 create_msft_typelib(typelib); 261 } 262 #endif 263 264 static void tlb_read(int fd, void *buf, int count) 265 { 266 if(read(fd, buf, count) < count) 267 error("error while reading importlib.\n"); 268 } 269 270 static void tlb_lseek(int fd, off_t offset) 271 { 272 if(lseek(fd, offset, SEEK_SET) == -1) 273 error("lseek failed\n"); 274 } 275 276 static void msft_read_guid(int fd, MSFT_SegDir *segdir, int offset, GUID *guid) 277 { 278 tlb_lseek(fd, segdir->pGuidTab.offset+offset); 279 tlb_read(fd, guid, sizeof(GUID)); 280 } 281 282 static void read_msft_importlib(importlib_t *importlib, int fd) 283 { 284 MSFT_Header header; 285 MSFT_SegDir segdir; 286 int *typeinfo_offs; 287 int i; 288 289 importlib->allocated = 0; 290 291 tlb_lseek(fd, 0); 292 tlb_read(fd, &header, sizeof(header)); 293 294 importlib->version = header.version; 295 296 typeinfo_offs = xmalloc(header.nrtypeinfos*sizeof(INT)); 297 tlb_read(fd, typeinfo_offs, header.nrtypeinfos*sizeof(INT)); 298 tlb_read(fd, &segdir, sizeof(segdir)); 299 300 msft_read_guid(fd, &segdir, header.posguid, &importlib->guid); 301 302 importlib->ntypeinfos = header.nrtypeinfos; 303 importlib->importinfos = xmalloc(importlib->ntypeinfos*sizeof(importinfo_t)); 304 305 for(i=0; i < importlib->ntypeinfos; i++) { 306 MSFT_TypeInfoBase base; 307 MSFT_NameIntro nameintro; 308 int len; 309 310 tlb_lseek(fd, sizeof(MSFT_Header) + header.nrtypeinfos*sizeof(INT) + sizeof(MSFT_SegDir) 311 + typeinfo_offs[i]); 312 tlb_read(fd, &base, sizeof(base)); 313 314 importlib->importinfos[i].importlib = importlib; 315 importlib->importinfos[i].flags = (base.typekind&0xf)<<24; 316 importlib->importinfos[i].offset = -1; 317 importlib->importinfos[i].id = i; 318 319 if(base.posguid != -1) { 320 importlib->importinfos[i].flags |= MSFT_IMPINFO_OFFSET_IS_GUID; 321 msft_read_guid(fd, &segdir, base.posguid, &importlib->importinfos[i].guid); 322 } 323 else memset( &importlib->importinfos[i].guid, 0, sizeof(importlib->importinfos[i].guid)); 324 325 tlb_lseek(fd, segdir.pNametab.offset + base.NameOffset); 326 tlb_read(fd, &nameintro, sizeof(nameintro)); 327 328 len = nameintro.namelen & 0xff; 329 330 importlib->importinfos[i].name = xmalloc(len+1); 331 tlb_read(fd, importlib->importinfos[i].name, len); 332 importlib->importinfos[i].name[len] = 0; 333 } 334 335 free(typeinfo_offs); 336 } 337 338 static int open_typelib(const char *name) 339 { 340 char *file_name; 341 int fd; 342 343 file_name = wpp_find_include(name, NULL); 344 if(!file_name) 345 return open(name, O_RDONLY | O_BINARY ); 346 347 fd = open(file_name, O_RDONLY | O_BINARY ); 348 free(file_name); 349 return fd; 350 } 351 352 static void read_importlib(importlib_t *importlib) 353 { 354 int fd; 355 INT magic; 356 357 fd = open_typelib(importlib->name); 358 359 /* widl extension: if importlib name has no .tlb extension, try using .tlb */ 360 if(fd < 0) { 361 const char *p = strrchr(importlib->name, '.'); 362 size_t len = p ? p - importlib->name : strlen(importlib->name); 363 if(strcmp(importlib->name + len, ".tlb")) { 364 char *tlb_name = xmalloc(len + 5); 365 memcpy(tlb_name, importlib->name, len); 366 strcpy(tlb_name + len, ".tlb"); 367 fd = open_typelib(tlb_name); 368 free(tlb_name); 369 } 370 } 371 372 if(fd < 0) 373 error("Could not find importlib %s.\n", importlib->name); 374 375 tlb_read(fd, &magic, sizeof(magic)); 376 377 switch(magic) { 378 case MSFT_MAGIC: 379 read_msft_importlib(importlib, fd); 380 break; 381 default: 382 error("Wrong or unsupported typelib magic %x\n", magic); 383 }; 384 385 close(fd); 386 } 387 388 #ifdef __REACTOS__ 389 void add_importlib(const char *name) 390 #else 391 void add_importlib(const char *name, typelib_t *typelib) 392 #endif 393 { 394 importlib_t *importlib; 395 396 if(!typelib) return; 397 398 LIST_FOR_EACH_ENTRY( importlib, &typelib->importlibs, importlib_t, entry ) 399 if(!strcmp(name, importlib->name)) 400 return; 401 402 chat("add_importlib: %s\n", name); 403 404 importlib = xmalloc(sizeof(*importlib)); 405 memset( importlib, 0, sizeof(*importlib) ); 406 importlib->name = xstrdup(name); 407 408 read_importlib(importlib); 409 list_add_head( &typelib->importlibs, &importlib->entry ); 410 } 411