4 * Copyright 2004 Ove Kaaven
5 * Copyright 2006 Jacek Caban for CodeWeavers
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.
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.
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
34 #include "wpp_private.h"
38 #include "widltypes.h"
39 #include "typelib_struct.h"
43 /* List of oleauto types that should be recognized by name.
44 * (most of) these seem to be intrinsic types in mktyplib.
45 * This table MUST be alphabetically sorted on the kw field.
47 static const struct oatype
{
54 {"DECIMAL", VT_DECIMAL
},
55 {"HRESULT", VT_HRESULT
},
57 {"LPWSTR", VT_LPWSTR
},
59 {"VARIANT", VT_VARIANT
},
60 {"VARIANT_BOOL", VT_BOOL
}
62 #define KWP(p) ((const struct oatype *)(p))
64 static int kw_cmp_func(const void *s1
, const void *s2
)
66 return strcmp(KWP(s1
)->kw
, KWP(s2
)->kw
);
69 static unsigned short builtin_vt(const type_t
*t
)
71 const char *kw
= t
->name
;
73 const struct oatype
*kwp
;
76 kwp
= bsearch(&key
, oatypes
, ARRAY_SIZE(oatypes
), sizeof(oatypes
[0]), kw_cmp_func
);
80 for (kwp
= NULL
, i
= 0; i
< ARRAY_SIZE(oatypes
); i
++)
81 if (!kw_cmp_func(&key
, &oatypes
[i
])) {
90 if (is_string_type (t
->attrs
, t
))
92 const type_t
*elem_type
;
94 elem_type
= type_array_get_element_type(t
);
96 elem_type
= type_pointer_get_ref_type(t
);
97 if (type_get_type(elem_type
) == TYPE_BASIC
)
99 switch (type_basic_get_type(elem_type
))
101 case TYPE_BASIC_CHAR
: return VT_LPSTR
;
102 case TYPE_BASIC_WCHAR
: return VT_LPWSTR
;
110 static int match(const char*n
, const char*m
)
113 return !strcmp(n
, m
);
116 unsigned short get_type_vt(type_t
*t
)
120 chat("get_type_vt: %p type->name %s\n", t
, t
->name
);
126 if (type_is_alias(t
) &&
127 (is_attr(t
->attrs
, ATTR_PUBLIC
) || is_attr(t
->attrs
, ATTR_WIREMARSHAL
)))
128 return VT_USERDEFINED
;
130 switch (type_get_type(t
)) {
132 switch (type_basic_get_type(t
)) {
133 case TYPE_BASIC_BYTE
:
135 case TYPE_BASIC_CHAR
:
136 case TYPE_BASIC_INT8
:
137 if (type_basic_get_sign(t
) > 0)
141 case TYPE_BASIC_WCHAR
:
142 return VT_I2
; /* mktyplib seems to parse wchar_t as short */
143 case TYPE_BASIC_INT16
:
144 if (type_basic_get_sign(t
) > 0)
149 if (type_basic_get_sign(t
) > 0)
153 case TYPE_BASIC_INT32
:
154 case TYPE_BASIC_LONG
:
155 case TYPE_BASIC_ERROR_STATUS_T
:
156 if (type_basic_get_sign(t
) > 0)
160 case TYPE_BASIC_INT64
:
161 case TYPE_BASIC_HYPER
:
162 if (type_basic_get_sign(t
) > 0)
166 case TYPE_BASIC_INT3264
:
167 if (pointer_size
== 8)
169 if (type_basic_get_sign(t
) > 0)
176 if (type_basic_get_sign(t
) > 0)
181 case TYPE_BASIC_FLOAT
:
183 case TYPE_BASIC_DOUBLE
:
185 case TYPE_BASIC_HANDLE
:
186 error("handles can't be used in typelibs\n");
194 if (type_array_is_decl_as_ptr(t
))
196 if (match(type_array_get_element_type(t
)->name
, "SAFEARRAY"))
204 if(match(t
->name
, "IUnknown"))
206 if(match(t
->name
, "IDispatch"))
208 return VT_USERDEFINED
;
215 case TYPE_ENCAPSULATED_UNION
:
216 case TYPE_RUNTIMECLASS
:
218 return VT_USERDEFINED
;
224 case TYPE_APICONTRACT
:
225 case TYPE_PARAMETERIZED_TYPE
:
227 /* not supposed to be here */
232 error("get_type_vt: functions not supported\n");
236 error("get_type_vt: bitfields not supported\n");
242 static void msft_read_guid(void *data
, MSFT_SegDir
*segdir
, int offset
, struct uuid
*guid
)
244 memcpy( guid
, (char *)data
+ segdir
->pGuidTab
.offset
+ offset
, sizeof(*guid
) );
247 static void read_msft_importlib(importlib_t
*importlib
, void *data
, unsigned int size
)
249 MSFT_Header
*header
= data
;
254 importlib
->allocated
= 0;
255 importlib
->version
= header
->version
;
257 typeinfo_offs
= (int *)(header
+ 1);
258 segdir
= (MSFT_SegDir
*)(typeinfo_offs
+ header
->nrtypeinfos
);
260 msft_read_guid(data
, segdir
, header
->posguid
, &importlib
->guid
);
262 importlib
->ntypeinfos
= header
->nrtypeinfos
;
263 importlib
->importinfos
= xmalloc(importlib
->ntypeinfos
*sizeof(importinfo_t
));
265 for(i
=0; i
< importlib
->ntypeinfos
; i
++) {
266 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)((char *)(segdir
+ 1) + typeinfo_offs
[i
]);
267 MSFT_NameIntro
*nameintro
;
270 importlib
->importinfos
[i
].importlib
= importlib
;
271 importlib
->importinfos
[i
].flags
= (base
->typekind
& 0xf)<<24;
272 importlib
->importinfos
[i
].offset
= -1;
273 importlib
->importinfos
[i
].id
= i
;
275 if(base
->posguid
!= -1) {
276 importlib
->importinfos
[i
].flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
277 msft_read_guid(data
, segdir
, base
->posguid
, &importlib
->importinfos
[i
].guid
);
279 else memset( &importlib
->importinfos
[i
].guid
, 0, sizeof(importlib
->importinfos
[i
].guid
));
281 nameintro
= (MSFT_NameIntro
*)((char *)data
+ segdir
->pNametab
.offset
+ base
->NameOffset
);
283 len
= nameintro
->namelen
& 0xff;
284 importlib
->importinfos
[i
].name
= xmalloc(len
+1);
285 memcpy( importlib
->importinfos
[i
].name
, nameintro
+ 1, len
);
286 importlib
->importinfos
[i
].name
[len
] = 0;
290 static unsigned int rva_to_va( const IMAGE_NT_HEADERS32
*nt
, unsigned int rva
)
292 IMAGE_SECTION_HEADER
*sec
= (IMAGE_SECTION_HEADER
*)((char *)&nt
->OptionalHeader
+ nt
->FileHeader
.SizeOfOptionalHeader
);
295 for (i
= 0; i
< nt
->FileHeader
.NumberOfSections
; i
++, sec
++)
296 if (sec
->VirtualAddress
<= rva
&& sec
->VirtualAddress
+ sec
->Misc
.VirtualSize
> rva
)
297 return sec
->PointerToRawData
+ (rva
- sec
->VirtualAddress
);
298 error( "no PE section found for addr %x\n", rva
);
301 static void read_pe_importlib(importlib_t
*importlib
, void *data
, unsigned int size
)
303 IMAGE_DOS_HEADER
*dos
= data
;
304 IMAGE_NT_HEADERS32
*nt
;
305 IMAGE_DATA_DIRECTORY
*dir
;
306 IMAGE_RESOURCE_DIRECTORY
*root
, *resdir
;
307 IMAGE_RESOURCE_DIRECTORY_ENTRY
*entry
;
308 IMAGE_RESOURCE_DATA_ENTRY
*resdata
;
312 if (dos
->e_lfanew
< sizeof(*dos
) || dos
->e_lfanew
>= size
) error( "not a PE file\n" );
313 nt
= (IMAGE_NT_HEADERS32
*)((char *)data
+ dos
->e_lfanew
);
314 if (nt
->Signature
!= IMAGE_NT_SIGNATURE
) error( "not a PE file\n" );
315 if ((char *)&nt
->OptionalHeader
+ nt
->FileHeader
.SizeOfOptionalHeader
> (char *)data
+ size
)
316 error( "invalid PE file\n" );
317 switch (nt
->OptionalHeader
.Magic
)
319 case IMAGE_NT_OPTIONAL_HDR32_MAGIC
:
320 dir
= &nt
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
];
322 case IMAGE_NT_OPTIONAL_HDR64_MAGIC
:
323 dir
= &((IMAGE_NT_HEADERS64
*)nt
)->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
];
326 error( "invalid PE file\n" );
328 if (!dir
->VirtualAddress
|| !dir
->Size
) error( "resource not found in PE file\n" );
329 va
= rva_to_va( nt
, dir
->VirtualAddress
);
330 if (va
+ dir
->Size
> size
) error( "invalid resource data in PE file\n" );
331 root
= resdir
= (IMAGE_RESOURCE_DIRECTORY
*)((char *)data
+ va
);
332 entry
= (IMAGE_RESOURCE_DIRECTORY_ENTRY
*)(resdir
+ 1);
333 for (i
= 0; i
< resdir
->NumberOfNamedEntries
; i
++, entry
++)
335 static const WCHAR typelibW
[] = {'T','Y','P','E','L','I','B'};
336 WCHAR
*name
= (WCHAR
*)((char *)root
+ entry
->NameOffset
);
337 if (name
[0] != ARRAY_SIZE(typelibW
)) continue;
338 if (!memcmp( name
+ 1, typelibW
, sizeof(typelibW
) )) break;
340 if (i
== resdir
->NumberOfNamedEntries
) error( "typelib resource not found in PE file\n" );
341 while (entry
->DataIsDirectory
)
343 resdir
= (IMAGE_RESOURCE_DIRECTORY
*)((char *)root
+ entry
->OffsetToDirectory
);
344 entry
= (IMAGE_RESOURCE_DIRECTORY_ENTRY
*)(resdir
+ 1);
346 resdata
= (IMAGE_RESOURCE_DATA_ENTRY
*)((char *)root
+ entry
->OffsetToData
);
347 ptr
= (char *)data
+ rva_to_va( nt
, resdata
->OffsetToData
);
348 if (memcmp( ptr
, "MSFT", 4 )) error( "invalid typelib found in PE file\n" );
349 read_msft_importlib( importlib
, ptr
, resdata
->Size
);
352 static void read_importlib(importlib_t
*importlib
)
357 fd
= open_typelib(importlib
->name
);
359 /* widl extension: if importlib name has no .tlb extension, try using .tlb */
360 if (fd
< 0 && !strendswith( importlib
->name
, ".tlb" ))
361 fd
= open_typelib( strmake( "%s.tlb", importlib
->name
));
364 error("Could not find importlib %s.\n", importlib
->name
);
366 size
= lseek( fd
, 0, SEEK_END
);
367 data
= xmalloc( size
);
368 lseek( fd
, 0, SEEK_SET
);
369 if (read( fd
, data
, size
) < size
) error("error while reading importlib.\n");
372 if (!memcmp( data
, "MSFT", 4 ))
373 read_msft_importlib(importlib
, data
, size
);
374 else if (!memcmp( data
, "MZ", 2 ))
375 read_pe_importlib(importlib
, data
, size
);
377 error("Wrong or unsupported typelib\n");
382 void add_importlib(const char *name
, typelib_t
*typelib
)
384 importlib_t
*importlib
;
388 LIST_FOR_EACH_ENTRY( importlib
, &typelib
->importlibs
, importlib_t
, entry
)
389 if(!strcmp(name
, importlib
->name
))
392 chat("add_importlib: %s\n", name
);
394 importlib
= xmalloc(sizeof(*importlib
));
395 memset( importlib
, 0, sizeof(*importlib
) );
396 importlib
->name
= xstrdup(name
);
398 read_importlib(importlib
);
399 list_add_head( &typelib
->importlibs
, &importlib
->entry
);