diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c index fb8fd665f90..77d5155487b 100644 --- a/tools/widl/typelib.c +++ b/tools/widl/typelib.c @@ -2,6 +2,7 @@ * IDL Compiler * * Copyright 2004 Ove Kaaven + * Copyright 2006 Jacek Caban for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,20 +20,33 @@ */ #include "config.h" +#include "wine/port.h" +#include "wine/wpp.h" #include #include +#include #include #include #include #include #include +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "windef.h" +#include "winbase.h" + +#include "wine/unicode.h" + #include "widl.h" #include "utils.h" #include "parser.h" #include "header.h" #include "typelib.h" +#include "widltypes.h" +#include "typelib_struct.h" int in_typelib = 0; @@ -279,9 +293,122 @@ void add_typedef(type_t *tdef, var_t *name) typelib->entry = entry; } +static void tlb_read(int fd, void *buf, size_t count) +{ + if(read(fd, buf, count) < count) + error("error while reading importlib.\n"); +} + +static void tlb_lseek(int fd, off_t offset) +{ + if(lseek(fd, offset, SEEK_SET) == -1) + error("lseek failed\n"); +} + +static void msft_read_guid(int fd, MSFT_SegDir *segdir, int offset, GUID *guid) +{ + tlb_lseek(fd, segdir->pGuidTab.offset+offset); + tlb_read(fd, guid, sizeof(GUID)); +} + +static void read_msft_importlib(importlib_t *importlib, int fd) +{ + MSFT_Header header; + MSFT_SegDir segdir; + int *typeinfo_offs; + int i; + + importlib->allocated = 0; + + tlb_lseek(fd, 0); + tlb_read(fd, &header, sizeof(header)); + + importlib->version = header.version; + + typeinfo_offs = xmalloc(header.nrtypeinfos*sizeof(INT)); + tlb_read(fd, typeinfo_offs, header.nrtypeinfos*sizeof(INT)); + tlb_read(fd, &segdir, sizeof(segdir)); + + msft_read_guid(fd, &segdir, header.posguid, &importlib->guid); + + importlib->ntypeinfos = header.nrtypeinfos; + importlib->importinfos = xmalloc(importlib->ntypeinfos*sizeof(importinfo_t)); + + for(i=0; i < importlib->ntypeinfos; i++) { + MSFT_TypeInfoBase base; + MSFT_NameIntro nameintro; + int len; + + tlb_lseek(fd, sizeof(MSFT_Header) + header.nrtypeinfos*sizeof(INT) + sizeof(MSFT_SegDir) + + typeinfo_offs[i]); + tlb_read(fd, &base, sizeof(base)); + + importlib->importinfos[i].importlib = importlib; + importlib->importinfos[i].flags = (base.typekind&0xf)<<24; + importlib->importinfos[i].offset = -1; + importlib->importinfos[i].id = i; + + if(base.posguid != -1) { + importlib->importinfos[i].flags |= MSFT_IMPINFO_OFFSET_IS_GUID; + msft_read_guid(fd, &segdir, base.posguid, &importlib->importinfos[i].guid); + } + + tlb_lseek(fd, segdir.pNametab.offset + base.NameOffset); + tlb_read(fd, &nameintro, sizeof(nameintro)); + + len = nameintro.namelen & 0xff; + + importlib->importinfos[i].name = xmalloc(len+1); + tlb_read(fd, importlib->importinfos[i].name, len); + importlib->importinfos[i].name[len] = 0; + } + + free(typeinfo_offs); +} + +static void read_importlib(importlib_t *importlib) +{ + int fd; + INT magic; + char *file_name; + + file_name = wpp_find_include(importlib->name, NULL); + if(file_name) { + fd = open(file_name, O_RDONLY); + free(file_name); + }else { + fd = open(importlib->name, O_RDONLY); + } + + if(fd < 0) + error("Could not open importlib %s.\n", importlib->name); + + tlb_read(fd, &magic, sizeof(magic)); + + switch(magic) { + case MSFT_MAGIC: + read_msft_importlib(importlib, fd); + break; + default: + error("Wrong or unsupported typelib magic %x\n", magic); + }; + + close(fd); +} + void add_importlib(const char *name) { + importlib_t *importlib; + if(!typelib) return; + importlib = xmalloc(sizeof(*importlib)); + importlib->name = xstrdup(name); + + read_importlib(importlib); + + LINK(importlib, typelib->importlibs); + typelib->importlibs = importlib; + warning("importlib is not yet supported.\n"); } diff --git a/tools/widl/typelib_struct.h b/tools/widl/typelib_struct.h index 961105caece..6067abbb66a 100644 --- a/tools/widl/typelib_struct.h +++ b/tools/widl/typelib_struct.h @@ -34,6 +34,8 @@ * with ICreateTypeLib2 have "MSFT". */ +#define MSFT_MAGIC 0x5446534d + /***************************************************** * MSFT typelibs * @@ -162,7 +164,7 @@ typedef struct tagMSFT_ImpInfo { /* if clear oGuid is a typeinfo index in the specified typelib */ /* bits 24 - 31: TKIND of reference */ INT oImpFile; /* offset in the Import File table */ - INT oGuid; /* offset in Guid table or typeinfo index (see bit 16 of res0) */ + INT oGuid; /* offset in Guid table or typeinfo index (see bit 16 of flags) */ } MSFT_ImpInfo; #define MSFT_IMPINFO_OFFSET_IS_GUID 0x00010000 diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index a2d917b3dc8..83d2311dd3f 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -42,6 +42,8 @@ typedef struct _func_t func_t; typedef struct _ifref_t ifref_t; typedef struct _class_t class_t; typedef struct _typelib_entry_t typelib_entry_t; +typedef struct _importlib_t importlib_t; +typedef struct _importinfo_t importinfo_t; typedef struct _typelib_t typelib_t; #define DECL_LINK(type) \ @@ -260,11 +262,37 @@ struct _typelib_entry_t { DECL_LINK(typelib_entry_t) }; +struct _importinfo_t { + int offset; + GUID guid; + int flags; + int id; + + char *name; + + importlib_t *importlib; +}; + +struct _importlib_t { + char *name; + + int version; + GUID guid; + + importinfo_t *importinfos; + int ntypeinfos; + + int allocated; + + DECL_LINK(importlib_t); +}; + struct _typelib_t { char *name; char *filename; attr_t *attrs; typelib_entry_t *entry; + importlib_t *importlibs; }; #endif